3 * @file src/Util/Crypto.php
5 namespace Friendica\Util;
7 use Friendica\Core\Config;
16 // supported algorithms are 'sha256', 'sha1'
18 * @param string $data data
19 * @param string $key key
20 * @param string $alg algorithm
23 public static function rsaSign($data, $key, $alg = 'sha256')
25 openssl_sign($data, $sig, $key, (($alg == 'sha1') ? OPENSSL_ALGO_SHA1 : $alg));
30 * @param string $data data
31 * @param string $sig signature
32 * @param string $key key
33 * @param string $alg algorithm
36 public static function rsaVerify($data, $sig, $key, $alg = 'sha256')
38 return openssl_verify($data, $sig, $key, (($alg == 'sha1') ? OPENSSL_ALGO_SHA1 : $alg));
42 * @param string $Der der formatted string
43 * @param string $Private key type optional, default false
46 private static function DerToPem($Der, $Private = false)
49 $Der = base64_encode($Der);
51 $lines = str_split($Der, 65);
52 $body = implode("\n", $lines);
54 $title = $Private ? 'RSA PRIVATE KEY' : 'PUBLIC KEY';
56 $result = "-----BEGIN {$title}-----\n";
57 $result .= $body . "\n";
58 $result .= "-----END {$title}-----\n";
64 * @param string $Der der formatted string
67 private static function DerToRsa($Der)
70 $Der = base64_encode($Der);
72 $lines = str_split($Der, 64);
73 $body = implode("\n", $lines);
75 $title = 'RSA PUBLIC KEY';
77 $result = "-----BEGIN {$title}-----\n";
78 $result .= $body . "\n";
79 $result .= "-----END {$title}-----\n";
85 * @param string $Modulus modulo
86 * @param string $PublicExponent exponent
89 private static function pkcs8Encode($Modulus, $PublicExponent)
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);
100 $bitStringValue = $keySequence->Encode();
101 $bitStringValue = chr(0x00) . $bitStringValue; //Add unused bits byte
102 $bitString = new ASNValue(ASNValue::TAG_BITSTRING);
103 $bitString->Value = $bitStringValue;
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();
114 * @param string $Modulus modulo
115 * @param string $PublicExponent exponent
118 private static function pkcs1Encode($Modulus, $PublicExponent)
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);
129 $bitStringValue = $keySequence->Encode();
130 return $bitStringValue;
134 * @param string $m modulo
135 * @param string $e exponent
138 public static function meToPem($m, $e)
140 $der = self::pkcs8Encode($m, $e);
141 $key = self::DerToPem($der, false);
146 * @param string $key key
147 * @param string $m modulo reference
148 * @param object $e exponent reference
151 private static function pubRsaToMe($key, &$m, &$e)
153 $lines = explode("\n", $key);
155 unset($lines[count($lines)]);
156 $x = base64_decode(implode('', $lines));
158 $r = ASN_BASE::parseASNString($x);
160 $m = base64url_decode($r[0]->asnData[0]->asnData);
161 $e = base64url_decode($r[0]->asnData[1]->asnData);
165 * @param string $key key
168 public static function rsaToPem($key)
170 self::pubRsaToMe($key, $m, $e);
171 return self::meToPem($m, $e);
175 * @param string $key key
178 private static function pemToRsa($key)
180 self::pemToMe($key, $m, $e);
181 return self::meToRsa($m, $e);
185 * @param string $key key
186 * @param string $m modulo reference
187 * @param string $e exponent reference
190 public static function pemToMe($key, &$m, &$e)
192 $lines = explode("\n", $key);
194 unset($lines[count($lines)]);
195 $x = base64_decode(implode('', $lines));
197 $r = ASN_BASE::parseASNString($x);
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);
204 * @param string $m modulo
205 * @param string $e exponent
208 private static function meToRsa($m, $e)
210 $der = self::pkcs1Encode($m, $e);
211 $key = self::DerToRsa($der);
216 * @param integer $bits number of bits
219 public static function newKeypair($bits)
222 'digest_alg' => 'sha1',
223 'private_key_bits' => $bits,
224 'encrypt_key' => false
227 $conf = Config::get('system', 'openssl_conf_file');
229 $openssl_options['config'] = $conf;
231 $result = openssl_pkey_new($openssl_options);
233 if (empty($result)) {
234 logger('new_keypair: failed');
239 $response = ['prvkey' => '', 'pubkey' => ''];
241 openssl_pkey_export($result, $response['prvkey']);
244 $pkey = openssl_pkey_get_details($result);
245 $response['pubkey'] = $pkey["key"];