PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / 3.1.13.4
JetBackup – Backup, Restore & Migrate v3.1.13.4
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 / PrivateKey.php
backup / src / JetBackup / 3rdparty / phpseclib3 / Crypt / EC Last commit date
BaseCurves 9 months ago Curves 9 months ago Formats 9 months ago .htaccess 9 months ago Parameters.php 9 months ago PrivateKey.php 9 months ago PublicKey.php 9 months ago index.html 9 months ago web.config 9 months ago
PrivateKey.php
253 lines
1 <?php
2
3 /**
4 * EC Private Key
5 *
6 * @author Jim Wigginton <terrafrost@php.net>
7 * @copyright 2015 Jim Wigginton
8 * @license http://www.opensource.org/licenses/mit-license.html MIT License
9 * @link http://phpseclib.sourceforge.net
10 */
11
12 declare(strict_types=1);
13
14 namespace phpseclib3\Crypt\EC;
15
16 use phpseclib3\Common\Functions\Strings;
17 use phpseclib3\Crypt\Common;
18 use phpseclib3\Crypt\EC;
19 use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
20 use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
21 use phpseclib3\Crypt\EC\Curves\Curve25519;
22 use phpseclib3\Crypt\EC\Curves\Ed25519;
23 use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
24 use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature;
25 use phpseclib3\Crypt\Hash;
26 use phpseclib3\Exception\RuntimeException;
27 use phpseclib3\Exception\UnsupportedOperationException;
28 use phpseclib3\Math\BigInteger;
29
30 /**
31 * EC Private Key
32 *
33 * @author Jim Wigginton <terrafrost@php.net>
34 */
35 final class PrivateKey extends EC implements Common\PrivateKey
36 {
37 use Common\Traits\PasswordProtected;
38
39 /**
40 * Private Key dA
41 *
42 * sign() converts this to a BigInteger so one might wonder why this is a FiniteFieldInteger instead of
43 * a BigInteger. That's because a FiniteFieldInteger, when converted to a byte string, is null padded by
44 * a certain amount whereas a BigInteger isn't.
45 *
46 * @var object
47 */
48 protected $dA;
49
50 /**
51 * @var string
52 */
53 protected $secret;
54
55 /**
56 * Multiplies an encoded point by the private key
57 *
58 * Used by ECDH
59 */
60 public function multiply(string $coordinates): string
61 {
62 if ($this->curve instanceof MontgomeryCurve) {
63 if ($this->curve instanceof Curve25519 && self::$engines['libsodium']) {
64 return sodium_crypto_scalarmult($this->dA->toBytes(), $coordinates);
65 }
66
67 $point = [$this->curve->convertInteger(new BigInteger(strrev($coordinates), 256))];
68 $point = $this->curve->multiplyPoint($point, $this->dA);
69 return strrev($point[0]->toBytes(true));
70 }
71 if (!$this->curve instanceof TwistedEdwardsCurve) {
72 $coordinates = "\0$coordinates";
73 }
74 $point = PKCS1::extractPoint($coordinates, $this->curve);
75 $point = $this->curve->multiplyPoint($point, $this->dA);
76 if ($this->curve instanceof TwistedEdwardsCurve) {
77 return $this->curve->encodePoint($point);
78 }
79 if (empty($point)) {
80 throw new RuntimeException('The infinity point is invalid');
81 }
82 return "\4" . $point[0]->toBytes(true) . $point[1]->toBytes(true);
83 }
84
85 /**
86 * Create a signature
87 *
88 * @see self::verify()
89 * @param string $message
90 */
91 public function sign($message)
92 {
93 if ($this->curve instanceof MontgomeryCurve) {
94 throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures');
95 }
96
97 $dA = $this->dA;
98 $order = $this->curve->getOrder();
99
100 $shortFormat = $this->shortFormat;
101 $format = $this->sigFormat;
102 if ($format === false) {
103 return false;
104 }
105
106 if ($this->curve instanceof TwistedEdwardsCurve) {
107 if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) {
108 $result = sodium_crypto_sign_detached($message, $this->withPassword()->toString('libsodium'));
109 return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $result) : $result;
110 }
111
112 // contexts (Ed25519ctx) are supported but prehashing (Ed25519ph) is not.
113 // quoting https://tools.ietf.org/html/rfc8032#section-8.5 ,
114 // "The Ed25519ph and Ed448ph variants ... SHOULD NOT be used"
115 $A = $this->curve->encodePoint($this->QA);
116 $curve = $this->curve;
117 $hash = new Hash($curve::HASH);
118
119 $secret = substr($hash->hash($this->secret), $curve::SIZE);
120
121 if ($curve instanceof Ed25519) {
122 $dom = !isset($this->context) ? '' :
123 'SigEd25519 no Ed25519 collisions' . "\0" . chr(strlen($this->context)) . $this->context;
124 } else {
125 $context = $this->context ?? '';
126 $dom = 'SigEd448' . "\0" . chr(strlen($context)) . $context;
127 }
128 // SHA-512(dom2(F, C) || prefix || PH(M))
129 $r = $hash->hash($dom . $secret . $message);
130 $r = strrev($r);
131 $r = new BigInteger($r, 256);
132 [, $r] = $r->divide($order);
133 $R = $curve->multiplyPoint($curve->getBasePoint(), $r);
134 $R = $curve->encodePoint($R);
135 $k = $hash->hash($dom . $R . $A . $message);
136 $k = strrev($k);
137 $k = new BigInteger($k, 256);
138 [, $k] = $k->divide($order);
139 $S = $k->multiply($dA)->add($r);
140 [, $S] = $S->divide($order);
141 $S = str_pad(strrev($S->toBytes()), $curve::SIZE, "\0");
142 return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $R . $S) : $R . $S;
143 }
144
145 if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
146 $signature = '';
147 // altho PHP's OpenSSL bindings only supported EC key creation in PHP 7.1 they've long
148 // supported signing / verification
149 // we use specified curves to avoid issues with OpenSSL possibly not supporting a given named curve;
150 // doing this may mean some curve-specific optimizations can't be used but idk if OpenSSL even
151 // has curve-specific optimizations
152 $result = openssl_sign($message, $signature, $this->withPassword()->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash());
153
154 if ($result) {
155 if ($shortFormat == 'ASN1') {
156 return $signature;
157 }
158
159 extract(ASN1Signature::load($signature));
160
161 return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s);
162 }
163 }
164
165 $e = $this->hash->hash($message);
166 $e = new BigInteger($e, 256);
167
168 $Ln = $this->hash->getLength() - $order->getLength();
169 $z = $Ln > 0 ? $e->bitwise_rightShift($Ln) : $e;
170
171 while (true) {
172 $k = BigInteger::randomRange(self::$one, $order->subtract(self::$one));
173 [$x, $y] = $this->curve->multiplyPoint($this->curve->getBasePoint(), $k);
174 $x = $x->toBigInteger();
175 [, $r] = $x->divide($order);
176 if ($r->equals(self::$zero)) {
177 continue;
178 }
179 $kinv = $k->modInverse($order);
180 $temp = $z->add($dA->multiply($r));
181 $temp = $kinv->multiply($temp);
182 [, $s] = $temp->divide($order);
183 if (!$s->equals(self::$zero)) {
184 break;
185 }
186 }
187
188 // the following is an RFC6979 compliant implementation of deterministic ECDSA
189 // it's unused because it's mainly intended for use when a good CSPRNG isn't
190 // available. if phpseclib's CSPRNG isn't good then even key generation is
191 // suspect
192 /*
193 // if this were actually being used it'd probably be better if this lived in load() and createKey()
194 $this->q = $this->curve->getOrder();
195 $dA = $this->dA->toBigInteger();
196 $this->x = $dA;
197
198 $h1 = $this->hash->hash($message);
199 $k = $this->computek($h1);
200 list($x, $y) = $this->curve->multiplyPoint($this->curve->getBasePoint(), $k);
201 $x = $x->toBigInteger();
202 list(, $r) = $x->divide($this->q);
203 $kinv = $k->modInverse($this->q);
204 $h1 = $this->bits2int($h1);
205 $temp = $h1->add($dA->multiply($r));
206 $temp = $kinv->multiply($temp);
207 list(, $s) = $temp->divide($this->q);
208 */
209
210 return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s);
211 }
212
213 /**
214 * Returns the private key
215 *
216 * @param array $options optional
217 */
218 public function toString(string $type, array $options = []): string
219 {
220 $type = self::validatePlugin('Keys', $type, 'savePrivateKey');
221
222 return $type::savePrivateKey($this->dA, $this->curve, $this->QA, $this->secret, $this->password, $options);
223 }
224
225 /**
226 * Returns the public key
227 *
228 * @see self::getPrivateKey()
229 */
230 public function getPublicKey()
231 {
232 $format = 'PKCS8';
233 if ($this->curve instanceof MontgomeryCurve) {
234 $format = 'MontgomeryPublic';
235 }
236
237 $type = self::validatePlugin('Keys', $format, 'savePublicKey');
238
239 $key = $type::savePublicKey($this->curve, $this->QA);
240 $key = EC::loadFormat($format, $key);
241 if ($this->curve instanceof MontgomeryCurve) {
242 return $key;
243 }
244 $key = $key
245 ->withHash($this->hash->getHash())
246 ->withSignatureFormat($this->shortFormat);
247 if ($this->curve instanceof TwistedEdwardsCurve) {
248 $key = $key->withContext($this->context);
249 }
250 return $key;
251 }
252 }
253