]> git.mxchange.org Git - friendica.git/blob - src/Util/Crypto.php
Merge pull request #5109 from rabuzarus/20180522_-_frio_nav_about_instance
[friendica.git] / src / Util / Crypto.php
1 <?php
2 /**
3  * @file src/Util/Crypto.php
4  */
5 namespace Friendica\Util;
6
7 use Friendica\Core\Config;
8 use ASN_BASE;
9 use ASNValue;
10
11 /**
12  * @brief Crypto class
13  */
14 class Crypto
15 {
16         // supported algorithms are 'sha256', 'sha1'
17         /**
18          * @param string $data data
19          * @param string $key  key
20          * @param string $alg  algorithm
21          * @return string
22          */
23         public static function rsaSign($data, $key, $alg = 'sha256')
24         {
25                 openssl_sign($data, $sig, $key, (($alg == 'sha1') ? OPENSSL_ALGO_SHA1 : $alg));
26                 return $sig;
27         }
28
29         /**
30          * @param string $data data
31          * @param string $sig  signature
32          * @param string $key  key
33          * @param string $alg  algorithm
34          * @return boolean
35          */
36         public static function rsaVerify($data, $sig, $key, $alg = 'sha256')
37         {
38                 return openssl_verify($data, $sig, $key, (($alg == 'sha1') ? OPENSSL_ALGO_SHA1 : $alg));
39         }
40
41         /**
42          * @param string $Der     der formatted string
43          * @param string $Private key type optional, default false
44          * @return string
45          */
46         private static function DerToPem($Der, $Private = false)
47         {
48                 //Encode:
49                 $Der = base64_encode($Der);
50                 //Split lines:
51                 $lines = str_split($Der, 65);
52                 $body = implode("\n", $lines);
53                 //Get title:
54                 $title = $Private ? 'RSA PRIVATE KEY' : 'PUBLIC KEY';
55                 //Add wrapping:
56                 $result = "-----BEGIN {$title}-----\n";
57                 $result .= $body . "\n";
58                 $result .= "-----END {$title}-----\n";
59
60                 return $result;
61         }
62
63         /**
64          * @param string $Der der formatted string
65          * @return string
66          */
67         private static function DerToRsa($Der)
68         {
69                 //Encode:
70                 $Der = base64_encode($Der);
71                 //Split lines:
72                 $lines = str_split($Der, 64);
73                 $body = implode("\n", $lines);
74                 //Get title:
75                 $title = 'RSA PUBLIC KEY';
76                 //Add wrapping:
77                 $result = "-----BEGIN {$title}-----\n";
78                 $result .= $body . "\n";
79                 $result .= "-----END {$title}-----\n";
80
81                 return $result;
82         }
83
84         /**
85          * @param string $Modulus        modulo
86          * @param string $PublicExponent exponent
87          * @return string
88          */
89         private static function pkcs8Encode($Modulus, $PublicExponent)
90         {
91                 //Encode key sequence
92                 $modulus = new ASNValue(ASNValue::TAG_INTEGER);
93                 $modulus->SetIntBuffer($Modulus);
94                 $publicExponent = new ASNValue(ASNValue::TAG_INTEGER);
95                 $publicExponent->SetIntBuffer($PublicExponent);
96                 $keySequenceItems = [$modulus, $publicExponent];
97                 $keySequence = new ASNValue(ASNValue::TAG_SEQUENCE);
98                 $keySequence->SetSequence($keySequenceItems);
99                 //Encode bit string
100                 $bitStringValue = $keySequence->Encode();
101                 $bitStringValue = chr(0x00) . $bitStringValue; //Add unused bits byte
102                 $bitString = new ASNValue(ASNValue::TAG_BITSTRING);
103                 $bitString->Value = $bitStringValue;
104                 //Encode body
105                 $bodyValue = "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00" . $bitString->Encode();
106                 $body = new ASNValue(ASNValue::TAG_SEQUENCE);
107                 $body->Value = $bodyValue;
108                 //Get DER encoded public key:
109                 $PublicDER = $body->Encode();
110                 return $PublicDER;
111         }
112
113         /**
114          * @param string $Modulus        modulo
115          * @param string $PublicExponent exponent
116          * @return string
117          */
118         private static function pkcs1Encode($Modulus, $PublicExponent)
119         {
120                 //Encode key sequence
121                 $modulus = new ASNValue(ASNValue::TAG_INTEGER);
122                 $modulus->SetIntBuffer($Modulus);
123                 $publicExponent = new ASNValue(ASNValue::TAG_INTEGER);
124                 $publicExponent->SetIntBuffer($PublicExponent);
125                 $keySequenceItems = [$modulus, $publicExponent];
126                 $keySequence = new ASNValue(ASNValue::TAG_SEQUENCE);
127                 $keySequence->SetSequence($keySequenceItems);
128                 //Encode bit string
129                 $bitStringValue = $keySequence->Encode();
130                 return $bitStringValue;
131         }
132
133         /**
134          * @param string $m modulo
135          * @param string $e exponent
136          * @return string
137          */
138         public static function meToPem($m, $e)
139         {
140                 $der = self::pkcs8Encode($m, $e);
141                 $key = self::DerToPem($der, false);
142                 return $key;
143         }
144
145         /**
146          * @param string $key key
147          * @param string $m   modulo reference
148          * @param object $e   exponent reference
149          * @return void
150          */
151         private static function pubRsaToMe($key, &$m, &$e)
152         {
153                 $lines = explode("\n", $key);
154                 unset($lines[0]);
155                 unset($lines[count($lines)]);
156                 $x = base64_decode(implode('', $lines));
157
158                 $r = ASN_BASE::parseASNString($x);
159
160                 $m = base64url_decode($r[0]->asnData[0]->asnData);
161                 $e = base64url_decode($r[0]->asnData[1]->asnData);
162         }
163
164         /**
165          * @param string $key key
166          * @return string
167          */
168         public static function rsaToPem($key)
169         {
170                 self::pubRsaToMe($key, $m, $e);
171                 return self::meToPem($m, $e);
172         }
173
174         /**
175          * @param string $key key
176          * @return string
177          */
178         private static function pemToRsa($key)
179         {
180                 self::pemToMe($key, $m, $e);
181                 return self::meToRsa($m, $e);
182         }
183
184         /**
185          * @param string $key key
186          * @param string $m   modulo reference
187          * @param string $e   exponent reference
188          * @return void
189          */
190         public static function pemToMe($key, &$m, &$e)
191         {
192                 $lines = explode("\n", $key);
193                 unset($lines[0]);
194                 unset($lines[count($lines)]);
195                 $x = base64_decode(implode('', $lines));
196
197                 $r = ASN_BASE::parseASNString($x);
198
199                 $m = base64url_decode($r[0]->asnData[1]->asnData[0]->asnData[0]->asnData);
200                 $e = base64url_decode($r[0]->asnData[1]->asnData[0]->asnData[1]->asnData);
201         }
202
203         /**
204          * @param string $m modulo
205          * @param string $e exponent
206          * @return string
207          */
208         private static function meToRsa($m, $e)
209         {
210                 $der = self::pkcs1Encode($m, $e);
211                 $key = self::DerToRsa($der);
212                 return $key;
213         }
214
215         /**
216          * @param integer $bits number of bits
217          * @return mixed
218          */
219         public static function newKeypair($bits)
220         {
221                 $openssl_options = [
222                         'digest_alg'       => 'sha1',
223                         'private_key_bits' => $bits,
224                         'encrypt_key'      => false
225                 ];
226
227                 $conf = Config::get('system', 'openssl_conf_file');
228                 if ($conf) {
229                         $openssl_options['config'] = $conf;
230                 }
231                 $result = openssl_pkey_new($openssl_options);
232
233                 if (empty($result)) {
234                         logger('new_keypair: failed');
235                         return false;
236                 }
237
238                 // Get private key
239                 $response = ['prvkey' => '', 'pubkey' => ''];
240
241                 openssl_pkey_export($result, $response['prvkey']);
242
243                 // Get public key
244                 $pkey = openssl_pkey_get_details($result);
245                 $response['pubkey'] = $pkey["key"];
246
247                 return $response;
248         }
249 }