Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
1.9 KiB

3 years ago
3 years ago
  1. <?php
  2. namespace Friendica\Util;
  3. use Friendica\Core\Logger;
  4. use Friendica\Model\APContact;
  5. /**
  6. * @brief Implements JSON-LD signatures
  7. *
  8. * Ported from Osada: https://framagit.org/macgirvin/osada
  9. */
  10. class LDSignature
  11. {
  12. public static function isSigned($data)
  13. {
  14. return !empty($data['signature']);
  15. }
  16. public static function getSigner($data)
  17. {
  18. if (!self::isSigned($data)) {
  19. return false;
  20. }
  21. $actor = JsonLD::fetchElement($data, 'actor', 'id');
  22. if (empty($actor) || !is_string($actor)) {
  23. return false;
  24. }
  25. $profile = APContact::getByURL($actor);
  26. if (empty($profile['pubkey'])) {
  27. return false;
  28. }
  29. $pubkey = $profile['pubkey'];
  30. $ohash = self::hash(self::signableOptions($data['signature']));
  31. $dhash = self::hash(self::signableData($data));
  32. $x = Crypto::rsaVerify($ohash . $dhash, base64_decode($data['signature']['signatureValue']), $pubkey);
  33. Logger::log('LD-verify: ' . intval($x));
  34. if (empty($x)) {
  35. return false;
  36. } else {
  37. return $actor;
  38. }
  39. }
  40. public static function sign($data, $owner)
  41. {
  42. $options = [
  43. 'type' => 'RsaSignature2017',
  44. 'nonce' => Strings::getRandomHex(64),
  45. 'creator' => $owner['url'] . '#main-key',
  46. 'created' => DateTimeFormat::utcNow(DateTimeFormat::ATOM)
  47. ];
  48. $ohash = self::hash(self::signableOptions($options));
  49. $dhash = self::hash(self::signableData($data));
  50. $options['signatureValue'] = base64_encode(Crypto::rsaSign($ohash . $dhash, $owner['uprvkey']));
  51. return array_merge($data, ['signature' => $options]);
  52. }
  53. private static function signableData($data)
  54. {
  55. unset($data['signature']);
  56. return $data;
  57. }
  58. private static function signableOptions($options)
  59. {
  60. $newopts = ['@context' => 'https://w3id.org/identity/v1'];
  61. unset($options['type']);
  62. unset($options['id']);
  63. unset($options['signatureValue']);
  64. return array_merge($newopts, $options);
  65. }
  66. private static function hash($obj)
  67. {
  68. return hash('sha256', JsonLD::normalize($obj));
  69. }
  70. }