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