mirror of
https://github.com/phpseclib/phpseclib.git
synced 2025-02-04 04:48:30 +00: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\Common\Functions\Strings;
|
||||||
use phpseclib\Math\PrimeField;
|
use phpseclib\Math\PrimeField;
|
||||||
use phpseclib\Math\BigInteger;
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Crypt\EC\Curves\Curve25519;
|
||||||
use phpseclib\Math\PrimeField\Integer as PrimeInteger;
|
use phpseclib\Math\PrimeField\Integer as PrimeInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -202,7 +203,8 @@ class Montgomery extends Base
|
|||||||
$temp = $da->subtract($cb);
|
$temp = $da->subtract($cb);
|
||||||
$z5 = $x1->multiply($temp->multiply($temp));
|
$z5 = $x1->multiply($temp->multiply($temp));
|
||||||
$x4 = $aa->multiply($bb);
|
$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 [
|
return [
|
||||||
[$x4, $z4],
|
[$x4, $z4],
|
||||||
|
@ -36,7 +36,7 @@ class Curve25519 extends Montgomery
|
|||||||
);
|
);
|
||||||
$this->setBasePoint(
|
$this->setBasePoint(
|
||||||
new BigInteger(9),
|
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
|
<?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
|
* "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
|
* 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;
|
namespace phpseclib\Crypt\EC\Formats\Keys;
|
||||||
|
|
||||||
use phpseclib\Crypt\EC\Curves\Curve25519;
|
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\Common\FiniteField\Integer;
|
||||||
use phpseclib\Math\BigInteger;
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Curve25519 Private Key Handler
|
* Montgomery Curve Private Key Handler
|
||||||
*
|
*
|
||||||
* @package EC
|
* @package EC
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
abstract class Curve25519Private
|
abstract class MontgomeryPrivate
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Is invisible flag
|
* Is invisible flag
|
||||||
@ -52,10 +54,19 @@ abstract class Curve25519Private
|
|||||||
*/
|
*/
|
||||||
public static function load($key, $password = '')
|
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 = ['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)
|
// note that EC::getEncodedCoordinates does some additional "magic" (it does strrev on the result)
|
||||||
$components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
|
$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
|
* Convert an EC public key to the appropriate format
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param \phpseclib\Crypt\EC\Curves\Curve25519 $curve
|
* @param \phpseclib\Crypt\EC\Curves\MontgomeryCurve $curve
|
||||||
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
* @return string
|
* @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
|
* @access public
|
||||||
* @param \phpseclib\Math\Common\FiniteField\Integer $privateKey
|
* @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 \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return string
|
* @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
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Curve25519 Public Key Handler
|
* Montgomery Public Key Handler
|
||||||
*
|
*
|
||||||
* PHP version 5
|
* PHP version 5
|
||||||
*
|
*
|
||||||
@ -16,17 +16,19 @@
|
|||||||
namespace phpseclib\Crypt\EC\Formats\Keys;
|
namespace phpseclib\Crypt\EC\Formats\Keys;
|
||||||
|
|
||||||
use phpseclib\Crypt\EC\Curves\Curve25519;
|
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\Common\FiniteField\Integer;
|
||||||
use phpseclib\Math\BigInteger;
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Curve25519 Public Key Handler
|
* Montgomery Public Key Handler
|
||||||
*
|
*
|
||||||
* @package EC
|
* @package EC
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
abstract class Curve25519Public
|
abstract class MontgomeryPublic
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Is invisible flag
|
* Is invisible flag
|
||||||
@ -45,10 +47,19 @@ abstract class Curve25519Public
|
|||||||
*/
|
*/
|
||||||
public static function load($key, $password = '')
|
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 = ['curve' => $curve];
|
||||||
$components['QA'] = [$components['curve']->convertInteger(new BigInteger(strrev($key), -256))];
|
$components['QA'] = [$components['curve']->convertInteger(new BigInteger(strrev($key), 256))];
|
||||||
|
|
||||||
return $components;
|
return $components;
|
||||||
}
|
}
|
||||||
@ -57,12 +68,12 @@ abstract class Curve25519Public
|
|||||||
* Convert an EC public key to the appropriate format
|
* Convert an EC public key to the appropriate format
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param \phpseclib\Crypt\EC\Curves\Curve25519 $curve
|
* @param \phpseclib\Crypt\EC\Curves\Montgomery $curve
|
||||||
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
* @return string
|
* @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';
|
$format = 'PKCS8';
|
||||||
if ($this->curve instanceof MontgomeryCurve) {
|
if ($this->curve instanceof MontgomeryCurve) {
|
||||||
$format = $this->curve instanceof Curve25519 ?
|
$format = 'MontgomeryPublic';
|
||||||
'Curve25519Public' :
|
|
||||||
'Curve448Public';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$type = self::validatePlugin('Keys', $format, 'savePublicKey');
|
$type = self::validatePlugin('Keys', $format, 'savePublicKey');
|
||||||
|
@ -153,11 +153,11 @@ Q3ADAIcv9LEmTBnSAOsCs1K9ExAmSv/T2/4+9dW28UYb+p/uV477d1wf+nCWS6VU
|
|||||||
$aes->setIV(substr($key, 16, 16));
|
$aes->setIV(substr($key, 16, 16));
|
||||||
|
|
||||||
$encrypted =
|
$encrypted =
|
||||||
$ourEphemeralPublic->toString('Curve25519Public') .
|
$ourEphemeralPublic->toString('MontgomeryPublic') .
|
||||||
$aes->encrypt($plaintext);
|
$aes->encrypt($plaintext);
|
||||||
|
|
||||||
$theirPublic = substr($encrypted, 0, 32);
|
$theirPublic = substr($encrypted, 0, 32);
|
||||||
$theirPublic = EC::loadFormat('Curve25519Public', $theirPublic);
|
$theirPublic = EC::loadFormat('MontgomeryPublic', $theirPublic);
|
||||||
|
|
||||||
$ourPrivate = $theirPrivate;
|
$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
|
// utilizing test vector from https://tools.ietf.org/html/rfc7748#section-6.1
|
||||||
|
|
||||||
$alicePrivate = EC::loadFormat('Curve25519Private', pack('H*', '77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a'));
|
$alicePrivate = EC::loadFormat('MontgomeryPrivate', pack('H*', '77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a'));
|
||||||
$bobPrivate = EC::loadFormat('Curve25519Private', pack('H*', '5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb'));
|
$bobPrivate = EC::loadFormat('MontgomeryPrivate', pack('H*', '5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb'));
|
||||||
|
|
||||||
$alicePublic = $alicePrivate->getPublicKey();
|
$alicePublic = $alicePrivate->getPublicKey();
|
||||||
$bobPublic = $bobPrivate->getPublicKey();
|
$bobPublic = $bobPrivate->getPublicKey();
|
||||||
|
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
'8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a',
|
'8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a',
|
||||||
bin2hex($alicePublic->toString('Curve25519Public'))
|
bin2hex($alicePublic->toString('MontgomeryPublic'))
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
'de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f',
|
'de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f',
|
||||||
bin2hex($bobPublic->toString('Curve25519Public'))
|
bin2hex($bobPublic->toString('MontgomeryPublic'))
|
||||||
);
|
);
|
||||||
|
|
||||||
$expected = pack('H*', '4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742');
|
$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($alicePrivate, $bobPublic));
|
||||||
$this->assertSame($expected, DH::computeSecret($bobPrivate, $alicePublic));
|
$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…
x
Reference in New Issue
Block a user