27 \fpoirotte\Pssht\Algorithms\AvailabilityInterface
50 if (strlen(
$pk) !== 32 || (
$sk !== null && strlen(
$sk) !== 32)) {
51 throw new \InvalidArgumentException();
64 $encoder->encodeString(self::getName());
65 $encoder->encodeString($this->pk);
68 public static function unserialize(\
fpoirotte\Pssht\Wire\
Decoder $decoder, $private = null)
70 $pk = $decoder->decodeString();
72 throw new \InvalidArgumentException();
74 return new static(
$pk, $private);
80 return function_exists(
'hash_algos') &&
81 function_exists(
'hash') &&
82 in_array(
'sha512', hash_algos());
85 protected static function encodeint($y)
87 $t = str_pad(gmp_strval($y, 16), 64, 0, STR_PAD_LEFT);
88 $res = strrev(pack(
'H*', $t));
92 protected static function encodepoint($P)
96 gmp_and($y, gmp_sub(gmp_pow(2, 256), 1)),
97 gmp_mul(gmp_and($x, 1), gmp_pow(2, 255))
99 $t = str_pad(gmp_strval($t, 16), 64, 0, STR_PAD_LEFT);
100 $res = strrev(pack(
'H*', $t));
104 protected static function hashint($m)
106 $h = hash(
'sha512', $m,
true);
107 $res = gmp_init(bin2hex(strrev($h)), 16);
111 protected static function decodeint($s)
113 return gmp_init(bin2hex(strrev($s)), 16);
116 protected static function decodepoint($s)
118 $curve = \fpoirotte\Pssht\ECC\ED25519::getInstance();
120 gmp_init(bin2hex(strrev($s)), 16),
121 gmp_sub(gmp_pow(2, 255), 1)
123 $x = $curve->xrecover($y);
124 if (gmp_cmp(gmp_and($x, 1), (ord(substr($s, -1)) >> 7) & 1)) {
125 $x = gmp_sub($curve->q, $x);
128 if (!static::isOnCurve($P)) {
134 protected static function isOnCurve($P)
136 $curve = \fpoirotte\Pssht\ECC\ED25519::getInstance();
138 $x2 = gmp_mul($x, $x);
139 $y2 = gmp_mul($y, $y);
142 gmp_sub(gmp_add(gmp_neg($x2), $y2), 1),
143 gmp_mul($curve->d, gmp_mul($x2, $y2))
147 return !gmp_cmp($t, 0);
152 if ($this->sk === null) {
153 throw new \RuntimeException();
156 $curve = \fpoirotte\Pssht\ECC\ED25519::getInstance();
157 $h = hash(
'sha512', $this->sk,
true);
161 gmp_init(bin2hex(strrev($h)), 16),
162 gmp_sub(gmp_pow(2, 254), 8)
165 $r = static::hashint(substr($h, 32) . $message);
166 $R = $curve->scalarmult($curve->B, $r);
167 $t = static::encodepoint($R) . $this->pk . $message;
178 return static::encodepoint($R) . static::encodeint($S);
181 public function check($message, $signature)
183 $curve = \fpoirotte\Pssht\ECC\ED25519::getInstance();
184 if (strlen($signature) !== 64) {
185 throw new \InvalidArgumentException();
188 $R = static::decodepoint(substr($signature, 0, 32));
193 $A = static::decodepoint($this->pk);
197 $S = static::decodeint(substr($signature, 32, 64));
198 $h = static::hashint(static::encodepoint($R) . $this->pk . $message);
199 $res1 = $curve->scalarmult($curve->B, $S);
200 $res2 = $curve->edwards($R, $curve->scalarmult($A, $h));
201 return (!gmp_cmp($res1[0], $res2[0]) &&
202 !gmp_cmp($res1[1], $res2[1]));
serialize(\fpoirotte\Pssht\Wire\Encoder $encoder)
__construct($pk, $sk=null)
check($message, $signature)
static getName()
Return the name of the algorithm.