18 abstract class Base implements 48 $this->rng = new \fpoirotte\Pssht\Random\OpenSSL();
53 return 'ecdsa-sha2-' . static::getIdentifier();
58 $encoder->encodeString(static::getName());
59 $encoder->encodeString(static::getIdentifier());
60 $encoder->encodeString(
62 \
fpoirotte\Pssht\ECC\Curve::getCurve(static::getIdentifier())
67 public static function unserialize(\
fpoirotte\Pssht\Wire\
Decoder $decoder, $private = null)
69 if ($decoder->decodeString() !== static::getIdentifier()) {
70 throw new \InvalidArgumentException();
72 $Q = \fpoirotte\Pssht\ECC\Point::unserialize(
73 \
fpoirotte\Pssht\ECC\Curve::getCurve(static::getIdentifier()),
74 $decoder->decodeString()
76 return new static(
$Q, $private);
79 public function sign($message, $raw_output =
false)
81 if ($this->d === null) {
82 throw new \RuntimeException();
85 $curve = \fpoirotte\Pssht\ECC\Curve::getCurve(static::getIdentifier());
86 $mod = $curve->getOrder();
87 $mlen = gmp_init(strlen(gmp_strval($mod, 2)));
88 $mlen = gmp_intval(gmp_div_q($mlen, 8, GMP_ROUND_PLUSINF));
89 $M = gmp_init(hash($this->getHash(), $message,
false), 16);
90 $generator = $curve->getGenerator();
95 $k = gmp_init(bin2hex($this->rng->getBytes($mlen)), 16);
96 }
while (gmp_cmp($k, gmp_sub($mod, 1)) >= 0);
97 $sig1 = $generator->multiply($curve, $k)->x;
98 }
while (gmp_cmp($sig1, 0) === 0);
100 $bezout = gmp_gcdext($k, $mod);
101 $k_inv = gmp_mod(gmp_add($bezout[
's'], $mod), $mod);
102 $sig2 = gmp_mod(gmp_mul($k_inv, gmp_add($M, gmp_mul($this->d, $sig1))), $mod);
103 }
while (gmp_cmp($sig2, 0) === 0);
105 $encoder = new \fpoirotte\Pssht\Wire\Encoder();
106 $encoder->encodeMpint($sig1);
107 $encoder->encodeMpint($sig2);
108 return $encoder->getBuffer()->get(0);
111 public function check($message, $signature)
113 $decoder = new \fpoirotte\Pssht\Wire\Decoder(
117 $curve = \fpoirotte\Pssht\ECC\Curve::getCurve(static::getIdentifier());
118 $sig1 = $decoder->decodeMpint();
119 $sig2 = $decoder->decodeMpint();
120 $mod = $curve->getOrder();
121 $M = gmp_init(hash($this->getHash(), $message,
false), 16);
122 $bezout = gmp_gcdext($sig2, $mod);
123 $w = gmp_mod(gmp_add($bezout[
's'], $mod), $mod);
124 $u1 = gmp_mod(gmp_mul($M, $w), $mod);
125 $u2 = gmp_mod(gmp_mul($sig1, $w), $mod);
126 $R = \fpoirotte\Pssht\ECC\Point::add(
128 $curve->getGenerator()->multiply($curve, $u1),
129 $this->Q->multiply($curve, $u2)
131 return (gmp_cmp($R->x, $sig1) === 0);
158 public function isValid()
160 $curve = \fpoirotte\Pssht\ECC\Curve::getCurve(static::getIdentifier());
161 if ($this->Q->isIdentity($curve)) {
165 $p = $curve->getModulus();
166 if (gmp_cmp($this->Q->x, 0) < 0 || gmp_cmp($this->Q->x, $p) >= 0 ||
167 gmp_cmp($this->Q->y, 0) < 0 || gmp_cmp($this->Q->y, $p) >= 0) {
171 $left = gmp_mod(gmp_mul($this->Q->y, $this->Q->y), $p);
175 gmp_pow($this->Q->x, 3),
176 gmp_mul($curve->getA(), $this->Q->x)
182 if (gmp_cmp($left, $right)) {
186 if ($curve->getCofactor() === 1) {
190 return $this->Q->multiply($curve->getOrder())->isIdentity();
193 public function getPublic()
serialize(\fpoirotte\Pssht\Wire\Encoder $encoder)
__construct(\fpoirotte\Pssht\ECC\Point $Q, $d=null)
setRNG(\fpoirotte\Pssht\Random\RandomInterface $rng)
check($message, $signature)
static getName()
Return the name of the algorithm.