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