PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / trunk
JetBackup – Backup, Restore & Migrate vtrunk
3.1.22.4 3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / src / JetBackup / 3rdparty / phpseclib3 / Crypt / EC / Formats / Keys / PKCS8.php
backup / src / JetBackup / 3rdparty / phpseclib3 / Crypt / EC / Formats / Keys Last commit date
.htaccess 1 year ago Common.php 1 year ago JWK.php 1 year ago MontgomeryPrivate.php 1 year ago MontgomeryPublic.php 1 year ago OpenSSH.php 1 year ago PKCS1.php 1 year ago PKCS8.php 1 year ago PuTTY.php 1 year ago XML.php 1 year ago index.html 1 year ago libsodium.php 1 year ago web.config 1 year ago
PKCS8.php
227 lines
1 <?php
2
3 /**
4 * PKCS#8 Formatted EC Key Handler
5 *
6 * PHP version 5
7 *
8 * Processes keys with the following headers:
9 *
10 * -----BEGIN ENCRYPTED PRIVATE KEY-----
11 * -----BEGIN PRIVATE KEY-----
12 * -----BEGIN PUBLIC KEY-----
13 *
14 * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
15 * is specific to private keys it's basically creating a DER-encoded wrapper
16 * for keys. This just extends that same concept to public keys (much like ssh-keygen)
17 *
18 * @author Jim Wigginton <terrafrost@php.net>
19 * @copyright 2015 Jim Wigginton
20 * @license http://www.opensource.org/licenses/mit-license.html MIT License
21 * @link http://phpseclib.sourceforge.net
22 */
23
24 declare(strict_types=1);
25
26 namespace phpseclib3\Crypt\EC\Formats\Keys;
27
28 use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
29 use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
30 use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
31 use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
32 use phpseclib3\Crypt\EC\Curves\Ed25519;
33 use phpseclib3\Crypt\EC\Curves\Ed448;
34 use phpseclib3\Exception\RuntimeException;
35 use phpseclib3\Exception\UnsupportedCurveException;
36 use phpseclib3\File\ASN1;
37 use phpseclib3\File\ASN1\Maps;
38 use phpseclib3\Math\BigInteger;
39 use phpseclib3\Math\Common\FiniteField\Integer;
40
41 /**
42 * PKCS#8 Formatted EC Key Handler
43 *
44 * @author Jim Wigginton <terrafrost@php.net>
45 */
46 abstract class PKCS8 extends Progenitor
47 {
48 use Common;
49
50 /**
51 * OID Name
52 *
53 * @var array
54 */
55 public const OID_NAME = ['id-ecPublicKey', 'id-Ed25519', 'id-Ed448'];
56
57 /**
58 * OID Value
59 *
60 * @var string
61 */
62 public const OID_VALUE = ['1.2.840.10045.2.1', '1.3.101.112', '1.3.101.113'];
63
64 /**
65 * Break a public or private key down into its constituent components
66 *
67 * @param string|array $key
68 */
69 public static function load($key, ?string $password = null): array
70 {
71 // initialize_static_variables() is defined in both the trait and the parent class
72 // when it's defined in two places it's the traits one that's called
73 // the parent one is needed, as well, but the parent one is called by other methods
74 // in the parent class as needed and in the context of the parent it's the parent
75 // one that's called
76 self::initialize_static_variables();
77
78 $key = parent::load($key, $password);
79
80 $type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
81
82 switch ($key[$type . 'Algorithm']['algorithm']) {
83 case 'id-Ed25519':
84 case 'id-Ed448':
85 return self::loadEdDSA($key);
86 }
87
88 $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
89 if (!$decoded) {
90 throw new RuntimeException('Unable to decode BER');
91 }
92 $params = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP);
93 if (!$params) {
94 throw new RuntimeException('Unable to decode the parameters using Maps\ECParameters');
95 }
96
97 $components = [];
98 $components['curve'] = self::loadCurveByParam($params);
99
100 if ($type == 'publicKey') {
101 $components['QA'] = self::extractPoint("\0" . $key['publicKey'], $components['curve']);
102
103 return $components;
104 }
105
106 $decoded = ASN1::decodeBER($key['privateKey']);
107 if (!$decoded) {
108 throw new RuntimeException('Unable to decode BER');
109 }
110 $key = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP);
111 if (isset($key['parameters']) && $params != $key['parameters']) {
112 throw new RuntimeException('The PKCS8 parameter field does not match the private key parameter field');
113 }
114
115 $components['dA'] = new BigInteger($key['privateKey'], 256);
116 $components['curve']->rangeCheck($components['dA']);
117 $components['QA'] = isset($key['publicKey']) ?
118 self::extractPoint($key['publicKey'], $components['curve']) :
119 $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
120
121 return $components;
122 }
123
124 /**
125 * Break a public or private EdDSA key down into its constituent components
126 */
127 private static function loadEdDSA(array $key): array
128 {
129 $components = [];
130
131 if (isset($key['privateKey'])) {
132 $components['curve'] = $key['privateKeyAlgorithm']['algorithm'] == 'id-Ed25519' ? new Ed25519() : new Ed448();
133
134 // 0x04 == octet string
135 // 0x20 == length (32 bytes)
136 if (substr($key['privateKey'], 0, 2) != "\x04\x20") {
137 throw new RuntimeException('The first two bytes of the private key field should be 0x0420');
138 }
139 $arr = $components['curve']->extractSecret(substr($key['privateKey'], 2));
140 $components['dA'] = $arr['dA'];
141 $components['secret'] = $arr['secret'];
142 }
143
144 if (isset($key['publicKey'])) {
145 if (!isset($components['curve'])) {
146 $components['curve'] = $key['publicKeyAlgorithm']['algorithm'] == 'id-Ed25519' ? new Ed25519() : new Ed448();
147 }
148
149 $components['QA'] = self::extractPoint($key['publicKey'], $components['curve']);
150 }
151
152 if (isset($key['privateKey']) && !isset($components['QA'])) {
153 $components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
154 }
155
156 return $components;
157 }
158
159 /**
160 * Convert an EC public key to the appropriate format
161 *
162 * @param Integer[] $publicKey
163 * @param array $options optional
164 */
165 public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = []): string
166 {
167 self::initialize_static_variables();
168
169 if ($curve instanceof MontgomeryCurve) {
170 throw new UnsupportedCurveException('Montgomery Curves are not supported');
171 }
172
173 if ($curve instanceof TwistedEdwardsCurve) {
174 return self::wrapPublicKey(
175 $curve->encodePoint($publicKey),
176 null,
177 $curve instanceof Ed25519 ? 'id-Ed25519' : 'id-Ed448'
178 );
179 }
180
181 $params = new ASN1\Element(self::encodeParameters($curve, false, $options));
182
183 $key = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
184
185 return self::wrapPublicKey($key, $params, 'id-ecPublicKey');
186 }
187
188 /**
189 * Convert a private key to the appropriate format.
190 *
191 * @param Integer[] $publicKey
192 */
193 public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, ?string $secret = null, ?string $password = null, array $options = []): string
194 {
195 self::initialize_static_variables();
196
197 if ($curve instanceof MontgomeryCurve) {
198 throw new UnsupportedCurveException('Montgomery Curves are not supported');
199 }
200
201 if ($curve instanceof TwistedEdwardsCurve) {
202 return self::wrapPrivateKey(
203 "\x04\x20" . $secret,
204 [],
205 null,
206 $password,
207 $curve instanceof Ed25519 ? 'id-Ed25519' : 'id-Ed448'
208 );
209 }
210
211 $publicKey = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
212
213 $params = new ASN1\Element(self::encodeParameters($curve, false, $options));
214
215 $key = [
216 'version' => 'ecPrivkeyVer1',
217 'privateKey' => $privateKey->toBytes(),
218 //'parameters' => $params,
219 'publicKey' => "\0" . $publicKey,
220 ];
221
222 $key = ASN1::encodeDER($key, Maps\ECPrivateKey::MAP);
223
224 return self::wrapPrivateKey($key, [], $params, $password, 'id-ecPublicKey', '', $options);
225 }
226 }
227