diff options
Diffstat (limited to 'vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php')
-rw-r--r-- | vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php new file mode 100644 index 0000000..4558ce3 --- /dev/null +++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php @@ -0,0 +1,172 @@ +<?php + +/** + * EC Public Key + * + * @author Jim Wigginton <[email protected]> + * @copyright 2015 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib3\Crypt\EC; + +use phpseclib3\Common\Functions\Strings; +use phpseclib3\Crypt\Common; +use phpseclib3\Crypt\EC; +use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; +use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; +use phpseclib3\Crypt\EC\Curves\Ed25519; +use phpseclib3\Crypt\EC\Formats\Keys\PKCS1; +use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature; +use phpseclib3\Crypt\Hash; +use phpseclib3\Exception\UnsupportedOperationException; +use phpseclib3\Math\BigInteger; + +/** + * EC Public Key + * + * @author Jim Wigginton <[email protected]> + */ +final class PublicKey extends EC implements Common\PublicKey +{ + use Common\Traits\Fingerprint; + + /** + * Verify a signature + * + * @see self::verify() + * @param string $message + * @param string $signature + * @return mixed + */ + public function verify($message, $signature) + { + if ($this->curve instanceof MontgomeryCurve) { + throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures'); + } + + $shortFormat = $this->shortFormat; + $format = $this->sigFormat; + if ($format === false) { + return false; + } + + $order = $this->curve->getOrder(); + + if ($this->curve instanceof TwistedEdwardsCurve) { + if ($shortFormat == 'SSH2') { + list(, $signature) = Strings::unpackSSH2('ss', $signature); + } + + if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) { + return sodium_crypto_sign_verify_detached($signature, $message, $this->toString('libsodium')); + } + + $curve = $this->curve; + if (strlen($signature) != 2 * $curve::SIZE) { + return false; + } + + $R = substr($signature, 0, $curve::SIZE); + $S = substr($signature, $curve::SIZE); + + try { + $R = PKCS1::extractPoint($R, $curve); + $R = $this->curve->convertToInternal($R); + } catch (\Exception $e) { + return false; + } + + $S = strrev($S); + $S = new BigInteger($S, 256); + + if ($S->compare($order) >= 0) { + return false; + } + + $A = $curve->encodePoint($this->QA); + + if ($curve instanceof Ed25519) { + $dom2 = !isset($this->context) ? '' : + 'SigEd25519 no Ed25519 collisions' . "\0" . chr(strlen($this->context)) . $this->context; + } else { + $context = isset($this->context) ? $this->context : ''; + $dom2 = 'SigEd448' . "\0" . chr(strlen($context)) . $context; + } + + $hash = new Hash($curve::HASH); + $k = $hash->hash($dom2 . substr($signature, 0, $curve::SIZE) . $A . $message); + $k = strrev($k); + $k = new BigInteger($k, 256); + list(, $k) = $k->divide($order); + + $qa = $curve->convertToInternal($this->QA); + + $lhs = $curve->multiplyPoint($curve->getBasePoint(), $S); + $rhs = $curve->multiplyPoint($qa, $k); + $rhs = $curve->addPoint($rhs, $R); + $rhs = $curve->convertToAffine($rhs); + + return $lhs[0]->equals($rhs[0]) && $lhs[1]->equals($rhs[1]); + } + + $params = $format::load($signature); + if ($params === false || count($params) != 2) { + return false; + } + extract($params); + + if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) { + $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature; + + $result = openssl_verify($message, $sig, $this->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash()); + + if ($result != -1) { + return (bool) $result; + } + } + + $n_1 = $order->subtract(self::$one); + if (!$r->between(self::$one, $n_1) || !$s->between(self::$one, $n_1)) { + return false; + } + + $e = $this->hash->hash($message); + $e = new BigInteger($e, 256); + + $Ln = $this->hash->getLength() - $order->getLength(); + $z = $Ln > 0 ? $e->bitwise_rightShift($Ln) : $e; + + $w = $s->modInverse($order); + list(, $u1) = $z->multiply($w)->divide($order); + list(, $u2) = $r->multiply($w)->divide($order); + + $u1 = $this->curve->convertInteger($u1); + $u2 = $this->curve->convertInteger($u2); + + list($x1, $y1) = $this->curve->multiplyAddPoints( + [$this->curve->getBasePoint(), $this->QA], + [$u1, $u2] + ); + + $x1 = $x1->toBigInteger(); + list(, $x1) = $x1->divide($order); + + return $x1->equals($r); + } + + /** + * Returns the public key + * + * @param string $type + * @param array $options optional + * @return string + */ + public function toString($type, array $options = []) + { + $type = self::validatePlugin('Keys', $type, 'savePublicKey'); + + return $type::savePublicKey($this->curve, $this->QA, $options); + } +} |