/** * @dataProvider vectorsP521 * @group large */ public function testP521($k, $x, $y) { $base = new \fpoirotte\Pssht\ECC\Point('0x00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66', '0x011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650'); $expected = new \fpoirotte\Pssht\ECC\Point($x, $y); $actual = $base->multiply(\fpoirotte\Pssht\ECC\Curve::getCurve('nistp521'), $k); $this->assertSame(gmp_strval($expected->x, 16), gmp_strval($actual->x, 16)); $this->assertSame(gmp_strval($expected->y, 16), gmp_strval($actual->y, 16)); }
protected function createResponse(\fpoirotte\Pssht\Wire\Decoder $decoder, \fpoirotte\Pssht\Transport $transport, array &$context, $hostAlgo) { $kexAlgo = $context['kexAlgo']; $kexAlgo = new $kexAlgo(); $curveName = str_replace('ecdh-sha2-', '', $kexAlgo::getName()); $cls = str_replace('nist', 'NIST', $curveName); $cls = "\\fpoirotte\\Pssht\\Messages\\KEX\\ECDH\\INIT\\{$cls}"; $message = $cls::unserialize($decoder); $curve = \fpoirotte\Pssht\ECC\Curve::getCurve($curveName); return new \fpoirotte\Pssht\Messages\KEX\ECDH\REPLY\RFC5656($curve, $message, $context['serverKeys'][$hostAlgo], $transport->getEncryptor(), $kexAlgo, $context['kex']['server'], $context['kex']['client'], $context['identity']['server'], $context['identity']['client']); }
public static function getCurve() { return \fpoirotte\Pssht\ECC\Curve::getCurve('nistp521'); }
public static function add(\fpoirotte\Pssht\ECC\Curve $curve, \fpoirotte\Pssht\ECC\Point $P, \fpoirotte\Pssht\ECC\Point $Q) { $mod = $curve->getModulus(); $xP = $P->coordinates['x']; $yP = $P->coordinates['y']; $xQ = $Q->coordinates['x']; $yQ = $Q->coordinates['y']; if (!gmp_cmp($xP, $xQ) && !gmp_cmp($yP, $yQ)) { $alphanum = gmp_add(gmp_mul('3', gmp_pow($xP, '2')), $curve->getA()); $alphaden = gmp_mul('2', $yP); } else { $alphanum = gmp_sub($yQ, $yP); $alphaden = gmp_sub($xQ, $xP); } $bezout = gmp_gcdext($alphaden, $mod); $alpha = gmp_mod(gmp_mul($alphanum, $bezout['s']), $mod); $xR = gmp_sub(gmp_sub(gmp_pow($alpha, '2'), $xP), $xQ); $yR = gmp_sub(gmp_mul($alpha, gmp_sub($xP, $xR)), $yP); return new static(gmp_mod(gmp_add($xR, $mod), $mod), gmp_mod(gmp_add($yR, $mod), $mod)); }
public function setUp() { \fpoirotte\Pssht\ECC\Curve::initialize(); }
/** * Construct a new SSH_MSG_KEXDH_REPLY message. * * \param fpoirotte::Pssht::ECC::Curve $curve * Elliptic curve in use. * * \param fpoirotte::Pssht::Messages::KEX::ECDH::INIT::RFC5656 $kexDHInit * Client's contribution to the Diffie-Hellman Key Exchange. * * \param fpoirotte::Pssht::PublicKeyInterface $key * Server's public key. * * \param fpoirotte::Pssht::EncryptionInterface $encryptionAlgo * Encryption algorithm in use. * * \param fpoirotte::Pssht::KEXInterface $kexAlgo * Key exchange algorithm to use. * * \param fpoirotte::Pssht::Messages::KEXINIT $serverKEX * Algorithms supported by the server. * * \param fpoirotte::Pssht::Messages::KEXINIT $clientKEX * Algorithms supported by the client. * * \param string $serverIdent * Server's identification string * * \param string $clientIdent * Client's identification string */ public function __construct(\fpoirotte\Pssht\ECC\Curve $curve, \fpoirotte\Pssht\Messages\KEX\ECDH\INIT\RFC5656 $kexDHInit, \fpoirotte\Pssht\PublicKeyInterface $key, \fpoirotte\Pssht\EncryptionInterface $encryptionAlgo, \fpoirotte\Pssht\KEXInterface $kexAlgo, \fpoirotte\Pssht\Messages\KEXINIT $serverKEX, \fpoirotte\Pssht\Messages\KEXINIT $clientKEX, $serverIdent, $clientIdent) { if (!is_string($serverIdent)) { throw new \InvalidArgumentException(); } if (!is_string($clientIdent)) { throw new \InvalidArgumentException(); } $len = strlen(gmp_strval($curve->getOrder(), 2)); $len = ceil($len / 8); $randBytes = openssl_random_pseudo_bytes($len); $d_S = gmp_mod(gmp_init(bin2hex($randBytes), 16), $curve->getModulus()); $this->Q_S = $curve->getGenerator()->multiply($curve, $d_S); $Q_C = $kexDHInit->getQ(); /// @FIXME this is not optimal... $algorithms = \fpoirotte\Pssht\Algorithms::factory(); $cls = $algorithms->getClass('PublicKey', 'ecdsa-sha2-' . $curve->getName()); $clientPK = new $cls($Q_C); if (!$clientPK->isValid()) { throw new \InvalidArgumentException(); } // EC Co-factor DH (sec1-v2, section 3.3.2). $P = $Q_C->multiply($curve, gmp_mul($curve->getCofactor(), $d_S)); if ($P->isIdentity($curve)) { throw new \InvalidArgumentException(); } $this->K = $P->x; $this->curve = $curve; $this->K_S = $key; $this->kexDHInit = $kexDHInit; $this->kexAlgo = $kexAlgo; $this->serverKEX = $serverKEX; $this->clientKEX = $clientKEX; $this->serverIdent = $serverIdent; $this->clientIdent = $clientIdent; $msgId = chr(\fpoirotte\Pssht\Messages\KEXINIT::getMessageId()); // $sub is used to create the structure for the hashing function. $sub = new \fpoirotte\Pssht\Wire\Encoder(new \fpoirotte\Pssht\Buffer()); $this->K_S->serialize($sub); $K_S = $sub->getBuffer()->get(0); $sub->encodeString($this->clientIdent); $sub->encodeString($this->serverIdent); // $sub2 is used to compute the value // of various fields inside the structure. $sub2 = new \fpoirotte\Pssht\Wire\Encoder(new \fpoirotte\Pssht\Buffer()); $sub2->encodeBytes($msgId); // Add message identifier. $this->clientKEX->serialize($sub2); $sub->encodeString($sub2->getBuffer()->get(0)); $sub2->encodeBytes($msgId); // Add message identifier. $this->serverKEX->serialize($sub2); $sub->encodeString($sub2->getBuffer()->get(0)); $sub->encodeString($K_S); $sub->encodeString($Q_C->serialize($curve)); $sub->encodeString($this->Q_S->serialize($curve)); $sub->encodeMpint($this->K); $logging = \Plop\Plop::getInstance(); $origData = $sub->getBuffer()->get(0); $data = wordwrap(bin2hex($origData), 4, ' ', true); $data = wordwrap($data, 32 + 7, PHP_EOL, true); $logging->debug("Signature payload:\r\n%s", array($data)); $this->H = $this->kexAlgo->hash($origData); }