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