mirror of
https://github.com/danog/tgseclib.git
synced 2024-11-30 04:39:02 +01:00
add support for Curve448
This commit is contained in:
parent
7cf5facae7
commit
68f3d7d8af
@ -30,6 +30,7 @@ use phpseclib\Math\Common\FiniteField\Integer;
|
||||
use phpseclib\Common\Functions\Strings;
|
||||
use phpseclib\Math\PrimeField;
|
||||
use phpseclib\Math\BigInteger;
|
||||
use phpseclib\Crypt\EC\Curves\Curve25519;
|
||||
use phpseclib\Math\PrimeField\Integer as PrimeInteger;
|
||||
|
||||
/**
|
||||
@ -202,7 +203,8 @@ class Montgomery extends Base
|
||||
$temp = $da->subtract($cb);
|
||||
$z5 = $x1->multiply($temp->multiply($temp));
|
||||
$x4 = $aa->multiply($bb);
|
||||
$z4 = $e->multiply($bb->add($this->a24->multiply($e)));
|
||||
$temp = static::class == Curve25519::class ? $bb : $aa;
|
||||
$z4 = $e->multiply($temp->add($this->a24->multiply($e)));
|
||||
|
||||
return [
|
||||
[$x4, $z4],
|
||||
|
@ -36,7 +36,7 @@ class Curve25519 extends Montgomery
|
||||
);
|
||||
$this->setBasePoint(
|
||||
new BigInteger(9),
|
||||
new BigInteger('14781619447589544791020593568409986887264606134616475288964881837755586237401', 16)
|
||||
new BigInteger('14781619447589544791020593568409986887264606134616475288964881837755586237401')
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
71
phpseclib/Crypt/EC/Curves/Curve448.php
Normal file
71
phpseclib/Crypt/EC/Curves/Curve448.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Curve448
|
||||
*
|
||||
* PHP version 5 and 7
|
||||
*
|
||||
* @category Crypt
|
||||
* @package EC
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2019 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://pear.php.net/package/Math_BigInteger
|
||||
*/
|
||||
|
||||
namespace phpseclib\Crypt\EC\Curves;
|
||||
|
||||
use phpseclib\Math\Common\FiniteField\Integer;
|
||||
use phpseclib\Crypt\EC\BaseCurves\Montgomery;
|
||||
use phpseclib\Math\BigInteger;
|
||||
|
||||
class Curve448 extends Montgomery
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// 2^448 - 2^224 - 1
|
||||
$this->setModulo(new BigInteger(
|
||||
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE' .
|
||||
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16));
|
||||
$this->a24 = $this->factory->newInteger(new BigInteger('39081'));
|
||||
$this->p = [$this->factory->newInteger(new BigInteger(5))];
|
||||
// 2^446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d
|
||||
$this->setOrder(new BigInteger(
|
||||
'3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' .
|
||||
'7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3', 16));
|
||||
|
||||
/*
|
||||
$this->setCoefficients(
|
||||
new BigInteger('156326'), // a
|
||||
);
|
||||
$this->setBasePoint(
|
||||
new BigInteger(5),
|
||||
new BigInteger(
|
||||
'355293926785568175264127502063783334808976399387714271831880898' .
|
||||
'435169088786967410002932673765864550910142774147268105838985595290' .
|
||||
'606362')
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply a point on the curve by a scalar
|
||||
*
|
||||
* Modifies the scalar as described at https://tools.ietf.org/html/rfc7748#page-8
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function multiplyPoint(array $p, Integer $d)
|
||||
{
|
||||
//$r = strrev(sodium_crypto_scalarmult($d->toBytes(), strrev($p[0]->toBytes())));
|
||||
//return [$this->factory->newInteger(new BigInteger($r, 256))];
|
||||
|
||||
$d = $d->toBytes();
|
||||
$d[0] = $d[0] & "\xFC";
|
||||
$d = strrev($d);
|
||||
$d|= "\x80";
|
||||
$d = $this->factory->newInteger(new BigInteger($d, 256));
|
||||
|
||||
return parent::multiplyPoint($p, $d);
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Curve25519 Private Key Handler
|
||||
* Montgomery Private Key Handler
|
||||
*
|
||||
* "Naked" Curve25519 private keys can pretty much be any sequence of random 32x bytes so unless
|
||||
* we have a "hidden" key handler pretty much every 32 byte string will be loaded as a curve25519
|
||||
@ -23,17 +23,19 @@
|
||||
namespace phpseclib\Crypt\EC\Formats\Keys;
|
||||
|
||||
use phpseclib\Crypt\EC\Curves\Curve25519;
|
||||
use phpseclib\Crypt\EC\Curves\Curve448;
|
||||
use phpseclib\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
|
||||
use phpseclib\Math\Common\FiniteField\Integer;
|
||||
use phpseclib\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Curve25519 Private Key Handler
|
||||
* Montgomery Curve Private Key Handler
|
||||
*
|
||||
* @package EC
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @access public
|
||||
*/
|
||||
abstract class Curve25519Private
|
||||
abstract class MontgomeryPrivate
|
||||
{
|
||||
/**
|
||||
* Is invisible flag
|
||||
@ -52,10 +54,19 @@ abstract class Curve25519Private
|
||||
*/
|
||||
public static function load($key, $password = '')
|
||||
{
|
||||
$curve = new Curve25519();
|
||||
switch (strlen($key)) {
|
||||
case 32:
|
||||
$curve = new Curve25519;
|
||||
break;
|
||||
case 56:
|
||||
$curve = new Curve448;
|
||||
break;
|
||||
default:
|
||||
throw new \LengthException('The only supported lengths are 32 and 56');
|
||||
}
|
||||
|
||||
$components = ['curve' => $curve];
|
||||
$components['dA'] = $components['curve']->convertInteger(new BigInteger($key, -256));
|
||||
$components['dA'] = $components['curve']->convertInteger(new BigInteger($key, 256));
|
||||
// note that EC::getEncodedCoordinates does some additional "magic" (it does strrev on the result)
|
||||
$components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
|
||||
|
||||
@ -66,13 +77,13 @@ abstract class Curve25519Private
|
||||
* Convert an EC public key to the appropriate format
|
||||
*
|
||||
* @access public
|
||||
* @param \phpseclib\Crypt\EC\Curves\Curve25519 $curve
|
||||
* @param \phpseclib\Crypt\EC\Curves\MontgomeryCurve $curve
|
||||
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||
* @return string
|
||||
*/
|
||||
public static function savePublicKey(Curve25519 $curve, array $publicKey)
|
||||
public static function savePublicKey(MontgomeryCurve $curve, array $publicKey)
|
||||
{
|
||||
return strrev($publicKey[0]->toBytes(true));
|
||||
return strrev($publicKey[0]->toBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,13 +91,13 @@ abstract class Curve25519Private
|
||||
*
|
||||
* @access public
|
||||
* @param \phpseclib\Math\Common\FiniteField\Integer $privateKey
|
||||
* @param \phpseclib\Crypt\EC\Curves\Curve25519 $curve
|
||||
* @param \phpseclib\Crypt\EC\Curves\Montgomery $curve
|
||||
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||
* @param string $password optional
|
||||
* @return string
|
||||
*/
|
||||
public static function savePrivateKey(Integer $privateKey, Curve25519 $curve, array $publicKey, $password = '')
|
||||
public static function savePrivateKey(Integer $privateKey, MontgomeryCurve $curve, array $publicKey, $password = '')
|
||||
{
|
||||
return $privateKey->toBytes(true);
|
||||
return $privateKey->toBytes();
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Curve25519 Public Key Handler
|
||||
* Montgomery Public Key Handler
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
@ -16,17 +16,19 @@
|
||||
namespace phpseclib\Crypt\EC\Formats\Keys;
|
||||
|
||||
use phpseclib\Crypt\EC\Curves\Curve25519;
|
||||
use phpseclib\Crypt\EC\Curves\Curve448;
|
||||
use phpseclib\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
|
||||
use phpseclib\Math\Common\FiniteField\Integer;
|
||||
use phpseclib\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Curve25519 Public Key Handler
|
||||
* Montgomery Public Key Handler
|
||||
*
|
||||
* @package EC
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @access public
|
||||
*/
|
||||
abstract class Curve25519Public
|
||||
abstract class MontgomeryPublic
|
||||
{
|
||||
/**
|
||||
* Is invisible flag
|
||||
@ -45,10 +47,19 @@ abstract class Curve25519Public
|
||||
*/
|
||||
public static function load($key, $password = '')
|
||||
{
|
||||
$curve = new Curve25519();
|
||||
switch (strlen($key)) {
|
||||
case 32:
|
||||
$curve = new Curve25519;
|
||||
break;
|
||||
case 56:
|
||||
$curve = new Curve448;
|
||||
break;
|
||||
default:
|
||||
throw new \LengthException('The only supported lengths are 32 and 56');
|
||||
}
|
||||
|
||||
$components = ['curve' => $curve];
|
||||
$components['QA'] = [$components['curve']->convertInteger(new BigInteger(strrev($key), -256))];
|
||||
$components['QA'] = [$components['curve']->convertInteger(new BigInteger(strrev($key), 256))];
|
||||
|
||||
return $components;
|
||||
}
|
||||
@ -57,12 +68,12 @@ abstract class Curve25519Public
|
||||
* Convert an EC public key to the appropriate format
|
||||
*
|
||||
* @access public
|
||||
* @param \phpseclib\Crypt\EC\Curves\Curve25519 $curve
|
||||
* @param \phpseclib\Crypt\EC\Curves\Montgomery $curve
|
||||
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||
* @return string
|
||||
*/
|
||||
public static function savePublicKey(Curve25519 $curve, array $publicKey)
|
||||
public static function savePublicKey(MontgomeryCurve $curve, array $publicKey)
|
||||
{
|
||||
return strrev($publicKey[0]->toBytes(true));
|
||||
return strrev($publicKey[0]->toBytes());
|
||||
}
|
||||
}
|
@ -235,9 +235,7 @@ class PrivateKey extends EC implements Common\PrivateKey
|
||||
{
|
||||
$format = 'PKCS8';
|
||||
if ($this->curve instanceof MontgomeryCurve) {
|
||||
$format = $this->curve instanceof Curve25519 ?
|
||||
'Curve25519Public' :
|
||||
'Curve448Public';
|
||||
$format = 'MontgomeryPublic';
|
||||
}
|
||||
|
||||
$type = self::validatePlugin('Keys', $format, 'savePublicKey');
|
||||
|
@ -153,11 +153,11 @@ Q3ADAIcv9LEmTBnSAOsCs1K9ExAmSv/T2/4+9dW28UYb+p/uV477d1wf+nCWS6VU
|
||||
$aes->setIV(substr($key, 16, 16));
|
||||
|
||||
$encrypted =
|
||||
$ourEphemeralPublic->toString('Curve25519Public') .
|
||||
$ourEphemeralPublic->toString('MontgomeryPublic') .
|
||||
$aes->encrypt($plaintext);
|
||||
|
||||
$theirPublic = substr($encrypted, 0, 32);
|
||||
$theirPublic = EC::loadFormat('Curve25519Public', $theirPublic);
|
||||
$theirPublic = EC::loadFormat('MontgomeryPublic', $theirPublic);
|
||||
|
||||
$ourPrivate = $theirPrivate;
|
||||
|
||||
@ -205,20 +205,20 @@ Q3ADAIcv9LEmTBnSAOsCs1K9ExAmSv/T2/4+9dW28UYb+p/uV477d1wf+nCWS6VU
|
||||
{
|
||||
// utilizing test vector from https://tools.ietf.org/html/rfc7748#section-6.1
|
||||
|
||||
$alicePrivate = EC::loadFormat('Curve25519Private', pack('H*', '77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a'));
|
||||
$bobPrivate = EC::loadFormat('Curve25519Private', pack('H*', '5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb'));
|
||||
$alicePrivate = EC::loadFormat('MontgomeryPrivate', pack('H*', '77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a'));
|
||||
$bobPrivate = EC::loadFormat('MontgomeryPrivate', pack('H*', '5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb'));
|
||||
|
||||
$alicePublic = $alicePrivate->getPublicKey();
|
||||
$bobPublic = $bobPrivate->getPublicKey();
|
||||
|
||||
$this->assertSame(
|
||||
'8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a',
|
||||
bin2hex($alicePublic->toString('Curve25519Public'))
|
||||
bin2hex($alicePublic->toString('MontgomeryPublic'))
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
'de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f',
|
||||
bin2hex($bobPublic->toString('Curve25519Public'))
|
||||
bin2hex($bobPublic->toString('MontgomeryPublic'))
|
||||
);
|
||||
|
||||
$expected = pack('H*', '4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742');
|
||||
@ -226,4 +226,41 @@ Q3ADAIcv9LEmTBnSAOsCs1K9ExAmSv/T2/4+9dW28UYb+p/uV477d1wf+nCWS6VU
|
||||
$this->assertSame($expected, DH::computeSecret($alicePrivate, $bobPublic));
|
||||
$this->assertSame($expected, DH::computeSecret($bobPrivate, $alicePublic));
|
||||
}
|
||||
|
||||
public function testCurve448()
|
||||
{
|
||||
// utilizing test vector from https://tools.ietf.org/html/rfc7748#section-6.2
|
||||
|
||||
$alicePrivate = EC::loadFormat('MontgomeryPrivate', pack('H*',
|
||||
'9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28d' .
|
||||
'd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b'
|
||||
));
|
||||
$bobPrivate = EC::loadFormat('MontgomeryPrivate', pack('H*',
|
||||
'1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d' .
|
||||
'6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d'
|
||||
));
|
||||
|
||||
$alicePublic = $alicePrivate->getPublicKey();
|
||||
$bobPublic = $bobPrivate->getPublicKey();
|
||||
|
||||
$this->assertSame(
|
||||
'9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c' .
|
||||
'22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0',
|
||||
bin2hex($alicePublic->toString('MontgomeryPublic'))
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
'3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b430' .
|
||||
'27d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609',
|
||||
bin2hex($bobPublic->toString('MontgomeryPublic'))
|
||||
);
|
||||
|
||||
$expected = pack('H*',
|
||||
'07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282b' .
|
||||
'b60c0b56fd2464c335543936521c24403085d59a449a5037514a879d'
|
||||
);
|
||||
|
||||
$this->assertSame($expected, DH::computeSecret($alicePrivate, $bobPublic));
|
||||
$this->assertSame($expected, DH::computeSecret($bobPrivate, $alicePublic));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user