]> git.mxchange.org Git - friendica.git/blob - src/Util/LDSignature.php
51086ac3e14a9b45e0caeedc4d11167e0ee16a10
[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
9 /**
10  * @brief Implements JSON-LD signatures
11  *
12  * Ported from Osada: https://framagit.org/macgirvin/osada
13  */
14 class LDSignature
15 {
16         public static function isSigned($data)
17         {
18                 return !empty($data['signature']);
19         }
20
21         public static function getSigner($data)
22         {
23                 if (!self::isSigned($data)) {
24                         return false;
25                 }
26
27 /*
28                 $creator = $data['signature']['creator'];
29                 $actor = JsonLD::fetchElement($data, 'actor', 'id');
30
31                 $url = (strpos($creator, '#') ? substr($creator, 0, strpos($creator, '#')) : $creator);
32
33                 $profile = ActivityPub::fetchprofile($url);
34                 if (!empty($profile)) {
35                         logger('Taking key from creator ' . $creator, LOGGER_DEBUG);
36                 } elseif ($url != $actor) {
37                         $profile = ActivityPub::fetchprofile($actor);
38                         if (empty($profile)) {
39                                 return false;
40                         }
41                         logger('Taking key from actor ' . $actor, LOGGER_DEBUG);
42                 }
43
44 */
45                 $actor = JsonLD::fetchElement($data, 'actor', 'id');
46                 if (empty($actor)) {
47                         return false;
48                 }
49
50                 $profile = ActivityPub::fetchprofile($actor);
51                 if (empty($profile['pubkey'])) {
52                         return false;
53                 }
54                 $pubkey = $profile['pubkey'];
55
56                 $ohash = self::hash(self::signable_options($data['signature']));
57                 $dhash = self::hash(self::signable_data($data));
58
59                 $x = Crypto::rsaVerify($ohash . $dhash, base64_decode($data['signature']['signatureValue']), $pubkey);
60                 logger('LD-verify: ' . intval($x));
61
62                 if (empty($x)) {
63                         return false;
64                 } else {
65                         return $actor;
66                 }
67         }
68
69         public static function sign($data, $owner)
70         {
71                 $options = [
72                         'type' => 'RsaSignature2017',
73                         'nonce' => random_string(64),
74                         'creator' => $owner['url'] . '#main-key',
75                         'created' => DateTimeFormat::utcNow(DateTimeFormat::ATOM)
76                 ];
77
78                 $ohash = self::hash(self::signable_options($options));
79                 $dhash = self::hash(self::signable_data($data));
80                 $options['signatureValue'] = base64_encode(Crypto::rsaSign($ohash . $dhash, $owner['uprvkey']));
81
82                 return array_merge($data, ['signature' => $options]);
83         }
84
85         private static function signable_data($data)
86         {
87                 unset($data['signature']);
88                 return $data;
89         }
90
91         private static function signable_options($options)
92         {
93                 $newopts = ['@context' => 'https://w3id.org/identity/v1'];
94
95                 unset($options['type']);
96                 unset($options['id']);
97                 unset($options['signatureValue']);
98
99                 return array_merge($newopts, $options);
100         }
101
102         private static function hash($obj)
103         {
104                 return hash('sha256', JsonLD::normalize($obj));
105         }
106 }