[ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * EC Public 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 namespace phpseclib3\Crypt\EC; 13 14 use phpseclib3\Common\Functions\Strings; 15 use phpseclib3\Crypt\Common; 16 use phpseclib3\Crypt\EC; 17 use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; 18 use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; 19 use phpseclib3\Crypt\EC\Curves\Ed25519; 20 use phpseclib3\Crypt\EC\Formats\Keys\PKCS1; 21 use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature; 22 use phpseclib3\Crypt\Hash; 23 use phpseclib3\Exception\UnsupportedOperationException; 24 use phpseclib3\Math\BigInteger; 25 26 /** 27 * EC Public Key 28 * 29 * @author Jim Wigginton <terrafrost@php.net> 30 */ 31 final class PublicKey extends EC implements Common\PublicKey 32 { 33 use Common\Traits\Fingerprint; 34 35 /** 36 * Verify a signature 37 * 38 * @see self::verify() 39 * @param string $message 40 * @param string $signature 41 * @return mixed 42 */ 43 public function verify($message, $signature) 44 { 45 if ($this->curve instanceof MontgomeryCurve) { 46 throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures'); 47 } 48 49 $shortFormat = $this->shortFormat; 50 $format = $this->sigFormat; 51 if ($format === false) { 52 return false; 53 } 54 55 $order = $this->curve->getOrder(); 56 57 if ($this->curve instanceof TwistedEdwardsCurve) { 58 if ($shortFormat == 'SSH2') { 59 list(, $signature) = Strings::unpackSSH2('ss', $signature); 60 } 61 62 if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) { 63 return sodium_crypto_sign_verify_detached($signature, $message, $this->toString('libsodium')); 64 } 65 66 $curve = $this->curve; 67 if (strlen($signature) != 2 * $curve::SIZE) { 68 return false; 69 } 70 71 $R = substr($signature, 0, $curve::SIZE); 72 $S = substr($signature, $curve::SIZE); 73 74 try { 75 $R = PKCS1::extractPoint($R, $curve); 76 $R = $this->curve->convertToInternal($R); 77 } catch (\Exception $e) { 78 return false; 79 } 80 81 $S = strrev($S); 82 $S = new BigInteger($S, 256); 83 84 if ($S->compare($order) >= 0) { 85 return false; 86 } 87 88 $A = $curve->encodePoint($this->QA); 89 90 if ($curve instanceof Ed25519) { 91 $dom2 = !isset($this->context) ? '' : 92 'SigEd25519 no Ed25519 collisions' . "\0" . chr(strlen($this->context)) . $this->context; 93 } else { 94 $context = isset($this->context) ? $this->context : ''; 95 $dom2 = 'SigEd448' . "\0" . chr(strlen($context)) . $context; 96 } 97 98 $hash = new Hash($curve::HASH); 99 $k = $hash->hash($dom2 . substr($signature, 0, $curve::SIZE) . $A . $message); 100 $k = strrev($k); 101 $k = new BigInteger($k, 256); 102 list(, $k) = $k->divide($order); 103 104 $qa = $curve->convertToInternal($this->QA); 105 106 $lhs = $curve->multiplyPoint($curve->getBasePoint(), $S); 107 $rhs = $curve->multiplyPoint($qa, $k); 108 $rhs = $curve->addPoint($rhs, $R); 109 $rhs = $curve->convertToAffine($rhs); 110 111 return $lhs[0]->equals($rhs[0]) && $lhs[1]->equals($rhs[1]); 112 } 113 114 $params = $format::load($signature); 115 if ($params === false || count($params) != 2) { 116 return false; 117 } 118 extract($params); 119 120 if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) { 121 $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature; 122 123 $result = openssl_verify($message, $sig, $this->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash()); 124 125 if ($result != -1) { 126 return (bool) $result; 127 } 128 } 129 130 $n_1 = $order->subtract(self::$one); 131 if (!$r->between(self::$one, $n_1) || !$s->between(self::$one, $n_1)) { 132 return false; 133 } 134 135 $e = $this->hash->hash($message); 136 $e = new BigInteger($e, 256); 137 138 $Ln = $this->hash->getLength() - $order->getLength(); 139 $z = $Ln > 0 ? $e->bitwise_rightShift($Ln) : $e; 140 141 $w = $s->modInverse($order); 142 list(, $u1) = $z->multiply($w)->divide($order); 143 list(, $u2) = $r->multiply($w)->divide($order); 144 145 $u1 = $this->curve->convertInteger($u1); 146 $u2 = $this->curve->convertInteger($u2); 147 148 list($x1, $y1) = $this->curve->multiplyAddPoints( 149 [$this->curve->getBasePoint(), $this->QA], 150 [$u1, $u2] 151 ); 152 153 $x1 = $x1->toBigInteger(); 154 list(, $x1) = $x1->divide($order); 155 156 return $x1->equals($r); 157 } 158 159 /** 160 * Returns the public key 161 * 162 * @param string $type 163 * @param array $options optional 164 * @return string 165 */ 166 public function toString($type, array $options = []) 167 { 168 $type = self::validatePlugin('Keys', $type, 'savePublicKey'); 169 170 return $type::savePublicKey($this->curve, $this->QA, $options); 171 } 172 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body