mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-26 11:37:33 +00:00
add ECDSA / EdDSA support
This commit is contained in:
parent
faa073ff2a
commit
0398f7a815
@ -16,6 +16,7 @@
|
|||||||
namespace phpseclib\Common\Functions;
|
namespace phpseclib\Common\Functions;
|
||||||
|
|
||||||
use phpseclib\Math\BigInteger;
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Math\Common\FiniteField;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common String Functions
|
* Common String Functions
|
||||||
@ -106,9 +107,8 @@ abstract class Strings
|
|||||||
* @param string $format
|
* @param string $format
|
||||||
* @param $data
|
* @param $data
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @access public
|
|
||||||
*/
|
*/
|
||||||
public static function unpackSSH2($format, $data)
|
public static function unpackSSH2($format, &$data)
|
||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
for ($i = 0; $i < strlen($format); $i++) {
|
for ($i = 0; $i < strlen($format); $i++) {
|
||||||
@ -205,8 +205,8 @@ abstract class Strings
|
|||||||
$result.= pack('Na*', strlen($element), $element);
|
$result.= pack('Na*', strlen($element), $element);
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
if (!$element instanceof BigInteger) {
|
if (!$element instanceof BigInteger && !$element instanceof FiniteField\Integer) {
|
||||||
throw new \InvalidArgumentException('A phpseclib\Math\BigInteger object was expected.');
|
throw new \InvalidArgumentException('A phpseclib\Math\BigInteger or phpseclib\Math\Common\FiniteField\Integer object was expected.');
|
||||||
}
|
}
|
||||||
$element = $element->toBytes(true);
|
$element = $element->toBytes(true);
|
||||||
$result.= pack('Na*', strlen($element), $element);
|
$result.= pack('Na*', strlen($element), $element);
|
||||||
@ -224,4 +224,95 @@ abstract class Strings
|
|||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert binary data into bits
|
||||||
|
*
|
||||||
|
* bin2hex / hex2bin refer to base-256 encoded data as binary, whilst
|
||||||
|
* decbin / bindec refer to base-2 encoded data as binary. For the purposes
|
||||||
|
* of this function, bin refers to base-256 encoded data whilst bits refers
|
||||||
|
* to base-2 encoded data
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $x
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function bits2bin($x)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
// the pure-PHP approach is faster than the GMP approach
|
||||||
|
if (function_exists('gmp_export')) {
|
||||||
|
return strlen($x) ? gmp_export(gmp_init($x, 2)) : gmp_init(0);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (preg_match('#[^01]#', $x)) {
|
||||||
|
throw new \RuntimeException('The only valid characters are 0 and 1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined('PHP_INT_MIN')) {
|
||||||
|
define('PHP_INT_MIN', ~PHP_INT_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = strlen($x);
|
||||||
|
if (!$length) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
$block_size = PHP_INT_SIZE << 3;
|
||||||
|
$pad = $block_size - ($length % $block_size);
|
||||||
|
if ($pad != $block_size) {
|
||||||
|
$x = str_repeat('0', $pad) . $x;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parts = str_split($x, $block_size);
|
||||||
|
$str = '';
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
$xor = $part[0] == '1' ? PHP_INT_MIN : 0;
|
||||||
|
$part[0] = '0';
|
||||||
|
$str.= pack(
|
||||||
|
PHP_INT_SIZE == 4 ? 'N' : 'J',
|
||||||
|
$xor ^ eval('return 0b' . $part . ';')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return ltrim($str, "\0");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert bits to binary data
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $x
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function bin2bits($x)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
// the pure-PHP approach is slower than the GMP approach BUT
|
||||||
|
// i want to the pure-PHP version to be easily unit tested as well
|
||||||
|
if (function_exists('gmp_import')) {
|
||||||
|
return gmp_strval(gmp_import($x), 2);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
$len = strlen($x);
|
||||||
|
$mod = $len % PHP_INT_SIZE;
|
||||||
|
if ($mod) {
|
||||||
|
$x = str_pad($x, $len + PHP_INT_SIZE - $mod, "\0", STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
$bits = '';
|
||||||
|
if (PHP_INT_SIZE == 4) {
|
||||||
|
$digits = unpack('N*', $x);
|
||||||
|
foreach ($digits as $digit) {
|
||||||
|
$bits.= sprintf('%032b', $digit);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$digits = unpack('J*', $x);
|
||||||
|
foreach ($digits as $digit) {
|
||||||
|
$bits.= sprintf('%064b', $digit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ltrim($bits, '0');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,8 @@ namespace phpseclib\Crypt\Common;
|
|||||||
use phpseclib\Math\BigInteger;
|
use phpseclib\Math\BigInteger;
|
||||||
use phpseclib\Crypt\Hash;
|
use phpseclib\Crypt\Hash;
|
||||||
use ParagonIE\ConstantTime\Base64;
|
use ParagonIE\ConstantTime\Base64;
|
||||||
|
use phpseclib\Exception\UnsupportedOperationException;
|
||||||
|
use phpseclib\Exception\FileNotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Class for all stream cipher classes
|
* Base Class for all stream cipher classes
|
||||||
@ -43,16 +45,6 @@ abstract class AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
protected static $one;
|
protected static $one;
|
||||||
|
|
||||||
/**
|
|
||||||
* Engine
|
|
||||||
*
|
|
||||||
* This is only used for key generation. Valid values are RSA::ENGINE_INTERNAL and RSA::ENGINE_OPENSSL
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
protected static $engine = NULL;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenSSL configuration file name.
|
* OpenSSL configuration file name.
|
||||||
*
|
*
|
||||||
@ -132,6 +124,17 @@ abstract class AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
protected $publicKeyFormat = 'PKCS8';
|
protected $publicKeyFormat = 'PKCS8';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters Format
|
||||||
|
*
|
||||||
|
* No setParametersFormat method exists because PKCS1 is the only format that supports
|
||||||
|
* parameters in both DSA and ECDSA (RSA doesn't have an analog)
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
protected $parametersFormat = 'PKCS1';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash function
|
* Hash function
|
||||||
*
|
*
|
||||||
@ -148,21 +151,13 @@ abstract class AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
private $hmac;
|
private $hmac;
|
||||||
|
|
||||||
/**#@+
|
|
||||||
* @access private
|
|
||||||
* @see self::__construct()
|
|
||||||
*/
|
|
||||||
/**
|
/**
|
||||||
* To use the pure-PHP implementation
|
* Available Engines
|
||||||
*/
|
|
||||||
const ENGINE_INTERNAL = 1;
|
|
||||||
/**
|
|
||||||
* To use the OpenSSL library
|
|
||||||
*
|
*
|
||||||
* (if enabled; otherwise, the internal implementation will be used)
|
* @var boolean[]
|
||||||
|
* @access private
|
||||||
*/
|
*/
|
||||||
const ENGINE_OPENSSL = 2;
|
protected static $engines = [];
|
||||||
/**#@-*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constructor
|
* The constructor
|
||||||
@ -180,57 +175,35 @@ abstract class AsymmetricKey
|
|||||||
/**
|
/**
|
||||||
* Tests engine validity
|
* Tests engine validity
|
||||||
*
|
*
|
||||||
* @return boolean
|
|
||||||
* @access public
|
* @access public
|
||||||
* @param int $val
|
* @param int $val
|
||||||
*/
|
*/
|
||||||
public static function isValidEngine($val)
|
public static function useBestEngine()
|
||||||
{
|
{
|
||||||
switch ($val) {
|
static::$engines = [
|
||||||
case self::ENGINE_OPENSSL:
|
'PHP' => true,
|
||||||
return extension_loaded('openssl') && file_exists(self::$configFile);
|
'OpenSSL' => extension_loaded('openssl') && file_exists(self::$configFile),
|
||||||
case self::ENGINE_INTERNAL:
|
// this test can be satisfied by either of the following:
|
||||||
return true;
|
// http://php.net/manual/en/book.sodium.php
|
||||||
}
|
// https://github.com/paragonie/sodium_compat
|
||||||
|
'libsodium' => function_exists('sodium_crypto_sign_keypair')
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the engine
|
|
||||||
*
|
|
||||||
* Only used in RSA::createKey. Valid values are RSA::ENGINE_OPENSSL and RSA::ENGINE_INTERNAL
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param int $val
|
|
||||||
*/
|
|
||||||
public static function setPreferredEngine($val)
|
|
||||||
{
|
|
||||||
static::$engine = null;
|
|
||||||
$candidateEngines = [
|
|
||||||
$val,
|
|
||||||
self::ENGINE_OPENSSL
|
|
||||||
];
|
];
|
||||||
foreach ($candidateEngines as $engine) {
|
|
||||||
if (static::isValidEngine($engine)) {
|
return static::$engines;
|
||||||
static::$engine = $engine;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isset(static::$engine)) {
|
|
||||||
static::$engine = self::ENGINE_INTERNAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the engine
|
* Flag to use internal engine only (useful for unit testing)
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public static function getEngine()
|
public static function useInternalEngine()
|
||||||
{
|
{
|
||||||
return self::$engine;
|
static::$engines = [
|
||||||
|
'PHP' => true,
|
||||||
|
'OpenSSL' => false,
|
||||||
|
'libsodium' => false
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,7 +216,7 @@ abstract class AsymmetricKey
|
|||||||
if (!isset(self::$zero)) {
|
if (!isset(self::$zero)) {
|
||||||
self::$zero= new BigInteger(0);
|
self::$zero= new BigInteger(0);
|
||||||
self::$one = new BigInteger(1);
|
self::$one = new BigInteger(1);
|
||||||
self::$configFile = __DIR__ . '/../openssl.cnf';
|
self::$configFile = __DIR__ . '/../../openssl.cnf';
|
||||||
}
|
}
|
||||||
|
|
||||||
self::loadPlugins('Keys');
|
self::loadPlugins('Keys');
|
||||||
@ -268,6 +241,10 @@ abstract class AsymmetricKey
|
|||||||
}
|
}
|
||||||
$name = $file->getBasename('.php');
|
$name = $file->getBasename('.php');
|
||||||
$type = 'phpseclib\Crypt\\' . static::ALGORITHM . '\\' . $format . '\\' . $name;
|
$type = 'phpseclib\Crypt\\' . static::ALGORITHM . '\\' . $format . '\\' . $name;
|
||||||
|
$reflect = new \ReflectionClass($type);
|
||||||
|
if ($reflect->isTrait()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
self::$plugins[static::ALGORITHM][$format][strtolower($name)] = $type;
|
self::$plugins[static::ALGORITHM][$format][strtolower($name)] = $type;
|
||||||
self::$origPlugins[static::ALGORITHM][$format][] = $name;
|
self::$origPlugins[static::ALGORITHM][$format][] = $name;
|
||||||
}
|
}
|
||||||
@ -305,7 +282,7 @@ abstract class AsymmetricKey
|
|||||||
* @param string $type
|
* @param string $type
|
||||||
* @return array|bool
|
* @return array|bool
|
||||||
*/
|
*/
|
||||||
public function load($key, $type)
|
protected function load($key, $type)
|
||||||
{
|
{
|
||||||
$components = false;
|
$components = false;
|
||||||
if ($type === false) {
|
if ($type === false) {
|
||||||
@ -343,9 +320,9 @@ abstract class AsymmetricKey
|
|||||||
* @access private
|
* @access private
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $type
|
* @param string $type
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function setPublicKey($key, $type)
|
protected function setPublicKey($key, $type)
|
||||||
{
|
{
|
||||||
$components = false;
|
$components = false;
|
||||||
if ($type === false) {
|
if ($type === false) {
|
||||||
@ -409,7 +386,7 @@ abstract class AsymmetricKey
|
|||||||
self::initialize_static_variables();
|
self::initialize_static_variables();
|
||||||
|
|
||||||
if (class_exists($fullname)) {
|
if (class_exists($fullname)) {
|
||||||
$meta = new \ReflectionClass($path);
|
$meta = new \ReflectionClass($fullname);
|
||||||
$shortname = $meta->getShortName();
|
$shortname = $meta->getShortName();
|
||||||
self::$plugins[static::ALGORITHM]['Keys'][strtolower($shortname)] = $fullname;
|
self::$plugins[static::ALGORITHM]['Keys'][strtolower($shortname)] = $fullname;
|
||||||
self::$origPlugins[static::ALGORITHM]['Keys'][] = $shortname;
|
self::$origPlugins[static::ALGORITHM]['Keys'][] = $shortname;
|
||||||
@ -471,6 +448,15 @@ abstract class AsymmetricKey
|
|||||||
return $key;
|
return $key;
|
||||||
}
|
}
|
||||||
$key = $this->getPublicKey($this->publicKeyFormat);
|
$key = $this->getPublicKey($this->publicKeyFormat);
|
||||||
|
if (is_string($key)) {
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!method_exists($this, 'getParameters')) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = $this->getParameters($this->parametersFormat);
|
||||||
return is_string($key) ? $key : '';
|
return is_string($key) ? $key : '';
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return '';
|
return '';
|
||||||
@ -499,6 +485,16 @@ abstract class AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
public function setPrivateKeyFormat($format)
|
public function setPrivateKeyFormat($format)
|
||||||
{
|
{
|
||||||
|
$type = self::validatePlugin('Keys', $format);
|
||||||
|
if ($type === false) {
|
||||||
|
throw new FileNotFoundException('Plugin not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = self::validatePlugin('Keys', $format, 'savePrivateKey');
|
||||||
|
if ($type === false) {
|
||||||
|
throw new UnsupportedOperationException('Plugin does not support private keys');
|
||||||
|
}
|
||||||
|
|
||||||
$this->privateKeyFormat = $format;
|
$this->privateKeyFormat = $format;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,9 +507,47 @@ abstract class AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
public function setPublicKeyFormat($format)
|
public function setPublicKeyFormat($format)
|
||||||
{
|
{
|
||||||
|
$type = self::validatePlugin('Keys', $format);
|
||||||
|
if ($type === false) {
|
||||||
|
throw new FileNotFoundException('Plugin not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = self::validatePlugin('Keys', $format, 'savePublicKey');
|
||||||
|
if ($type === false) {
|
||||||
|
throw new UnsupportedOperationException('Plugin does not support public keys');
|
||||||
|
}
|
||||||
|
|
||||||
$this->publicKeyFormat = $format;
|
$this->publicKeyFormat = $format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the key format
|
||||||
|
*
|
||||||
|
* Sets both the public key and private key formats to the specified format if those formats support
|
||||||
|
* the key type
|
||||||
|
*
|
||||||
|
* @see self::__toString()
|
||||||
|
* @access public
|
||||||
|
* @param string $format
|
||||||
|
*/
|
||||||
|
public function setKeyFormat($format)
|
||||||
|
{
|
||||||
|
$type = self::validatePlugin('Keys', $format);
|
||||||
|
if ($type === false) {
|
||||||
|
throw new FileNotFoundException('Plugin not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->setPrivateKeyFormat($format);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->setPublicKeyFormat($format);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the format of the loaded key.
|
* Returns the format of the loaded key.
|
||||||
*
|
*
|
||||||
|
@ -64,12 +64,12 @@ abstract class OpenSSH
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $type
|
* @param string $type
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function load($key, $type)
|
public static function load($key, $type)
|
||||||
{
|
{
|
||||||
if (!is_string($key)) {
|
if (!is_string($key)) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
$parts = explode(' ', $key, 3);
|
$parts = explode(' ', $key, 3);
|
||||||
@ -79,21 +79,20 @@ abstract class OpenSSH
|
|||||||
$comment = isset($parts[1]) ? $parts[1] : false;
|
$comment = isset($parts[1]) ? $parts[1] : false;
|
||||||
} else {
|
} else {
|
||||||
if ($parts[0] != $type) {
|
if ($parts[0] != $type) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Expected a ' . $type . ' key - got a ' . $parts[0] . ' key');
|
||||||
}
|
}
|
||||||
$key = Base64::decode($parts[1]);
|
$key = Base64::decode($parts[1]);
|
||||||
$comment = isset($parts[2]) ? $parts[2] : false;
|
$comment = isset($parts[2]) ? $parts[2] : false;
|
||||||
}
|
}
|
||||||
if ($key === false) {
|
if ($key === false) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (substr($key, 0, 11) != "\0\0\0\7$type") {
|
if (Strings::shift($key, strlen($type) + 4) != "\0\0\0" . chr(strlen($type)) . $type) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key appears to be malformed');
|
||||||
}
|
}
|
||||||
Strings::shift($key, 11);
|
|
||||||
if (strlen($key) <= 4) {
|
if (strlen($key) <= 4) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key appears to be malformed');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $key;
|
return $key;
|
||||||
|
@ -22,6 +22,7 @@ use phpseclib\Crypt\AES;
|
|||||||
use phpseclib\Crypt\DES;
|
use phpseclib\Crypt\DES;
|
||||||
use phpseclib\Crypt\TripleDES;
|
use phpseclib\Crypt\TripleDES;
|
||||||
use phpseclib\File\ASN1;
|
use phpseclib\File\ASN1;
|
||||||
|
use phpseclib\Exception\UnsupportedAlgorithmException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PKCS1 Formatted Key Handler
|
* PKCS1 Formatted Key Handler
|
||||||
@ -93,7 +94,7 @@ abstract class PKCS1 extends PKCS
|
|||||||
case preg_match("#^DES-$modes$#", $algo, $matches):
|
case preg_match("#^DES-$modes$#", $algo, $matches):
|
||||||
return new DES(self::getEncryptionMode($matches[1]));
|
return new DES(self::getEncryptionMode($matches[1]));
|
||||||
default:
|
default:
|
||||||
throw new \UnexpectedValueException('Unsupported encryption algorithmn');
|
throw new UnsupportedAlgorithmException($algo . ' is not a supported algorithm');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,12 +123,12 @@ abstract class PKCS1 extends PKCS
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected static function load($key, $password)
|
protected static function load($key, $password)
|
||||||
{
|
{
|
||||||
if (!is_string($key)) {
|
if (!is_string($key)) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
|
/* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
|
||||||
@ -163,7 +164,7 @@ abstract class PKCS1 extends PKCS
|
|||||||
if ($decoded !== false) {
|
if ($decoded !== false) {
|
||||||
$key = $decoded;
|
$key = $decoded;
|
||||||
} elseif (self::$format == self::MODE_PEM) {
|
} elseif (self::$format == self::MODE_PEM) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Expected base64-encoded PEM format but was unable to decode base64 text');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,7 @@ abstract class PKCS8 extends PKCS
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a SymmetricKey object based on a PBES1 $algo
|
* Returns a SymmetricKey object based on a PBES1 $algo
|
||||||
|
*
|
||||||
* @return \phpseclib\Crypt\Common\SymmetricKey
|
* @return \phpseclib\Crypt\Common\SymmetricKey
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $algo
|
* @param string $algo
|
||||||
@ -267,51 +268,54 @@ abstract class PKCS8 extends PKCS
|
|||||||
private static function initialize_static_variables()
|
private static function initialize_static_variables()
|
||||||
{
|
{
|
||||||
if (!static::$childOIDsLoaded) {
|
if (!static::$childOIDsLoaded) {
|
||||||
ASN1::loadOIDs([static::OID_VALUE => static::OID_NAME]);
|
ASN1::loadOIDs(is_array(static::OID_NAME) ?
|
||||||
|
array_combine(static::OID_NAME, static::OID_VALUE) :
|
||||||
|
[static::OID_NAME => static::OID_VALUE]
|
||||||
|
);
|
||||||
static::$childOIDsLoaded = true;
|
static::$childOIDsLoaded = true;
|
||||||
}
|
}
|
||||||
if (!self::$oidsLoaded) {
|
if (!self::$oidsLoaded) {
|
||||||
// from https://tools.ietf.org/html/rfc2898
|
// from https://tools.ietf.org/html/rfc2898
|
||||||
ASN1::loadOIDs([
|
ASN1::loadOIDs([
|
||||||
// PBES1 encryption schemes
|
// PBES1 encryption schemes
|
||||||
'1.2.840.113549.1.5.1' => 'pbeWithMD2AndDES-CBC',
|
'pbeWithMD2AndDES-CBC' => '1.2.840.113549.1.5.1',
|
||||||
'1.2.840.113549.1.5.4' => 'pbeWithMD2AndRC2-CBC',
|
'pbeWithMD2AndRC2-CBC' => '1.2.840.113549.1.5.4',
|
||||||
'1.2.840.113549.1.5.3' => 'pbeWithMD5AndDES-CBC',
|
'pbeWithMD5AndDES-CBC' => '1.2.840.113549.1.5.3',
|
||||||
'1.2.840.113549.1.5.6' => 'pbeWithMD5AndRC2-CBC',
|
'pbeWithMD5AndRC2-CBC' => '1.2.840.113549.1.5.6',
|
||||||
'1.2.840.113549.1.5.10'=> 'pbeWithSHA1AndDES-CBC',
|
'pbeWithSHA1AndDES-CBC'=> '1.2.840.113549.1.5.10',
|
||||||
'1.2.840.113549.1.5.11'=> 'pbeWithSHA1AndRC2-CBC',
|
'pbeWithSHA1AndRC2-CBC'=> '1.2.840.113549.1.5.11',
|
||||||
|
|
||||||
// from PKCS#12:
|
// from PKCS#12:
|
||||||
// https://tools.ietf.org/html/rfc7292
|
// https://tools.ietf.org/html/rfc7292
|
||||||
'1.2.840.113549.1.12.1.1' => 'pbeWithSHAAnd128BitRC4',
|
'pbeWithSHAAnd128BitRC4' => '1.2.840.113549.1.12.1.1',
|
||||||
'1.2.840.113549.1.12.1.2' => 'pbeWithSHAAnd40BitRC4',
|
'pbeWithSHAAnd40BitRC4' => '1.2.840.113549.1.12.1.2',
|
||||||
'1.2.840.113549.1.12.1.3' => 'pbeWithSHAAnd3-KeyTripleDES-CBC',
|
'pbeWithSHAAnd3-KeyTripleDES-CBC' => '1.2.840.113549.1.12.1.3',
|
||||||
'1.2.840.113549.1.12.1.4' => 'pbeWithSHAAnd2-KeyTripleDES-CBC',
|
'pbeWithSHAAnd2-KeyTripleDES-CBC' => '1.2.840.113549.1.12.1.4',
|
||||||
'1.2.840.113549.1.12.1.5' => 'pbeWithSHAAnd128BitRC2-CBC',
|
'pbeWithSHAAnd128BitRC2-CBC' => '1.2.840.113549.1.12.1.5',
|
||||||
'1.2.840.113549.1.12.1.6' => 'pbeWithSHAAnd40BitRC2-CBC',
|
'pbeWithSHAAnd40BitRC2-CBC' => '1.2.840.113549.1.12.1.6',
|
||||||
|
|
||||||
'1.2.840.113549.1.5.12' => 'id-PBKDF2',
|
'id-PBKDF2' => '1.2.840.113549.1.5.12',
|
||||||
'1.2.840.113549.1.5.13' => 'id-PBES2',
|
'id-PBES2' => '1.2.840.113549.1.5.13',
|
||||||
'1.2.840.113549.1.5.14' => 'id-PBMAC1',
|
'id-PBMAC1' => '1.2.840.113549.1.5.14',
|
||||||
|
|
||||||
// from PKCS#5 v2.1:
|
// from PKCS#5 v2.1:
|
||||||
// http://www.rsa.com/rsalabs/pkcs/files/h11302-wp-pkcs5v2-1-password-based-cryptography-standard.pdf
|
// http://www.rsa.com/rsalabs/pkcs/files/h11302-wp-pkcs5v2-1-password-based-cryptography-standard.pdf
|
||||||
'1.2.840.113549.2.7' => 'id-hmacWithSHA1',
|
'id-hmacWithSHA1' => '1.2.840.113549.2.7',
|
||||||
'1.2.840.113549.2.8' => 'id-hmacWithSHA224',
|
'id-hmacWithSHA224' => '1.2.840.113549.2.8',
|
||||||
'1.2.840.113549.2.9' => 'id-hmacWithSHA256',
|
'id-hmacWithSHA256' => '1.2.840.113549.2.9',
|
||||||
'1.2.840.113549.2.10'=> 'id-hmacWithSHA384',
|
'id-hmacWithSHA384'=> '1.2.840.113549.2.10',
|
||||||
'1.2.840.113549.2.11'=> 'id-hmacWithSHA512',
|
'id-hmacWithSHA512'=> '1.2.840.113549.2.11',
|
||||||
'1.2.840.113549.2.12'=> 'id-hmacWithSHA512-224',
|
'id-hmacWithSHA512-224'=> '1.2.840.113549.2.12',
|
||||||
'1.2.840.113549.2.13'=> 'id-hmacWithSHA512-256',
|
'id-hmacWithSHA512-256'=> '1.2.840.113549.2.13',
|
||||||
|
|
||||||
'1.3.14.3.2.7' => 'desCBC',
|
'desCBC' => '1.3.14.3.2.7',
|
||||||
'1.2.840.113549.3.7' => 'des-EDE3-CBC',
|
'des-EDE3-CBC' => '1.2.840.113549.3.7',
|
||||||
'1.2.840.113549.3.2' => 'rc2CBC',
|
'rc2CBC' => '1.2.840.113549.3.2',
|
||||||
'1.2.840.113549.3.9' => 'rc5-CBC-PAD',
|
'rc5-CBC-PAD' => '1.2.840.113549.3.9',
|
||||||
|
|
||||||
'2.16.840.1.101.3.4.1.2' => 'aes128-CBC-PAD',
|
'aes128-CBC-PAD' => '2.16.840.1.101.3.4.1.2',
|
||||||
'2.16.840.1.101.3.4.1.22'=> 'aes192-CBC-PAD',
|
'aes192-CBC-PAD'=> '2.16.840.1.101.3.4.1.22',
|
||||||
'2.16.840.1.101.3.4.1.42'=> 'aes256-CBC-PAD'
|
'aes256-CBC-PAD'=> '2.16.840.1.101.3.4.1.42'
|
||||||
]);
|
]);
|
||||||
self::$oidsLoaded = true;
|
self::$oidsLoaded = true;
|
||||||
}
|
}
|
||||||
@ -323,14 +327,14 @@ abstract class PKCS8 extends PKCS
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected static function load($key, $password = '')
|
protected static function load($key, $password = '')
|
||||||
{
|
{
|
||||||
self::initialize_static_variables();
|
self::initialize_static_variables();
|
||||||
|
|
||||||
if (!is_string($key)) {
|
if (!is_string($key)) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self::$format != self::MODE_DER) {
|
if (self::$format != self::MODE_DER) {
|
||||||
@ -338,13 +342,13 @@ abstract class PKCS8 extends PKCS
|
|||||||
if ($decoded !== false) {
|
if ($decoded !== false) {
|
||||||
$key = $decoded;
|
$key = $decoded;
|
||||||
} elseif (self::$format == self::MODE_PEM) {
|
} elseif (self::$format == self::MODE_PEM) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Expected base64-encoded PEM format but was unable to decode base64 text');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$decoded = ASN1::decodeBER($key);
|
$decoded = ASN1::decodeBER($key);
|
||||||
if (empty($decoded)) {
|
if (empty($decoded)) {
|
||||||
return false;
|
throw new \RuntimeException('Unable to decode BER');
|
||||||
}
|
}
|
||||||
|
|
||||||
$meta = [];
|
$meta = [];
|
||||||
@ -379,7 +383,7 @@ abstract class PKCS8 extends PKCS
|
|||||||
$key = $cipher->decrypt($decrypted['encryptedData']);
|
$key = $cipher->decrypt($decrypted['encryptedData']);
|
||||||
$decoded = ASN1::decodeBER($key);
|
$decoded = ASN1::decodeBER($key);
|
||||||
if (empty($decoded)) {
|
if (empty($decoded)) {
|
||||||
return false;
|
throw new \RuntimeException('Unable to decode BER 2');
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -442,7 +446,7 @@ abstract class PKCS8 extends PKCS
|
|||||||
$key = $cipher->decrypt($decrypted['encryptedData']);
|
$key = $cipher->decrypt($decrypted['encryptedData']);
|
||||||
$decoded = ASN1::decodeBER($key);
|
$decoded = ASN1::decodeBER($key);
|
||||||
if (empty($decoded)) {
|
if (empty($decoded)) {
|
||||||
return false;
|
throw new \RuntimeException('Unable to decode BER 3');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -458,11 +462,22 @@ abstract class PKCS8 extends PKCS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$private = ASN1::asn1map($decoded[0], Maps\PrivateKeyInfo::MAP);
|
$private = ASN1::asn1map($decoded[0], Maps\OneAsymmetricKey::MAP);
|
||||||
if (is_array($private)) {
|
if (is_array($private)) {
|
||||||
return $private['privateKeyAlgorithm']['algorithm'] == static::OID_NAME ?
|
if (isset($private['privateKeyAlgorithm']['parameters']) && !$private['privateKeyAlgorithm']['parameters'] instanceof ASN1\Element && isset($decoded[0]['content'][1]['content'][1])) {
|
||||||
$private + $meta :
|
$temp = $decoded[0]['content'][1]['content'][1];
|
||||||
false;
|
$private['privateKeyAlgorithm']['parameters'] = new ASN1\Element(substr($key, $temp['start'], $temp['length']));
|
||||||
|
}
|
||||||
|
if (is_array(static::OID_NAME)) {
|
||||||
|
if (!in_array($private['privateKeyAlgorithm']['algorithm'], static::OID_NAME)) {
|
||||||
|
throw new UnsupportedAlgorithmException($private['privateKeyAlgorithm']['algorithm'] . ' is not a supported key type');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($private['privateKeyAlgorithm']['algorithm'] != static::OID_NAME) {
|
||||||
|
throw new UnsupportedAlgorithmException('Only ' . static::OID_NAME . ' keys are supported; this is a ' . $private['privateKeyAlgorithm']['algorithm'] . ' key');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $private + $meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncryptedPrivateKeyInfo and PublicKeyInfo have largely identical "signatures". the only difference
|
// EncryptedPrivateKeyInfo and PublicKeyInfo have largely identical "signatures". the only difference
|
||||||
@ -470,9 +485,23 @@ abstract class PKCS8 extends PKCS
|
|||||||
// string represents the number of bits in the last byte that are to be ignored but, currently,
|
// string represents the number of bits in the last byte that are to be ignored but, currently,
|
||||||
// bit strings wanting a non-zero amount of bits trimmed are not supported
|
// bit strings wanting a non-zero amount of bits trimmed are not supported
|
||||||
$public = ASN1::asn1map($decoded[0], Maps\PublicKeyInfo::MAP);
|
$public = ASN1::asn1map($decoded[0], Maps\PublicKeyInfo::MAP);
|
||||||
|
|
||||||
if (is_array($public)) {
|
if (is_array($public)) {
|
||||||
if ($public['publicKey'][0] != "\0" || $public['publicKeyAlgorithm']['algorithm'] != static::OID_NAME) {
|
if ($public['publicKey'][0] != "\0") {
|
||||||
return false;
|
throw new \UnexpectedValueException('The first byte of the public key should be null - not ' . Hex::encode($val));
|
||||||
|
}
|
||||||
|
if (is_array(static::OID_NAME)) {
|
||||||
|
if (!in_array($public['publicKeyAlgorithm']['algorithm'], static::OID_NAME)) {
|
||||||
|
throw new UnsupportedAlgorithmException($private['publicKeyAlgorithm']['algorithm'] . ' is not a supported key type');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($public['publicKeyAlgorithm']['algorithm'] != static::OID_NAME) {
|
||||||
|
throw new UnsupportedAlgorithmException('Only ' . static::OID_NAME . ' keys are supported; this is a ' . $private['publicKeyAlgorithm']['algorithm'] . ' key');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($public['publicKeyAlgorithm']['parameters']) && !$public['publicKeyAlgorithm']['parameters'] instanceof ASN1\Element && isset($decoded[0]['content'][0]['content'][1])) {
|
||||||
|
$temp = $decoded[0]['content'][0]['content'][1];
|
||||||
|
$public['publicKeyAlgorithm']['parameters'] = new ASN1\Element(substr($key, $temp['start'], $temp['length']));
|
||||||
}
|
}
|
||||||
$public['publicKey'] = substr($public['publicKey'], 1);
|
$public['publicKey'] = substr($public['publicKey'], 1);
|
||||||
return $public;
|
return $public;
|
||||||
@ -489,16 +518,18 @@ abstract class PKCS8 extends PKCS
|
|||||||
* @param string $attr
|
* @param string $attr
|
||||||
* @param mixed $params
|
* @param mixed $params
|
||||||
* @param string $password
|
* @param string $password
|
||||||
|
* @param string $oid optional
|
||||||
|
* @param string $publicKey optional
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected static function wrapPrivateKey($key, $attr, $params, $password)
|
protected static function wrapPrivateKey($key, $attr, $params, $password, $oid = null, $publicKey = '')
|
||||||
{
|
{
|
||||||
self::initialize_static_variables();
|
self::initialize_static_variables();
|
||||||
|
|
||||||
$key = [
|
$key = [
|
||||||
'version' => 'v1',
|
'version' => 'v1',
|
||||||
'privateKeyAlgorithm' => [
|
'privateKeyAlgorithm' => [
|
||||||
'algorithm' => static::OID_NAME,
|
'algorithm' => is_string(static::OID_NAME) ? static::OID_NAME : $oid,
|
||||||
'parameters' => $params
|
'parameters' => $params
|
||||||
],
|
],
|
||||||
'privateKey' => $key
|
'privateKey' => $key
|
||||||
@ -506,7 +537,11 @@ abstract class PKCS8 extends PKCS
|
|||||||
if (!empty($attr)) {
|
if (!empty($attr)) {
|
||||||
$key['attributes'] = $attr;
|
$key['attributes'] = $attr;
|
||||||
}
|
}
|
||||||
$key = ASN1::encodeDER($key, Maps\PrivateKeyInfo::MAP);
|
if (!empty($publicKey)) {
|
||||||
|
$key['version'] = 'v2';
|
||||||
|
$key['publicKey'] = $publicKey;
|
||||||
|
}
|
||||||
|
$key = ASN1::encodeDER($key, Maps\OneAsymmetricKey::MAP);
|
||||||
if (!empty($password) && is_string($password)) {
|
if (!empty($password) && is_string($password)) {
|
||||||
$salt = Random::string(8);
|
$salt = Random::string(8);
|
||||||
$iterationCount = self::$defaultIterationCount;
|
$iterationCount = self::$defaultIterationCount;
|
||||||
@ -590,13 +625,13 @@ abstract class PKCS8 extends PKCS
|
|||||||
* @param mixed $params
|
* @param mixed $params
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected static function wrapPublicKey($key, $params)
|
protected static function wrapPublicKey($key, $params, $oid = null)
|
||||||
{
|
{
|
||||||
self::initialize_static_variables();
|
self::initialize_static_variables();
|
||||||
|
|
||||||
$key = [
|
$key = [
|
||||||
'publicKeyAlgorithm' => [
|
'publicKeyAlgorithm' => [
|
||||||
'algorithm' => static::OID_NAME,
|
'algorithm' => is_string(static::OID_NAME) ? static::OID_NAME : $oid,
|
||||||
'parameters' => $params
|
'parameters' => $params
|
||||||
],
|
],
|
||||||
'publicKey' => "\0" . $key
|
'publicKey' => "\0" . $key
|
||||||
|
@ -21,6 +21,7 @@ use phpseclib\Crypt\AES;
|
|||||||
use phpseclib\Crypt\Hash;
|
use phpseclib\Crypt\Hash;
|
||||||
use phpseclib\Crypt\Random;
|
use phpseclib\Crypt\Random;
|
||||||
use phpseclib\Common\Functions\Strings;
|
use phpseclib\Common\Functions\Strings;
|
||||||
|
use phpseclib\Exception\UnsupportedAlgorithmException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PuTTY Formatted Key Handler
|
* PuTTY Formatted Key Handler
|
||||||
@ -75,26 +76,26 @@ abstract class PuTTY
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $password
|
* @param string $password
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected static function load($key, $password)
|
protected static function load($key, $password)
|
||||||
{
|
{
|
||||||
if (!is_string($key)) {
|
if (!is_string($key)) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strpos($key, 'BEGIN SSH2 PUBLIC KEY')) {
|
if (strpos($key, 'BEGIN SSH2 PUBLIC KEY') !== false) {
|
||||||
$data = preg_split('#[\r\n]+#', $key);
|
$data = preg_split('#[\r\n]+#', $key);
|
||||||
$data = array_splice($data, 2, -1);
|
$data = array_splice($data, 2, -1);
|
||||||
$data = implode('', $data);
|
$data = implode('', $data);
|
||||||
|
|
||||||
$components = call_user_func([static::PUBLIC_HANDLER, 'load'], $data);
|
$components = call_user_func([static::PUBLIC_HANDLER, 'load'], $data);
|
||||||
if ($components === false) {
|
if ($components === false) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Unable to decode public key');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!preg_match('#Comment: "(.+)"#', $key, $matches)) {
|
if (!preg_match('#Comment: "(.+)"#', $key, $matches)) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key is missing a comment');
|
||||||
}
|
}
|
||||||
$components['comment'] = str_replace(['\\\\', '\"'], ['\\', '"'], $matches[1]);
|
$components['comment'] = str_replace(['\\\\', '\"'], ['\\', '"'], $matches[1]);
|
||||||
|
|
||||||
@ -105,8 +106,12 @@ abstract class PuTTY
|
|||||||
|
|
||||||
$key = preg_split('#\r\n|\r|\n#', trim($key));
|
$key = preg_split('#\r\n|\r|\n#', trim($key));
|
||||||
$type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0]));
|
$type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0]));
|
||||||
if ($type != static::TYPE) {
|
$components['type'] = $type;
|
||||||
return false;
|
if (!in_array($type, static::$types)) {
|
||||||
|
$error = count(static::$types) == 1 ?
|
||||||
|
'Only ' . static::$types[0] . ' keys are supported. ' :
|
||||||
|
'';
|
||||||
|
throw new UnsupportedAlgorithmException($error . 'This is an unsupported ' . $type . ' key');
|
||||||
}
|
}
|
||||||
$encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1]));
|
$encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1]));
|
||||||
$components['comment'] = trim(preg_replace('#Comment: (.+)#', '$1', $key[2]));
|
$components['comment'] = trim(preg_replace('#Comment: (.+)#', '$1', $key[2]));
|
||||||
@ -114,12 +119,12 @@ abstract class PuTTY
|
|||||||
$publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3]));
|
$publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3]));
|
||||||
$public = Base64::decode(implode('', array_map('trim', array_slice($key, 4, $publicLength))));
|
$public = Base64::decode(implode('', array_map('trim', array_slice($key, 4, $publicLength))));
|
||||||
|
|
||||||
$source = Strings::packSSH2('ssss', static::TYPE, $encryption, $components['comment'], $public);
|
$source = Strings::packSSH2('ssss', $type, $encryption, $components['comment'], $public);
|
||||||
|
|
||||||
extract(unpack('Nlength', Strings::shift($public, 4)));
|
extract(unpack('Nlength', Strings::shift($public, 4)));
|
||||||
/** @var integer $length */
|
$newtype = Strings::shift($public, $length);
|
||||||
if (Strings::shift($public, $length) != static::TYPE) {
|
if ($newtype != $type) {
|
||||||
return false;
|
throw new \RuntimeException('The binary type does not match the human readable type field');
|
||||||
}
|
}
|
||||||
|
|
||||||
$components['public'] = $public;
|
$components['public'] = $public;
|
||||||
@ -165,19 +170,20 @@ abstract class PuTTY
|
|||||||
* @access private
|
* @access private
|
||||||
* @param string $public
|
* @param string $public
|
||||||
* @param string $private
|
* @param string $private
|
||||||
|
* @param string $type
|
||||||
* @param string $password
|
* @param string $password
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected static function wrapPrivateKey($public, $private, $password)
|
protected static function wrapPrivateKey($public, $private, $type, $password)
|
||||||
{
|
{
|
||||||
$key = "PuTTY-User-Key-File-2: " . static::TYPE . "\r\nEncryption: ";
|
$key = "PuTTY-User-Key-File-2: " . $type . "\r\nEncryption: ";
|
||||||
$encryption = (!empty($password) || is_string($password)) ? 'aes256-cbc' : 'none';
|
$encryption = (!empty($password) || is_string($password)) ? 'aes256-cbc' : 'none';
|
||||||
$key.= $encryption;
|
$key.= $encryption;
|
||||||
$key.= "\r\nComment: " . self::$comment . "\r\n";
|
$key.= "\r\nComment: " . self::$comment . "\r\n";
|
||||||
|
|
||||||
$public = Strings::packSSH2('s', static::TYPE) . $public;
|
$public = Strings::packSSH2('s', $type) . $public;
|
||||||
|
|
||||||
$source = Strings::packSSH2('ssss', static::TYPE, $encryption, self::$comment, $public);
|
$source = Strings::packSSH2('ssss', $type, $encryption, self::$comment, $public);
|
||||||
|
|
||||||
$public = Base64::encode($public);
|
$public = Base64::encode($public);
|
||||||
$key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
|
$key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
|
||||||
@ -215,11 +221,12 @@ abstract class PuTTY
|
|||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @param string $key
|
* @param string $key
|
||||||
|
* @param string $type
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected static function wrapPublicKey($key)
|
protected static function wrapPublicKey($key, $type)
|
||||||
{
|
{
|
||||||
$key = pack('Na*a*', strlen(static::TYPE), static::TYPE, $key);
|
$key = pack('Na*a*', strlen($type), $type, $key);
|
||||||
$key = "---- BEGIN SSH2 PUBLIC KEY ----\r\n" .
|
$key = "---- BEGIN SSH2 PUBLIC KEY ----\r\n" .
|
||||||
'Comment: "' . str_replace(['\\', '"'], ['\\\\', '\"'], self::$comment) . "\"\r\n" .
|
'Comment: "' . str_replace(['\\', '"'], ['\\\\', '\"'], self::$comment) . "\"\r\n" .
|
||||||
chunk_split(Base64::encode($key), 64) .
|
chunk_split(Base64::encode($key), 64) .
|
||||||
|
@ -34,7 +34,8 @@ use ParagonIE\ConstantTime\Base64;
|
|||||||
use phpseclib\File\ASN1;
|
use phpseclib\File\ASN1;
|
||||||
use phpseclib\Math\BigInteger;
|
use phpseclib\Math\BigInteger;
|
||||||
use phpseclib\Crypt\Common\AsymmetricKey;
|
use phpseclib\Crypt\Common\AsymmetricKey;
|
||||||
use phpseclib\Common\Functions\Strings;
|
use phpseclib\Math\PrimeField;
|
||||||
|
use phpseclib\Crypt\ECDSA\Signature\ASN1 as ASN1Signature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP FIPS 186-4 compliant implementation of DSA.
|
* Pure-PHP FIPS 186-4 compliant implementation of DSA.
|
||||||
@ -95,14 +96,6 @@ class DSA extends AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
private $y;
|
private $y;
|
||||||
|
|
||||||
/**
|
|
||||||
* Parameters Format
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
private $parametersFormat = 'PKCS1';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create DSA parameters
|
* Create DSA parameters
|
||||||
*
|
*
|
||||||
@ -111,10 +104,14 @@ class DSA extends AsymmetricKey
|
|||||||
* @param int $N
|
* @param int $N
|
||||||
* @return \phpseclib\Crypt\DSA|bool
|
* @return \phpseclib\Crypt\DSA|bool
|
||||||
*/
|
*/
|
||||||
static function createParameters($L = 2048, $N = 224)
|
public static function createParameters($L = 2048, $N = 224)
|
||||||
{
|
{
|
||||||
self::initialize_static_variables();
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if (!isset(self::$engines['PHP'])) {
|
||||||
|
self::useBestEngine();
|
||||||
|
}
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case $N == 160:
|
case $N == 160:
|
||||||
/*
|
/*
|
||||||
@ -186,10 +183,14 @@ class DSA extends AsymmetricKey
|
|||||||
* @access public
|
* @access public
|
||||||
* @return array|DSA
|
* @return array|DSA
|
||||||
*/
|
*/
|
||||||
static function createKey(...$args)
|
public static function createKey(...$args)
|
||||||
{
|
{
|
||||||
self::initialize_static_variables();
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if (!isset(self::$engines['PHP'])) {
|
||||||
|
self::useBestEngine();
|
||||||
|
}
|
||||||
|
|
||||||
if (count($args) == 2 && is_int($args[0]) && is_int($args[1])) {
|
if (count($args) == 2 && is_int($args[0]) && is_int($args[1])) {
|
||||||
$private = self::createParameters($args[0], $args[1]);
|
$private = self::createParameters($args[0], $args[1]);
|
||||||
} else if (count($args) == 1 && $args[0] instanceof DSA) {
|
} else if (count($args) == 1 && $args[0] instanceof DSA) {
|
||||||
@ -220,6 +221,12 @@ class DSA extends AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
public function load($key, $type = false)
|
public function load($key, $type = false)
|
||||||
{
|
{
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if (!isset(self::$engines['PHP'])) {
|
||||||
|
self::useBestEngine();
|
||||||
|
}
|
||||||
|
|
||||||
if ($key instanceof DSA) {
|
if ($key instanceof DSA) {
|
||||||
$this->privateKeyFormat = $key->privateKeyFormat;
|
$this->privateKeyFormat = $key->privateKeyFormat;
|
||||||
$this->publicKeyFormat = $key->publicKeyFormat;
|
$this->publicKeyFormat = $key->publicKeyFormat;
|
||||||
@ -236,6 +243,13 @@ class DSA extends AsymmetricKey
|
|||||||
|
|
||||||
$components = parent::load($key, $type);
|
$components = parent::load($key, $type);
|
||||||
if ($components === false) {
|
if ($components === false) {
|
||||||
|
$this->format = null;
|
||||||
|
$this->p = null;
|
||||||
|
$this->q = null;
|
||||||
|
$this->g = null;
|
||||||
|
$this->x = null;
|
||||||
|
$this->y = null;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,9 +266,7 @@ class DSA extends AsymmetricKey
|
|||||||
$this->g = $components['g'];
|
$this->g = $components['g'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($components['x'])) {
|
$this->x = isset($components['x']) ? $components['x'] : null;
|
||||||
$this->x = $components['x'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($components['y'])) {
|
if (isset($components['y'])) {
|
||||||
$this->y = $components['y'];
|
$this->y = $components['y'];
|
||||||
@ -281,27 +293,6 @@ class DSA extends AsymmetricKey
|
|||||||
['L' => 0, 'N' => 0];
|
['L' => 0, 'N' => 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* __toString() magic method
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function __toString()
|
|
||||||
{
|
|
||||||
$key = parent::__toString();
|
|
||||||
if (!empty($key)) {
|
|
||||||
return $key;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$key = $this->getParameters($this->parametersFormat);
|
|
||||||
return is_string($key) ? $key : '';
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the private key
|
* Returns the private key
|
||||||
*
|
*
|
||||||
@ -331,6 +322,28 @@ class DSA extends AsymmetricKey
|
|||||||
return $type::savePrivateKey($this->p, $this->q, $this->g, $this->y, $this->x, $this->password);
|
return $type::savePrivateKey($this->p, $this->q, $this->g, $this->y, $this->x, $this->password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the key a private key?
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPrivateKey()
|
||||||
|
{
|
||||||
|
return isset($this->x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the key a public key?
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPublicKey()
|
||||||
|
{
|
||||||
|
return isset($this->p);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the public key
|
* Returns the public key
|
||||||
*
|
*
|
||||||
@ -354,8 +367,14 @@ class DSA extends AsymmetricKey
|
|||||||
* @param string $type optional
|
* @param string $type optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getPublicKey($type = 'PKCS8')
|
public function getPublicKey($type = null)
|
||||||
{
|
{
|
||||||
|
$returnObj = false;
|
||||||
|
if ($type === null) {
|
||||||
|
$returnObj = true;
|
||||||
|
$type = 'PKCS8';
|
||||||
|
}
|
||||||
|
|
||||||
$type = self::validatePlugin('Keys', $type, 'savePublicKey');
|
$type = self::validatePlugin('Keys', $type, 'savePublicKey');
|
||||||
if ($type === false) {
|
if ($type === false) {
|
||||||
return false;
|
return false;
|
||||||
@ -368,7 +387,15 @@ class DSA extends AsymmetricKey
|
|||||||
$this->y = $this->g->powMod($this->x, $this->p);
|
$this->y = $this->g->powMod($this->x, $this->p);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $type::savePublicKey($this->p, $this->q, $this->g, $this->y);
|
$key = $type::savePublicKey($this->p, $this->q, $this->g, $this->y);
|
||||||
|
if (!$returnObj) {
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
$public = clone $this;
|
||||||
|
$public->load($key, 'PKCS8');
|
||||||
|
|
||||||
|
return $public;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -397,6 +424,20 @@ class DSA extends AsymmetricKey
|
|||||||
return $type::saveParameters($this->p, $this->q, $this->g);
|
return $type::saveParameters($this->p, $this->q, $this->g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current engine being used
|
||||||
|
*
|
||||||
|
* @see self::useInternalEngine()
|
||||||
|
* @see self::useBestEngine()
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getEngine()
|
||||||
|
{
|
||||||
|
return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ?
|
||||||
|
'OpenSSL' : 'PHP';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a signature
|
* Create a signature
|
||||||
*
|
*
|
||||||
@ -406,8 +447,9 @@ class DSA extends AsymmetricKey
|
|||||||
* @param string $format optional
|
* @param string $format optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
function sign($message, $format = 'Raw')
|
public function sign($message, $format = 'ASN1')
|
||||||
{
|
{
|
||||||
|
$shortFormat = $format;
|
||||||
$format = self::validatePlugin('Signature', $format);
|
$format = self::validatePlugin('Signature', $format);
|
||||||
if ($format === false) {
|
if ($format === false) {
|
||||||
return false;
|
return false;
|
||||||
@ -417,6 +459,24 @@ class DSA extends AsymmetricKey
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
|
||||||
|
$signature = '';
|
||||||
|
$result = openssl_sign($message, $signature, $this->getPrivateKey(), $this->hash->getHash());
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
if ($shortFormat == 'ASN1') {
|
||||||
|
return $signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
extract(ASN1Signature::load($signature));
|
||||||
|
|
||||||
|
return $format::save($r, $s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$h = $this->hash->hash($message);
|
||||||
|
$h = $this->bits2int($h);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
$k = BigInteger::randomRange(self::$one, $this->q->subtract(self::$one));
|
$k = BigInteger::randomRange(self::$one, $this->q->subtract(self::$one));
|
||||||
$r = $this->g->powMod($k, $this->p);
|
$r = $this->g->powMod($k, $this->p);
|
||||||
@ -425,8 +485,6 @@ class DSA extends AsymmetricKey
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$kinv = $k->modInverse($this->q);
|
$kinv = $k->modInverse($this->q);
|
||||||
$h = $this->hash->hash($message);
|
|
||||||
$h = $this->bits2int($h);
|
|
||||||
$temp = $h->add($this->x->multiply($r));
|
$temp = $h->add($this->x->multiply($r));
|
||||||
$temp = $kinv->multiply($temp);
|
$temp = $kinv->multiply($temp);
|
||||||
list(, $s) = $temp->divide($this->q);
|
list(, $s) = $temp->divide($this->q);
|
||||||
@ -464,7 +522,7 @@ class DSA extends AsymmetricKey
|
|||||||
* @param string $format optional
|
* @param string $format optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
function verify($message, $signature, $format = 'Raw')
|
public function verify($message, $signature, $format = 'ASN1')
|
||||||
{
|
{
|
||||||
$format = self::validatePlugin('Signature', $format);
|
$format = self::validatePlugin('Signature', $format);
|
||||||
if ($format === false) {
|
if ($format === false) {
|
||||||
@ -481,6 +539,16 @@ class DSA extends AsymmetricKey
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
|
||||||
|
$sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature;
|
||||||
|
|
||||||
|
$result = openssl_verify($message, $sig, $this->getPublicKey(), $this->hash->getHash());
|
||||||
|
|
||||||
|
if ($result != -1) {
|
||||||
|
return (bool) $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$q_1 = $this->q->subtract(self::$one);
|
$q_1 = $this->q->subtract(self::$one);
|
||||||
if (!$r->between(self::$one, $q_1) || !$s->between(self::$one, $q_1)) {
|
if (!$r->between(self::$one, $q_1) || !$s->between(self::$one, $q_1)) {
|
||||||
return false;
|
return false;
|
||||||
@ -496,6 +564,6 @@ class DSA extends AsymmetricKey
|
|||||||
list(, $v) = $v1->multiply($v2)->divide($this->p);
|
list(, $v) = $v1->multiply($v2)->divide($this->p);
|
||||||
list(, $v) = $v->divide($this->q);
|
list(, $v) = $v->divide($this->q);
|
||||||
|
|
||||||
return Strings::equals($v->toBytes(), $r->toBytes());
|
return $v->equals($r);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -37,18 +37,15 @@ abstract class OpenSSH extends Progenitor
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function load($key, $password = '')
|
public static function load($key, $password = '')
|
||||||
{
|
{
|
||||||
$key = parent::load($key, 'ssh-dss');
|
$key = parent::load($key, 'ssh-dss');
|
||||||
if ($key === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = Strings::unpackSSH2('iiii', $key);
|
$result = Strings::unpackSSH2('iiii', $key);
|
||||||
if ($result === false) {
|
if ($result === false) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key appears to be malformed');
|
||||||
}
|
}
|
||||||
list($p, $q, $g, $y) = $result;
|
list($p, $q, $g, $y) = $result;
|
||||||
|
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
*
|
*
|
||||||
* Analogous to ssh-keygen's pem format (as specified by -m)
|
* Analogous to ssh-keygen's pem format (as specified by -m)
|
||||||
*
|
*
|
||||||
|
* Also, technically, PKCS1 decribes RSA but I am not aware of a formal specification for DSA.
|
||||||
|
* The DSA private key format seems to have been adapted from the RSA private key format so
|
||||||
|
* we're just re-using that as the name.
|
||||||
|
*
|
||||||
* @category Crypt
|
* @category Crypt
|
||||||
* @package DSA
|
* @package DSA
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
@ -32,7 +36,7 @@ use phpseclib\File\ASN1\Maps;
|
|||||||
use ParagonIE\ConstantTime\Base64;
|
use ParagonIE\ConstantTime\Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PKCS#1 Formatted RSA Key Handler
|
* PKCS#1 Formatted DSA Key Handler
|
||||||
*
|
*
|
||||||
* @package RSA
|
* @package RSA
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
@ -46,22 +50,15 @@ abstract class PKCS1 extends Progenitor
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function load($key, $password = '')
|
public static function load($key, $password = '')
|
||||||
{
|
{
|
||||||
if (!is_string($key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$key = parent::load($key, $password);
|
$key = parent::load($key, $password);
|
||||||
if ($key === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$decoded = ASN1::decodeBER($key);
|
$decoded = ASN1::decodeBER($key);
|
||||||
if (empty($decoded)) {
|
if (empty($decoded)) {
|
||||||
return false;
|
throw new \RuntimeException('Unable to decode BER');
|
||||||
}
|
}
|
||||||
|
|
||||||
$key = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP);
|
$key = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP);
|
||||||
@ -75,7 +72,11 @@ abstract class PKCS1 extends Progenitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
$key = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP);
|
$key = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP);
|
||||||
return is_array($key) ? $key : false;
|
if (is_array($key)) {
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \RuntimeException('Unable to perform ASN1 mapping');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,47 +69,45 @@ abstract class PKCS8 extends Progenitor
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function load($key, $password = '')
|
public static function load($key, $password = '')
|
||||||
{
|
{
|
||||||
if (!is_string($key)) {
|
if (!is_string($key)) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
$isPublic = strpos($key, 'PUBLIC') !== false;
|
$isPublic = strpos($key, 'PUBLIC') !== false;
|
||||||
|
|
||||||
$key = parent::load($key, $password);
|
$key = parent::load($key, $password);
|
||||||
if ($key === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
|
$type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case !$isPublic && $type == 'publicKey':
|
case !$isPublic && $type == 'publicKey':
|
||||||
|
throw new \UnexpectedValueException('Human readable string claims non-public key but DER encoded string claims public key');
|
||||||
case $isPublic && $type == 'privateKey':
|
case $isPublic && $type == 'privateKey':
|
||||||
return false;
|
throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
|
||||||
}
|
}
|
||||||
|
|
||||||
$decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
|
$decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
|
||||||
if (empty($decoded)) {
|
if (empty($decoded)) {
|
||||||
return false;
|
throw new \RuntimeException('Unable to decode BER of parameters');
|
||||||
}
|
}
|
||||||
$components = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP);
|
$components = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP);
|
||||||
if (!is_array($components)) {
|
if (!is_array($components)) {
|
||||||
return false;
|
throw new \RuntimeException('Unable to perform ASN1 mapping on parameters');
|
||||||
}
|
}
|
||||||
|
|
||||||
$decoded = ASN1::decodeBER($key[$type]);
|
$decoded = ASN1::decodeBER($key[$type]);
|
||||||
if (empty($decoded)) {
|
if (empty($decoded)) {
|
||||||
return false;
|
throw new \RuntimeException('Unable to decode BER');
|
||||||
}
|
}
|
||||||
|
|
||||||
$var = $type == 'privateKey' ? 'x' : 'y';
|
$var = $type == 'privateKey' ? 'x' : 'y';
|
||||||
$components[$var] = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP);
|
$components[$var] = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP);
|
||||||
if (!$components[$var] instanceof BigInteger) {
|
if (!$components[$var] instanceof BigInteger) {
|
||||||
return false;
|
throw new \RuntimeException('Unable to perform ASN1 mapping');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($key['meta'])) {
|
if (isset($key['meta'])) {
|
||||||
|
@ -44,10 +44,10 @@ abstract class PuTTY extends Progenitor
|
|||||||
/**
|
/**
|
||||||
* Algorithm Identifier
|
* Algorithm Identifier
|
||||||
*
|
*
|
||||||
* @var string
|
* @var array
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
const TYPE = 'ssh-dss';
|
protected static $types = ['ssh-dss'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Break a public or private key down into its constituent components
|
* Break a public or private key down into its constituent components
|
||||||
@ -55,31 +55,29 @@ abstract class PuTTY extends Progenitor
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function load($key, $password = '')
|
public static function load($key, $password = '')
|
||||||
{
|
{
|
||||||
$components = parent::load($key, $password);
|
$components = parent::load($key, $password);
|
||||||
if ($components === false || !isset($components['private'])) {
|
if (!isset($components['private'])) {
|
||||||
return $components;
|
return $components;
|
||||||
}
|
}
|
||||||
|
extract($components);
|
||||||
|
unset($components['public'], $components['private']);
|
||||||
|
|
||||||
$result = Strings::unpackSSH2('iiii', $components['public']);
|
$result = Strings::unpackSSH2('iiii', $public);
|
||||||
if ($result === false) {
|
if ($result === false) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key appears to be malformed');
|
||||||
}
|
}
|
||||||
list($p, $q, $g, $y) = $result;
|
list($p, $q, $g, $y) = $result;
|
||||||
|
|
||||||
$result = Strings::unpackSSH2('i', $components['private']);
|
$result = Strings::unpackSSH2('i', $private);
|
||||||
if ($result === false) {
|
if ($result === false) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key appears to be malformed');
|
||||||
}
|
}
|
||||||
list($x) = $result;
|
list($x) = $result;
|
||||||
|
|
||||||
if (isset($components['comment'])) {
|
|
||||||
$comment = $components['comment'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return compact('p', 'q', 'g', 'y', 'x', 'comment');
|
return compact('p', 'q', 'g', 'y', 'x', 'comment');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +93,7 @@ abstract class PuTTY extends Progenitor
|
|||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '')
|
public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = false)
|
||||||
{
|
{
|
||||||
if ($q->getLength() != 160) {
|
if ($q->getLength() != 160) {
|
||||||
throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160');
|
throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160');
|
||||||
@ -104,7 +102,7 @@ abstract class PuTTY extends Progenitor
|
|||||||
$public = Strings::packSSH2('iiii', $p, $q, $g, $y);
|
$public = Strings::packSSH2('iiii', $p, $q, $g, $y);
|
||||||
$private = Strings::packSSH2('i', $x);
|
$private = Strings::packSSH2('i', $x);
|
||||||
|
|
||||||
return self::wrapPrivateKey($public, $private, $password);
|
return self::wrapPrivateKey($public, $private, 'ssh-dsa', $password);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,6 +121,6 @@ abstract class PuTTY extends Progenitor
|
|||||||
throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160');
|
throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160');
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::wrapPublicKey(Strings::packSSH2('iiii', $p, $q, $g, $y));
|
return self::wrapPublicKey(Strings::packSSH2('iiii', $p, $q, $g, $y), 'ssh-dsa');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,12 +34,12 @@ abstract class Raw
|
|||||||
* @access public
|
* @access public
|
||||||
* @param array $key
|
* @param array $key
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function load($key, $password = '')
|
public static function load($key, $password = '')
|
||||||
{
|
{
|
||||||
if (!is_array($key)) {
|
if (!is_array($key)) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key should be a array - not a ' . gettype($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
@ -50,7 +50,7 @@ abstract class Raw
|
|||||||
case !isset($key['x']) && !isset($key['y']):
|
case !isset($key['x']) && !isset($key['y']):
|
||||||
case isset($key['x']) && !$key['x'] instanceof BigInteger:
|
case isset($key['x']) && !$key['x'] instanceof BigInteger:
|
||||||
case isset($key['y']) && !$key['y'] instanceof BigInteger:
|
case isset($key['y']) && !$key['y'] instanceof BigInteger:
|
||||||
return false;
|
throw new \UnexpectedValueException('Key appears to be malformed');
|
||||||
}
|
}
|
||||||
|
|
||||||
$options = ['p' => 1, 'q' => 1, 'g' => 1, 'x' => 1, 'y' => 1];
|
$options = ['p' => 1, 'q' => 1, 'g' => 1, 'x' => 1, 'y' => 1];
|
||||||
|
@ -39,12 +39,12 @@ abstract class XML
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function load($key, $password = '')
|
public static function load($key, $password = '')
|
||||||
{
|
{
|
||||||
if (!is_string($key)) {
|
if (!is_string($key)) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
$use_errors = libxml_use_internal_errors(true);
|
$use_errors = libxml_use_internal_errors(true);
|
||||||
@ -54,7 +54,7 @@ abstract class XML
|
|||||||
$key = '<xml>' . $key . '</xml>';
|
$key = '<xml>' . $key . '</xml>';
|
||||||
}
|
}
|
||||||
if (!$dom->loadXML($key)) {
|
if (!$dom->loadXML($key)) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key does not appear to contain XML');
|
||||||
}
|
}
|
||||||
$xpath = new \DOMXPath($dom);
|
$xpath = new \DOMXPath($dom);
|
||||||
$keys = ['p', 'q', 'g', 'y', 'j', 'seed', 'pgencounter'];
|
$keys = ['p', 'q', 'g', 'y', 'j', 'seed', 'pgencounter'];
|
||||||
@ -95,7 +95,7 @@ abstract class XML
|
|||||||
libxml_use_internal_errors($use_errors);
|
libxml_use_internal_errors($use_errors);
|
||||||
|
|
||||||
if (!isset($components['y'])) {
|
if (!isset($components['y'])) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key is missing y component');
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PKCS Signature Handler
|
* ASN1 Signature Handler
|
||||||
*
|
*
|
||||||
* PHP version 5
|
* PHP version 5
|
||||||
*
|
*
|
||||||
@ -19,17 +19,17 @@
|
|||||||
namespace phpseclib\Crypt\DSA\Signature;
|
namespace phpseclib\Crypt\DSA\Signature;
|
||||||
|
|
||||||
use phpseclib\Math\BigInteger;
|
use phpseclib\Math\BigInteger;
|
||||||
use phpseclib\File\ASN1;
|
use phpseclib\File\ASN1 as Encoder;
|
||||||
use phpseclib\File\ASN1\Maps;
|
use phpseclib\File\ASN1\Maps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PKCS Signature Handler
|
* ASN1 Signature Handler
|
||||||
*
|
*
|
||||||
* @package Common
|
* @package Common
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
abstract class PKCS
|
abstract class ASN1
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Loads a signature
|
* Loads a signature
|
||||||
@ -44,11 +44,11 @@ abstract class PKCS
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$decoded = ASN1::decodeBER($sig);
|
$decoded = Encoder::decodeBER($sig);
|
||||||
if (empty($decoded)) {
|
if (empty($decoded)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$components = ASN1::asn1map($decoded[0], Maps\DssSigValue::MAP);
|
$components = Encoder::asn1map($decoded[0], Maps\DssSigValue::MAP);
|
||||||
|
|
||||||
return $components;
|
return $components;
|
||||||
}
|
}
|
708
phpseclib/Crypt/ECDSA.php
Normal file
708
phpseclib/Crypt/ECDSA.php
Normal file
@ -0,0 +1,708 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of ECDSA.
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* Here's an example of how to create signatures and verify signatures with this library:
|
||||||
|
* <code>
|
||||||
|
* <?php
|
||||||
|
* include 'vendor/autoload.php';
|
||||||
|
*
|
||||||
|
* extract(\phpseclib\Crypt\ECDSA::createKey());
|
||||||
|
*
|
||||||
|
* $plaintext = 'terrafrost';
|
||||||
|
*
|
||||||
|
* $signature = $privatekey->sign($plaintext, 'ASN1');
|
||||||
|
*
|
||||||
|
* echo $publickey->verify($plaintext, $signature) ? 'verified' : 'unverified';
|
||||||
|
* ?>
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2016 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Crypt\Common\AsymmetricKey;
|
||||||
|
use phpseclib\Exception\UnsupportedCurveException;
|
||||||
|
use phpseclib\File\ASN1;
|
||||||
|
use phpseclib\File\ASN1\Maps\ECParameters;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
||||||
|
use phpseclib\Crypt\ECDSA\Curves\Ed25519;
|
||||||
|
use phpseclib\Crypt\ECDSA\Keys\PKCS1;
|
||||||
|
use phpseclib\Crypt\ECDSA\Keys\PKCS8;
|
||||||
|
use phpseclib\Crypt\ECDSA\Signature\ASN1 as ASN1Signature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of ECDSA.
|
||||||
|
*
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
class ECDSA extends AsymmetricKey
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Algorithm Name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
const ALGORITHM = 'ECDSA';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private Key dA
|
||||||
|
*
|
||||||
|
* sign() converts this to a BigInteger so one might wonder why this is a FiniteFieldInteger instead of
|
||||||
|
* a BigInteger. That's because a FiniteFieldInteger, when converted to a byte string, is null padded by
|
||||||
|
* a certain amount whereas a BigInteger isn't.
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
private $dA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public Key QA
|
||||||
|
*
|
||||||
|
* @var object[]
|
||||||
|
*/
|
||||||
|
private $QA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curve
|
||||||
|
*
|
||||||
|
* @var \phpseclib\Crypt\ECDSA\BaseCurves\Base
|
||||||
|
*/
|
||||||
|
private $curve;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curve Name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $curveName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curve Order
|
||||||
|
*
|
||||||
|
* Used for deterministic ECDSA
|
||||||
|
*
|
||||||
|
* @var \phpseclib\Math\BigInteger
|
||||||
|
*/
|
||||||
|
protected $q;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for the private key
|
||||||
|
*
|
||||||
|
* Used for deterministic ECDSA. AsymmetricKey expects $x. I don't like x because
|
||||||
|
* with x you have x * the base point yielding an (x, y)-coordinate that is the
|
||||||
|
* public key. But the x is different depending on which side of the equal sign
|
||||||
|
* you're on. It's less ambiguous if you do dA * base point = (x, y)-coordinate.
|
||||||
|
*
|
||||||
|
* @var \phpseclib\Math\BigInteger
|
||||||
|
*/
|
||||||
|
protected $x;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for the private key
|
||||||
|
*
|
||||||
|
* Used for deterministic ECDSA. AsymmetricKey expects $x. I don't like x because
|
||||||
|
* with x you have x * the base point yielding an (x, y)-coordinate that is the
|
||||||
|
* public key. But the x is different depending on which side of the equal sign
|
||||||
|
* you're on. It's less ambiguous if you do dA * base point = (x, y)-coordinate.
|
||||||
|
*
|
||||||
|
* @var \phpseclib\Math\BigInteger
|
||||||
|
*/
|
||||||
|
private $context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create public / private key pair.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $curve
|
||||||
|
* @return \phpseclib\Crypt\ECDSA[]
|
||||||
|
*/
|
||||||
|
public static function createKey($curve)
|
||||||
|
{
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if (!isset(self::$engines['PHP'])) {
|
||||||
|
self::useBestEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$engines['libsodium'] && $curve == 'Ed25519' && function_exists('sodium_crypto_sign_keypair')) {
|
||||||
|
$kp = sodium_crypto_sign_keypair();
|
||||||
|
|
||||||
|
$privatekey = new static();
|
||||||
|
$privatekey->load(sodium_crypto_sign_secretkey($kp));
|
||||||
|
|
||||||
|
$publickey = new static();
|
||||||
|
$publickey->load(sodium_crypto_sign_publickey($kp));
|
||||||
|
|
||||||
|
$publickey->curveName = $privatekey->curveName = $curve;
|
||||||
|
|
||||||
|
return compact('privatekey', 'publickey');
|
||||||
|
}
|
||||||
|
|
||||||
|
$privatekey = new static();
|
||||||
|
|
||||||
|
$curveName = $curve;
|
||||||
|
$curve = '\phpseclib\Crypt\ECDSA\Curves\\' . $curve;
|
||||||
|
if (!class_exists($curve)) {
|
||||||
|
throw new UnsupportedCurveException('Named Curve of ' . $curve . ' is not supported');
|
||||||
|
}
|
||||||
|
$curve = new $curve();
|
||||||
|
$privatekey->dA = $dA = $curve->createRandomMultiplier();
|
||||||
|
$privatekey->QA = $curve->multiplyPoint($curve->getBasePoint(), $dA);
|
||||||
|
$privatekey->curve = $curve;
|
||||||
|
|
||||||
|
$publickey = clone $privatekey;
|
||||||
|
unset($publickey->dA);
|
||||||
|
unset($publickey->x);
|
||||||
|
|
||||||
|
$publickey->curveName = $privatekey->curveName = $curveName;
|
||||||
|
|
||||||
|
return compact('privatekey', 'publickey');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a public or private key
|
||||||
|
*
|
||||||
|
* Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param int $type optional
|
||||||
|
*/
|
||||||
|
public function load($key, $type = false)
|
||||||
|
{
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if (!isset(self::$engines['PHP'])) {
|
||||||
|
self::useBestEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($key instanceof ECDSA) {
|
||||||
|
$this->privateKeyFormat = $key->privateKeyFormat;
|
||||||
|
$this->publicKeyFormat = $key->publicKeyFormat;
|
||||||
|
$this->format = $key->format;
|
||||||
|
$this->dA = isset($key->dA) ? $key->dA : null;
|
||||||
|
$this->QA = $key->QA;
|
||||||
|
$this->curve = $key->curve;
|
||||||
|
$this->parametersFormat = $key->parametersFormat;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$components = parent::load($key, $type);
|
||||||
|
if ($components === false) {
|
||||||
|
$this->format = null;
|
||||||
|
$this->dA = null;
|
||||||
|
$this->QA = null;
|
||||||
|
$this->curve = null;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->curve = $components['curve'];
|
||||||
|
$this->QA = $components['QA'];
|
||||||
|
$this->dA = isset($components['dA']) ? $components['dA'] : null;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the curve
|
||||||
|
*
|
||||||
|
* Returns a string if it's a named curve, an array if not
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string|array
|
||||||
|
*/
|
||||||
|
public function getCurve()
|
||||||
|
{
|
||||||
|
if ($this->curveName) {
|
||||||
|
return $this->curveName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->curve instanceof TwistedEdwardsCurve) {
|
||||||
|
$this->curveName = $this->curve instanceof Ed25519 ? 'Ed25519' : 'Ed448';
|
||||||
|
return $this->curveName;
|
||||||
|
}
|
||||||
|
|
||||||
|
$namedCurves = PKCS1::isUsingNamedCurves();
|
||||||
|
PKCS1::useNamedCurve();
|
||||||
|
|
||||||
|
$params = $this->getParameters();
|
||||||
|
$decoded = ASN1::extractBER($params);
|
||||||
|
$decoded = ASN1::decodeBER($decoded);
|
||||||
|
$decoded = ASN1::asn1map($decoded[0], ECParameters::MAP);
|
||||||
|
if (isset($decoded['namedCurve'])) {
|
||||||
|
$this->curveName = $decoded['namedCurve'];
|
||||||
|
|
||||||
|
if (!$namedCurves) {
|
||||||
|
PKCS1::useSpecifiedCurve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $decoded['namedCurve'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$namedCurves) {
|
||||||
|
PKCS1::useSpecifiedCurve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key size
|
||||||
|
*
|
||||||
|
* Quoting https://tools.ietf.org/html/rfc5656#section-2,
|
||||||
|
*
|
||||||
|
* "The size of a set of elliptic curve domain parameters on a prime
|
||||||
|
* curve is defined as the number of bits in the binary representation
|
||||||
|
* of the field order, commonly denoted by p. Size on a
|
||||||
|
* characteristic-2 curve is defined as the number of bits in the binary
|
||||||
|
* representation of the field, commonly denoted by m. A set of
|
||||||
|
* elliptic curve domain parameters defines a group of order n generated
|
||||||
|
* by a base point P"
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getLength()
|
||||||
|
{
|
||||||
|
if (!isset($this->QA)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->curve->getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the key a private key?
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPrivateKey()
|
||||||
|
{
|
||||||
|
return isset($this->dA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the key a public key?
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPublicKey()
|
||||||
|
{
|
||||||
|
return isset($this->QA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the private key
|
||||||
|
*
|
||||||
|
* @see self::getPublicKey()
|
||||||
|
* @access public
|
||||||
|
* @param string $type optional
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getPrivateKey($type = 'PKCS8')
|
||||||
|
{
|
||||||
|
$type = self::validatePlugin('Keys', $type, 'savePrivateKey');
|
||||||
|
if ($type === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->dA)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $type::savePrivateKey($this->dA, $this->curve, $this->QA, $this->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the public key
|
||||||
|
*
|
||||||
|
* @see self::getPrivateKey()
|
||||||
|
* @access public
|
||||||
|
* @param string $type optional
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getPublicKey($type = null)
|
||||||
|
{
|
||||||
|
$returnObj = false;
|
||||||
|
if ($type === null) {
|
||||||
|
$returnObj = true;
|
||||||
|
$type = 'PKCS8';
|
||||||
|
}
|
||||||
|
$type = self::validatePlugin('Keys', $type, 'savePublicKey');
|
||||||
|
if ($type === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->QA)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = $type::savePublicKey($this->curve, $this->QA);
|
||||||
|
if ($returnObj) {
|
||||||
|
$public = clone $this;
|
||||||
|
$public->load($key, 'PKCS8');
|
||||||
|
|
||||||
|
return $public;
|
||||||
|
}
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parameters
|
||||||
|
*
|
||||||
|
* A public / private key is only returned if the currently loaded "key" contains an x or y
|
||||||
|
* value.
|
||||||
|
*
|
||||||
|
* @see self::getPublicKey()
|
||||||
|
* @see self::getPrivateKey()
|
||||||
|
* @access public
|
||||||
|
* @param string $type optional
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getParameters($type = 'PKCS1')
|
||||||
|
{
|
||||||
|
$type = self::validatePlugin('Keys', $type, 'saveParameters');
|
||||||
|
if ($type === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->curve) || $this->curve instanceof TwistedEdwardsCurve) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $type::saveParameters($this->curve);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current engine being used
|
||||||
|
*
|
||||||
|
* @see self::useInternalEngine()
|
||||||
|
* @see self::useBestEngine()
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getEngine()
|
||||||
|
{
|
||||||
|
if (!isset($this->curve)) {
|
||||||
|
throw new \RuntimeException('getEngine should not be called until after a key has been loaded');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->curve instanceof TwistedEdwardsCurve) {
|
||||||
|
return $this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context) ?
|
||||||
|
'libsodium' : 'PHP';
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ?
|
||||||
|
'OpenSSL' : 'PHP';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the context
|
||||||
|
*
|
||||||
|
* Used by Ed25519 / Ed448.
|
||||||
|
*
|
||||||
|
* @see self::sign()
|
||||||
|
* @see self::verify()
|
||||||
|
* @access public
|
||||||
|
* @param string $context optional
|
||||||
|
*/
|
||||||
|
public function setContext($context = null)
|
||||||
|
{
|
||||||
|
if (!isset($context)) {
|
||||||
|
$this->context = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!is_string($context)) {
|
||||||
|
throw new \RuntimeException('setContext expects a string');
|
||||||
|
}
|
||||||
|
if (strlen($context) > 255) {
|
||||||
|
throw new \RuntimeException('The context is supposed to be, at most, 255 bytes long');
|
||||||
|
}
|
||||||
|
$this->context = $context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a signature
|
||||||
|
*
|
||||||
|
* @see self::verify()
|
||||||
|
* @access public
|
||||||
|
* @param string $message
|
||||||
|
* @param string $format optional
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function sign($message, $format = 'ASN1')
|
||||||
|
{
|
||||||
|
if (!isset($this->dA)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dA = $this->dA->toBigInteger();
|
||||||
|
|
||||||
|
$order = $this->curve->getOrder();
|
||||||
|
|
||||||
|
if ($this->curve instanceof TwistedEdwardsCurve) {
|
||||||
|
if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) {
|
||||||
|
return sodium_crypto_sign_detached($message, $this->getPrivateKey('libsodium'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// contexts (Ed25519ctx) are supported but prehashing (Ed25519ph) is not.
|
||||||
|
// quoting https://tools.ietf.org/html/rfc8032#section-8.5 ,
|
||||||
|
// "The Ed25519ph and Ed448ph variants ... SHOULD NOT be used"
|
||||||
|
$A = $this->curve->encodePoint($this->QA);
|
||||||
|
$curve = $this->curve;
|
||||||
|
$hash = new Hash($curve::HASH);
|
||||||
|
|
||||||
|
$secret = substr($hash->hash($this->dA->secret), $curve::SIZE);
|
||||||
|
|
||||||
|
if ($curve instanceof Ed25519) {
|
||||||
|
$dom = !isset($this->context) ? '' :
|
||||||
|
'SigEd25519 no Ed25519 collisions' . "\0" . chr(strlen($this->context)) . $this->context;
|
||||||
|
} else {
|
||||||
|
$context = isset($this->context) ? $this->context : '';
|
||||||
|
$dom = 'SigEd448' . "\0" . chr(strlen($context)) . $context;
|
||||||
|
}
|
||||||
|
// SHA-512(dom2(F, C) || prefix || PH(M))
|
||||||
|
$r = $hash->hash($dom . $secret . $message);
|
||||||
|
$r = strrev($r);
|
||||||
|
$r = new BigInteger($r, 256);
|
||||||
|
list(, $r) = $r->divide($order);
|
||||||
|
$R = $curve->multiplyPoint($curve->getBasePoint(), $curve->convertInteger($r));
|
||||||
|
$R = $curve->encodePoint($R);
|
||||||
|
$k = $hash->hash($dom . $R . $A . $message);
|
||||||
|
$k = strrev($k);
|
||||||
|
$k = new BigInteger($k, 256);
|
||||||
|
list(, $k) = $k->divide($order);
|
||||||
|
$S = $k->multiply($dA)->add($r);
|
||||||
|
list(, $S) = $S->divide($order);
|
||||||
|
$S = str_pad(strrev($S->toBytes()), $curve::SIZE, "\0");
|
||||||
|
return $R . $S;
|
||||||
|
}
|
||||||
|
|
||||||
|
$shortFormat = $format;
|
||||||
|
$format = self::validatePlugin('Signature', $format);
|
||||||
|
if ($format === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
|
||||||
|
$namedCurves = PKCS8::isUsingNamedCurves();
|
||||||
|
|
||||||
|
// use specified curves to avoid issues with OpenSSL possibly not supporting a given named curve;
|
||||||
|
// doing this may mean some curve-specific optimizations can't be used but idk if OpenSSL even
|
||||||
|
// has curve-specific optimizations
|
||||||
|
PKCS8::useSpecifiedCurve();
|
||||||
|
|
||||||
|
$signature = '';
|
||||||
|
// altho PHP's OpenSSL bindings only supported ECDSA key creation in PHP 7.1 they've long
|
||||||
|
// supported signing / verification
|
||||||
|
$result = openssl_sign($message, $signature, $this->getPrivateKey(), $this->hash->getHash());
|
||||||
|
|
||||||
|
if ($namedCurves) {
|
||||||
|
PKCS8::useNamedCurve();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
if ($shortFormat == 'ASN1') {
|
||||||
|
return $signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
extract(ASN1Signature::load($signature));
|
||||||
|
|
||||||
|
return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$e = $this->hash->hash($message);
|
||||||
|
$e = new BigInteger($e, 256);
|
||||||
|
|
||||||
|
$Ln = $this->hash->getLength() - $order->getLength();
|
||||||
|
$z = $Ln > 0 ? $e->bitwise_rightShift($Ln) : $e;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
$k = BigInteger::randomRange(self::$one, $order->subtract(self::$one));
|
||||||
|
list($x, $y) = $this->curve->multiplyPoint($this->curve->getBasePoint(), $this->curve->convertInteger($k));
|
||||||
|
$x = $x->toBigInteger();
|
||||||
|
list(, $r) = $x->divide($order);
|
||||||
|
if ($r->equals(self::$zero)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$kinv = $k->modInverse($order);
|
||||||
|
$temp = $z->add($dA->multiply($r));
|
||||||
|
$temp = $kinv->multiply($temp);
|
||||||
|
list(, $s) = $temp->divide($order);
|
||||||
|
if (!$s->equals(self::$zero)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the following is an RFC6979 compliant implementation of deterministic ECDSA
|
||||||
|
// it's unused because it's mainly intended for use when a good CSPRNG isn't
|
||||||
|
// available. if phpseclib's CSPRNG isn't good then even key generation is
|
||||||
|
// suspect
|
||||||
|
/*
|
||||||
|
// if this were actually being used it'd probably be better if this lived in load() and createKey()
|
||||||
|
$this->q = $this->curve->getOrder();
|
||||||
|
$dA = $this->dA->toBigInteger();
|
||||||
|
$this->x = $dA;
|
||||||
|
|
||||||
|
$h1 = $this->hash->hash($message);
|
||||||
|
$k = $this->computek($h1);
|
||||||
|
list($x, $y) = $this->curve->multiplyPoint($this->curve->getBasePoint(), $this->curve->convertInteger($k));
|
||||||
|
$x = $x->toBigInteger();
|
||||||
|
list(, $r) = $x->divide($this->q);
|
||||||
|
$kinv = $k->modInverse($this->q);
|
||||||
|
$h1 = $this->bits2int($h1);
|
||||||
|
$temp = $h1->add($dA->multiply($r));
|
||||||
|
$temp = $kinv->multiply($temp);
|
||||||
|
list(, $s) = $temp->divide($this->q);
|
||||||
|
*/
|
||||||
|
|
||||||
|
return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a signature
|
||||||
|
*
|
||||||
|
* @see self::verify()
|
||||||
|
* @access public
|
||||||
|
* @param string $message
|
||||||
|
* @param string $format optional
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function verify($message, $signature, $format = 'ASN1')
|
||||||
|
{
|
||||||
|
if (!isset($this->QA)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$order = $this->curve->getOrder();
|
||||||
|
|
||||||
|
if ($this->curve instanceof TwistedEdwardsCurve) {
|
||||||
|
if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) {
|
||||||
|
return sodium_crypto_sign_verify_detached($signature, $message, $this->getPublicKey('libsodium'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$curve = $this->curve;
|
||||||
|
if (strlen($signature) != 2 * $curve::SIZE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$R = substr($signature, 0, $curve::SIZE);
|
||||||
|
$S = substr($signature, $curve::SIZE);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$R = PKCS1::extractPoint($R, $curve);
|
||||||
|
$R = $this->curve->convertToInternal($R);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$S = strrev($S);
|
||||||
|
$S = new BigInteger($S, 256);
|
||||||
|
|
||||||
|
if ($S->compare($order) >= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$A = $curve->encodePoint($this->QA);
|
||||||
|
|
||||||
|
if ($curve instanceof Ed25519) {
|
||||||
|
$dom2 = !isset($this->context) ? '' :
|
||||||
|
'SigEd25519 no Ed25519 collisions' . "\0" . chr(strlen($this->context)) . $this->context;
|
||||||
|
} else {
|
||||||
|
$context = isset($this->context) ? $this->context : '';
|
||||||
|
$dom2 = 'SigEd448' . "\0" . chr(strlen($context)) . $context;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash = new Hash($curve::HASH);
|
||||||
|
$k = $hash->hash($dom2 . substr($signature, 0, $curve::SIZE) . $A . $message);
|
||||||
|
$k = strrev($k);
|
||||||
|
$k = new BigInteger($k, 256);
|
||||||
|
list(, $k) = $k->divide($order);
|
||||||
|
|
||||||
|
$qa = $curve->convertToInternal($this->QA);
|
||||||
|
|
||||||
|
$lhs = $curve->multiplyPoint($curve->getBasePoint(), $curve->convertInteger($S));
|
||||||
|
$rhs = $curve->multiplyPoint($qa, $curve->convertInteger($k));
|
||||||
|
$rhs = $curve->addPoint($rhs, $R);
|
||||||
|
$rhs = $curve->convertToAffine($rhs);
|
||||||
|
|
||||||
|
return $lhs[0]->equals($rhs[0]) && $lhs[1]->equals($rhs[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$format = self::validatePlugin('Signature', $format);
|
||||||
|
if ($format === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = $format::load($signature);
|
||||||
|
if ($params === false || count($params) != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
extract($params);
|
||||||
|
|
||||||
|
if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
|
||||||
|
$namedCurves = PKCS8::isUsingNamedCurves();
|
||||||
|
|
||||||
|
PKCS8::useSpecifiedCurve();
|
||||||
|
|
||||||
|
$sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature;
|
||||||
|
|
||||||
|
$result = openssl_verify($message, $sig, $this->getPublicKey(), $this->hash->getHash());
|
||||||
|
|
||||||
|
if ($namedCurves) {
|
||||||
|
PKCS8::useNamedCurve();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result != -1) {
|
||||||
|
return (bool) $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$n_1 = $order->subtract(self::$one);
|
||||||
|
if (!$r->between(self::$one, $n_1) || !$s->between(self::$one, $n_1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$e = $this->hash->hash($message);
|
||||||
|
$e = new BigInteger($e, 256);
|
||||||
|
|
||||||
|
$Ln = $this->hash->getLength() - $order->getLength();
|
||||||
|
$z = $Ln > 0 ? $e->bitwise_rightShift($Ln) : $e;
|
||||||
|
|
||||||
|
$w = $s->modInverse($order);
|
||||||
|
list(, $u1) = $z->multiply($w)->divide($order);
|
||||||
|
list(, $u2) = $r->multiply($w)->divide($order);
|
||||||
|
|
||||||
|
$u1 = $this->curve->convertInteger($u1);
|
||||||
|
$u2 = $this->curve->convertInteger($u2);
|
||||||
|
|
||||||
|
list($x1, $y1) = $this->curve->multiplyAddPoints(
|
||||||
|
[$this->curve->getBasePoint(), $this->QA],
|
||||||
|
[$u1, $u2]
|
||||||
|
);
|
||||||
|
|
||||||
|
$x1 = $x1->toBigInteger();
|
||||||
|
list(, $x1) = $x1->divide($order);
|
||||||
|
|
||||||
|
return $x1->equals($r);
|
||||||
|
}
|
||||||
|
}
|
220
phpseclib/Crypt/ECDSA/BaseCurves/Base.php
Normal file
220
phpseclib/Crypt/ECDSA/BaseCurves/Base.php
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curve methods common to all curves
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\BaseCurves;
|
||||||
|
|
||||||
|
use phpseclib\Math\Common\FiniteField;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base
|
||||||
|
*
|
||||||
|
* @package Prime
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
abstract class Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Doubles
|
||||||
|
*
|
||||||
|
* @var object[]
|
||||||
|
*/
|
||||||
|
protected $doubles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NAF Points
|
||||||
|
*
|
||||||
|
* @var int[]
|
||||||
|
*/
|
||||||
|
private $naf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Order
|
||||||
|
*
|
||||||
|
* @var BigInteger
|
||||||
|
*/
|
||||||
|
protected $order;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finite Field Integer factory
|
||||||
|
*
|
||||||
|
* @var \phpseclib\Math\FiniteField\Integer
|
||||||
|
*/
|
||||||
|
protected $factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a random integer
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
|
public function randomInteger()
|
||||||
|
{
|
||||||
|
return $this->factory->randomInteger();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a BigInteger to a FiniteField integer
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
|
public function convertInteger(BigInteger $x)
|
||||||
|
{
|
||||||
|
return $this->factory->newInteger($x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the length, in bytes, of the modulo
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getLengthInBytes()
|
||||||
|
{
|
||||||
|
return $this->factory->getLengthInBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the length, in bits, of the modulo
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getLength()
|
||||||
|
{
|
||||||
|
return $this->factory->getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiply a point on the curve by a scalar
|
||||||
|
*
|
||||||
|
* Uses the montgomery ladder technique as described here:
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Montgomery_ladder
|
||||||
|
* https://github.com/phpecc/phpecc/issues/16#issuecomment-59176772
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function multiplyPoint(array $p, FiniteField\Integer $d)
|
||||||
|
{
|
||||||
|
$alreadyInternal = isset($p[2]);
|
||||||
|
$r = $alreadyInternal ?
|
||||||
|
[[], $p] :
|
||||||
|
[[], $this->convertToInternal($p)];
|
||||||
|
|
||||||
|
$d = $d->toBits();
|
||||||
|
for ($i = 0; $i < strlen($d); $i++) {
|
||||||
|
$d_i = (int) $d[$i];
|
||||||
|
$r[1 - $d_i] = $this->addPoint($r[0], $r[1]);
|
||||||
|
$r[$d_i] = $this->doublePoint($r[$d_i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $alreadyInternal ? $r[0] : $this->convertToAffine($r[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a random scalar multiplier
|
||||||
|
*
|
||||||
|
* @return FiniteField
|
||||||
|
*/
|
||||||
|
public function createRandomMultiplier()
|
||||||
|
{
|
||||||
|
static $one;
|
||||||
|
if (!isset($one)) {
|
||||||
|
$one = new BigInteger(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dA = BigInteger::randomRange($one, $this->order->subtract($one));
|
||||||
|
return $this->factory->newInteger($dA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the Order
|
||||||
|
*/
|
||||||
|
public function setOrder(BigInteger $order)
|
||||||
|
{
|
||||||
|
$this->order = $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Order
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\BigInteger
|
||||||
|
*/
|
||||||
|
public function getOrder()
|
||||||
|
{
|
||||||
|
return $this->order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a custom defined modular reduction function
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
|
public function setReduction(callable $func)
|
||||||
|
{
|
||||||
|
$this->factory->setReduction($func);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the affine point
|
||||||
|
*
|
||||||
|
* @return object[]
|
||||||
|
*/
|
||||||
|
public function convertToAffine(array $p)
|
||||||
|
{
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an affine point to a jacobian coordinate
|
||||||
|
*
|
||||||
|
* @return object[]
|
||||||
|
*/
|
||||||
|
public function convertToInternal(array $p)
|
||||||
|
{
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Negates a point
|
||||||
|
*
|
||||||
|
* @return object[]
|
||||||
|
*/
|
||||||
|
public function negatePoint(array $p)
|
||||||
|
{
|
||||||
|
$temp = [
|
||||||
|
$p[0],
|
||||||
|
$p[1]->negate()
|
||||||
|
];
|
||||||
|
if (isset($p[2])) {
|
||||||
|
$temp[] = $p[2];
|
||||||
|
}
|
||||||
|
return $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiply and Add Points
|
||||||
|
*
|
||||||
|
* @return int[]
|
||||||
|
*/
|
||||||
|
public function multiplyAddPoints(array $points, array $scalars)
|
||||||
|
{
|
||||||
|
$p1 = $this->convertToInternal($points[0]);
|
||||||
|
$p2 = $this->convertToInternal($points[1]);
|
||||||
|
$p1 = $this->multiplyPoint($p1, $scalars[0]);
|
||||||
|
$p2 = $this->multiplyPoint($p2, $scalars[1]);
|
||||||
|
$r = $this->addPoint($p1, $p2);
|
||||||
|
return $this->convertToAffine($r);
|
||||||
|
}
|
||||||
|
}
|
378
phpseclib/Crypt/ECDSA/BaseCurves/Binary.php
Normal file
378
phpseclib/Crypt/ECDSA/BaseCurves/Binary.php
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curves over y^2 + x*y = x^3 + a*x^2 + b
|
||||||
|
*
|
||||||
|
* These are curves used in SEC 2 over prime fields: http://www.secg.org/SEC2-Ver-1.0.pdf
|
||||||
|
* The curve is a weierstrass curve with a[3] and a[2] set to 0.
|
||||||
|
*
|
||||||
|
* Uses Jacobian Coordinates for speed if able:
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Jacobian_curve
|
||||||
|
* https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\BaseCurves;
|
||||||
|
|
||||||
|
use phpseclib\Common\Functions\Strings;
|
||||||
|
use phpseclib\Math\BinaryField;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Math\BinaryField\Integer as BinaryInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curves over y^2 + x*y = x^3 + a*x^2 + b
|
||||||
|
*
|
||||||
|
* @package Binary
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
class Binary extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Binary Field Integer factory
|
||||||
|
*
|
||||||
|
* @var \phpseclib\Math\BinaryFields
|
||||||
|
*/
|
||||||
|
protected $factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cofficient for x^1
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $a;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cofficient for x^0
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $b;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base Point
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $p;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number one over the specified finite field
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $one;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The modulo
|
||||||
|
*
|
||||||
|
* @var BigInteger
|
||||||
|
*/
|
||||||
|
protected $modulo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Order
|
||||||
|
*
|
||||||
|
* @var BigInteger
|
||||||
|
*/
|
||||||
|
protected $order;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the modulo
|
||||||
|
*/
|
||||||
|
public function setModulo(...$modulo)
|
||||||
|
{
|
||||||
|
$this->modulo = $modulo;
|
||||||
|
$this->factory = new BinaryField(...$modulo);
|
||||||
|
|
||||||
|
$this->one = $this->factory->newInteger("\1");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set coefficients a and b
|
||||||
|
*
|
||||||
|
* @param string $a
|
||||||
|
* @param string $b
|
||||||
|
*/
|
||||||
|
public function setCoefficients($a, $b)
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
$this->a = $this->factory->newInteger(pack('H*', $a));
|
||||||
|
$this->b = $this->factory->newInteger(pack('H*', $b));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set x and y coordinates for the base point
|
||||||
|
*
|
||||||
|
* @param string|BinaryInteger $x
|
||||||
|
* @param string|BinaryInteger $y
|
||||||
|
*/
|
||||||
|
public function setBasePoint($x, $y)
|
||||||
|
{
|
||||||
|
switch (true) {
|
||||||
|
case !is_string($x) && !$x instanceof BinaryInteger:
|
||||||
|
throw new \UnexpectedValueException('Argument 1 passed to Binary::setBasePoint() must be a string or an instance of BinaryField\Integer');
|
||||||
|
case !is_string($y) && !$y instanceof BinaryInteger:
|
||||||
|
throw new \UnexpectedValueException('Argument 2 passed to Binary::setBasePoint() must be a string or an instance of BinaryField\Integer');
|
||||||
|
}
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
$this->p = [
|
||||||
|
is_string($x) ? $this->factory->newInteger(pack('H*', $x)) : $x,
|
||||||
|
is_string($y) ? $this->factory->newInteger(pack('H*', $y)) : $y
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the base point as an array
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getBasePoint()
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (!isset($this->p)) {
|
||||||
|
throw new \RuntimeException('setBasePoint needs to be called before this method');
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return $this->p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds two points on the curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
public function addPoint(array $p, array $q)
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count($p) || !count($q)) {
|
||||||
|
if (count($q)) {
|
||||||
|
return $q;
|
||||||
|
}
|
||||||
|
if (count($p)) {
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($p[2]) || !isset($q[2])) {
|
||||||
|
throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($p[0]->equals($q[0])) {
|
||||||
|
return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// formulas from http://hyperelliptic.org/EFD/g12o/auto-shortw-jacobian.html
|
||||||
|
|
||||||
|
list($x1, $y1, $z1) = $p;
|
||||||
|
list($x2, $y2, $z2) = $q;
|
||||||
|
|
||||||
|
$o1 = $z1->multiply($z1);
|
||||||
|
$b = $x2->multiply($o1);
|
||||||
|
|
||||||
|
if ($z2->equals($this->one)) {
|
||||||
|
$d = $y2->multiply($o1)->multiply($z1);
|
||||||
|
$e = $x1->add($b);
|
||||||
|
$f = $y1->add($d);
|
||||||
|
$z3 = $e->multiply($z1);
|
||||||
|
$h = $f->multiply($x2)->add($z3->multiply($y2));
|
||||||
|
$i = $f->add($z3);
|
||||||
|
$g = $z3->multiply($z3);
|
||||||
|
$p1 = $this->a->multiply($g);
|
||||||
|
$p2 = $f->multiply($i);
|
||||||
|
$p3 = $e->multiply($e)->multiply($e);
|
||||||
|
$x3 = $p1->add($p2)->add($p3);
|
||||||
|
$y3 = $i->multiply($x3)->add($g->multiply($h));
|
||||||
|
|
||||||
|
return [$x3, $y3, $z3];
|
||||||
|
}
|
||||||
|
|
||||||
|
$o2 = $z2->multiply($z2);
|
||||||
|
$a = $x1->multiply($o2);
|
||||||
|
$c = $y1->multiply($o2)->multiply($z2);
|
||||||
|
$d = $y2->multiply($o1)->multiply($z1);
|
||||||
|
$e = $a->add($b);
|
||||||
|
$f = $c->add($d);
|
||||||
|
$g = $e->multiply($z1);
|
||||||
|
$h = $f->multiply($x2)->add($g->multiply($y2));
|
||||||
|
$z3 = $g->multiply($z2);
|
||||||
|
$i = $f->add($z3);
|
||||||
|
$p1 = $this->a->multiply($z3->multiply($z3));
|
||||||
|
$p2 = $f->multiply($i);
|
||||||
|
$p3 = $e->multiply($e)->multiply($e);
|
||||||
|
$x3 = $p1->add($p2)->add($p3);
|
||||||
|
$y3 = $i->multiply($x3)->add($g->multiply($g)->multiply($h));
|
||||||
|
|
||||||
|
return [$x3, $y3, $z3];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doubles a point on a curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
public function doublePoint(array $p)
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count($p)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($p[2])) {
|
||||||
|
throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
|
||||||
|
}
|
||||||
|
|
||||||
|
// formulas from http://hyperelliptic.org/EFD/g12o/auto-shortw-jacobian.html
|
||||||
|
|
||||||
|
list($x1, $y1, $z1) = $p;
|
||||||
|
|
||||||
|
$a = $x1->multiply($x1);
|
||||||
|
$b = $a->multiply($a);
|
||||||
|
|
||||||
|
if ($z1->equals($this->one)) {
|
||||||
|
$x3 = $b->add($this->b);
|
||||||
|
$z3 = clone $x1;
|
||||||
|
$p1 = $a->add($y1)->add($z3)->multiply($this->b);
|
||||||
|
$p2 = $a->add($y1)->multiply($b);
|
||||||
|
$y3 = $p1->add($p2);
|
||||||
|
|
||||||
|
return [$x3, $y3, $z3];
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = $z1->multiply($z1);
|
||||||
|
$d = $c->multiply($c);
|
||||||
|
$x3 = $b->add($this->b->multiply($d->multiply($d)));
|
||||||
|
$z3 = $x1->multiply($c);
|
||||||
|
$p1 = $b->multiply($z3);
|
||||||
|
$p2 = $a->add($y1->multiply($z1))->add($z3)->multiply($x3);
|
||||||
|
$y3 = $p1->add($p2);
|
||||||
|
|
||||||
|
return [$x3, $y3, $z3];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the X coordinate and the derived Y coordinate
|
||||||
|
*
|
||||||
|
* Not supported because it is covered by patents.
|
||||||
|
* Quoting https://www.openssl.org/docs/man1.1.0/apps/ecparam.html ,
|
||||||
|
*
|
||||||
|
* "Due to patent issues the compressed option is disabled by default for binary curves
|
||||||
|
* and can be enabled by defining the preprocessor macro OPENSSL_EC_BIN_PT_COMP at
|
||||||
|
* compile time."
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function derivePoint($m)
|
||||||
|
{
|
||||||
|
throw new \RuntimeException('Point compression on binary finite field elliptic curves is not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether or not the x / y values satisfy the equation
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function verifyPoint(array $p)
|
||||||
|
{
|
||||||
|
list($x, $y) = $p;
|
||||||
|
$lhs = $y->multiply($y);
|
||||||
|
$lhs = $lhs->add($x->multiply($y));
|
||||||
|
$x2 = $x->multiply($x);
|
||||||
|
$x3 = $x2->multiply($x);
|
||||||
|
$rhs = $x3->add($this->a->multiply($x2))->add($this->b);
|
||||||
|
|
||||||
|
return $lhs->equals($rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the modulo
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\BigInteger
|
||||||
|
*/
|
||||||
|
public function getModulo()
|
||||||
|
{
|
||||||
|
return $this->modulo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the a coefficient
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer
|
||||||
|
*/
|
||||||
|
public function getA()
|
||||||
|
{
|
||||||
|
return $this->a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the a coefficient
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer
|
||||||
|
*/
|
||||||
|
public function getB()
|
||||||
|
{
|
||||||
|
return $this->b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the affine point
|
||||||
|
*
|
||||||
|
* A Jacobian Coordinate is of the form (x, y, z).
|
||||||
|
* To convert a Jacobian Coordinate to an Affine Point
|
||||||
|
* you do (x / z^2, y / z^3)
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer[]
|
||||||
|
*/
|
||||||
|
public function convertToAffine(array $p)
|
||||||
|
{
|
||||||
|
if (!isset($p[2])) {
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
list($x, $y, $z) = $p;
|
||||||
|
$z = $this->one->divide($z);
|
||||||
|
$z2 = $z->multiply($z);
|
||||||
|
return [
|
||||||
|
$x->multiply($z2),
|
||||||
|
$y->multiply($z2)->multiply($z)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an affine point to a jacobian coordinate
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer[]
|
||||||
|
*/
|
||||||
|
public function convertToInternal(array $p)
|
||||||
|
{
|
||||||
|
if (isset($p[2])) {
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
$p[2] = clone $this->one;
|
||||||
|
$p['fresh'] = true;
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
}
|
324
phpseclib/Crypt/ECDSA/BaseCurves/KoblitzPrime.php
Normal file
324
phpseclib/Crypt/ECDSA/BaseCurves/KoblitzPrime.php
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generalized Koblitz Curves over y^2 = x^3 + b.
|
||||||
|
*
|
||||||
|
* According to http://www.secg.org/SEC2-Ver-1.0.pdf Koblitz curves are over the GF(2**m)
|
||||||
|
* finite field. Both the $a$ and $b$ coefficients are either 0 or 1. However, SEC2
|
||||||
|
* generalizes the definition to include curves over GF(P) "which possess an efficiently
|
||||||
|
* computable endomorphism".
|
||||||
|
*
|
||||||
|
* For these generalized Koblitz curves $b$ doesn't have to be 0 or 1. Whether or not $a$
|
||||||
|
* has any restrictions on it is unclear, however, for all the GF(P) Koblitz curves defined
|
||||||
|
* in SEC2 v1.0 $a$ is $0$ so all of the methods defined herein will assume that it is.
|
||||||
|
*
|
||||||
|
* I suppose we could rename the $b$ coefficient to $a$, however, the documentation refers
|
||||||
|
* to $b$ so we'll just keep it.
|
||||||
|
*
|
||||||
|
* If a later version of SEC2 comes out wherein some $a$ values are non-zero we can create a
|
||||||
|
* new method for those. eg. KoblitzA1Prime.php or something.
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\BaseCurves;
|
||||||
|
|
||||||
|
use phpseclib\Common\Functions\Strings;
|
||||||
|
use phpseclib\Math\PrimeField;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Math\PrimeField\Integer as PrimeInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curves over y^2 = x^3 + b
|
||||||
|
*
|
||||||
|
* @package KoblitzPrime
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
class KoblitzPrime extends Prime
|
||||||
|
{
|
||||||
|
// don't overwrite setCoefficients() with one that only accepts one parameter so that
|
||||||
|
// one might be able to switch between KoblitzPrime and Prime more easily (for benchmarking
|
||||||
|
// purposes).
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiply and Add Points
|
||||||
|
*
|
||||||
|
* Uses a efficiently computable endomorphism to achieve a slight speedup
|
||||||
|
*
|
||||||
|
* Adapted from https://git.io/vxbrP
|
||||||
|
*
|
||||||
|
* @return int[]
|
||||||
|
*/
|
||||||
|
public function multiplyAddPoints(array $points, array $scalars)
|
||||||
|
{
|
||||||
|
static $zero, $one, $two;
|
||||||
|
if (!isset($two)) {
|
||||||
|
$two = new BigInteger(2);
|
||||||
|
$one = new BigInteger(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->beta)) {
|
||||||
|
// get roots
|
||||||
|
$inv = $this->one->divide($this->two)->negate();
|
||||||
|
$s = $this->three->negate()->squareRoot()->multiply($inv);
|
||||||
|
$betas = [
|
||||||
|
$inv->add($s),
|
||||||
|
$inv->subtract($s)
|
||||||
|
];
|
||||||
|
$this->beta = $betas[0]->compare($betas[1]) < 0 ? $betas[0] : $betas[1];
|
||||||
|
//echo strtoupper($this->beta->toHex(true)) . "\n"; exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->basis)) {
|
||||||
|
$factory = new PrimeField($this->order);
|
||||||
|
$tempOne = $factory->newInteger($one);
|
||||||
|
$tempTwo = $factory->newInteger($two);
|
||||||
|
$tempThree = $factory->newInteger(new BigInteger(3));
|
||||||
|
|
||||||
|
$inv = $tempOne->divide($tempTwo)->negate();
|
||||||
|
$s = $tempThree->negate()->squareRoot()->multiply($inv);
|
||||||
|
|
||||||
|
$lambdas = [
|
||||||
|
$inv->add($s),
|
||||||
|
$inv->subtract($s)
|
||||||
|
];
|
||||||
|
|
||||||
|
$lhs = $this->multiplyPoint($this->p, $lambdas[0])[0];
|
||||||
|
$rhs = $this->p[0]->multiply($this->beta);
|
||||||
|
$lambda = $lhs->equals($rhs) ? $lambdas[0] : $lambdas[1];
|
||||||
|
|
||||||
|
$this->basis = static::extendedGCD($lambda->toBigInteger(), $this->order);
|
||||||
|
///*
|
||||||
|
foreach ($this->basis as $basis) {
|
||||||
|
echo strtoupper($basis['a']->toHex(true)) . "\n";
|
||||||
|
echo strtoupper($basis['b']->toHex(true)) . "\n\n";
|
||||||
|
}
|
||||||
|
exit;
|
||||||
|
//*/
|
||||||
|
}
|
||||||
|
|
||||||
|
$npoints = $nscalars = [];
|
||||||
|
for ($i = 0; $i < count($points); $i++) {
|
||||||
|
$p = $points[$i];
|
||||||
|
$k = $scalars[$i]->toBigInteger();
|
||||||
|
|
||||||
|
// begin split
|
||||||
|
list($v1, $v2) = $this->basis;
|
||||||
|
|
||||||
|
$c1 = $v2['b']->multiply($k);
|
||||||
|
list($c1, $r) = $c1->divide($this->order);
|
||||||
|
if ($this->order->compare($r->multiply($two)) <= 0) {
|
||||||
|
$c1 = $c1->add($one);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c2 = $v1['b']->negate()->multiply($k);
|
||||||
|
list($c2, $r) = $c2->divide($this->order);
|
||||||
|
if ($this->order->compare($r->multiply($two)) <= 0) {
|
||||||
|
$c2 = $c2->add($one);
|
||||||
|
}
|
||||||
|
|
||||||
|
$p1 = $c1->multiply($v1['a']);
|
||||||
|
$p2 = $c2->multiply($v2['a']);
|
||||||
|
$q1 = $c1->multiply($v1['b']);
|
||||||
|
$q2 = $c2->multiply($v2['b']);
|
||||||
|
|
||||||
|
$k1 = $k->subtract($p1)->subtract($p2);
|
||||||
|
$k2 = $q1->add($q2)->negate();
|
||||||
|
// end split
|
||||||
|
|
||||||
|
$beta = [
|
||||||
|
$p[0]->multiply($this->beta),
|
||||||
|
$p[1],
|
||||||
|
clone $this->one
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isset($p['naf'])) {
|
||||||
|
$beta['naf'] = array_map(function($p) {
|
||||||
|
return [
|
||||||
|
$p[0]->multiply($this->beta),
|
||||||
|
$p[1],
|
||||||
|
clone $this->one
|
||||||
|
];
|
||||||
|
}, $p['naf']);
|
||||||
|
$beta['nafwidth'] = $p['nafwidth'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($k1->isNegative()) {
|
||||||
|
$k1 = $k1->negate();
|
||||||
|
$p = $this->negatePoint($p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($k2->isNegative()) {
|
||||||
|
$k2 = $k2->negate();
|
||||||
|
$beta = $this->negatePoint($beta);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pos = 2 * $i;
|
||||||
|
$npoints[$pos] = $p;
|
||||||
|
$nscalars[$pos] = $this->factory->newInteger($k1);
|
||||||
|
|
||||||
|
$pos++;
|
||||||
|
$npoints[$pos] = $beta;
|
||||||
|
$nscalars[$pos] = $this->factory->newInteger($k2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::multiplyAddPoints($npoints, $nscalars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the numerator and denominator of the slope
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
protected function doublePointHelper(array $p)
|
||||||
|
{
|
||||||
|
$numerator = $this->three->multiply($p[0])->multiply($p[0]);
|
||||||
|
$denominator = $this->two->multiply($p[1]);
|
||||||
|
return [$numerator, $denominator];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doubles a jacobian coordinate on the curve
|
||||||
|
*
|
||||||
|
* See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
protected function jacobianDoublePoint(array $p)
|
||||||
|
{
|
||||||
|
list($x1, $y1, $z1) = $p;
|
||||||
|
$a = $x1->multiply($x1);
|
||||||
|
$b = $y1->multiply($y1);
|
||||||
|
$c = $b->multiply($b);
|
||||||
|
$d = $x1->add($b);
|
||||||
|
$d = $d->multiply($d)->subtract($a)->subtract($c)->multiply($this->two);
|
||||||
|
$e = $this->three->multiply($a);
|
||||||
|
$f = $e->multiply($e);
|
||||||
|
$x3 = $f->subtract($this->two->multiply($d));
|
||||||
|
$y3 = $e->multiply($d->subtract($x3))->subtract(
|
||||||
|
$this->eight->multiply($c));
|
||||||
|
$z3 = $this->two->multiply($y1)->multiply($z1);
|
||||||
|
return [$x3, $y3, $z3];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doubles a "fresh" jacobian coordinate on the curve
|
||||||
|
*
|
||||||
|
* See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
protected function jacobianDoublePointMixed(array $p)
|
||||||
|
{
|
||||||
|
list($x1, $y1) = $p;
|
||||||
|
$xx = $x1->multiply($x1);
|
||||||
|
$yy = $y1->multiply($y1);
|
||||||
|
$yyyy = $yy->multiply($yy);
|
||||||
|
$s = $x1->add($yy);
|
||||||
|
$s = $s->multiply($s)->subtract($xx)->subtract($yyyy)->multiply($this->two);
|
||||||
|
$m = $this->three->multiply($xx);
|
||||||
|
$t = $m->multiply($m)->subtract($this->two->multiply($s));
|
||||||
|
$x3 = $t;
|
||||||
|
$y3 = $s->subtract($t);
|
||||||
|
$y3 = $m->multiply($y3)->subtract($this->eight->multiply($yyyy));
|
||||||
|
$z3 = $this->two->multiply($y1);
|
||||||
|
return [$x3, $y3, $z3];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether or not the x / y values satisfy the equation
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function verifyPoint(array $p)
|
||||||
|
{
|
||||||
|
list($x, $y) = $p;
|
||||||
|
$lhs = $y->multiply($y);
|
||||||
|
$temp = $x->multiply($x)->multiply($x);
|
||||||
|
$rhs = $temp->add($this->b);
|
||||||
|
|
||||||
|
return $lhs->equals($rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the parameters needed from the Euclidean algorithm as discussed at
|
||||||
|
* http://diamond.boisestate.edu/~liljanab/MATH308/GuideToECC.pdf#page=148
|
||||||
|
*
|
||||||
|
* @param BigInteger $n
|
||||||
|
* @return BigInteger[]
|
||||||
|
*/
|
||||||
|
protected static function extendedGCD(BigInteger $u, BigInteger $v)
|
||||||
|
{
|
||||||
|
$one = new BigInteger(1);
|
||||||
|
$zero = new BigInteger();
|
||||||
|
|
||||||
|
$a = clone $one;
|
||||||
|
$b = clone $zero;
|
||||||
|
$c = clone $zero;
|
||||||
|
$d = clone $one;
|
||||||
|
|
||||||
|
$stop = $v->bitwise_rightShift($v->getLength() >> 1);
|
||||||
|
|
||||||
|
$a1 = clone $zero;
|
||||||
|
$b1 = clone $zero;
|
||||||
|
$a2 = clone $zero;
|
||||||
|
$b2 = clone $zero;
|
||||||
|
|
||||||
|
$postGreatestIndex = 0;
|
||||||
|
|
||||||
|
while (!$v->equals($zero)) {
|
||||||
|
list($q) = $u->divide($v);
|
||||||
|
|
||||||
|
$temp = $u;
|
||||||
|
$u = $v;
|
||||||
|
$v = $temp->subtract($v->multiply($q));
|
||||||
|
|
||||||
|
$temp = $a;
|
||||||
|
$a = $c;
|
||||||
|
$c = $temp->subtract($a->multiply($q));
|
||||||
|
|
||||||
|
$temp = $b;
|
||||||
|
$b = $d;
|
||||||
|
$d = $temp->subtract($b->multiply($q));
|
||||||
|
|
||||||
|
if ($v->compare($stop) > 0) {
|
||||||
|
$a0 = $v;
|
||||||
|
$b0 = $c;
|
||||||
|
} else {
|
||||||
|
$postGreatestIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($postGreatestIndex == 1) {
|
||||||
|
$a1 = $v;
|
||||||
|
$b1 = $c->negate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($postGreatestIndex == 2) {
|
||||||
|
$rhs = $a0->multiply($a0)->add($b0->multiply($b0));
|
||||||
|
$lhs = $v->multiply($v)->add($b->multiply($b));
|
||||||
|
if ($lhs->compare($rhs) <= 0) {
|
||||||
|
$a2 = $a0;
|
||||||
|
$b2 = $b0->negate();
|
||||||
|
} else {
|
||||||
|
$a2 = $v;
|
||||||
|
$b2 = $c->negate();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
['a' => $a1, 'b' => $b1],
|
||||||
|
['a' => $a2, 'b' => $b2]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
774
phpseclib/Crypt/ECDSA/BaseCurves/Prime.php
Normal file
774
phpseclib/Crypt/ECDSA/BaseCurves/Prime.php
Normal file
@ -0,0 +1,774 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curves over y^2 = x^3 + a*x + b
|
||||||
|
*
|
||||||
|
* These are curves used in SEC 2 over prime fields: http://www.secg.org/SEC2-Ver-1.0.pdf
|
||||||
|
* The curve is a weierstrass curve with a[1], a[3] and a[2] set to 0.
|
||||||
|
*
|
||||||
|
* Uses Jacobian Coordinates for speed if able:
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Jacobian_curve
|
||||||
|
* https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\BaseCurves;
|
||||||
|
|
||||||
|
use phpseclib\Math\Common\FiniteField\Integer;
|
||||||
|
use phpseclib\Common\Functions\Strings;
|
||||||
|
use phpseclib\Math\PrimeField;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Math\PrimeField\Integer as PrimeInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curves over y^2 = x^3 + a*x + b
|
||||||
|
*
|
||||||
|
* @package Prime
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
class Prime extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Prime Field Integer factory
|
||||||
|
*
|
||||||
|
* @var \phpseclib\Math\PrimeFields
|
||||||
|
*/
|
||||||
|
protected $factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cofficient for x^1
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $a;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cofficient for x^0
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $b;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base Point
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $p;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number one over the specified finite field
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $one;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number two over the specified finite field
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $two;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number three over the specified finite field
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $three;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number four over the specified finite field
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $four;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number eight over the specified finite field
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $eight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The modulo
|
||||||
|
*
|
||||||
|
* @var BigInteger
|
||||||
|
*/
|
||||||
|
protected $modulo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Order
|
||||||
|
*
|
||||||
|
* @var BigInteger
|
||||||
|
*/
|
||||||
|
protected $order;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the modulo
|
||||||
|
*/
|
||||||
|
public function setModulo(BigInteger $modulo)
|
||||||
|
{
|
||||||
|
$this->modulo = $modulo;
|
||||||
|
$this->factory = new PrimeField($modulo);
|
||||||
|
$this->two = $this->factory->newInteger(new BigInteger(2));
|
||||||
|
$this->three = $this->factory->newInteger(new BigInteger(3));
|
||||||
|
// used by jacobian coordinates
|
||||||
|
$this->one = $this->factory->newInteger(new BigInteger(1));
|
||||||
|
$this->four = $this->factory->newInteger(new BigInteger(4));
|
||||||
|
$this->eight = $this->factory->newInteger(new BigInteger(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set coefficients a and b
|
||||||
|
*/
|
||||||
|
public function setCoefficients(BigInteger $a, BigInteger $b)
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
$this->a = $this->factory->newInteger($a);
|
||||||
|
$this->b = $this->factory->newInteger($b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set x and y coordinates for the base point
|
||||||
|
*
|
||||||
|
* @param BigInteger|PrimeInteger $x
|
||||||
|
* @param BigInteger|PrimeInteger $y
|
||||||
|
* @return PrimeInteger[]
|
||||||
|
*/
|
||||||
|
public function setBasePoint($x, $y)
|
||||||
|
{
|
||||||
|
switch (true) {
|
||||||
|
case !$x instanceof BigInteger && !$x instanceof PrimeInteger:
|
||||||
|
throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer');
|
||||||
|
case !$y instanceof BigInteger && !$y instanceof PrimeInteger:
|
||||||
|
throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer');
|
||||||
|
}
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
$this->p = [
|
||||||
|
$x instanceof BigInteger ? $this->factory->newInteger($x) : $x,
|
||||||
|
$y instanceof BigInteger ? $this->factory->newInteger($y) : $y
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the base point as an array
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getBasePoint()
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (!isset($this->p)) {
|
||||||
|
throw new \RuntimeException('setBasePoint needs to be called before this method');
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return $this->p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds two "fresh" jacobian form on the curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
protected function jacobianAddPointMixedXY(array $p, array $q)
|
||||||
|
{
|
||||||
|
list($u1, $s1) = $p;
|
||||||
|
list($u2, $s2) = $q;
|
||||||
|
if ($u1->equals($u2)) {
|
||||||
|
if (!$s1->equals($s2)) {
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
return $this->doublePoint($p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$h = $u2->subtract($u1);
|
||||||
|
$r = $s2->subtract($s1);
|
||||||
|
$h2 = $h->multiply($h);
|
||||||
|
$h3 = $h2->multiply($h);
|
||||||
|
$v = $u1->multiply($h2);
|
||||||
|
$x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two));
|
||||||
|
$y3 = $r->multiply(
|
||||||
|
$v->subtract($x3))->subtract(
|
||||||
|
$s1->multiply($h3));
|
||||||
|
return [$x3, $y3, $h];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds one "fresh" jacobian form on the curve
|
||||||
|
*
|
||||||
|
* The second parameter should be the "fresh" one
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
protected function jacobianAddPointMixedX(array $p, array $q)
|
||||||
|
{
|
||||||
|
list($u1, $s1, $z1) = $p;
|
||||||
|
list($x2, $y2) = $q;
|
||||||
|
|
||||||
|
$z12 = $z1->multiply($z1);
|
||||||
|
|
||||||
|
$u2 = $x2->multiply($z12);
|
||||||
|
$s2 = $y2->multiply($z12->multiply($z1));
|
||||||
|
if ($u1->equals($u2)) {
|
||||||
|
if (!$s1->equals($s2)) {
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
return $this->doublePoint($p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$h = $u2->subtract($u1);
|
||||||
|
$r = $s2->subtract($s1);
|
||||||
|
$h2 = $h->multiply($h);
|
||||||
|
$h3 = $h2->multiply($h);
|
||||||
|
$v = $u1->multiply($h2);
|
||||||
|
$x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two));
|
||||||
|
$y3 = $r->multiply(
|
||||||
|
$v->subtract($x3))->subtract(
|
||||||
|
$s1->multiply($h3));
|
||||||
|
$z3 = $h->multiply($z1);
|
||||||
|
return [$x3, $y3, $z3];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds two jacobian coordinates on the curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
protected function jacobianAddPoint(array $p, array $q)
|
||||||
|
{
|
||||||
|
list($x1, $y1, $z1) = $p;
|
||||||
|
list($x2, $y2, $z2) = $q;
|
||||||
|
|
||||||
|
$z12 = $z1->multiply($z1);
|
||||||
|
$z22 = $z2->multiply($z2);
|
||||||
|
|
||||||
|
$u1 = $x1->multiply($z22);
|
||||||
|
$u2 = $x2->multiply($z12);
|
||||||
|
$s1 = $y1->multiply($z22->multiply($z2));
|
||||||
|
$s2 = $y2->multiply($z12->multiply($z1));
|
||||||
|
if ($u1->equals($u2)) {
|
||||||
|
if (!$s1->equals($s2)) {
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
return $this->doublePoint($p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$h = $u2->subtract($u1);
|
||||||
|
$r = $s2->subtract($s1);
|
||||||
|
$h2 = $h->multiply($h);
|
||||||
|
$h3 = $h2->multiply($h);
|
||||||
|
$v = $u1->multiply($h2);
|
||||||
|
$x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two));
|
||||||
|
$y3 = $r->multiply(
|
||||||
|
$v->subtract($x3))->subtract(
|
||||||
|
$s1->multiply($h3));
|
||||||
|
$z3 = $h->multiply($z1)->multiply($z2);
|
||||||
|
return [$x3, $y3, $z3];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds two points on the curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
public function addPoint(array $p, array $q)
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count($p) || !count($q)) {
|
||||||
|
if (count($q)) {
|
||||||
|
return $q;
|
||||||
|
}
|
||||||
|
if (count($p)) {
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// use jacobian coordinates
|
||||||
|
if (isset($p[2]) && isset($q[2])) {
|
||||||
|
if (isset($p['fresh']) && isset($q['fresh'])) {
|
||||||
|
return $this->jacobianAddPointMixedXY($p, $q);
|
||||||
|
}
|
||||||
|
if (isset($p['fresh'])) {
|
||||||
|
return $this->jacobianAddPointMixedX($q, $p);
|
||||||
|
}
|
||||||
|
if (isset($q['fresh'])) {
|
||||||
|
return $this->jacobianAddPointMixedX($p, $q);
|
||||||
|
}
|
||||||
|
return $this->jacobianAddPoint($p, $q);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($p[2]) || isset($q[2])) {
|
||||||
|
throw new \RuntimeException('Affine coordinates need to be manually converted to Jacobi coordinates or vice versa');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($p[0]->equals($q[0])) {
|
||||||
|
if (!$p[1]->equals($q[1])) {
|
||||||
|
return [];
|
||||||
|
} else { // eg. doublePoint
|
||||||
|
list($numerator, $denominator) = $this->doublePointHelper($p);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$numerator = $q[1]->subtract($p[1]);
|
||||||
|
$denominator = $q[0]->subtract($p[0]);
|
||||||
|
}
|
||||||
|
$slope = $numerator->divide($denominator);
|
||||||
|
$x = $slope->multiply($slope)->subtract($p[0])->subtract($q[0]);
|
||||||
|
$y = $slope->multiply($p[0]->subtract($x))->subtract($p[1]);
|
||||||
|
|
||||||
|
return [$x, $y];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the numerator and denominator of the slope
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
protected function doublePointHelper(array $p)
|
||||||
|
{
|
||||||
|
$numerator = $this->three->multiply($p[0])->multiply($p[0])->add($this->a);
|
||||||
|
$denominator = $this->two->multiply($p[1]);
|
||||||
|
return [$numerator, $denominator];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doubles a jacobian coordinate on the curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
protected function jacobianDoublePoint(array $p)
|
||||||
|
{
|
||||||
|
list($x, $y, $z) = $p;
|
||||||
|
$x2 = $x->multiply($x);
|
||||||
|
$y2 = $y->multiply($y);
|
||||||
|
$z2 = $z->multiply($z);
|
||||||
|
$s = $this->four->multiply($x)->multiply($y2);
|
||||||
|
$m1 = $this->three->multiply($x2);
|
||||||
|
$m2 = $this->a->multiply($z2->multiply($z2));
|
||||||
|
$m = $m1->add($m2);
|
||||||
|
$x1 = $m->multiply($m)->subtract($this->two->multiply($s));
|
||||||
|
$y1 = $m->multiply($s->subtract($x1))->subtract(
|
||||||
|
$this->eight->multiply($y2->multiply($y2)));
|
||||||
|
$z1 = $this->two->multiply($y)->multiply($z);
|
||||||
|
return [$x1, $y1, $z1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doubles a "fresh" jacobian coordinate on the curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
protected function jacobianDoublePointMixed(array $p)
|
||||||
|
{
|
||||||
|
list($x, $y) = $p;
|
||||||
|
$x2 = $x->multiply($x);
|
||||||
|
$y2 = $y->multiply($y);
|
||||||
|
$s = $this->four->multiply($x)->multiply($y2);
|
||||||
|
$m1 = $this->three->multiply($x2);
|
||||||
|
$m = $m1->add($this->a);
|
||||||
|
$x1 = $m->multiply($m)->subtract($this->two->multiply($s));
|
||||||
|
$y1 = $m->multiply($s->subtract($x1))->subtract(
|
||||||
|
$this->eight->multiply($y2->multiply($y2)));
|
||||||
|
$z1 = $this->two->multiply($y);
|
||||||
|
return [$x1, $y1, $z1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doubles a point on a curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
public function doublePoint(array $p)
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count($p)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// use jacobian coordinates
|
||||||
|
if (isset($p[2])) {
|
||||||
|
if (isset($p['fresh'])) {
|
||||||
|
return $this->jacobianDoublePointMixed($p);
|
||||||
|
}
|
||||||
|
return $this->jacobianDoublePoint($p);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($numerator, $denominator) = $this->doublePointHelper($p);
|
||||||
|
|
||||||
|
$slope = $numerator->divide($denominator);
|
||||||
|
|
||||||
|
$x = $slope->multiply($slope)->subtract($p[0])->subtract($p[0]);
|
||||||
|
$y = $slope->multiply($p[0]->subtract($x))->subtract($p[1]);
|
||||||
|
|
||||||
|
return [$x, $y];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the X coordinate and the derived Y coordinate
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function derivePoint($m)
|
||||||
|
{
|
||||||
|
$y = ord(Strings::shift($m));
|
||||||
|
$x = new BigInteger($m, 256);
|
||||||
|
$xp = $this->convertInteger($x);
|
||||||
|
switch ($y) {
|
||||||
|
case 2: $ypn = false; break;
|
||||||
|
case 3: $ypn = true; break;
|
||||||
|
default:
|
||||||
|
throw new \RuntimeException('Coordinate not in recognized format');
|
||||||
|
}
|
||||||
|
$temp = $xp->multiply($this->a);
|
||||||
|
$temp = $xp->multiply($xp)->multiply($xp)->add($temp);
|
||||||
|
$temp = $temp->add($this->b);
|
||||||
|
$b = $temp->squareRoot();
|
||||||
|
if (!$b) {
|
||||||
|
throw new \RuntimeException('Unable to derive Y coordinate');
|
||||||
|
}
|
||||||
|
$bn = $b->isOdd();
|
||||||
|
$yp = $ypn == $bn ? $b : $b->negate();
|
||||||
|
return [$xp, $yp];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether or not the x / y values satisfy the equation
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function verifyPoint(array $p)
|
||||||
|
{
|
||||||
|
list($x, $y) = $p;
|
||||||
|
$lhs = $y->multiply($y);
|
||||||
|
$temp = $x->multiply($this->a);
|
||||||
|
$temp = $x->multiply($x)->multiply($x)->add($temp);
|
||||||
|
$rhs = $temp->add($this->b);
|
||||||
|
|
||||||
|
return $lhs->equals($rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the modulo
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\BigInteger
|
||||||
|
*/
|
||||||
|
public function getModulo()
|
||||||
|
{
|
||||||
|
return $this->modulo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the a coefficient
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer
|
||||||
|
*/
|
||||||
|
public function getA()
|
||||||
|
{
|
||||||
|
return $this->a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the a coefficient
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer
|
||||||
|
*/
|
||||||
|
public function getB()
|
||||||
|
{
|
||||||
|
return $this->b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiply and Add Points
|
||||||
|
*
|
||||||
|
* Adapted from https://git.io/vxPUH
|
||||||
|
*
|
||||||
|
* @return int[]
|
||||||
|
*/
|
||||||
|
public function multiplyAddPoints(array $points, array $scalars)
|
||||||
|
{
|
||||||
|
$length = count($points);
|
||||||
|
|
||||||
|
foreach ($points as &$point) {
|
||||||
|
$point = $this->convertToInternal($point);
|
||||||
|
}
|
||||||
|
|
||||||
|
$wnd = [$this->getNAFPoints($points[0], 7)];
|
||||||
|
$wndWidth = [isset($points[0]['nafwidth']) ? $points[0]['nafwidth'] : 7];
|
||||||
|
for ($i = 1; $i < $length; $i++) {
|
||||||
|
$wnd[] = $this->getNAFPoints($points[$i], 1);
|
||||||
|
$wndWidth[] = isset($points[$i]['nafwidth']) ? $points[$i]['nafwidth'] : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$naf = [];
|
||||||
|
|
||||||
|
// comb all window NAFs
|
||||||
|
|
||||||
|
$max = 0;
|
||||||
|
for ($i = $length - 1; $i >= 1; $i-= 2) {
|
||||||
|
$a = $i - 1;
|
||||||
|
$b = $i;
|
||||||
|
if ($wndWidth[$a] != 1 || $wndWidth[$b] != 1) {
|
||||||
|
$naf[$a] = $scalars[$a]->getNAF($wndWidth[$a]);
|
||||||
|
$naf[$b] = $scalars[$b]->getNAF($wndWidth[$b]);
|
||||||
|
$max = max(count($naf[$a]), count($naf[$b]), $max);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$comb = [
|
||||||
|
$points[$a], // 1
|
||||||
|
null, // 3
|
||||||
|
null, // 5
|
||||||
|
$points[$b] // 7
|
||||||
|
];
|
||||||
|
|
||||||
|
$comb[1] = $this->addPoint($points[$a], $points[$b]);
|
||||||
|
$comb[2] = $this->addPoint($points[$a], $this->negatePoint($points[$b]));
|
||||||
|
|
||||||
|
$index = [
|
||||||
|
-3, /* -1 -1 */
|
||||||
|
-1, /* -1 0 */
|
||||||
|
-5, /* -1 1 */
|
||||||
|
-7, /* 0 -1 */
|
||||||
|
0, /* 0 -1 */
|
||||||
|
7, /* 0 1 */
|
||||||
|
5, /* 1 -1 */
|
||||||
|
1, /* 1 0 */
|
||||||
|
3 /* 1 1 */
|
||||||
|
];
|
||||||
|
|
||||||
|
$jsf = self::getJSFPoints($scalars[$a], $scalars[$b]);
|
||||||
|
|
||||||
|
$max = max(count($jsf[0]), $max);
|
||||||
|
if ($max > 0) {
|
||||||
|
$naf[$a] = array_fill(0, $max, 0);
|
||||||
|
$naf[$b] = array_fill(0, $max, 0);
|
||||||
|
} else {
|
||||||
|
$naf[$a] = [];
|
||||||
|
$naf[$b] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($j = 0; $j < $max; $j++) {
|
||||||
|
$ja = isset($jsf[0][$j]) ? $jsf[0][$j] : 0;
|
||||||
|
$jb = isset($jsf[1][$j]) ? $jsf[1][$j] : 0;
|
||||||
|
|
||||||
|
$naf[$a][$j] = $index[3 * ($ja + 1) + $jb + 1];
|
||||||
|
$naf[$b][$j] = 0;
|
||||||
|
$wnd[$a] = $comb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$acc = [];
|
||||||
|
$temp = [0, 0, 0, 0];
|
||||||
|
for ($i = $max; $i >= 0; $i--) {
|
||||||
|
$k = 0;
|
||||||
|
while ($i >= 0) {
|
||||||
|
$zero = true;
|
||||||
|
for ($j = 0; $j < $length; $j++) {
|
||||||
|
$temp[$j] = isset($naf[$j][$i]) ? $naf[$j][$i] : 0;
|
||||||
|
if ($temp[$j] != 0) {
|
||||||
|
$zero = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$zero) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$k++;
|
||||||
|
$i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($i >= 0) {
|
||||||
|
$k++;
|
||||||
|
}
|
||||||
|
while ($k--) {
|
||||||
|
$acc = $this->doublePoint($acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($i < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($j = 0; $j < $length; $j++) {
|
||||||
|
$z = $temp[$j];
|
||||||
|
$p = null;
|
||||||
|
if ($z == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$p = $z > 0 ?
|
||||||
|
$wnd[$j][($z - 1) >> 1] :
|
||||||
|
$this->negatePoint($wnd[$j][(-$z - 1) >> 1]);
|
||||||
|
$acc = $this->addPoint($acc, $p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->convertToAffine($acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Precomputes NAF points
|
||||||
|
*
|
||||||
|
* Adapted from https://git.io/vxY1f
|
||||||
|
*
|
||||||
|
* @return int[]
|
||||||
|
*/
|
||||||
|
private function getNAFPoints($point, $wnd)
|
||||||
|
{
|
||||||
|
if (isset($point['naf'])) {
|
||||||
|
return $point['naf'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = [$point];
|
||||||
|
$max = (1 << $wnd) - 1;
|
||||||
|
$dbl = $max == 1 ? null : $this->doublePoint($point);
|
||||||
|
for ($i = 1; $i < $max; $i++) {
|
||||||
|
$res[] = $this->addPoint($res[$i - 1], $dbl);
|
||||||
|
}
|
||||||
|
|
||||||
|
$point['naf'] = $res;
|
||||||
|
|
||||||
|
/*
|
||||||
|
$str = '';
|
||||||
|
foreach ($res as $re) {
|
||||||
|
$re[0] = bin2hex($re[0]->toBytes());
|
||||||
|
$re[1] = bin2hex($re[1]->toBytes());
|
||||||
|
$str.= " ['$re[0]', '$re[1]'],\r\n";
|
||||||
|
}
|
||||||
|
file_put_contents('temp.txt', $str);
|
||||||
|
exit;
|
||||||
|
*/
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Precomputes points in Joint Sparse Form
|
||||||
|
*
|
||||||
|
* Adapted from https://git.io/vxrpD
|
||||||
|
*
|
||||||
|
* @return int[]
|
||||||
|
*/
|
||||||
|
private static function getJSFPoints(Integer $k1, Integer $k2)
|
||||||
|
{
|
||||||
|
static $three;
|
||||||
|
if (!isset($three)) {
|
||||||
|
$three = new BigInteger(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
$jsf = [[], []];
|
||||||
|
$k1 = $k1->toBigInteger();
|
||||||
|
$k2 = $k2->toBigInteger();
|
||||||
|
$d1 = 0;
|
||||||
|
$d2 = 0;
|
||||||
|
|
||||||
|
while ($k1->compare(new BigInteger(-$d1)) > 0 || $k2->compare(new BigInteger(-$d2)) > 0) {
|
||||||
|
// first phase
|
||||||
|
$m14 = $k1->testBit(0) + 2 * $k1->testBit(1);
|
||||||
|
$m14+= $d1;
|
||||||
|
$m14&= 3;
|
||||||
|
|
||||||
|
$m24 = $k2->testBit(0) + 2 * $k2->testBit(1);
|
||||||
|
$m24+= $d2;
|
||||||
|
$m24&= 3;
|
||||||
|
|
||||||
|
if ($m14 == 3) {
|
||||||
|
$m14 = -1;
|
||||||
|
}
|
||||||
|
if ($m24 == 3) {
|
||||||
|
$m24 = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$u1 = 0;
|
||||||
|
if ($m14 & 1) { // if $m14 is odd
|
||||||
|
$m8 = $k1->testBit(0) + 2 * $k1->testBit(1) + 4 * $k1->testBit(2);
|
||||||
|
$m8+= $d1;
|
||||||
|
$m8&= 7;
|
||||||
|
$u1 = ($m8 == 3 || $m8 == 5) && $m24 == 2 ? -$m14 : $m14;
|
||||||
|
}
|
||||||
|
$jsf[0][] = $u1;
|
||||||
|
|
||||||
|
$u2 = 0;
|
||||||
|
if ($m24 & 1) { // if $m24 is odd
|
||||||
|
$m8 = $k2->testBit(0) + 2 * $k2->testBit(1) + 4 * $k2->testBit(2);
|
||||||
|
$m8+= $d2;
|
||||||
|
$m8&= 7;
|
||||||
|
$u2 = ($m8 == 3 || $m8 == 5) && $m14 == 2 ? -$m24 : $m24;
|
||||||
|
}
|
||||||
|
$jsf[1][] = $u2;
|
||||||
|
|
||||||
|
// second phase
|
||||||
|
if (2 * $d1 == $u1 + 1) {
|
||||||
|
$d1 = 1 - $d1;
|
||||||
|
}
|
||||||
|
if (2 * $d2 == $u2 + 1) {
|
||||||
|
$d2 = 1 - $d2;
|
||||||
|
}
|
||||||
|
$k1 = $k1->bitwise_rightShift(1);
|
||||||
|
$k2 = $k2->bitwise_rightShift(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $jsf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the affine point
|
||||||
|
*
|
||||||
|
* A Jacobian Coordinate is of the form (x, y, z).
|
||||||
|
* To convert a Jacobian Coordinate to an Affine Point
|
||||||
|
* you do (x / z^2, y / z^3)
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer[]
|
||||||
|
*/
|
||||||
|
public function convertToAffine(array $p)
|
||||||
|
{
|
||||||
|
if (!isset($p[2])) {
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
list($x, $y, $z) = $p;
|
||||||
|
$z = $this->one->divide($z);
|
||||||
|
$z2 = $z->multiply($z);
|
||||||
|
return [
|
||||||
|
$x->multiply($z2),
|
||||||
|
$y->multiply($z2)->multiply($z)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an affine point to a jacobian coordinate
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer[]
|
||||||
|
*/
|
||||||
|
public function convertToInternal(array $p)
|
||||||
|
{
|
||||||
|
if (isset($p[2])) {
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
$p[2] = clone $this->one;
|
||||||
|
$p['fresh'] = true;
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
}
|
236
phpseclib/Crypt/ECDSA/BaseCurves/TwistedEdwards.php
Normal file
236
phpseclib/Crypt/ECDSA/BaseCurves/TwistedEdwards.php
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curves over a*x^2 + y^2 = 1 + d*x^2*y^2
|
||||||
|
*
|
||||||
|
* http://www.secg.org/SEC2-Ver-1.0.pdf provides for curves with custom parameters.
|
||||||
|
* ie. the coefficients can be arbitrary set through specially formatted keys, etc.
|
||||||
|
* As such, Prime.php is built very generically and it's not able to take full
|
||||||
|
* advantage of curves with 0 coefficients to produce simplified point doubling,
|
||||||
|
* point addition. Twisted Edwards curves, in contrast, do not have a way, currently,
|
||||||
|
* to customize them. As such, we can omit the super generic stuff from this class
|
||||||
|
* and let the named curves (Ed25519 and Ed448) define their own custom tailored
|
||||||
|
* point addition and point doubling methods.
|
||||||
|
*
|
||||||
|
* More info:
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Twisted_Edwards_curve
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\BaseCurves;
|
||||||
|
|
||||||
|
use phpseclib\Math\PrimeField;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Math\PrimeField\Integer as PrimeInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curves over a*x^2 + y^2 = 1 + d*x^2*y^2
|
||||||
|
*
|
||||||
|
* @package Prime
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
class TwistedEdwards extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The modulo
|
||||||
|
*
|
||||||
|
* @var BigInteger
|
||||||
|
*/
|
||||||
|
protected $modulo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cofficient for x^2
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $a;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cofficient for x^2*y^2
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $d;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base Point
|
||||||
|
*
|
||||||
|
* @var object[]
|
||||||
|
*/
|
||||||
|
protected $p;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number zero over the specified finite field
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $zero;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number one over the specified finite field
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $one;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number two over the specified finite field
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
protected $two;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the modulo
|
||||||
|
*/
|
||||||
|
public function setModulo(BigInteger $modulo)
|
||||||
|
{
|
||||||
|
$this->modulo = $modulo;
|
||||||
|
$this->factory = new PrimeField($modulo);
|
||||||
|
$this->zero = $this->factory->newInteger(new BigInteger(0));
|
||||||
|
$this->one = $this->factory->newInteger(new BigInteger(1));
|
||||||
|
$this->two = $this->factory->newInteger(new BigInteger(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set coefficients a and b
|
||||||
|
*/
|
||||||
|
public function setCoefficients(BigInteger $a, BigInteger $d)
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
$this->a = $this->factory->newInteger($a);
|
||||||
|
$this->d = $this->factory->newInteger($d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set x and y coordinates for the base point
|
||||||
|
*/
|
||||||
|
public function setBasePoint($x, $y)
|
||||||
|
{
|
||||||
|
switch (true) {
|
||||||
|
case !$x instanceof BigInteger && !$x instanceof PrimeInteger:
|
||||||
|
throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer');
|
||||||
|
case !$y instanceof BigInteger && !$y instanceof PrimeInteger:
|
||||||
|
throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer');
|
||||||
|
}
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
$this->p = [
|
||||||
|
$x instanceof BigInteger ? $this->factory->newInteger($x) : $x,
|
||||||
|
$y instanceof BigInteger ? $this->factory->newInteger($y) : $y
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the a coefficient
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer
|
||||||
|
*/
|
||||||
|
public function getA()
|
||||||
|
{
|
||||||
|
return $this->a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the a coefficient
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer
|
||||||
|
*/
|
||||||
|
public function getD()
|
||||||
|
{
|
||||||
|
return $this->d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the base point as an array
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getBasePoint()
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (!isset($this->p)) {
|
||||||
|
throw new \RuntimeException('setBasePoint needs to be called before this method');
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return $this->p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the affine point
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer[]
|
||||||
|
*/
|
||||||
|
public function convertToAffine(array $p)
|
||||||
|
{
|
||||||
|
if (!isset($p[2])) {
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
list($x, $y, $z) = $p;
|
||||||
|
$z = $this->one->divide($z);
|
||||||
|
return [
|
||||||
|
$x->multiply($z),
|
||||||
|
$y->multiply($z)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the modulo
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\BigInteger
|
||||||
|
*/
|
||||||
|
public function getModulo()
|
||||||
|
{
|
||||||
|
return $this->modulo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether or not the x / y values satisfy the equation
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function verifyPoint(array $p)
|
||||||
|
{
|
||||||
|
list($x, $y) = $p;
|
||||||
|
$x2 = $x->multiply($x);
|
||||||
|
$y2 = $y->multiply($y);
|
||||||
|
|
||||||
|
$lhs = $this->a->multiply($x2)->add($y2);
|
||||||
|
$rhs = $this->d->multiply($x2)->multiply($y2)->add($this->one);
|
||||||
|
|
||||||
|
return $lhs->equals($rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether or not the x / y values satisfy the equation
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function get(array $p)
|
||||||
|
{
|
||||||
|
list($x, $y) = $p;
|
||||||
|
$x2 = $x->multiply($x);
|
||||||
|
$y2 = $y->multiply($y);
|
||||||
|
|
||||||
|
$lhs = $this->a->multiply($x2)->add($y2);
|
||||||
|
$rhs = $this->d->multiply($x2)->multiply($y2)->add($this->one);
|
||||||
|
|
||||||
|
return $lhs->equals($rhs);
|
||||||
|
}
|
||||||
|
}
|
334
phpseclib/Crypt/ECDSA/Curves/Ed25519.php
Normal file
334
phpseclib/Crypt/ECDSA/Curves/Ed25519.php
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ed25519
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\TwistedEdwards;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Crypt\Hash;
|
||||||
|
use phpseclib\Crypt\Random;
|
||||||
|
|
||||||
|
class Ed25519 extends TwistedEdwards
|
||||||
|
{
|
||||||
|
const HASH = 'sha512';
|
||||||
|
/*
|
||||||
|
Per https://tools.ietf.org/html/rfc8032#page-6 EdDSA has several parameters, one of which is b:
|
||||||
|
|
||||||
|
2. An integer b with 2^(b-1) > p. EdDSA public keys have exactly b
|
||||||
|
bits, and EdDSA signatures have exactly 2*b bits. b is
|
||||||
|
recommended to be a multiple of 8, so public key and signature
|
||||||
|
lengths are an integral number of octets.
|
||||||
|
|
||||||
|
SIZE corresponds to b
|
||||||
|
*/
|
||||||
|
const SIZE = 32;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// 2^255 - 19
|
||||||
|
$this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
// -1
|
||||||
|
new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC', 16), // a
|
||||||
|
// -121665/121666
|
||||||
|
new BigInteger('52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3', 16) // d
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A', 16),
|
||||||
|
new BigInteger('6666666666666666666666666666666666666666666666666666666666666658', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED', 16));
|
||||||
|
// algorithm 14.47 from http://cacr.uwaterloo.ca/hac/about/chap14.pdf#page=16
|
||||||
|
/*
|
||||||
|
$this->setReduction(function($x) {
|
||||||
|
$parts = $x->bitwise_split(255);
|
||||||
|
$className = $this->className;
|
||||||
|
|
||||||
|
if (count($parts) > 2) {
|
||||||
|
list(, $r) = $x->divide($className::$modulo);
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
$zero = new BigInteger();
|
||||||
|
$c = new BigInteger(19);
|
||||||
|
|
||||||
|
switch (count($parts)) {
|
||||||
|
case 2:
|
||||||
|
list($qi, $ri) = $parts;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
$qi = $zero;
|
||||||
|
list($ri) = $parts;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
return $zero;
|
||||||
|
}
|
||||||
|
$r = $ri;
|
||||||
|
|
||||||
|
while ($qi->compare($zero) > 0) {
|
||||||
|
$temp = $qi->multiply($c)->bitwise_split(255);
|
||||||
|
if (count($temp) == 2) {
|
||||||
|
list($qi, $ri) = $temp;
|
||||||
|
} else {
|
||||||
|
$qi = $zero;
|
||||||
|
list($ri) = $temp;
|
||||||
|
}
|
||||||
|
$r = $r->add($ri);
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($r->compare($className::$modulo) > 0) {
|
||||||
|
$r = $r->subtract($className::$modulo);
|
||||||
|
}
|
||||||
|
return $r;
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recover X from Y
|
||||||
|
*
|
||||||
|
* Implements steps 2-4 at https://tools.ietf.org/html/rfc8032#section-5.1.3
|
||||||
|
*
|
||||||
|
* Used by ECDSA\Keys\Common.php
|
||||||
|
*
|
||||||
|
* @param BigInteger $x
|
||||||
|
* @param boolean $sign
|
||||||
|
* @return object[]
|
||||||
|
*/
|
||||||
|
public function recoverX(BigInteger $y, $sign)
|
||||||
|
{
|
||||||
|
$y = $this->factory->newInteger($y);
|
||||||
|
|
||||||
|
$y2 = $y->multiply($y);
|
||||||
|
$u = $y2->subtract($this->one);
|
||||||
|
$v = $this->d->multiply($y2)->add($this->one);
|
||||||
|
$x2 = $u->divide($v);
|
||||||
|
if ($x2->equals($this->zero)) {
|
||||||
|
if ($sign) {
|
||||||
|
throw new \RuntimeException('Unable to recover X coordinate (x2 = 0)');
|
||||||
|
}
|
||||||
|
return clone $this->zero;
|
||||||
|
}
|
||||||
|
// find the square root
|
||||||
|
/* we don't do $x2->squareRoot() because, quoting from
|
||||||
|
https://tools.ietf.org/html/rfc8032#section-5.1.1:
|
||||||
|
|
||||||
|
"For point decoding or "decompression", square roots modulo p are
|
||||||
|
needed. They can be computed using the Tonelli-Shanks algorithm or
|
||||||
|
the special case for p = 5 (mod 8). To find a square root of a,
|
||||||
|
first compute the candidate root x = a^((p+3)/8) (mod p)."
|
||||||
|
*/
|
||||||
|
$exp = $this->getModulo()->add(new BigInteger(3));
|
||||||
|
$exp = $exp->bitwise_rightShift(3);
|
||||||
|
$x = $x2->pow($exp);
|
||||||
|
|
||||||
|
// If v x^2 = -u (mod p), set x <-- x * 2^((p-1)/4), which is a square root.
|
||||||
|
if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) {
|
||||||
|
$temp = $this->getModulo()->subtract(new BigInteger(1));
|
||||||
|
$temp = $temp->bitwise_rightShift(2);
|
||||||
|
$temp = $this->two->pow($temp);
|
||||||
|
$x = $x->multiply($temp);
|
||||||
|
if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) {
|
||||||
|
throw new \RuntimeException('Unable to recover X coordinate');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($x->isOdd() != $sign) {
|
||||||
|
$x = $x->negate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$x, $y];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract Secret Scalar
|
||||||
|
*
|
||||||
|
* Implements steps 1-3 at https://tools.ietf.org/html/rfc8032#section-5.1.5
|
||||||
|
*
|
||||||
|
* Used by the various key handlers
|
||||||
|
*
|
||||||
|
* @param string $str
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer
|
||||||
|
*/
|
||||||
|
public function extractSecret($str)
|
||||||
|
{
|
||||||
|
if (strlen($str) != 32) {
|
||||||
|
throw new \LengthException('Private Key should be 32-bytes long');
|
||||||
|
}
|
||||||
|
// 1. Hash the 32-byte private key using SHA-512, storing the digest in
|
||||||
|
// a 64-octet large buffer, denoted h. Only the lower 32 bytes are
|
||||||
|
// used for generating the public key.
|
||||||
|
$hash = new Hash('sha512');
|
||||||
|
$h = $hash->hash($str);
|
||||||
|
$h = substr($h, 0, 32);
|
||||||
|
// 2. Prune the buffer: The lowest three bits of the first octet are
|
||||||
|
// cleared, the highest bit of the last octet is cleared, and the
|
||||||
|
// second highest bit of the last octet is set.
|
||||||
|
$h[0] = $h[0] & chr(0xF8);
|
||||||
|
$h = strrev($h);
|
||||||
|
$h[0] = ($h[0] & chr(0x3F)) | chr(0x40);
|
||||||
|
// 3. Interpret the buffer as the little-endian integer, forming a
|
||||||
|
// secret scalar s.
|
||||||
|
$dA = new BigInteger($h, 256);
|
||||||
|
$dA = $this->factory->newInteger($dA);
|
||||||
|
|
||||||
|
$dA->secret = $str;
|
||||||
|
return $dA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a point as a string
|
||||||
|
*
|
||||||
|
* @param string $str
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encodePoint($point)
|
||||||
|
{
|
||||||
|
list($x, $y) = $point;
|
||||||
|
$y = $y->toBytes();
|
||||||
|
$y[0] = $y[0] & chr(0x7F);
|
||||||
|
if ($x->isOdd()) {
|
||||||
|
$y[0] = $y[0] | chr(0x80);
|
||||||
|
}
|
||||||
|
$y = strrev($y);
|
||||||
|
|
||||||
|
return $y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a random scalar multiplier
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer
|
||||||
|
*/
|
||||||
|
public function createRandomMultiplier()
|
||||||
|
{
|
||||||
|
return $this->extractSecret(Random::string(32));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an affine point to an extended homogeneous coordinate
|
||||||
|
*
|
||||||
|
* From https://tools.ietf.org/html/rfc8032#section-5.1.4 :
|
||||||
|
*
|
||||||
|
* A point (x,y) is represented in extended homogeneous coordinates (X, Y, Z, T),
|
||||||
|
* with x = X/Z, y = Y/Z, x * y = T/Z.
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer[]
|
||||||
|
*/
|
||||||
|
public function convertToInternal(array $p)
|
||||||
|
{
|
||||||
|
if (empty($p)) {
|
||||||
|
return [clone $this->zero, clone $this->one, clone $this->one, clone $this->zero];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($p[2])) {
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
$p[2] = clone $this->one;
|
||||||
|
$p[3] = $p[0]->multiply($p[1]);
|
||||||
|
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doubles a point on a curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
public function doublePoint(array $p)
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count($p)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($p[2])) {
|
||||||
|
throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
|
||||||
|
}
|
||||||
|
|
||||||
|
// from https://tools.ietf.org/html/rfc8032#page-12
|
||||||
|
|
||||||
|
list($x1, $y1, $z1, $t1) = $p;
|
||||||
|
|
||||||
|
$a = $x1->multiply($x1);
|
||||||
|
$b = $y1->multiply($y1);
|
||||||
|
$c = $this->two->multiply($z1)->multiply($z1);
|
||||||
|
$h = $a->add($b);
|
||||||
|
$temp = $x1->add($y1);
|
||||||
|
$e = $h->subtract($temp->multiply($temp));
|
||||||
|
$g = $a->subtract($b);
|
||||||
|
$f = $c->add($g);
|
||||||
|
|
||||||
|
$x3 = $e->multiply($f);
|
||||||
|
$y3 = $g->multiply($h);
|
||||||
|
$t3 = $e->multiply($h);
|
||||||
|
$z3 = $f->multiply($g);
|
||||||
|
|
||||||
|
return [$x3, $y3, $z3, $t3];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds two points on the curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
public function addPoint(array $p, array $q)
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count($p) || !count($q)) {
|
||||||
|
if (count($q)) {
|
||||||
|
return $q;
|
||||||
|
}
|
||||||
|
if (count($p)) {
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($p[2]) || !isset($q[2])) {
|
||||||
|
throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($p[0]->equals($q[0])) {
|
||||||
|
return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// from https://tools.ietf.org/html/rfc8032#page-12
|
||||||
|
|
||||||
|
list($x1, $y1, $z1, $t1) = $p;
|
||||||
|
list($x2, $y2, $z2, $t2) = $q;
|
||||||
|
|
||||||
|
$a = $y1->subtract($x1)->multiply($y2->subtract($x2));
|
||||||
|
$b = $y1->add($x1)->multiply($y2->add($x2));
|
||||||
|
$c = $t1->multiply($this->two)->multiply($this->d)->multiply($t2);
|
||||||
|
$d = $z1->multiply($this->two)->multiply($z2);
|
||||||
|
$e = $b->subtract($a);
|
||||||
|
$f = $d->subtract($c);
|
||||||
|
$g = $d->add($c);
|
||||||
|
$h = $b->add($a);
|
||||||
|
|
||||||
|
$x3 = $e->multiply($f);
|
||||||
|
$y3 = $g->multiply($h);
|
||||||
|
$t3 = $e->multiply($h);
|
||||||
|
$z3 = $f->multiply($g);
|
||||||
|
|
||||||
|
return [$x3, $y3, $z3, $t3];
|
||||||
|
}
|
||||||
|
}
|
267
phpseclib/Crypt/ECDSA/Curves/Ed448.php
Normal file
267
phpseclib/Crypt/ECDSA/Curves/Ed448.php
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ed448
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\TwistedEdwards;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Crypt\Hash;
|
||||||
|
use phpseclib\Crypt\Random;
|
||||||
|
|
||||||
|
class Ed448 extends TwistedEdwards
|
||||||
|
{
|
||||||
|
const HASH = 'shake256-912';
|
||||||
|
const SIZE = 57;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// 2^448 - 2^224 - 1
|
||||||
|
$this->setModulo(new BigInteger(
|
||||||
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE' .
|
||||||
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger(1),
|
||||||
|
// -39081
|
||||||
|
new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE' .
|
||||||
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6756', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('4F1970C66BED0DED221D15A622BF36DA9E146570470F1767EA6DE324' .
|
||||||
|
'A3D3A46412AE1AF72AB66511433B80E18B00938E2626A82BC70CC05E', 16),
|
||||||
|
new BigInteger('693F46716EB6BC248876203756C9C7624BEA73736CA3984087789C1E' .
|
||||||
|
'05A0C2D73AD3FF1CE67C39C4FDBD132C4ED7C8AD9808795BF230FA14', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger(
|
||||||
|
'3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' .
|
||||||
|
'7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3', 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recover X from Y
|
||||||
|
*
|
||||||
|
* Implements steps 2-4 at https://tools.ietf.org/html/rfc8032#section-5.2.3
|
||||||
|
*
|
||||||
|
* Used by ECDSA\Keys\Common.php
|
||||||
|
*
|
||||||
|
* @param BigInteger $x
|
||||||
|
* @param boolean $sign
|
||||||
|
* @return object[]
|
||||||
|
*/
|
||||||
|
public function recoverX(BigInteger $y, $sign)
|
||||||
|
{
|
||||||
|
$y = $this->factory->newInteger($y);
|
||||||
|
|
||||||
|
$y2 = $y->multiply($y);
|
||||||
|
$u = $y2->subtract($this->one);
|
||||||
|
$v = $this->d->multiply($y2)->subtract($this->one);
|
||||||
|
$x2 = $u->divide($v);
|
||||||
|
if ($x2->equals($this->zero)) {
|
||||||
|
if ($sign) {
|
||||||
|
throw new \RuntimeException('Unable to recover X coordinate (x2 = 0)');
|
||||||
|
}
|
||||||
|
return clone $this->zero;
|
||||||
|
}
|
||||||
|
// find the square root
|
||||||
|
$exp = $this->getModulo()->add(new BigInteger(1));
|
||||||
|
$exp = $exp->bitwise_rightShift(2);
|
||||||
|
$x = $x2->pow($exp);
|
||||||
|
|
||||||
|
if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) {
|
||||||
|
throw new \RuntimeException('Unable to recover X coordinate');
|
||||||
|
}
|
||||||
|
if ($x->isOdd() != $sign) {
|
||||||
|
$x = $x->negate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$x, $y];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract Secret Scalar
|
||||||
|
*
|
||||||
|
* Implements steps 1-3 at https://tools.ietf.org/html/rfc8032#section-5.2.5
|
||||||
|
*
|
||||||
|
* Used by the various key handlers
|
||||||
|
*
|
||||||
|
* @param string $str
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer
|
||||||
|
*/
|
||||||
|
public function extractSecret($str)
|
||||||
|
{
|
||||||
|
if (strlen($str) != 57) {
|
||||||
|
throw new \LengthException('Private Key should be 57-bytes long');
|
||||||
|
}
|
||||||
|
// 1. Hash the 57-byte private key using SHAKE256(x, 114), storing the
|
||||||
|
// digest in a 114-octet large buffer, denoted h. Only the lower 57
|
||||||
|
// bytes are used for generating the public key.
|
||||||
|
$hash = new Hash('shake256-912');
|
||||||
|
$h = $hash->hash($str);
|
||||||
|
$h = substr($h, 0, 57);
|
||||||
|
// 2. Prune the buffer: The two least significant bits of the first
|
||||||
|
// octet are cleared, all eight bits the last octet are cleared, and
|
||||||
|
// the highest bit of the second to last octet is set.
|
||||||
|
$h[0] = $h[0] & chr(0xFC);
|
||||||
|
$h = strrev($h);
|
||||||
|
$h[0] = "\0";
|
||||||
|
$h[1] = $h[1] | chr(0x80);
|
||||||
|
// 3. Interpret the buffer as the little-endian integer, forming a
|
||||||
|
// secret scalar s.
|
||||||
|
$dA = new BigInteger($h, 256);
|
||||||
|
$dA = $this->factory->newInteger($dA);
|
||||||
|
|
||||||
|
$dA->secret = $str;
|
||||||
|
return $dA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a point as a string
|
||||||
|
*
|
||||||
|
* @param string $str
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encodePoint($point)
|
||||||
|
{
|
||||||
|
list($x, $y) = $point;
|
||||||
|
$y = "\0" . $y->toBytes();
|
||||||
|
if ($x->isOdd()) {
|
||||||
|
$y[0] = $y[0] | chr(0x80);
|
||||||
|
}
|
||||||
|
$y = strrev($y);
|
||||||
|
|
||||||
|
return $y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a random scalar multiplier
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer
|
||||||
|
*/
|
||||||
|
public function createRandomMultiplier()
|
||||||
|
{
|
||||||
|
return $this->extractSecret(Random::string(57));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an affine point to an extended homogeneous coordinate
|
||||||
|
*
|
||||||
|
* From https://tools.ietf.org/html/rfc8032#section-5.2.4 :
|
||||||
|
*
|
||||||
|
* A point (x,y) is represented in extended homogeneous coordinates (X, Y, Z, T),
|
||||||
|
* with x = X/Z, y = Y/Z, x * y = T/Z.
|
||||||
|
*
|
||||||
|
* @return \phpseclib\Math\PrimeField\Integer[]
|
||||||
|
*/
|
||||||
|
public function convertToInternal(array $p)
|
||||||
|
{
|
||||||
|
if (empty($p)) {
|
||||||
|
return [clone $this->zero, clone $this->one, clone $this->one];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($p[2])) {
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
$p[2] = clone $this->one;
|
||||||
|
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doubles a point on a curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
public function doublePoint(array $p)
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count($p)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($p[2])) {
|
||||||
|
throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
|
||||||
|
}
|
||||||
|
|
||||||
|
// from https://tools.ietf.org/html/rfc8032#page-18
|
||||||
|
|
||||||
|
list($x1, $y1, $z1) = $p;
|
||||||
|
|
||||||
|
$b = $x1->add($y1);
|
||||||
|
$b = $b->multiply($b);
|
||||||
|
$c = $x1->multiply($x1);
|
||||||
|
$d = $y1->multiply($y1);
|
||||||
|
$e = $c->add($d);
|
||||||
|
$h = $z1->multiply($z1);
|
||||||
|
$j = $e->subtract($this->two->multiply($h));
|
||||||
|
|
||||||
|
$x3 = $b->subtract($e)->multiply($j);
|
||||||
|
$y3 = $c->subtract($d)->multiply($e);
|
||||||
|
$z3 = $e->multiply($j);
|
||||||
|
|
||||||
|
return [$x3, $y3, $z3];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds two points on the curve
|
||||||
|
*
|
||||||
|
* @return FiniteField[]
|
||||||
|
*/
|
||||||
|
public function addPoint(array $p, array $q)
|
||||||
|
{
|
||||||
|
if (!isset($this->factory)) {
|
||||||
|
throw new \RuntimeException('setModulo needs to be called before this method');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count($p) || !count($q)) {
|
||||||
|
if (count($q)) {
|
||||||
|
return $q;
|
||||||
|
}
|
||||||
|
if (count($p)) {
|
||||||
|
return $p;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($p[2]) || !isset($q[2])) {
|
||||||
|
throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($p[0]->equals($q[0])) {
|
||||||
|
return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// from https://tools.ietf.org/html/rfc8032#page-17
|
||||||
|
|
||||||
|
list($x1, $y1, $z1) = $p;
|
||||||
|
list($x2, $y2, $z2) = $q;
|
||||||
|
|
||||||
|
$a = $z1->multiply($z2);
|
||||||
|
$b = $a->multiply($a);
|
||||||
|
$c = $x1->multiply($x2);
|
||||||
|
$d = $y1->multiply($y2);
|
||||||
|
$e = $this->d->multiply($c)->multiply($d);
|
||||||
|
$f = $b->subtract($e);
|
||||||
|
$g = $b->add($e);
|
||||||
|
$h = $x1->add($y1)->multiply($x2->add($y2));
|
||||||
|
|
||||||
|
$x3 = $a->multiply($f)->multiply($h->subtract($c)->subtract($d));
|
||||||
|
$y3 = $a->multiply($g)->multiply($d->subtract($c));
|
||||||
|
$z3 = $f->multiply($g);
|
||||||
|
|
||||||
|
return [$x3, $y3, $z3];
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP160r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP160r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP160r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP160r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620F', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('340E7BE2A280EB74E2BE61BADA745D97E8F7C300', 16),
|
||||||
|
new BigInteger('1E589A8595423412134FAA2DBDEC95C8D8675E58', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3', 16),
|
||||||
|
new BigInteger('1667CB477A1A8EC338F94741669C976316DA6321', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('E95E4A5F737059DC60DF5991D45029409E60FC09', 16));
|
||||||
|
}
|
||||||
|
}
|
49
phpseclib/Crypt/ECDSA/Curves/brainpoolP160t1.php
Normal file
49
phpseclib/Crypt/ECDSA/Curves/brainpoolP160t1.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP160t1
|
||||||
|
*
|
||||||
|
* This curve is a twisted version of brainpoolP160r1 with A = -3. With brainpool,
|
||||||
|
* the curves ending in r1 are the "regular" curves and the curves ending in "t1"
|
||||||
|
* are the twisted version of the r1 curves. Per https://tools.ietf.org/html/rfc5639#page-7
|
||||||
|
* you can convert a point on an r1 curve to a point on a t1 curve thusly:
|
||||||
|
*
|
||||||
|
* F(x,y) := (x*Z^2, y*Z^3)
|
||||||
|
*
|
||||||
|
* The advantage of A = -3 is that some of the point doubling and point addition can be
|
||||||
|
* slightly optimized. See http://hyperelliptic.org/EFD/g1p/auto-shortw-projective-3.html
|
||||||
|
* vs http://hyperelliptic.org/EFD/g1p/auto-shortw-projective.html for example.
|
||||||
|
*
|
||||||
|
* phpseclib does not currently take advantage of this optimization opportunity
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP160t1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620F', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620C', 16), // eg. -3
|
||||||
|
new BigInteger('7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('B199B13B9B34EFC1397E64BAEB05ACC265FF2378', 16),
|
||||||
|
new BigInteger('ADD6718B7C7C1961F0991B842443772152C9E0AD', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('E95E4A5F737059DC60DF5991D45029409E60FC09', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP192r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP192r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP192r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP192r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF', 16),
|
||||||
|
new BigInteger('469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6', 16),
|
||||||
|
new BigInteger('14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP192t1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP192t1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP192t1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP192t1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294', 16), // eg. -3
|
||||||
|
new BigInteger('13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129', 16),
|
||||||
|
new BigInteger('097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP224r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP224r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP224r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP224r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43', 16),
|
||||||
|
new BigInteger('2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D', 16),
|
||||||
|
new BigInteger('58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP224t1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP224t1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP224t1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP224t1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC', 16), // eg. -3
|
||||||
|
new BigInteger('4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580', 16),
|
||||||
|
new BigInteger('0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP256r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP256r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP256r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP256r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9', 16),
|
||||||
|
new BigInteger('26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', 16),
|
||||||
|
new BigInteger('547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP256t1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/brainpoolP256t1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP256t1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP256t1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374', 16), // eg. -3
|
||||||
|
new BigInteger('662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4', 16),
|
||||||
|
new BigInteger('2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16));
|
||||||
|
}
|
||||||
|
}
|
42
phpseclib/Crypt/ECDSA/Curves/brainpoolP320r1.php
Normal file
42
phpseclib/Crypt/ECDSA/Curves/brainpoolP320r1.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP320r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP320r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F9' .
|
||||||
|
'2B9EC7893EC28FCD412B1F1B32E27', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F4' .
|
||||||
|
'92F375A97D860EB4', 16),
|
||||||
|
new BigInteger('520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD88453981' .
|
||||||
|
'6F5EB4AC8FB1F1A6', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C7' .
|
||||||
|
'10AF8D0D39E20611', 16),
|
||||||
|
new BigInteger('14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7' .
|
||||||
|
'D35245D1692E8EE1', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D4' .
|
||||||
|
'82EC7EE8658E98691555B44C59311', 16));
|
||||||
|
}
|
||||||
|
}
|
42
phpseclib/Crypt/ECDSA/Curves/brainpoolP320t1.php
Normal file
42
phpseclib/Crypt/ECDSA/Curves/brainpoolP320t1.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP320t1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP320t1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F9' .
|
||||||
|
'2B9EC7893EC28FCD412B1F1B32E27', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28' .
|
||||||
|
'FCD412B1F1B32E24', 16), // eg. -3
|
||||||
|
new BigInteger('A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CE' .
|
||||||
|
'B5B4FEF422340353', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF' .
|
||||||
|
'3357F624A21BED52', 16),
|
||||||
|
new BigInteger('63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B' .
|
||||||
|
'1B9BC0455FB0D2C3', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D4' .
|
||||||
|
'82EC7EE8658E98691555B44C59311', 16));
|
||||||
|
}
|
||||||
|
}
|
48
phpseclib/Crypt/ECDSA/Curves/brainpoolP384r1.php
Normal file
48
phpseclib/Crypt/ECDSA/Curves/brainpoolP384r1.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP384r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP384r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger(
|
||||||
|
'8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A7' .
|
||||||
|
'1874700133107EC53', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger(
|
||||||
|
'7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503' .
|
||||||
|
'AD4EB04A8C7DD22CE2826', 16),
|
||||||
|
new BigInteger(
|
||||||
|
'4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DB' .
|
||||||
|
'C9943AB78696FA504C11', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger(
|
||||||
|
'1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D' .
|
||||||
|
'646AAEF87B2E247D4AF1E', 16),
|
||||||
|
new BigInteger(
|
||||||
|
'8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E464621779' .
|
||||||
|
'1811142820341263C5315', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger(
|
||||||
|
'8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC31' .
|
||||||
|
'03B883202E9046565', 16));
|
||||||
|
}
|
||||||
|
}
|
48
phpseclib/Crypt/ECDSA/Curves/brainpoolP384t1.php
Normal file
48
phpseclib/Crypt/ECDSA/Curves/brainpoolP384t1.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP384t1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP384t1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger(
|
||||||
|
'8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A7' .
|
||||||
|
'1874700133107EC53', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger(
|
||||||
|
'8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901' .
|
||||||
|
'D1A71874700133107EC50', 16), // eg. -3
|
||||||
|
new BigInteger(
|
||||||
|
'7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B8' .
|
||||||
|
'8805CED70355A33B471EE', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger(
|
||||||
|
'18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946' .
|
||||||
|
'A5F54D8D0AA2F418808CC', 16),
|
||||||
|
new BigInteger(
|
||||||
|
'25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC' .
|
||||||
|
'2B2912675BF5B9E582928', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger(
|
||||||
|
'8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC31' .
|
||||||
|
'03B883202E9046565', 16));
|
||||||
|
}
|
||||||
|
}
|
48
phpseclib/Crypt/ECDSA/Curves/brainpoolP512r1.php
Normal file
48
phpseclib/Crypt/ECDSA/Curves/brainpoolP512r1.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP512r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP512r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger(
|
||||||
|
'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC' .
|
||||||
|
'66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger(
|
||||||
|
'7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA82' .
|
||||||
|
'53AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA', 16),
|
||||||
|
new BigInteger(
|
||||||
|
'3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C' .
|
||||||
|
'1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger(
|
||||||
|
'81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D' .
|
||||||
|
'0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', 16),
|
||||||
|
new BigInteger(
|
||||||
|
'7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5' .
|
||||||
|
'F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger(
|
||||||
|
'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA' .
|
||||||
|
'92619418661197FAC10471DB1D381085DDADDB58796829CA90069', 16));
|
||||||
|
}
|
||||||
|
}
|
48
phpseclib/Crypt/ECDSA/Curves/brainpoolP512t1.php
Normal file
48
phpseclib/Crypt/ECDSA/Curves/brainpoolP512t1.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* brainpoolP512t1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class brainpoolP512t1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger(
|
||||||
|
'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC' .
|
||||||
|
'66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger(
|
||||||
|
'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC' .
|
||||||
|
'66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0', 16), // eg. -3
|
||||||
|
new BigInteger(
|
||||||
|
'7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA23049' .
|
||||||
|
'76540F6450085F2DAE145C22553B465763689180EA2571867423E', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger(
|
||||||
|
'640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CD' .
|
||||||
|
'B3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA', 16),
|
||||||
|
new BigInteger(
|
||||||
|
'5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEE' .
|
||||||
|
'F216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger(
|
||||||
|
'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA' .
|
||||||
|
'92619418661197FAC10471DB1D381085DDADDB58796829CA90069', 16));
|
||||||
|
}
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistb233.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistb233.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nistb233
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistb233 extends sect233r1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistb409.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistb409.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nistb409
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistb409 extends sect409r1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistk163.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistk163.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nistk163
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistk163 extends sect163k1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistk233.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistk233.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nistk233
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistk233 extends sect233k1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistk283.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistk283.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect283k1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistk283 extends sect283k1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistk409.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistk409.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nistk409
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistk409 extends sect409k1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistp192.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistp192.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nistp192
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistp192 extends secp192r1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistp224.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistp224.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nistp224
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistp224 extends secp224r1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistp256.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistp256.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nistp256
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistp256 extends secp256r1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistp384.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistp384.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nistp384
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistp384 extends secp384r1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistp521.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistp521.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nistp521
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistp521 extends secp521r1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/nistt571.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/nistt571.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nistt571
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class nistt571 extends sect571k1
|
||||||
|
{
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/prime192v1.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/prime192v1.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prime192v1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class prime192v1 extends secp192r1
|
||||||
|
{
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/prime192v2.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/prime192v2.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prime192v2
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class prime192v2 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16),
|
||||||
|
new BigInteger('CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A', 16),
|
||||||
|
new BigInteger('6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/prime192v3.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/prime192v3.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prime192v3
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class prime192v3 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16),
|
||||||
|
new BigInteger('22123DC2395A05CAA7423DAECCC94760A7D462256BD56916', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896', 16),
|
||||||
|
new BigInteger('38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/prime239v1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/prime239v1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prime239v1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class prime239v1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16),
|
||||||
|
new BigInteger('6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF', 16),
|
||||||
|
new BigInteger('7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/prime239v2.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/prime239v2.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prime239v2
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class prime239v2 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16),
|
||||||
|
new BigInteger('617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7', 16),
|
||||||
|
new BigInteger('5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/prime239v3.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/prime239v3.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prime239v3
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class prime239v3 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16),
|
||||||
|
new BigInteger('255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A', 16),
|
||||||
|
new BigInteger('1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551', 16));
|
||||||
|
}
|
||||||
|
}
|
20
phpseclib/Crypt/ECDSA/Curves/prime256v1.php
Normal file
20
phpseclib/Crypt/ECDSA/Curves/prime256v1.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prime256v1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
final class prime256v1 extends secp256r1
|
||||||
|
{
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/secp112r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/secp112r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp112r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp112r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('DB7C2ABF62E35E668076BEAD208B', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('DB7C2ABF62E35E668076BEAD2088', 16),
|
||||||
|
new BigInteger('659EF8BA043916EEDE8911702B22', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('09487239995A5EE76B55F9C2F098', 16),
|
||||||
|
new BigInteger('A89CE5AF8724C0A23E0E0FF77500', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('DB7C2ABF62E35E7628DFAC6561C5', 16));
|
||||||
|
}
|
||||||
|
}
|
37
phpseclib/Crypt/ECDSA/Curves/secp112r2.php
Normal file
37
phpseclib/Crypt/ECDSA/Curves/secp112r2.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp112r2
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp112r2 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// same modulo as secp112r1
|
||||||
|
$this->setModulo(new BigInteger('DB7C2ABF62E35E668076BEAD208B', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('6127C24C05F38A0AAAF65C0EF02C', 16),
|
||||||
|
new BigInteger('51DEF1815DB5ED74FCC34C85D709', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('4BA30AB5E892B4E1649DD0928643', 16),
|
||||||
|
new BigInteger('ADCD46F5882E3747DEF36E956E97', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('36DF0AAFD8B8D7597CA10520D04B', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/secp128r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/secp128r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp128r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp128r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC', 16),
|
||||||
|
new BigInteger('E87579C11079F43DD824993C2CEE5ED3', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('161FF7528B899B2D0C28607CA52C5B86', 16),
|
||||||
|
new BigInteger('CF5AC8395BAFEB13C02DA292DDED7A83', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('FFFFFFFE0000000075A30D1B9038A115', 16));
|
||||||
|
}
|
||||||
|
}
|
37
phpseclib/Crypt/ECDSA/Curves/secp128r2.php
Normal file
37
phpseclib/Crypt/ECDSA/Curves/secp128r2.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp128r2
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp128r2 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// same as secp128r1
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('D6031998D1B3BBFEBF59CC9BBFF9AEE1', 16),
|
||||||
|
new BigInteger('5EEEFCA380D02919DC2C6558BB6D8A5D', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('7B6AA5D85E572983E6FB32A7CDEBC140', 16),
|
||||||
|
new BigInteger('27B6916A894D3AEE7106FE805FC34B44', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('3FFFFFFF7FFFFFFFBE0024720613B5A3', 16));
|
||||||
|
}
|
||||||
|
}
|
48
phpseclib/Crypt/ECDSA/Curves/secp160k1.php
Normal file
48
phpseclib/Crypt/ECDSA/Curves/secp160k1.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp160k1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\KoblitzPrime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp160k1 extends KoblitzPrime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// same as secp160r2
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('0000000000000000000000000000000000000000', 16),
|
||||||
|
new BigInteger('0000000000000000000000000000000000000007', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('3B4C382CE37AA192A4019E763036F4F5DD4D7EBB', 16),
|
||||||
|
new BigInteger('938CF935318FDCED6BC28286531733C3F03C4FEE', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('0100000000000000000001B8FA16DFAB9ACA16B6B3', 16));
|
||||||
|
|
||||||
|
$this->basis = [];
|
||||||
|
$this->basis[] = [
|
||||||
|
'a' => new BigInteger('0096341F1138933BC2F505', -16),
|
||||||
|
'b' => new BigInteger('FF6E9D0418C67BB8D5F562', -16)
|
||||||
|
];
|
||||||
|
$this->basis[] = [
|
||||||
|
'a' => new BigInteger('01BDCB3A09AAAABEAFF4A8', -16),
|
||||||
|
'b' => new BigInteger('04D12329FF0EF498EA67', -16)
|
||||||
|
];
|
||||||
|
$this->beta = $this->factory->newInteger(new BigInteger('645B7345A143464942CC46D7CF4D5D1E1E6CBB68', -16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/secp160r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/secp160r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp160r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp160r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC', 16),
|
||||||
|
new BigInteger('1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('4A96B5688EF573284664698968C38BB913CBFC82', 16),
|
||||||
|
new BigInteger('23A628553168947D59DCC912042351377AC5FB32', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('0100000000000000000001F4C8F927AED3CA752257', 16));
|
||||||
|
}
|
||||||
|
}
|
37
phpseclib/Crypt/ECDSA/Curves/secp160r2.php
Normal file
37
phpseclib/Crypt/ECDSA/Curves/secp160r2.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp160r2
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp160r2 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// same as secp160k1
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70', 16),
|
||||||
|
new BigInteger('B4E134D3FB59EB8BAB57274904664D5AF50388BA', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('52DCB034293A117E1F4FF11B30F7199D3144CE6D', 16),
|
||||||
|
new BigInteger('FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('0100000000000000000000351EE786A818F3A1A16B', 16));
|
||||||
|
}
|
||||||
|
}
|
47
phpseclib/Crypt/ECDSA/Curves/secp192k1.php
Normal file
47
phpseclib/Crypt/ECDSA/Curves/secp192k1.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp192k1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\KoblitzPrime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp192k1 extends KoblitzPrime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('000000000000000000000000000000000000000000000000', 16),
|
||||||
|
new BigInteger('000000000000000000000000000000000000000000000003', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D', 16),
|
||||||
|
new BigInteger('9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D', 16));
|
||||||
|
|
||||||
|
$this->basis = [];
|
||||||
|
$this->basis[] = [
|
||||||
|
'a' => new BigInteger('00B3FB3400DEC5C4ADCEB8655C', -16),
|
||||||
|
'b' => new BigInteger('8EE96418CCF4CFC7124FDA0F', -16)
|
||||||
|
];
|
||||||
|
$this->basis[] = [
|
||||||
|
'a' => new BigInteger('01D90D03E8F096B9948B20F0A9', -16),
|
||||||
|
'b' => new BigInteger('42E49819ABBA9474E1083F6B', -16)
|
||||||
|
];
|
||||||
|
$this->beta = $this->factory->newInteger(new BigInteger('447A96E6C647963E2F7809FEAAB46947F34B0AA3CA0BBA74', -16));
|
||||||
|
}
|
||||||
|
}
|
80
phpseclib/Crypt/ECDSA/Curves/secp192r1.php
Normal file
80
phpseclib/Crypt/ECDSA/Curves/secp192r1.php
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp192r1
|
||||||
|
*
|
||||||
|
* This is the NIST P-192 curve
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp192r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$modulo = new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16);
|
||||||
|
$this->setModulo($modulo);
|
||||||
|
|
||||||
|
// algorithm 2.27 from http://diamond.boisestate.edu/~liljanab/MATH308/GuideToECC.pdf#page=66
|
||||||
|
/* in theory this should be faster than regular modular reductions save for one small issue.
|
||||||
|
to convert to / from base-2**8 with BCMath you have to call bcmul() and bcdiv() a lot.
|
||||||
|
to convert to / from base-2**8 with PHP64 you have to call base256_rshift() a lot.
|
||||||
|
in short, converting to / from base-2**8 is pretty expensive and that expense is
|
||||||
|
enough to offset whatever else might be gained by a simplified reduction algorithm.
|
||||||
|
now, if PHP supported unsigned integers things might be different. no bit-shifting
|
||||||
|
would be required for the PHP engine and it'd be a lot faster. but as is, BigInteger
|
||||||
|
uses base-2**31 or base-2**26 depending on whether or not the system is has a 32-bit
|
||||||
|
or a 64-bit OS.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
$m_length = $this->getLengthInBytes();
|
||||||
|
$this->setReduction(function($c) use ($m_length) {
|
||||||
|
$cBytes = $c->toBytes();
|
||||||
|
$className = $this->className;
|
||||||
|
|
||||||
|
if (strlen($cBytes) > 2 * $m_length) {
|
||||||
|
list(, $r) = $c->divide($className::$modulo);
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
$c = str_pad($cBytes, 48, "\0", STR_PAD_LEFT);
|
||||||
|
$c = array_reverse(str_split($c, 8));
|
||||||
|
|
||||||
|
$null = "\0\0\0\0\0\0\0\0";
|
||||||
|
$s1 = new BigInteger($c[2] . $c[1] . $c[0], 256);
|
||||||
|
$s2 = new BigInteger($null . $c[3] . $c[3], 256);
|
||||||
|
$s3 = new BigInteger($c[4] . $c[4] . $null, 256);
|
||||||
|
$s4 = new BigInteger($c[5] . $c[5] . $c[5], 256);
|
||||||
|
|
||||||
|
$r = $s1->add($s2)->add($s3)->add($s4);
|
||||||
|
while ($r->compare($className::$modulo) >= 0) {
|
||||||
|
$r = $r->subtract($className::$modulo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $r;
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16),
|
||||||
|
new BigInteger('64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012', 16),
|
||||||
|
new BigInteger('07192B95FFC8DA78631011ED6B24CDD573F977A11E794811', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831', 16));
|
||||||
|
}
|
||||||
|
}
|
47
phpseclib/Crypt/ECDSA/Curves/secp224k1.php
Normal file
47
phpseclib/Crypt/ECDSA/Curves/secp224k1.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp224k1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\KoblitzPrime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp224k1 extends KoblitzPrime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('00000000000000000000000000000000000000000000000000000000', 16),
|
||||||
|
new BigInteger('00000000000000000000000000000000000000000000000000000005', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C', 16),
|
||||||
|
new BigInteger('7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7', 16));
|
||||||
|
|
||||||
|
$this->basis = [];
|
||||||
|
$this->basis[] = [
|
||||||
|
'a' => new BigInteger('00B8ADF1378A6EB73409FA6C9C637D', -16),
|
||||||
|
'b' => new BigInteger('94730F82B358A3776A826298FA6F', -16)
|
||||||
|
];
|
||||||
|
$this->basis[] = [
|
||||||
|
'a' => new BigInteger('01DCE8D2EC6184CAF0A972769FCC8B', -16),
|
||||||
|
'b' => new BigInteger('4D2100BA3DC75AAB747CCF355DEC', -16)
|
||||||
|
];
|
||||||
|
$this->beta = $this->factory->newInteger(new BigInteger('01F178FFA4B17C89E6F73AECE2AAD57AF4C0A748B63C830947B27E04', -16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/secp224r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/secp224r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp224r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp224r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE', 16),
|
||||||
|
new BigInteger('B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21', 16),
|
||||||
|
new BigInteger('BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D', 16));
|
||||||
|
}
|
||||||
|
}
|
51
phpseclib/Crypt/ECDSA/Curves/secp256k1.php
Normal file
51
phpseclib/Crypt/ECDSA/Curves/secp256k1.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp256k1
|
||||||
|
*
|
||||||
|
* This is the curve used in Bitcoin
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
//use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\KoblitzPrime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
//class secp256k1 extends Prime
|
||||||
|
class secp256k1 extends KoblitzPrime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('0000000000000000000000000000000000000000000000000000000000000000', 16),
|
||||||
|
new BigInteger('0000000000000000000000000000000000000000000000000000000000000007', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16));
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', 16),
|
||||||
|
new BigInteger('483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 16)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->basis = [];
|
||||||
|
$this->basis[] = [
|
||||||
|
'a' => new BigInteger('3086D221A7D46BCDE86C90E49284EB15', -16),
|
||||||
|
'b' => new BigInteger('FF1BBC8129FEF177D790AB8056F5401B3D', -16)
|
||||||
|
];
|
||||||
|
$this->basis[] = [
|
||||||
|
'a' => new BigInteger('114CA50F7A8E2F3F657C1108D9D44CFD8', -16),
|
||||||
|
'b' => new BigInteger('3086D221A7D46BCDE86C90E49284EB15', -16)
|
||||||
|
];
|
||||||
|
$this->beta = $this->factory->newInteger(new BigInteger('7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE', -16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/secp256r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/secp256r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp256r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp256r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC', 16),
|
||||||
|
new BigInteger('5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296', 16),
|
||||||
|
new BigInteger('4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551', 16));
|
||||||
|
}
|
||||||
|
}
|
54
phpseclib/Crypt/ECDSA/Curves/secp384r1.php
Normal file
54
phpseclib/Crypt/ECDSA/Curves/secp384r1.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp384r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp384r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger(
|
||||||
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF',
|
||||||
|
16
|
||||||
|
));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger(
|
||||||
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC',
|
||||||
|
16
|
||||||
|
),
|
||||||
|
new BigInteger(
|
||||||
|
'B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF',
|
||||||
|
16
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger(
|
||||||
|
'AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7',
|
||||||
|
16
|
||||||
|
),
|
||||||
|
new BigInteger(
|
||||||
|
'3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F',
|
||||||
|
16
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger(
|
||||||
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973',
|
||||||
|
16
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
48
phpseclib/Crypt/ECDSA/Curves/secp521r1.php
Normal file
48
phpseclib/Crypt/ECDSA/Curves/secp521r1.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secp521r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class secp521r1 extends Prime
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' .
|
||||||
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' .
|
||||||
|
'FFFF', 16));
|
||||||
|
$this->setCoefficients(
|
||||||
|
new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' .
|
||||||
|
'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' .
|
||||||
|
'FFFC', 16),
|
||||||
|
new BigInteger('0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF1' .
|
||||||
|
'09E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B50' .
|
||||||
|
'3F00', 16)
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
new BigInteger('00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D' .
|
||||||
|
'3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5' .
|
||||||
|
'BD66', 16),
|
||||||
|
new BigInteger('011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E' .
|
||||||
|
'662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD1' .
|
||||||
|
'6650', 16)
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' .
|
||||||
|
'FFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E9138' .
|
||||||
|
'6409', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect113r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect113r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect113r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect113r1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(113, 9, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'003088250CA6E7C7FE649CE85820F7',
|
||||||
|
'00E8BEE4D3E2260744188BE0E9C723'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'009D73616F35F4AB1407D73562C10F',
|
||||||
|
'00A52830277958EE84D1315ED31886'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('0100000000000000D9CCEC8A39E56F', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect113r2.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect113r2.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect113r2
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect113r2 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(113, 9, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'00689918DBEC7E5A0DD6DFC0AA55C7',
|
||||||
|
'0095E9A9EC9B297BD4BF36E059184F'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'01A57A6A7B26CA5EF52FCDB8164797',
|
||||||
|
'00B3ADC94ED1FE674C06E695BABA1D'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('010000000000000108789B2496AF93', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect131r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect131r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect131r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect131r1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(131, 8, 3, 2, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'07A11B09A76B562144418FF3FF8C2570B8',
|
||||||
|
'0217C05610884B63B9C6C7291678F9D341'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'0081BAF91FDF9833C40F9C181343638399',
|
||||||
|
'078C6E7EA38C001F73C8134B1B4EF9E150'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('0400000000000000023123953A9464B54D', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect131r2.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect131r2.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect131r2
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect131r2 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(131, 8, 3, 2, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'03E5A88919D7CAFCBF415F07C2176573B2',
|
||||||
|
'04B8266A46C55657AC734CE38F018F2192'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'0356DCD8F2F95031AD652D23951BB366A8',
|
||||||
|
'0648F06D867940A5366D9E265DE9EB240F'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('0400000000000000016954A233049BA98F', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect163k1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect163k1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect163k1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect163k1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(163, 7, 6, 3, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'000000000000000000000000000000000000000001',
|
||||||
|
'000000000000000000000000000000000000000001'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8',
|
||||||
|
'0289070FB05D38FF58321F2E800536D538CCDAA3D9'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('04000000000000000000020108A2E0CC0D99F8A5EF', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect163r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect163r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect163r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect163r1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(163, 7, 6, 3, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'07B6882CAAEFA84F9554FF8428BD88E246D2782AE2',
|
||||||
|
'0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'0369979697AB43897789566789567F787A7876A654',
|
||||||
|
'00435EDB42EFAFB2989D51FEFCE3C80988F41FF883'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect163r2.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect163r2.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect163r2
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect163r2 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(163, 7, 6, 3, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'000000000000000000000000000000000000000001',
|
||||||
|
'020A601907B8C953CA1481EB10512F78744A3205FD'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'03F0EBA16286A2D57EA0991168D4994637E8343E36',
|
||||||
|
'00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('040000000000000000000292FE77E70C12A4234C33', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect193r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect193r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect193r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect193r1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(193, 15, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01',
|
||||||
|
'00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1',
|
||||||
|
'0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('01000000000000000000000000C7F34A778F443ACC920EBA49', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect193r2.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect193r2.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect193r2
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect193r2 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(193, 15, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B',
|
||||||
|
'00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F',
|
||||||
|
'01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('010000000000000000000000015AAB561B005413CCD4EE99D5', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect233k1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect233k1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect233k1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect233k1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(233, 74, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000',
|
||||||
|
'000000000000000000000000000000000000000000000000000000000001'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126',
|
||||||
|
'01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect233r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect233r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect233r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect233r1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(233, 74, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'000000000000000000000000000000000000000000000000000000000001',
|
||||||
|
'0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B',
|
||||||
|
'01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect239k1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect239k1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect239k1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wiggint on <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect239k1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(239, 158, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000',
|
||||||
|
'000000000000000000000000000000000000000000000000000000000001'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC',
|
||||||
|
'76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect283k1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect283k1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect283k1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wiggint on <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect283k1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(283, 12, 7, 5, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000000000000001'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836',
|
||||||
|
'01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61', 16));
|
||||||
|
}
|
||||||
|
}
|
36
phpseclib/Crypt/ECDSA/Curves/sect283r1.php
Normal file
36
phpseclib/Crypt/ECDSA/Curves/sect283r1.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect283r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wiggint on <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect283r1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(283, 12, 7, 5, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000000000000001',
|
||||||
|
'027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053',
|
||||||
|
'03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger('03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307', 16));
|
||||||
|
}
|
||||||
|
}
|
39
phpseclib/Crypt/ECDSA/Curves/sect409k1.php
Normal file
39
phpseclib/Crypt/ECDSA/Curves/sect409k1.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect409k1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wiggint on <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect409k1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(409, 87, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||||
|
'00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746',
|
||||||
|
'01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger(
|
||||||
|
'7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F' .
|
||||||
|
'83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF', 16
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
39
phpseclib/Crypt/ECDSA/Curves/sect409r1.php
Normal file
39
phpseclib/Crypt/ECDSA/Curves/sect409r1.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect409r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wiggint on <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect409r1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(409, 87, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001',
|
||||||
|
'0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7',
|
||||||
|
'0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger(
|
||||||
|
'010000000000000000000000000000000000000000000000000001E2' .
|
||||||
|
'AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173', 16
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
43
phpseclib/Crypt/ECDSA/Curves/sect571k1.php
Normal file
43
phpseclib/Crypt/ECDSA/Curves/sect571k1.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect571k1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wiggint on <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect571k1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(571, 10, 5, 2, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000000000000000' .
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000000000000000' .
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000000000000001'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA443709584' .
|
||||||
|
'93B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972',
|
||||||
|
'0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0' .
|
||||||
|
'AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger(
|
||||||
|
'020000000000000000000000000000000000000000000000000000000000000000000000' .
|
||||||
|
'131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001
', 16
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
43
phpseclib/Crypt/ECDSA/Curves/sect571r1.php
Normal file
43
phpseclib/Crypt/ECDSA/Curves/sect571r1.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sect571r1
|
||||||
|
*
|
||||||
|
* PHP version 5 and 7
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wiggint on <terrafrost@php.net>
|
||||||
|
* @copyright 2017 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://pear.php.net/package/Math_BigInteger
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Curves;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
|
class sect571r1 extends Binary
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->setModulo(571, 10, 5, 2, 0);
|
||||||
|
$this->setCoefficients(
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000000000000000' .
|
||||||
|
'000000000000000000000000000000000000000000000000000000000000000000000001',
|
||||||
|
'02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD' .
|
||||||
|
'8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A'
|
||||||
|
);
|
||||||
|
$this->setBasePoint(
|
||||||
|
'0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950' .
|
||||||
|
'F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19',
|
||||||
|
'037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43' .
|
||||||
|
'BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B'
|
||||||
|
);
|
||||||
|
$this->setOrder(new BigInteger(
|
||||||
|
'03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' .
|
||||||
|
'E661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47
', 16
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
558
phpseclib/Crypt/ECDSA/Keys/Common.php
Normal file
558
phpseclib/Crypt/ECDSA/Keys/Common.php
Normal file
@ -0,0 +1,558 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic ECDSA Key Parsing Helper functions
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2015 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Keys;
|
||||||
|
|
||||||
|
use ParagonIE\ConstantTime\Hex;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Base as BaseCurve;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime as PrimeCurve;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Binary as BinaryCurve;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
||||||
|
use phpseclib\Common\Functions\Strings;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Math\PrimeField;
|
||||||
|
use phpseclib\File\ASN1;
|
||||||
|
use phpseclib\File\ASN1\Maps;
|
||||||
|
use phpseclib\Exception\UnsupportedCurveException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic ECDSA Key Parsing Helper functions
|
||||||
|
*
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
trait Common
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Curve OIDs
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $curveOIDs = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Child OIDs loaded
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected static $childOIDsLoaded = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use Named Curves
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $useNamedCurves = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize static variables
|
||||||
|
*/
|
||||||
|
private static function initialize_static_variables()
|
||||||
|
{
|
||||||
|
if (empty(self::$curveOIDs)) {
|
||||||
|
// the sec* curves are from the standards for efficient cryptography group
|
||||||
|
// sect* curves are curves over binary finite fields
|
||||||
|
// secp* curves are curves over prime finite fields
|
||||||
|
// sec*r* curves are regular curves; sec*k* curves are koblitz curves
|
||||||
|
// brainpool*r* curves are regular prime finite field curves
|
||||||
|
// brainpool*t* curves are twisted versions of the brainpool*r* curves
|
||||||
|
self::$curveOIDs = [
|
||||||
|
// from https://tools.ietf.org/html/rfc5915
|
||||||
|
'secp192r1' => '1.2.840.10045.3.1.1', // aka prime192v1
|
||||||
|
'sect163k1' => '1.3.132.0.1',
|
||||||
|
'sect163r2' => '1.3.132.0.15',
|
||||||
|
'secp224r1' => '1.3.132.0.33',
|
||||||
|
'sect233k1'=> '1.3.132.0.26',
|
||||||
|
'sect233r1'=> '1.3.132.0.27',
|
||||||
|
'secp256r1' => '1.2.840.10045.3.1.7', // aka prime256v1
|
||||||
|
'sect283k1' => '1.3.132.0.16',
|
||||||
|
'sect283r1' => '1.3.132.0.17',
|
||||||
|
'secp384r1' => '1.3.132.0.34',
|
||||||
|
'sect409k1' => '1.3.132.0.36',
|
||||||
|
'sect409r1' => '1.3.132.0.37',
|
||||||
|
'secp521r1' => '1.3.132.0.35',
|
||||||
|
'sect571k1' => '1.3.132.0.38',
|
||||||
|
'sect571r1' => '1.3.132.0.39',
|
||||||
|
// from http://www.secg.org/SEC2-Ver-1.0.pdf
|
||||||
|
'secp112r1' => '1.3.132.0.6',
|
||||||
|
'secp112r2' => '1.3.132.0.7',
|
||||||
|
'secp128r1' => '1.3.132.0.28',
|
||||||
|
'secp128r2' => '1.3.132.0.29',
|
||||||
|
'secp160k1' => '1.3.132.0.9',
|
||||||
|
'secp160r1' => '1.3.132.0.8',
|
||||||
|
'secp160r2' => '1.3.132.0.30',
|
||||||
|
'secp192k1' => '1.3.132.0.31',
|
||||||
|
'secp224k1' => '1.3.132.0.32',
|
||||||
|
'secp256k1' => '1.3.132.0.10',
|
||||||
|
|
||||||
|
'sect113r1' => '1.3.132.0.4',
|
||||||
|
'sect113r2' => '1.3.132.0.5',
|
||||||
|
'sect131r1' => '1.3.132.0.22',
|
||||||
|
'sect131r2' => '1.3.132.0.23',
|
||||||
|
'sect163r1' => '1.3.132.0.2',
|
||||||
|
'sect193r1' => '1.3.132.0.24',
|
||||||
|
'sect193r2' => '1.3.132.0.25',
|
||||||
|
'sect239k1' => '1.3.132.0.3',
|
||||||
|
|
||||||
|
// from http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.202.2977&rep=rep1&type=pdf#page=36
|
||||||
|
/*
|
||||||
|
'c2pnb163v1' => '1.2.840.10045.3.0.1', // J.4.1, example 1
|
||||||
|
'c2pnb163v2' => '1.2.840.10045.3.0.2', // J.4.1, example 2
|
||||||
|
'c2pnb163v3' => '1.2.840.10045.3.0.3', // J.4.1, example 3
|
||||||
|
'c2pnb172w1' => '1.2.840.10045.3.0.4', // J.4.2, example 1
|
||||||
|
'c2tnb191v1' => '1.2.840.10045.3.0.5', // J.4.3, example 1
|
||||||
|
'c2tnb191v2' => '1.2.840.10045.3.0.6', // J.4.3, example 2
|
||||||
|
'c2tnb191v3' => '1.2.840.10045.3.0.7', // J.4.3, example 3
|
||||||
|
'c2onb191v4' => '1.2.840.10045.3.0.8', // J.4.3, example 4
|
||||||
|
'c2onb191v5' => '1.2.840.10045.3.0.9', // J.4.3, example 5
|
||||||
|
'c2pnb208w1' => '1.2.840.10045.3.0.10', // J.4.4, example 1
|
||||||
|
'c2tnb239v1' => '1.2.840.10045.3.0.11', // J.4.5, example 1
|
||||||
|
'c2tnb239v2' => '1.2.840.10045.3.0.12', // J.4.5, example 2
|
||||||
|
'c2tnb239v3' => '1.2.840.10045.3.0.13', // J.4.5, example 3
|
||||||
|
'c2onb239v4' => '1.2.840.10045.3.0.14', // J.4.5, example 4
|
||||||
|
'c2onb239v5' => '1.2.840.10045.3.0.15', // J.4.5, example 5
|
||||||
|
'c2pnb272w1' => '1.2.840.10045.3.0.16', // J.4.6, example 1
|
||||||
|
'c2pnb304w1' => '1.2.840.10045.3.0.17', // J.4.7, example 1
|
||||||
|
'c2tnb359v1' => '1.2.840.10045.3.0.18', // J.4.8, example 1
|
||||||
|
'c2pnb368w1' => '1.2.840.10045.3.0.19', // J.4.9, example 1
|
||||||
|
'c2tnb431r1' => '1.2.840.10045.3.0.20', // J.4.10, example 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
'prime192v1' => '1.2.840.10045.3.1.1', // J.5.1, example 1 (aka secp192r1)
|
||||||
|
'prime192v2' => '1.2.840.10045.3.1.2', // J.5.1, example 2
|
||||||
|
'prime192v3' => '1.2.840.10045.3.1.3', // J.5.1, example 3
|
||||||
|
'prime239v1' => '1.2.840.10045.3.1.4', // J.5.2, example 1
|
||||||
|
'prime239v2' => '1.2.840.10045.3.1.5', // J.5.2, example 2
|
||||||
|
'prime239v3' => '1.2.840.10045.3.1.6', // J.5.2, example 3
|
||||||
|
'prime256v1' => '1.2.840.10045.3.1.7', // J.5.3, example 1 (aka secp256r1)
|
||||||
|
|
||||||
|
// https://tools.ietf.org/html/rfc5656#section-10
|
||||||
|
'nistp256' => '1.2.840.10045.3.1.7', // aka secp256r1
|
||||||
|
'nistp384' => '1.3.132.0.34', // aka secp384r1
|
||||||
|
'nistp521' => '1.3.132.0.35', // aka secp521r1
|
||||||
|
|
||||||
|
'nistk163' => '1.3.132.0.1', // aka sect163k1
|
||||||
|
'nistp192' => '1.2.840.10045.3.1.1', // aka secp192r1
|
||||||
|
'nistp224' => '1.3.132.0.33', // aka secp224r1
|
||||||
|
'nistk233' => '1.3.132.0.26', // aka sect233k1
|
||||||
|
'nistb233' => '1.3.132.0.27', // aka sect233r1
|
||||||
|
'nistk283' => '1.3.132.0.16', // aka sect283k1
|
||||||
|
'nistk409' => '1.3.132.0.36', // aka sect409k1
|
||||||
|
'nistb409' => '1.3.132.0.37', // aka sect409r1
|
||||||
|
'nistt571' => '1.3.132.0.38', // aka sect571k1
|
||||||
|
|
||||||
|
// http://www.ecc-brainpool.org/download/Domain-parameters.pdf
|
||||||
|
// https://tools.ietf.org/html/rfc5639
|
||||||
|
'brainpoolP160r1' => '1.3.36.3.3.2.8.1.1.1',
|
||||||
|
'brainpoolP160t1' => '1.3.36.3.3.2.8.1.1.2',
|
||||||
|
'brainpoolP192r1' => '1.3.36.3.3.2.8.1.1.3',
|
||||||
|
'brainpoolP192t1' => '1.3.36.3.3.2.8.1.1.4',
|
||||||
|
'brainpoolP224r1' => '1.3.36.3.3.2.8.1.1.5',
|
||||||
|
'brainpoolP224t1' => '1.3.36.3.3.2.8.1.1.6',
|
||||||
|
'brainpoolP256r1' => '1.3.36.3.3.2.8.1.1.7',
|
||||||
|
'brainpoolP256t1' => '1.3.36.3.3.2.8.1.1.8',
|
||||||
|
'brainpoolP320r1' => '1.3.36.3.3.2.8.1.1.9',
|
||||||
|
'brainpoolP320t1' => '1.3.36.3.3.2.8.1.1.10',
|
||||||
|
'brainpoolP384r1' => '1.3.36.3.3.2.8.1.1.11',
|
||||||
|
'brainpoolP384t1' => '1.3.36.3.3.2.8.1.1.12',
|
||||||
|
'brainpoolP512r1' => '1.3.36.3.3.2.8.1.1.13',
|
||||||
|
'brainpoolP512t1' => '1.3.36.3.3.2.8.1.1.14'
|
||||||
|
];
|
||||||
|
ASN1::loadOIDs([
|
||||||
|
'prime-field' => '1.2.840.10045.1.1',
|
||||||
|
'characteristic-two-field' => '1.2.840.10045.1.2',
|
||||||
|
'characteristic-two-basis' => '1.2.840.10045.1.2.3',
|
||||||
|
// per http://www.secg.org/SEC1-Ver-1.0.pdf#page=84, gnBasis "not used here"
|
||||||
|
'gnBasis' => '1.2.840.10045.1.2.3.1', // NULL
|
||||||
|
'tpBasis' => '1.2.840.10045.1.2.3.2', // Trinomial
|
||||||
|
'ppBasis' => '1.2.840.10045.1.2.3.3' // Pentanomial
|
||||||
|
] + self::$curveOIDs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explicitly set the curve
|
||||||
|
*
|
||||||
|
* If the key contains an implicit curve phpseclib needs the curve
|
||||||
|
* to be explicitly provided
|
||||||
|
*
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
*/
|
||||||
|
public static function setImplicitCurve(BaseCurve $curve)
|
||||||
|
{
|
||||||
|
self::$implicitCurve = $curve;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an instance of \phpseclib\Crypt\ECDSA\BaseCurves\Base based
|
||||||
|
* on the curve parameters
|
||||||
|
*
|
||||||
|
* @param array $params
|
||||||
|
* @return \phpseclib\Crypt\ECDSA\BaseCurves\Base|false
|
||||||
|
*/
|
||||||
|
protected static function loadCurveByParam(array $params)
|
||||||
|
{
|
||||||
|
if (count($params) > 1) {
|
||||||
|
throw new \RuntimeException('No parameters are present');
|
||||||
|
}
|
||||||
|
if (isset($params['namedCurve'])) {
|
||||||
|
$curve = '\phpseclib\Crypt\ECDSA\Curves\\' . $params['namedCurve'];
|
||||||
|
if (!class_exists($curve)) {
|
||||||
|
throw new UnsupportedCurveException('Named Curve of ' . $params['namedCurve'] . ' is not supported');
|
||||||
|
}
|
||||||
|
return new $curve();
|
||||||
|
}
|
||||||
|
if (isset($params['implicitCurve'])) {
|
||||||
|
if (!isset(self::$implicitCurve)) {
|
||||||
|
throw new \RuntimeException('Implicit curves can be provided by calling setImplicitCurve');
|
||||||
|
}
|
||||||
|
return self::$implicitCurve;
|
||||||
|
}
|
||||||
|
if (isset($params['specifiedCurve'])) {
|
||||||
|
$data = $params['specifiedCurve'];
|
||||||
|
switch ($data['fieldID']['fieldType']) {
|
||||||
|
case 'prime-field':
|
||||||
|
$curve = new PrimeCurve();
|
||||||
|
$curve->setModulo($data['fieldID']['parameters']);
|
||||||
|
$curve->setCoefficients(
|
||||||
|
new BigInteger($data['curve']['a'], 256),
|
||||||
|
new BigInteger($data['curve']['b'], 256)
|
||||||
|
);
|
||||||
|
$point = self::extractPoint("\0" . $data['base'], $curve);
|
||||||
|
$curve->setBasePoint(...$point);
|
||||||
|
$curve->setOrder($data['order']);
|
||||||
|
return $curve;
|
||||||
|
case 'characteristic-two-field':
|
||||||
|
$curve = new BinaryCurve();
|
||||||
|
$params = ASN1::decodeBER($data['fieldID']['parameters']);
|
||||||
|
$params = ASN1::asn1map($params[0], Maps\Characteristic_two::MAP);
|
||||||
|
$modulo = [(int) $params['m']->toString()];
|
||||||
|
switch ($params['basis']) {
|
||||||
|
case 'tpBasis':
|
||||||
|
$modulo[] = (int) $params['parameters']->toString();
|
||||||
|
break;
|
||||||
|
case 'ppBasis':
|
||||||
|
$temp = ASN1::decodeBER($params['parameters']);
|
||||||
|
$temp = ASN1::asn1map($temp[0], Maps\Pentanomial::MAP);
|
||||||
|
$modulo[] = (int) $temp['k3']->toString();
|
||||||
|
$modulo[] = (int) $temp['k2']->toString();
|
||||||
|
$modulo[] = (int) $temp['k1']->toString();
|
||||||
|
}
|
||||||
|
$modulo[] = 0;
|
||||||
|
$curve->setModulo(...$modulo);
|
||||||
|
$len = ceil($modulo[0] / 8);
|
||||||
|
$curve->setCoefficients(
|
||||||
|
Hex::encode($data['curve']['a']),
|
||||||
|
Hex::encode($data['curve']['b'])
|
||||||
|
);
|
||||||
|
$point = self::extractPoint("\0" . $data['base'], $curve);
|
||||||
|
$curve->setBasePoint(...$point);
|
||||||
|
$curve->setOrder($data['order']);
|
||||||
|
return $curve;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedCurveException('Field Type of ' . $data['fieldID']['fieldType'] . ' is not supported');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new \RuntimeException('No valid parameters are present');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract points from a string
|
||||||
|
*
|
||||||
|
* Supports both compressed and uncompressed points
|
||||||
|
*
|
||||||
|
* @param string $str
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
* @return object[]
|
||||||
|
*/
|
||||||
|
public static function extractPoint($str, BaseCurve $curve)
|
||||||
|
{
|
||||||
|
if ($curve instanceof TwistedEdwardsCurve) {
|
||||||
|
// first step of point deciding as discussed at the following URL's:
|
||||||
|
// https://tools.ietf.org/html/rfc8032#section-5.1.3
|
||||||
|
// https://tools.ietf.org/html/rfc8032#section-5.2.3
|
||||||
|
$y = $str;
|
||||||
|
$y = strrev($y);
|
||||||
|
$sign = (bool) (ord($y[0]) & 0x80);
|
||||||
|
$y[0] = $y[0] & chr(0x7F);
|
||||||
|
$y = new BigInteger($y, 256);
|
||||||
|
if ($y->compare($curve->getModulo()) >= 0) {
|
||||||
|
throw new \RuntimeException('The Y coordinate should not be >= the modulo');
|
||||||
|
}
|
||||||
|
$point = $curve->recoverX($y, $sign);
|
||||||
|
if (!$curve->verifyPoint($point)) {
|
||||||
|
throw new \RuntimeException('Unable to verify that point exists on curve');
|
||||||
|
}
|
||||||
|
return $point;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the first byte of a bit string represents the number of bits in the last byte that are to be ignored but,
|
||||||
|
// currently, bit strings wanting a non-zero amount of bits trimmed are not supported
|
||||||
|
if (($val = Strings::shift($str)) != "\0") {
|
||||||
|
throw new \UnexpectedValueException('extractPoint expects the first byte to be null - not ' . Hex::encode($val));
|
||||||
|
}
|
||||||
|
if ($str == "\0") {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$keylen = strlen($str);
|
||||||
|
$order = $curve->getLengthInBytes();
|
||||||
|
// point compression is being used
|
||||||
|
if ($keylen == $order + 1) {
|
||||||
|
return $curve->derivePoint($str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// point compression is not being used
|
||||||
|
if ($keylen == 2 * $order + 1) {
|
||||||
|
preg_match("#(.)(.{{$order}})(.{{$order}})#s", $str, $matches);
|
||||||
|
list(, $w, $x, $y) = $matches;
|
||||||
|
if ($w != "\4") {
|
||||||
|
throw new \UnexpectedValueException('The first byte of an uncompressed point should be 04 - not ' . Hex::encode($val));
|
||||||
|
}
|
||||||
|
$point = [
|
||||||
|
$curve->convertInteger(new BigInteger($x, 256)),
|
||||||
|
$curve->convertInteger(new BigInteger($y, 256))
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!$curve->verifyPoint($point)) {
|
||||||
|
throw new \RuntimeException('Unable to verify that point exists on curve');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $point;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \UnexpectedValueException('The string representation of the points is not of an appropriate length');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode Parameters
|
||||||
|
*
|
||||||
|
* @todo Maybe at some point this could be moved to __toString() for each of the curves?
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
* @param bool $returnArray
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
private static function encodeParameters(BaseCurve $curve, $returnArray = false)
|
||||||
|
{
|
||||||
|
$reflect = new \ReflectionClass($curve);
|
||||||
|
$name = $reflect->getShortName();
|
||||||
|
if (isset(self::$curveOIDs[$name]) && self::$useNamedCurves) {
|
||||||
|
return $returnArray ?
|
||||||
|
['namedCurve' => $name] :
|
||||||
|
ASN1::encodeDER(['namedCurve' => $name], Maps\ECParameters::MAP);
|
||||||
|
}
|
||||||
|
if (self::$useNamedCurves) {
|
||||||
|
foreach (new \DirectoryIterator(__DIR__ . '/../Curves/') as $file) {
|
||||||
|
if ($file->getExtension() != 'php') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$testName = $file->getBasename('.php');
|
||||||
|
$class = 'phpseclib\Crypt\ECDSA\Curves\\' . $testName;
|
||||||
|
$reflect = new \ReflectionClass($class);
|
||||||
|
if ($reflect->isFinal()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$candidate = new $class();
|
||||||
|
switch ($name) {
|
||||||
|
case 'Prime':
|
||||||
|
if (!$candidate instanceof PrimeCurve) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!$candidate->getModulo()->equals($curve->getModulo())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($candidate->getA()->toBytes() != $curve->getA()->toBytes()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($candidate->getB()->toBytes() != $curve->getB()->toBytes()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
list($candidateX, $candidateY) = $candidate->getBasePoint();
|
||||||
|
list($curveX, $curveY) = $curve->getBasePoint();
|
||||||
|
if ($candidateX->toBytes() != $curveX->toBytes()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($candidateY->toBytes() != $curveY->toBytes()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $returnArray ?
|
||||||
|
['namedCurve' => $testName] :
|
||||||
|
ASN1::encodeDER(['namedCurve' => $testName], Maps\ECParameters::MAP);
|
||||||
|
case 'Binary':
|
||||||
|
if (!$candidate instanceof BinaryCurve) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($candidate->getModulo() != $curve->getModulo()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($candidate->getA()->toBytes() != $curve->getA()->toBytes()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($candidate->getB()->toBytes() != $curve->getB()->toBytes()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
list($candidateX, $candidateY) = $candidate->getBasePoint();
|
||||||
|
list($curveX, $curveY) = $curve->getBasePoint();
|
||||||
|
if ($candidateX->toBytes() != $curveX->toBytes()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($candidateY->toBytes() != $curveY->toBytes()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $returnArray ?
|
||||||
|
['namedCurve' => $testName] :
|
||||||
|
ASN1::encodeDER(['namedCurve' => $testName], Maps\ECParameters::MAP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$order = $curve->getOrder();
|
||||||
|
// we could try to calculate the order thusly:
|
||||||
|
// https://crypto.stackexchange.com/a/27914/4520
|
||||||
|
// https://en.wikipedia.org/wiki/Schoof%E2%80%93Elkies%E2%80%93Atkin_algorithm
|
||||||
|
if (!$order) {
|
||||||
|
throw new \RuntimeException('Specified Curves need the order to be specified');
|
||||||
|
}
|
||||||
|
$point = $curve->getBasePoint();
|
||||||
|
$x = $point[0]->toBytes();
|
||||||
|
$y = $point[1]->toBytes();
|
||||||
|
|
||||||
|
if ($curve instanceof PrimeCurve) {
|
||||||
|
/*
|
||||||
|
* valid versions are:
|
||||||
|
*
|
||||||
|
* ecdpVer1:
|
||||||
|
* - neither the curve or the base point are generated verifiably randomly.
|
||||||
|
* ecdpVer2:
|
||||||
|
* - curve and base point are generated verifiably at random and curve.seed is present
|
||||||
|
* ecdpVer3:
|
||||||
|
* - base point is generated verifiably at random but curve is not. curve.seed is present
|
||||||
|
*/
|
||||||
|
// other (optional) parameters can be calculated using the methods discused at
|
||||||
|
// https://crypto.stackexchange.com/q/28947/4520
|
||||||
|
$data = [
|
||||||
|
'version' => 'ecdpVer1',
|
||||||
|
'fieldID' => [
|
||||||
|
'fieldType' => 'prime-field',
|
||||||
|
'parameters' => $curve->getModulo()
|
||||||
|
],
|
||||||
|
'curve' => [
|
||||||
|
'a' => $curve->getA()->toBytes(),
|
||||||
|
'b' => $curve->getB()->toBytes()
|
||||||
|
],
|
||||||
|
'base' => "\4" . $x . $y,
|
||||||
|
'order' => $order
|
||||||
|
];
|
||||||
|
|
||||||
|
return $returnArray ?
|
||||||
|
['specifiedCurve' => $data] :
|
||||||
|
ASN1::encodeDER(['specifiedCurve' => $data], Maps\ECParameters::MAP);
|
||||||
|
}
|
||||||
|
if ($curve instanceof BinaryCurve) {
|
||||||
|
$modulo = $curve->getModulo();
|
||||||
|
$basis = count($modulo);
|
||||||
|
$m = array_shift($modulo);
|
||||||
|
array_pop($modulo); // the last parameter should always be 0
|
||||||
|
//rsort($modulo);
|
||||||
|
switch ($basis) {
|
||||||
|
case 3:
|
||||||
|
$basis = 'tpBasis';
|
||||||
|
$modulo = new BigInteger($modulo[0]);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
$basis = 'ppBasis';
|
||||||
|
// these should be in strictly ascending order (hence the commented out rsort above)
|
||||||
|
$modulo = [
|
||||||
|
'k1' => new BigInteger($modulo[2]),
|
||||||
|
'k2' => new BigInteger($modulo[1]),
|
||||||
|
'k3' => new BigInteger($modulo[0])
|
||||||
|
];
|
||||||
|
$modulo = ASN1::encodeDER($modulo, Maps\Pentanomial::MAP);
|
||||||
|
$modulo = new ASN1\Element($modulo);
|
||||||
|
}
|
||||||
|
$params = ASN1::encodeDER([
|
||||||
|
'm' => new BigInteger($m),
|
||||||
|
'basis' => $basis,
|
||||||
|
'parameters' => $modulo
|
||||||
|
], Maps\Characteristic_two::MAP);
|
||||||
|
$params = new ASN1\Element($params);
|
||||||
|
$a = ltrim($curve->getA()->toBytes(), "\0");
|
||||||
|
if (!strlen($a)) {
|
||||||
|
$a = "\0";
|
||||||
|
}
|
||||||
|
$b = ltrim($curve->getB()->toBytes(), "\0");
|
||||||
|
if (!strlen($b)) {
|
||||||
|
$b = "\0";
|
||||||
|
}
|
||||||
|
$data = [
|
||||||
|
'version' => 'ecdpVer1',
|
||||||
|
'fieldID' => [
|
||||||
|
'fieldType' => 'characteristic-two-field',
|
||||||
|
'parameters' => $params
|
||||||
|
],
|
||||||
|
'curve' => [
|
||||||
|
'a' => $a,
|
||||||
|
'b' => $b
|
||||||
|
],
|
||||||
|
'base' => "\4" . $x . $y,
|
||||||
|
'order' => $order
|
||||||
|
];
|
||||||
|
|
||||||
|
return $returnArray ?
|
||||||
|
['specifiedCurve' => $data] :
|
||||||
|
ASN1::encodeDER(['specifiedCurve' => $data], Maps\ECParameters::MAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnsupportedCurveException('Curve cannot be serialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use Specified Curve
|
||||||
|
*
|
||||||
|
* A specified curve has all the coefficients, the base points, etc, explicitely included.
|
||||||
|
* A specified curve is a more verbose way of representing a curve
|
||||||
|
*/
|
||||||
|
public static function useSpecifiedCurve()
|
||||||
|
{
|
||||||
|
self::$useNamedCurves = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use Named Curve
|
||||||
|
*
|
||||||
|
* A named curve does not include any parameters. It is up to the ECDSA parameters to
|
||||||
|
* know what the coefficients, the base points, etc, are from the name of the curve.
|
||||||
|
* A named curve is a more concise way of representing a curve
|
||||||
|
*/
|
||||||
|
public static function useNamedCurve()
|
||||||
|
{
|
||||||
|
self::$useNamedCurves = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if named curves are being used by default
|
||||||
|
*
|
||||||
|
* If a named curve is not being used by default than specified curves are being utilized
|
||||||
|
*/
|
||||||
|
public static function isUsingNamedCurves()
|
||||||
|
{
|
||||||
|
return self::$useNamedCurves;
|
||||||
|
}
|
||||||
|
}
|
275
phpseclib/Crypt/ECDSA/Keys/OpenSSH.php
Normal file
275
phpseclib/Crypt/ECDSA/Keys/OpenSSH.php
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenSSH Formatted ECDSA Key Handler
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* Place in $HOME/.ssh/authorized_keys
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2015 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Keys;
|
||||||
|
|
||||||
|
use ParagonIE\ConstantTime\Base64;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Common\Functions\Strings;
|
||||||
|
use phpseclib\Crypt\Common\Keys\OpenSSH as Progenitor;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Base as BaseCurve;
|
||||||
|
use phpseclib\Exception\UnsupportedCurveException;
|
||||||
|
use phpseclib\Crypt\ECDSA\Curves\Ed25519;
|
||||||
|
use phpseclib\Math\Common\FiniteField\Integer;
|
||||||
|
use phpseclib\Crypt\Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenSSH Formatted ECDSA Key Handler
|
||||||
|
*
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
abstract class OpenSSH extends Progenitor
|
||||||
|
{
|
||||||
|
use Common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported Key Types
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $types = [
|
||||||
|
'ecdsa-sha2-nistp256',
|
||||||
|
'ecdsa-sha2-nistp384',
|
||||||
|
'ecdsa-sha2-nistp521',
|
||||||
|
'ssh-ed25519'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break a public or private key down into its constituent components
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param string $password optional
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function load($key, $password = '')
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
key format is described here:
|
||||||
|
https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD
|
||||||
|
|
||||||
|
this is only supported for ECDSA because of Ed25519. ssh-keygen doesn't generate a
|
||||||
|
PKCS1/8 formatted private key for Ed25519 - it generates an OpenSSH formatted
|
||||||
|
private key. probably because, at the time of this writing, there's not an actual
|
||||||
|
IETF RFC describing an Ed25519 format
|
||||||
|
*/
|
||||||
|
if (strpos($key, 'BEGIN OPENSSH PRIVATE KEY') !== false) {
|
||||||
|
$key = preg_replace('#(?:^-.*?-[\r\n]*$)|\s#ms', '', $key);
|
||||||
|
$key = Base64::decode($key);
|
||||||
|
$magic = Strings::shift($key, 15);
|
||||||
|
if ($magic != "openssh-key-v1\0") {
|
||||||
|
throw new \RuntimeException('Expected openssh-key-v1');
|
||||||
|
}
|
||||||
|
list($ciphername, $kdfname, $kdfoptions, $numKeys) = Strings::unpackSSH2('sssN', $key);
|
||||||
|
if ($numKeys != 1) {
|
||||||
|
throw new \RuntimeException('Although the OpenSSH private key format supports multiple keys phpseclib does not');
|
||||||
|
}
|
||||||
|
if (strlen($kdfoptions) || $kdfname != 'none' || $ciphername != 'none') {
|
||||||
|
/*
|
||||||
|
OpenSSH private keys use a customized version of bcrypt. specifically, instead of encrypting
|
||||||
|
OrpheanBeholderScryDoubt 64 times OpenSSH's bcrypt variant encrypts
|
||||||
|
OxychromaticBlowfishSwatDynamite 64 times. so we can't use crypt().
|
||||||
|
|
||||||
|
bcrypt is basically Blowfish with an altered key expansion. whereas Blowfish just runs the
|
||||||
|
key through the key expansion bcrypt interleaves the key expansion with the salt and
|
||||||
|
password. this renders openssl / mcrypt unusuable. this forces us to use a pure-PHP implementation
|
||||||
|
of bcrypt. the problem with that is that pure-PHP is too slow to be practically useful.
|
||||||
|
|
||||||
|
in addition to encrypting a different string 64 times the OpenSSH also performs bcrypt from
|
||||||
|
scratch $rounds times. calling crypt() 64x with bcrypt takes 0.7s. PHP is going to be naturally
|
||||||
|
slower. pure-PHP is 215x slower than OpenSSL for AES and pure-PHP is 43x slower for bcrypt.
|
||||||
|
43 * 0.7 = 30s. no one wants to wait 30s to load a private key.
|
||||||
|
|
||||||
|
another way to think about this.. according to wikipedia's article on Blowfish,
|
||||||
|
"Each new key requires pre-processing equivalent to encrypting about 4 kilobytes of text".
|
||||||
|
key expansion is done (9+64*2)*160 times. multiply that by 4 and it turns out that Blowfish,
|
||||||
|
OpenSSH style, is the equivalent of encrypting ~80mb of text.
|
||||||
|
|
||||||
|
more supporting evidence: sodium_compat does not implement Argon2 (another password hashing
|
||||||
|
algorithm) because "It's not feasible to polyfill scrypt or Argon2 into PHP and get reasonable
|
||||||
|
performance. Users would feel motivated to select parameters that downgrade security to avoid
|
||||||
|
denial of service (DoS) attacks. The only winning move is not to play"
|
||||||
|
-- https://github.com/paragonie/sodium_compat/blob/master/README.md
|
||||||
|
*/
|
||||||
|
throw new \RuntimeException('Encrypted OpenSSH private keys are not supported');
|
||||||
|
//list($salt, $rounds) = Strings::unpackSSH2('sN', $kdfoptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($publicKey, $paddedKey) = Strings::unpackSSH2('ss', $key);
|
||||||
|
list($type, $publicKey) = Strings::unpackSSH2('ss', $publicKey);
|
||||||
|
if ($type != 'ssh-ed25519') {
|
||||||
|
throw new UnsupportedCurveException('ssh-ed25519 is the only supported curve for OpenSSH public keys');
|
||||||
|
}
|
||||||
|
list($checkint1, $checkint2, $type, $publicKey2, $privateKey, $comment) = Strings::unpackSSH2('NNssss', $paddedKey);
|
||||||
|
// any leftover bytes in $paddedKey are for padding? but they should be sequential bytes. eg. 1, 2, 3, etc.
|
||||||
|
if ($checkint1 != $checkint2) {
|
||||||
|
throw new \RuntimeException('The two checkints do not match');
|
||||||
|
}
|
||||||
|
if ($type != 'ssh-ed25519') {
|
||||||
|
throw new UnsupportedCurveException('ssh-ed25519 is the only supported curve for OpenSSH private keys');
|
||||||
|
}
|
||||||
|
if ($publicKey != $publicKey2 || $publicKey2 != substr($privateKey, 32)) {
|
||||||
|
throw new \RuntimeException('The public keys do not match up');
|
||||||
|
}
|
||||||
|
$privateKey = substr($privateKey, 0, 32);
|
||||||
|
$curve = new Ed25519();
|
||||||
|
return [
|
||||||
|
'curve' => $curve,
|
||||||
|
'dA' => $curve->extractSecret($privateKey),
|
||||||
|
'QA' => self::extractPoint($publicKey, $curve),
|
||||||
|
'comment' => $comment
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$parts = explode(' ', $key, 3);
|
||||||
|
|
||||||
|
if (!isset($parts[1])) {
|
||||||
|
$key = Base64::decode($parts[0]);
|
||||||
|
$comment = isset($parts[1]) ? $parts[1] : false;
|
||||||
|
} else {
|
||||||
|
$asciiType = $parts[0];
|
||||||
|
if (!in_array($asciiType, self::$types)) {
|
||||||
|
throw new \RuntimeException('Keys of type ' . $asciiType . ' are not supported');
|
||||||
|
}
|
||||||
|
$key = Base64::decode($parts[1]);
|
||||||
|
$comment = isset($parts[2]) ? $parts[2] : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
list($binaryType) = Strings::unpackSSH2('s', $key);
|
||||||
|
if (isset($asciiType) && $asciiType != $binaryType) {
|
||||||
|
throw new \RuntimeException('Two different types of keys are claimed: ' . $asciiType . ' and ' . $binaryType);
|
||||||
|
} elseif (!isset($asciiType) && !in_array($binaryType, self::$types)) {
|
||||||
|
throw new \RuntimeException('Keys of type ' . $binaryType . ' are not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($binaryType == 'ssh-ed25519') {
|
||||||
|
if (Strings::shift($key, 4) != "\0\0\0\x20") {
|
||||||
|
throw new \RuntimeException('Length of ssh-ed25519 key should be 32');
|
||||||
|
}
|
||||||
|
|
||||||
|
$curve = new Ed25519();
|
||||||
|
$qa = self::extractPoint($key, $curve);
|
||||||
|
} else {
|
||||||
|
list($curveName, $publicKey) = Strings::unpackSSH2('ss', $key);
|
||||||
|
$curveName = '\phpseclib\Crypt\ECDSA\Curves\\' . $curveName;
|
||||||
|
$curve = new $curveName();
|
||||||
|
|
||||||
|
$qa = self::extractPoint("\0" . $publicKey, $curve);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'curve' => $curve,
|
||||||
|
'QA' => $qa,
|
||||||
|
'comment' => $comment
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an ECDSA public key to the appropriate format
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function savePublicKey(BaseCurve $curve, array $publicKey)
|
||||||
|
{
|
||||||
|
if ($curve instanceof Ed25519) {
|
||||||
|
$key = Strings::packSSH2('ss', 'ssh-ed25519', $curve->encodePoint($publicKey));
|
||||||
|
$key = 'ssh-ed25519 ' . Base64::encode($key) . ' ' . self::$comment;
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
$reflect = new \ReflectionClass($curve);
|
||||||
|
$name = $reflect->getShortName();
|
||||||
|
|
||||||
|
$oid = self::$curveOIDs[$name];
|
||||||
|
$aliases = array_filter(self::$curveOIDs, function($v) use ($oid) {
|
||||||
|
return $v == $oid;
|
||||||
|
});
|
||||||
|
$aliases = array_keys($aliases);
|
||||||
|
|
||||||
|
for ($i = 0; $i < count($aliases); $i++) {
|
||||||
|
if (in_array('ecdsa-sha2-' . $aliases[$i], self::$types)) {
|
||||||
|
$alias = $aliases[$i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($alias)) {
|
||||||
|
throw new UnsupportedCurveException($name . ' is not a curve that the OpenSSH plugin supports');
|
||||||
|
}
|
||||||
|
|
||||||
|
$points = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
|
||||||
|
$key = Strings::packSSH2('sss', 'ecdsa-sha2-' . $alias, $alias, $points);
|
||||||
|
|
||||||
|
if (self::$binary) {
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = 'ecdsa-sha2-' . $alias . ' ' . Base64::encode($key) . ' ' . self::$comment;
|
||||||
|
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a private key to the appropriate format.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer $privateKey
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\Curves\Ed25519 $curve
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
|
* @param string $password optional
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function savePrivateKey(Integer $privateKey, Ed25519 $curve, array $publicKey, $password = '')
|
||||||
|
{
|
||||||
|
if (!isset($privateKey->secret)) {
|
||||||
|
throw new \RuntimeException('Private Key does not have a secret set');
|
||||||
|
}
|
||||||
|
if (strlen($privateKey->secret) != 32) {
|
||||||
|
throw new \RuntimeException('Private Key secret is not of the correct length');
|
||||||
|
}
|
||||||
|
|
||||||
|
list(, $checkint) = unpack('N', Random::string(4));
|
||||||
|
$pubKey = $curve->encodePoint($publicKey);
|
||||||
|
|
||||||
|
$publicKey = Strings::packSSH2('ss', 'ssh-ed25519', $pubKey);
|
||||||
|
$paddedKey = Strings::packSSH2('NNssss', $checkint, $checkint, 'ssh-ed25519', $pubKey, $privateKey->secret . $pubKey, self::$comment);
|
||||||
|
/*
|
||||||
|
from http://tools.ietf.org/html/rfc4253#section-6 :
|
||||||
|
|
||||||
|
Note that the length of the concatenation of 'packet_length',
|
||||||
|
'padding_length', 'payload', and 'random padding' MUST be a multiple
|
||||||
|
of the cipher block size or 8, whichever is larger.
|
||||||
|
*/
|
||||||
|
$paddingLength = (7 * strlen($paddedKey)) % 8;
|
||||||
|
for ($i = 1; $i <= $paddingLength; $i++) {
|
||||||
|
$paddedKey.= chr($i);
|
||||||
|
}
|
||||||
|
$key = Strings::packSSH2('sssNss', 'none', 'none', '', 1, $publicKey, $paddedKey);
|
||||||
|
$key = "openssh-key-v1\0$key";
|
||||||
|
|
||||||
|
return "-----BEGIN OPENSSH PRIVATE KEY-----\r\n" .
|
||||||
|
chunk_split(Base64::encode($key), 70) .
|
||||||
|
"-----END OPENSSH PRIVATE KEY-----";
|
||||||
|
}
|
||||||
|
}
|
141
phpseclib/Crypt/ECDSA/Keys/PKCS1.php
Normal file
141
phpseclib/Crypt/ECDSA/Keys/PKCS1.php
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "PKCS1" (RFC5915) Formatted ECDSA Key Handler
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* Used by File/X509.php
|
||||||
|
*
|
||||||
|
* Processes keys with the following headers:
|
||||||
|
*
|
||||||
|
* -----BEGIN EC PRIVATE KEY-----
|
||||||
|
* -----BEGIN EC PARAMETERS-----
|
||||||
|
*
|
||||||
|
* Technically, PKCS1 is for RSA keys, only, but we're using PKCS1 to describe
|
||||||
|
* DSA, whose format isn't really formally described anywhere, so might as well
|
||||||
|
* use it to describe this, too. PKCS1 is easier to remember than RFC5915, after
|
||||||
|
* all. I suppose this could also be named IETF but idk
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2015 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Keys;
|
||||||
|
|
||||||
|
use phpseclib\Math\Common\FiniteField\Integer;
|
||||||
|
use phpseclib\Crypt\Common\Keys\PKCS1 as Progenitor;
|
||||||
|
use phpseclib\File\ASN1;
|
||||||
|
use phpseclib\File\ASN1\Maps;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Base as BaseCurve;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use ParagonIE\ConstantTime\Base64;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
||||||
|
use phpseclib\Exception\UnsupportedCurveException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "PKCS1" (RFC5915) Formatted ECDSA Key Handler
|
||||||
|
*
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
abstract class PKCS1 extends Progenitor
|
||||||
|
{
|
||||||
|
use Common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break a public or private key down into its constituent components
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param string $password optional
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function load($key, $password = '')
|
||||||
|
{
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
$key = parent::load($key, $password);
|
||||||
|
|
||||||
|
$decoded = ASN1::decodeBER($key);
|
||||||
|
if (empty($decoded)) {
|
||||||
|
throw new \RuntimeException('Unable to decode BER');
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP);
|
||||||
|
if (is_array($key)) {
|
||||||
|
return ['curve' => self::loadCurveByParam($key)];
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP);
|
||||||
|
if (!is_array($key)) {
|
||||||
|
throw new \RuntimeException('Unable to perform ASN1 mapping');
|
||||||
|
}
|
||||||
|
|
||||||
|
$components = [];
|
||||||
|
$components['curve'] = self::loadCurveByParam($key['parameters']);
|
||||||
|
$temp = new BigInteger($key['privateKey'], 256);
|
||||||
|
$components['dA'] = $components['curve']->convertInteger($temp);
|
||||||
|
$components['QA'] = self::extractPoint($key['publicKey'], $components['curve']);
|
||||||
|
|
||||||
|
return $components;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert ECDSA parameters to the appropriate format
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function saveParameters(BaseCurve $curve)
|
||||||
|
{
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if ($curve instanceof TwistedEdwardsCurve) {
|
||||||
|
throw new UnsupportedCurveException('TwistedEdwards Curves are not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = self::encodeParameters($curve);
|
||||||
|
|
||||||
|
return "-----BEGIN EC PARAMETERS-----\r\n" .
|
||||||
|
chunk_split(Base64::encode($key), 64) .
|
||||||
|
"-----END EC PARAMETERS-----\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a private key to the appropriate format.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer $privateKey
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
|
* @param string $password optional
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function savePrivateKey(Integer $privateKey, BaseCurve $curve, array $publicKey, $password = '')
|
||||||
|
{
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if ($curve instanceof TwistedEdwardsCurve) {
|
||||||
|
throw new UnsupportedCurveException('TwistedEdwards Curves are not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$publicKey = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
|
||||||
|
|
||||||
|
$key = [
|
||||||
|
'version' => 'ecPrivkeyVer1',
|
||||||
|
'privateKey' => $privateKey->toBytes(),
|
||||||
|
'parameters' => new ASN1\Element(self::encodeParameters($curve)),
|
||||||
|
'publicKey' => "\0" . $publicKey
|
||||||
|
];
|
||||||
|
|
||||||
|
$key = ASN1::encodeDER($key, Maps\ECPrivateKey::MAP);
|
||||||
|
|
||||||
|
return self::wrapPrivateKey($key, 'EC', $password);
|
||||||
|
}
|
||||||
|
}
|
233
phpseclib/Crypt/ECDSA/Keys/PKCS8.php
Normal file
233
phpseclib/Crypt/ECDSA/Keys/PKCS8.php
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PKCS#8 Formatted ECDSA Key Handler
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* Processes keys with the following headers:
|
||||||
|
*
|
||||||
|
* -----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||||
|
* -----BEGIN PRIVATE KEY-----
|
||||||
|
* -----BEGIN PUBLIC KEY-----
|
||||||
|
*
|
||||||
|
* Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
|
||||||
|
* is specific to private keys it's basically creating a DER-encoded wrapper
|
||||||
|
* for keys. This just extends that same concept to public keys (much like ssh-keygen)
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2015 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Keys;
|
||||||
|
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Crypt\Common\Keys\PKCS8 as Progenitor;
|
||||||
|
use phpseclib\File\ASN1;
|
||||||
|
use phpseclib\File\ASN1\Maps;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Base as BaseCurve;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
||||||
|
use phpseclib\Math\Common\FiniteField\Integer;
|
||||||
|
use phpseclib\Crypt\ECDSA\Curves\Ed25519;
|
||||||
|
use phpseclib\Crypt\ECDSA\Curves\Ed448;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PKCS#8 Formatted ECDSA Key Handler
|
||||||
|
*
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
abstract class PKCS8 extends Progenitor
|
||||||
|
{
|
||||||
|
use Common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OID Name
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
const OID_NAME = ['id-ecPublicKey', 'id-Ed25519', 'id-Ed448'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OID Value
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
const OID_VALUE = ['1.2.840.10045.2.1', '1.3.101.112', '1.3.101.113'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break a public or private key down into its constituent components
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param string $password optional
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function load($key, $password = '')
|
||||||
|
{
|
||||||
|
// initialize_static_variables() is defined in both the trait and the parent class
|
||||||
|
// when it's defined in two places it's the traits one that's called
|
||||||
|
// the parent one is needed, as well, but the parent one is called by other methods
|
||||||
|
// in the parent class as needed and in the context of the parent it's the parent
|
||||||
|
// one that's called
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if (!is_string($key)) {
|
||||||
|
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||||
|
}
|
||||||
|
|
||||||
|
$isPublic = strpos($key, 'PUBLIC') !== false;
|
||||||
|
|
||||||
|
$key = parent::load($key, $password);
|
||||||
|
|
||||||
|
$type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
|
||||||
|
|
||||||
|
switch (true) {
|
||||||
|
case !$isPublic && $type == 'publicKey':
|
||||||
|
throw new \UnexpectedValueException('Human readable string claims non-public key but DER encoded string claims public key');
|
||||||
|
case $isPublic && $type == 'privateKey':
|
||||||
|
throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($key[$type . 'Algorithm']['algorithm']) {
|
||||||
|
case 'id-Ed25519':
|
||||||
|
case 'id-Ed448':
|
||||||
|
return self::loadEdDSA($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
|
||||||
|
$params = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP);
|
||||||
|
|
||||||
|
$components = [];
|
||||||
|
$components['curve'] = self::loadCurveByParam($params);
|
||||||
|
|
||||||
|
if ($isPublic) {
|
||||||
|
$components['QA'] = self::extractPoint("\0" . $key['publicKey'], $components['curve']);
|
||||||
|
|
||||||
|
return $components;
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoded = ASN1::decodeBER($key['privateKey']);
|
||||||
|
$key = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP);
|
||||||
|
if (isset($key['parameters']) && $params != $key['parameters']) {
|
||||||
|
throw new \RuntimeException('The PKCS8 parameter field does not match the private key parameter field');
|
||||||
|
}
|
||||||
|
|
||||||
|
$temp = new BigInteger($key['privateKey'], 256);
|
||||||
|
$components['dA'] = $components['curve']->convertInteger($temp);
|
||||||
|
|
||||||
|
$components['QA'] = self::extractPoint($key['publicKey'], $components['curve']);
|
||||||
|
|
||||||
|
return $components;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break a public or private EdDSA key down into its constituent components
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private static function loadEdDSA(array $key)
|
||||||
|
{
|
||||||
|
$components = [];
|
||||||
|
|
||||||
|
if (isset($key['privateKey'])) {
|
||||||
|
$components['curve'] = $key['privateKeyAlgorithm']['algorithm'] == 'id-Ed25519' ? new Ed25519() : new Ed448();
|
||||||
|
|
||||||
|
// 0x04 == octet string
|
||||||
|
// 0x20 == length (32 bytes)
|
||||||
|
if (substr($key['privateKey'], 0, 2) != "\x04\x20") {
|
||||||
|
throw new \RuntimeException('The first two bytes of the private key field should be 0x0420');
|
||||||
|
}
|
||||||
|
$components['dA'] = $components['curve']->extractSecret(substr($key['privateKey'], 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($key['publicKey'])) {
|
||||||
|
if (!isset($components['curve'])) {
|
||||||
|
$components['curve'] = $key['publicKeyAlgorithm']['algorithm'] == 'id-Ed25519' ? new Ed25519() : new Ed448();
|
||||||
|
}
|
||||||
|
|
||||||
|
$components['QA'] = self::extractPoint(substr($key['publicKey'], 1), $components['curve']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($key['privateKey']) && !isset($components['QA'])) {
|
||||||
|
$components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $components;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an ECDSA public key to the appropriate format
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function savePublicKey(BaseCurve $curve, array $publicKey)
|
||||||
|
{
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if ($curve instanceof TwistedEdwardsCurve) {
|
||||||
|
return self::wrapPublicKey(
|
||||||
|
$curve->encodePoint($publicKey),
|
||||||
|
null,
|
||||||
|
$curve instanceof Ed25519 ? 'id-Ed25519' : 'id-Ed448'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = new ASN1\Element(self::encodeParameters($curve));
|
||||||
|
|
||||||
|
$key = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
|
||||||
|
|
||||||
|
return self::wrapPublicKey($key, $params, 'id-ecPublicKey');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a private key to the appropriate format.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer $privateKey
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
|
* @param string $password optional
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function savePrivateKey(Integer $privateKey, BaseCurve $curve, array $publicKey, $password = '')
|
||||||
|
{
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if ($curve instanceof TwistedEdwardsCurve) {
|
||||||
|
return self::wrapPrivateKey(
|
||||||
|
"\x04\x20" . $privateKey->secret,
|
||||||
|
[],
|
||||||
|
null,
|
||||||
|
$password,
|
||||||
|
$curve instanceof Ed25519 ? 'id-Ed25519' : 'id-Ed448',
|
||||||
|
$curve->encodePoint($publicKey)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$publicKey = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
|
||||||
|
|
||||||
|
$params = new ASN1\Element(self::encodeParameters($curve));
|
||||||
|
|
||||||
|
$key = [
|
||||||
|
'version' => 'ecPrivkeyVer1',
|
||||||
|
'privateKey' => $privateKey->toBytes(),
|
||||||
|
//'parameters' => $params,
|
||||||
|
'publicKey' => "\0" . $publicKey
|
||||||
|
];
|
||||||
|
|
||||||
|
$key = ASN1::encodeDER($key, Maps\ECPrivateKey::MAP);
|
||||||
|
|
||||||
|
return self::wrapPrivateKey($key, [], $params, $password, 'id-ecPublicKey');
|
||||||
|
}
|
||||||
|
}
|
145
phpseclib/Crypt/ECDSA/Keys/PuTTY.php
Normal file
145
phpseclib/Crypt/ECDSA/Keys/PuTTY.php
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PuTTY Formatted ECDSA Key Handler
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2015 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Keys;
|
||||||
|
|
||||||
|
use ParagonIE\ConstantTime\Base64;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Common\Functions\Strings;
|
||||||
|
use phpseclib\Crypt\Common\Keys\PuTTY as Progenitor;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Base as BaseCurve;
|
||||||
|
use phpseclib\Math\Common\FiniteField\Integer;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PuTTY Formatted ECDSA Key Handler
|
||||||
|
*
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
abstract class PuTTY extends Progenitor
|
||||||
|
{
|
||||||
|
use Common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public Handler
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
const PUBLIC_HANDLER = 'phpseclib\Crypt\ECDSA\Keys\OpenSSH';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported Key Types
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
protected static $types = [
|
||||||
|
'ecdsa-sha2-nistp256',
|
||||||
|
'ecdsa-sha2-nistp384',
|
||||||
|
'ecdsa-sha2-nistp521',
|
||||||
|
'ssh-ed25519'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break a public or private key down into its constituent components
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param string $password optional
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function load($key, $password = '')
|
||||||
|
{
|
||||||
|
$components = parent::load($key, $password);
|
||||||
|
if (!isset($components['private'])) {
|
||||||
|
return $components;
|
||||||
|
}
|
||||||
|
|
||||||
|
$private = $components['private'];
|
||||||
|
|
||||||
|
$temp = Base64::encode(Strings::packSSH2('s', $components['type']) . $components['public']);
|
||||||
|
$components = OpenSSH::load($components['type'] . ' ' . $temp . ' ' . $components['comment']);
|
||||||
|
|
||||||
|
if ($components['curve'] instanceof TwistedEdwardsCurve) {
|
||||||
|
if (Strings::shift($private, 4) != "\0\0\0\x20") {
|
||||||
|
throw new \RuntimeException('Length of ssh-ed25519 key should be 32');
|
||||||
|
}
|
||||||
|
$components['dA'] = $components['curve']->extractSecret($private);
|
||||||
|
} else {
|
||||||
|
list($temp) = Strings::unpackSSH2('i', $private);
|
||||||
|
$components['dA'] = $components['curve']->convertInteger($temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $components;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a private key to the appropriate format.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer $privateKey
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
|
* @param string $password optional
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function savePrivateKey(Integer $privateKey, BaseCurve $curve, array $publicKey, $password = false)
|
||||||
|
{
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
$public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey));
|
||||||
|
$name = $public[0];
|
||||||
|
$public = Base64::decode($public[1]);
|
||||||
|
list(, $length) = unpack('N', Strings::shift($public, 4));
|
||||||
|
Strings::shift($public, $length);
|
||||||
|
|
||||||
|
// PuTTY pads private keys with a null byte per the following:
|
||||||
|
// https://github.com/github/putty/blob/a3d14d77f566a41fc61dfdc5c2e0e384c9e6ae8b/sshecc.c#L1926
|
||||||
|
if (!$curve instanceof TwistedEdwardsCurve) {
|
||||||
|
$private = $privateKey->toBytes();
|
||||||
|
if (!(strlen($privateKey->toBits()) & 7)) {
|
||||||
|
$private ="\0$private";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$private = $curve instanceof TwistedEdwardsCurve ?
|
||||||
|
Strings::packSSH2('s', $privateKey->secret) :
|
||||||
|
Strings::packSSH2('s', $private);
|
||||||
|
|
||||||
|
return self::wrapPrivateKey($public, $private, $name, $password);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an ECDSA public key to the appropriate format
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField[] $publicKey
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function savePublicKey(BaseCurve $curve, array $publicKey)
|
||||||
|
{
|
||||||
|
$public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey));
|
||||||
|
$type = $public[0];
|
||||||
|
$public = Base64::decode($public[1]);
|
||||||
|
list(, $length) = unpack('N', Strings::shift($public, 4));
|
||||||
|
Strings::shift($public, $length);
|
||||||
|
|
||||||
|
return self::wrapPublicKey($public, $type);
|
||||||
|
}
|
||||||
|
}
|
480
phpseclib/Crypt/ECDSA/Keys/XML.php
Normal file
480
phpseclib/Crypt/ECDSA/Keys/XML.php
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML Formatted ECDSA Key Handler
|
||||||
|
*
|
||||||
|
* More info:
|
||||||
|
*
|
||||||
|
* https://www.w3.org/TR/xmldsig-core/#sec-ECKeyValue
|
||||||
|
* http://en.wikipedia.org/wiki/XML_Signature
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2015 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Keys;
|
||||||
|
|
||||||
|
use ParagonIE\ConstantTime\Base64;
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Base as BaseCurve;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\Prime as PrimeCurve;
|
||||||
|
use phpseclib\Crypt\ECDSA\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
||||||
|
use phpseclib\Exception\UnsupportedCurveException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML Formatted ECDSA Key Handler
|
||||||
|
*
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
abstract class XML
|
||||||
|
{
|
||||||
|
use Common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default namespace
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private static $namespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag for using RFC4050 syntax
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $rfc4050 = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break a public or private key down into its constituent components
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param string $password optional
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function load($key, $password = '')
|
||||||
|
{
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if (!is_string($key)) {
|
||||||
|
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||||
|
}
|
||||||
|
|
||||||
|
$use_errors = libxml_use_internal_errors(true);
|
||||||
|
|
||||||
|
$temp = self::isolateNamespace($key, 'http://www.w3.org/2009/xmldsig11#');
|
||||||
|
if ($temp) {
|
||||||
|
$key = $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
$temp = self::isolateNamespace($key, 'http://www.w3.org/2001/04/xmldsig-more#');
|
||||||
|
if ($temp) {
|
||||||
|
$key = $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dom = new \DOMDocument();
|
||||||
|
if (substr($key, 0, 5) != '<?xml') {
|
||||||
|
$key = '<xml>' . $key . '</xml>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$dom->loadXML($key)) {
|
||||||
|
libxml_use_internal_errors($use_errors);
|
||||||
|
throw new \UnexpectedValueException('Key does not appear to contain XML');
|
||||||
|
}
|
||||||
|
$xpath = new \DOMXPath($dom);
|
||||||
|
libxml_use_internal_errors($use_errors);
|
||||||
|
$curve = self::loadCurveByParam($xpath);
|
||||||
|
|
||||||
|
$pubkey = self::query($xpath, 'publickey', 'Public Key is not present');
|
||||||
|
|
||||||
|
$QA = self::query($xpath, 'ecdsakeyvalue')->length ?
|
||||||
|
self::extractPointRFC4050($xpath, $curve) :
|
||||||
|
self::extractPoint("\0" . $pubkey, $curve);
|
||||||
|
|
||||||
|
libxml_use_internal_errors($use_errors);
|
||||||
|
|
||||||
|
return compact('curve', 'QA');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Case-insensitive xpath query
|
||||||
|
*
|
||||||
|
* @param \DOMXPath $xpath
|
||||||
|
* @param string $name
|
||||||
|
* @param string $error optional
|
||||||
|
* @param bool $decode optional
|
||||||
|
* @return \DOMNodeList
|
||||||
|
*/
|
||||||
|
private static function query($xpath, $name, $error = null, $decode = true)
|
||||||
|
{
|
||||||
|
$query = '/';
|
||||||
|
$names = explode('/', $name);
|
||||||
|
foreach ($names as $name) {
|
||||||
|
$query.= "/*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$name']";
|
||||||
|
}
|
||||||
|
$result = $xpath->query($query);
|
||||||
|
if (!isset($error)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$result->length) {
|
||||||
|
throw new \RuntimeException($error);
|
||||||
|
}
|
||||||
|
return $decode ? self::decodeValue($result->item(0)->textContent) : $result->item(0)->textContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the first element in the relevant namespace, strips the namespacing and returns the XML for that element.
|
||||||
|
*
|
||||||
|
* @param string $xml
|
||||||
|
* @param string $ns
|
||||||
|
*/
|
||||||
|
private static function isolateNamespace($xml, $ns)
|
||||||
|
{
|
||||||
|
$dom = new \DOMDocument();
|
||||||
|
if (!$dom->loadXML($xml)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$xpath = new \DOMXPath($dom);
|
||||||
|
$nodes = $xpath->query("//*[namespace::*[.='$ns'] and not(../namespace::*[.='$ns'])]");
|
||||||
|
if (!$nodes->length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$node = $nodes->item(0);
|
||||||
|
$ns_name = $node->lookupPrefix($ns);
|
||||||
|
$node->removeAttributeNS($ns, $ns_name);
|
||||||
|
return $dom->saveXML($node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the value
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
private static function decodeValue($value)
|
||||||
|
{
|
||||||
|
return Base64::decode(str_replace(["\r", "\n", ' ', "\t"], '', $value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract points from an XML document
|
||||||
|
*
|
||||||
|
* @param \DOMXPath $xpath
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
* @return object[]
|
||||||
|
*/
|
||||||
|
private static function extractPointRFC4050(\DOMXPath $xpath, BaseCurve $curve)
|
||||||
|
{
|
||||||
|
$x = self::query($xpath, 'publickey/x');
|
||||||
|
$y = self::query($xpath, 'publickey/y');
|
||||||
|
if (!$x->length || !$x->item(0)->hasAttribute('Value')) {
|
||||||
|
throw new \RuntimeException('Public Key / X coordinate not found');
|
||||||
|
}
|
||||||
|
if (!$y->length || !$y->item(0)->hasAttribute('Value')) {
|
||||||
|
throw new \RuntimeException('Public Key / Y coordinate not found');
|
||||||
|
}
|
||||||
|
$point = [
|
||||||
|
$curve->convertInteger(new BigInteger($x->item(0)->getAttribute('Value'))),
|
||||||
|
$curve->convertInteger(new BigInteger($y->item(0)->getAttribute('Value')))
|
||||||
|
];
|
||||||
|
if (!$curve->verifyPoint($point)) {
|
||||||
|
throw new \RuntimeException('Unable to verify that point exists on curve');
|
||||||
|
}
|
||||||
|
return $point;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an instance of \phpseclib\Crypt\ECDSA\BaseCurves\Base based
|
||||||
|
* on the curve parameters
|
||||||
|
*
|
||||||
|
* @param \DomXPath $xpath
|
||||||
|
* @return \phpseclib\Crypt\ECDSA\BaseCurves\Base|false
|
||||||
|
*/
|
||||||
|
private static function loadCurveByParam(\DOMXPath $xpath)
|
||||||
|
{
|
||||||
|
$namedCurve = self::query($xpath, 'namedcurve');
|
||||||
|
if ($namedCurve->length == 1) {
|
||||||
|
$oid = $namedCurve->item(0)->getAttribute('URN');
|
||||||
|
$oid = preg_replace('#[^\d.]#', '', $oid);
|
||||||
|
$name = array_search($oid, self::$curveOIDs);
|
||||||
|
if ($name === false) {
|
||||||
|
throw new UnsupportedCurveException('Curve with OID of ' . $oid . ' is not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$curve = '\phpseclib\Crypt\ECDSA\Curves\\' . $name;
|
||||||
|
if (!class_exists($curve)) {
|
||||||
|
throw new UnsupportedCurveException('Named Curve of ' . $name . ' is not supported');
|
||||||
|
}
|
||||||
|
return new $curve();
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = self::query($xpath, 'explicitparams');
|
||||||
|
if ($params->length) {
|
||||||
|
return self::loadCurveByParamRFC4050($xpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = self::query($xpath, 'ecparameters');
|
||||||
|
if (!$params->length) {
|
||||||
|
throw new \RuntimeException('No parameters are present');
|
||||||
|
}
|
||||||
|
|
||||||
|
$fieldTypes = [
|
||||||
|
'prime-field' => ['fieldid/prime/p'],
|
||||||
|
'gnb' => ['fieldid/gnb/m'],
|
||||||
|
'tnb' => ['fieldid/tnb/k'],
|
||||||
|
'pnb' => ['fieldid/pnb/k1', 'fieldid/pnb/k2', 'fieldid/pnb/k3'],
|
||||||
|
'unknown' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($fieldTypes as $type => $queries) {
|
||||||
|
foreach ($queries as $query) {
|
||||||
|
$result = self::query($xpath, $query);
|
||||||
|
if (!$result->length) {
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
$param = preg_replace('#.*/#', '', $query);
|
||||||
|
$$param = self::decodeValue($result->item(0)->textContent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = self::query($xpath, 'curve/a', 'A coefficient is not present');
|
||||||
|
$b = self::query($xpath, 'curve/b', 'B coefficient is not present');
|
||||||
|
$base = self::query($xpath, 'base', 'Base point is not present');
|
||||||
|
$order = self::query($xpath, 'order', 'Order is not present');
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'prime-field':
|
||||||
|
$curve = new PrimeCurve();
|
||||||
|
$curve->setModulo(new BigInteger($p, 256));
|
||||||
|
$curve->setCoefficients(
|
||||||
|
new BigInteger($a, 256),
|
||||||
|
new BigInteger($b, 256)
|
||||||
|
);
|
||||||
|
$point = self::extractPoint("\0" . $base, $curve);
|
||||||
|
$curve->setBasePoint(...$point);
|
||||||
|
$curve->setOrder(new BigInteger($order, 256));
|
||||||
|
return $curve;
|
||||||
|
case 'gnb':
|
||||||
|
case 'tnb':
|
||||||
|
case 'pnb':
|
||||||
|
default:
|
||||||
|
throw new UnsupportedCurveException('Field Type of ' . $type . ' is not supported');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an instance of \phpseclib\Crypt\ECDSA\BaseCurves\Base based
|
||||||
|
* on the curve parameters
|
||||||
|
*
|
||||||
|
* @param \DomXPath $xpath
|
||||||
|
* @return \phpseclib\Crypt\ECDSA\BaseCurves\Base|false
|
||||||
|
*/
|
||||||
|
private static function loadCurveByParamRFC4050(\DOMXPath $xpath)
|
||||||
|
{
|
||||||
|
$fieldTypes = [
|
||||||
|
'prime-field' => ['primefieldparamstype/p'],
|
||||||
|
'unknown' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($fieldTypes as $type => $queries) {
|
||||||
|
foreach ($queries as $query) {
|
||||||
|
$result = self::query($xpath, $query);
|
||||||
|
if (!$result->length) {
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
$param = preg_replace('#.*/#', '', $query);
|
||||||
|
$$param = $result->item(0)->textContent;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = self::query($xpath, 'curveparamstype/a', 'A coefficient is not present', false);
|
||||||
|
$b = self::query($xpath, 'curveparamstype/b', 'B coefficient is not present', false);
|
||||||
|
$x = self::query($xpath, 'basepointparams/basepoint/ecpointtype/x', 'Base Point X is not present', false);
|
||||||
|
$y = self::query($xpath, 'basepointparams/basepoint/ecpointtype/y', 'Base Point Y is not present', false);
|
||||||
|
$order = self::query($xpath, 'order', 'Order is not present', false);
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'prime-field':
|
||||||
|
$curve = new PrimeCurve();
|
||||||
|
|
||||||
|
$p = str_replace(["\r", "\n", ' ', "\t"], '', $p);
|
||||||
|
$curve->setModulo(new BigInteger($p));
|
||||||
|
|
||||||
|
$a = str_replace(["\r", "\n", ' ', "\t"], '', $a);
|
||||||
|
$b = str_replace(["\r", "\n", ' ', "\t"], '', $b);
|
||||||
|
$curve->setCoefficients(
|
||||||
|
new BigInteger($a),
|
||||||
|
new BigInteger($b)
|
||||||
|
);
|
||||||
|
|
||||||
|
$x = str_replace(["\r", "\n", ' ', "\t"], '', $x);
|
||||||
|
$y = str_replace(["\r", "\n", ' ', "\t"], '', $y);
|
||||||
|
$curve->setBasePoint(
|
||||||
|
new BigInteger($x),
|
||||||
|
new BigInteger($y)
|
||||||
|
);
|
||||||
|
|
||||||
|
$order = str_replace(["\r", "\n", ' ', "\t"], '', $order);
|
||||||
|
$curve->setOrder(new BigInteger($order));
|
||||||
|
return $curve;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedCurveException('Field Type of ' . $type . ' is not supported');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the namespace. dsig11 is the most common one.
|
||||||
|
*
|
||||||
|
* Set to null to unset. Used only for creating public keys.
|
||||||
|
*
|
||||||
|
* @param string $namespace
|
||||||
|
*/
|
||||||
|
public static function setNamespace($namespace)
|
||||||
|
{
|
||||||
|
self::$namespace = $namespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the XML syntax specified in https://tools.ietf.org/html/rfc4050
|
||||||
|
*/
|
||||||
|
public static function enableRFC4050Syntax()
|
||||||
|
{
|
||||||
|
self::$rfc4050 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the XML syntax specified in https://www.w3.org/TR/xmldsig-core/#sec-ECParameters
|
||||||
|
*/
|
||||||
|
public static function disableRFC4050Syntax()
|
||||||
|
{
|
||||||
|
self::$rfc4050 = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a public key to the appropriate format
|
||||||
|
*
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function savePublicKey(BaseCurve $curve, array $publicKey)
|
||||||
|
{
|
||||||
|
self::initialize_static_variables();
|
||||||
|
|
||||||
|
if ($curve instanceof TwistedEdwardsCurve) {
|
||||||
|
throw new UnsupportedCurveException('TwistedEdwards Curves are not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty(static::$namespace)) {
|
||||||
|
$pre = $post = '';
|
||||||
|
} else {
|
||||||
|
$pre = static::$namespace . ':';
|
||||||
|
$post = ':' . static::$namespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$rfc4050) {
|
||||||
|
return '<' . $pre . 'ECDSAKeyValue xmlns' . $post . '="http://www.w3.org/2001/04/xmldsig-more#">' . "\r\n" .
|
||||||
|
self::encodeXMLParameters($curve, $pre) . "\r\n" .
|
||||||
|
'<' . $pre . 'PublicKey>' . "\r\n" .
|
||||||
|
'<' . $pre . 'X Value="' . $publicKey[0] . '" />' . "\r\n" .
|
||||||
|
'<' . $pre . 'Y Value="' . $publicKey[1] . '" />' . "\r\n" .
|
||||||
|
'</' . $pre . 'PublicKey>' . "\r\n" .
|
||||||
|
'</' . $pre . 'ECDSAKeyValue>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$publicKey = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
|
||||||
|
|
||||||
|
return '<' . $pre . 'ECKeyValue xmlns' . $post . '="http://www.w3.org/2009/xmldsig11#">' . "\r\n" .
|
||||||
|
self::encodeXMLParameters($curve, $pre) . "\r\n" .
|
||||||
|
'<' . $pre . 'PublicKey>' . Base64::encode($publicKey) . '</' . $pre . 'PublicKey>' . "\r\n" .
|
||||||
|
'</' . $pre . 'ECKeyValue>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode Parameters
|
||||||
|
*
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\BaseCurves\Base $curve
|
||||||
|
* @param string $pre
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
private static function encodeXMLParameters(BaseCurve $curve, $pre)
|
||||||
|
{
|
||||||
|
$result = self::encodeParameters($curve, true);
|
||||||
|
|
||||||
|
if (isset($result['namedCurve'])) {
|
||||||
|
$namedCurve = '<' . $pre . 'NamedCurve URI="urn:oid:' . self::$curveOIDs[$result['namedCurve']] . '" />';
|
||||||
|
return self::$rfc4050 ?
|
||||||
|
'<DomainParameters>' . str_replace('URI', 'URN', $namedCurve) . '</DomainParameters>' :
|
||||||
|
$namedCurve;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$rfc4050) {
|
||||||
|
$xml = '<' . $pre . 'ExplicitParams>' . "\r\n" .
|
||||||
|
'<' . $pre . 'FieldParams>' . "\r\n";
|
||||||
|
$temp = $result['specifiedCurve'];
|
||||||
|
switch ($temp['fieldID']['fieldType']) {
|
||||||
|
case 'prime-field':
|
||||||
|
$xml.= '<' . $pre . 'PrimeFieldParamsType>' . "\r\n" .
|
||||||
|
'<' . $pre . 'P>' . $temp['fieldID']['parameters'] . '</' . $pre . 'P>' . "\r\n" .
|
||||||
|
'</' . $pre . 'PrimeFieldParamsType>' . "\r\n";
|
||||||
|
$a = $curve->getA();
|
||||||
|
$b = $curve->getB();
|
||||||
|
list($x, $y) = $curve->getBasePoint();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedCurveException('Field Type of ' . $temp['fieldID']['fieldType'] . ' is not supported');
|
||||||
|
}
|
||||||
|
$xml.= '</' . $pre . 'FieldParams>' . "\r\n" .
|
||||||
|
'<' . $pre . 'CurveParamsType>' . "\r\n" .
|
||||||
|
'<' . $pre . 'A>' . $a . '</' . $pre . 'A>' . "\r\n" .
|
||||||
|
'<' . $pre . 'B>' . $b . '</' . $pre . 'B>' . "\r\n" .
|
||||||
|
'</' . $pre . 'CurveParamsType>' . "\r\n" .
|
||||||
|
'<' . $pre . 'BasePointParams>' . "\r\n" .
|
||||||
|
'<' . $pre . 'BasePoint>' . "\r\n" .
|
||||||
|
'<' . $pre . 'ECPointType>' . "\r\n" .
|
||||||
|
'<' . $pre . 'X>' . $x . '</' . $pre . 'X>' . "\r\n" .
|
||||||
|
'<' . $pre . 'Y>' . $y . '</' . $pre . 'Y>' . "\r\n" .
|
||||||
|
'</' . $pre . 'ECPointType>' . "\r\n" .
|
||||||
|
'</' . $pre . 'BasePoint>' . "\r\n" .
|
||||||
|
'<' . $pre . 'Order>' . $curve->getOrder() . '</' . $pre . 'Order>' . "\r\n" .
|
||||||
|
'</' . $pre . 'BasePointParams>' . "\r\n" .
|
||||||
|
'</' . $pre . 'ExplicitParams>' . "\r\n";
|
||||||
|
|
||||||
|
return $xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($result['specifiedCurve'])) {
|
||||||
|
$xml = '<' . $pre . 'ECParameters>' . "\r\n" .
|
||||||
|
'<' . $pre . 'FieldID>' . "\r\n";
|
||||||
|
$temp = $result['specifiedCurve'];
|
||||||
|
switch ($temp['fieldID']['fieldType']) {
|
||||||
|
case 'prime-field':
|
||||||
|
$xml.= '<' . $pre . 'Prime>' . "\r\n" .
|
||||||
|
'<' . $pre . 'P>' . Base64::encode($temp['fieldID']['parameters']->toBytes()) . '</' . $pre . 'P>' . "\r\n" .
|
||||||
|
'</' . $pre . 'Prime>' . "\r\n" ;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedCurveException('Field Type of ' . $temp['fieldID']['fieldType'] . ' is not supported');
|
||||||
|
}
|
||||||
|
$xml.= '</' . $pre . 'FieldID>' . "\r\n" .
|
||||||
|
'<' . $pre . 'Curve>' . "\r\n" .
|
||||||
|
'<' . $pre . 'A>' . Base64::encode($temp['curve']['a']) . '</' . $pre . 'A>' . "\r\n" .
|
||||||
|
'<' . $pre . 'B>' . Base64::encode($temp['curve']['b']) . '</' . $pre . 'B>' . "\r\n" .
|
||||||
|
'</' . $pre . 'Curve>' . "\r\n" .
|
||||||
|
'<' . $pre . 'Base>' . Base64::encode($temp['base']) . '</' . $pre . 'Base>' . "\r\n" .
|
||||||
|
'<' . $pre . 'Order>' . Base64::encode($temp['order']) . '</' . $pre . 'Order>' . "\r\n" .
|
||||||
|
'</' . $pre . 'ECParameters>';
|
||||||
|
return $xml;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
111
phpseclib/Crypt/ECDSA/Keys/libsodium.php
Normal file
111
phpseclib/Crypt/ECDSA/Keys/libsodium.php
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libsodium Key Handler
|
||||||
|
*
|
||||||
|
* Different NaCl implementations store the key differently.
|
||||||
|
* https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/ elaborates.
|
||||||
|
* libsodium appears to use the same format as SUPERCOP.
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2015 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Keys;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\ECDSA\Curves\Ed25519;
|
||||||
|
use phpseclib\Math\Common\FiniteField\Integer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libsodium Key Handler
|
||||||
|
*
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
abstract class libsodium
|
||||||
|
{
|
||||||
|
use Common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break a public or private key down into its constituent components
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param string $password optional
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function load($key, $password = '')
|
||||||
|
{
|
||||||
|
switch (strlen($key)) {
|
||||||
|
case 32:
|
||||||
|
$public = $key;
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
$private = substr($key, 0, 32);
|
||||||
|
$public = substr($key, -32);
|
||||||
|
break;
|
||||||
|
case 96:
|
||||||
|
$public = substr($key, -32);
|
||||||
|
if (substr($key, 32, 32) != $public) {
|
||||||
|
throw new \RuntimeException('Keys with 96 bytes should have the 2nd and 3rd set of 32 bytes match');
|
||||||
|
}
|
||||||
|
$private = substr($key, 0, 32);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new \RuntimeException('libsodium keys need to either be 32 bytes long, 64 bytes long or 96 bytes long');
|
||||||
|
}
|
||||||
|
|
||||||
|
$curve = new Ed25519();
|
||||||
|
$components = ['curve' => $curve];
|
||||||
|
if (isset($private)) {
|
||||||
|
$components['dA'] = $curve->extractSecret($private);
|
||||||
|
}
|
||||||
|
$components['QA'] = isset($public) ?
|
||||||
|
self::extractPoint($public, $curve) :
|
||||||
|
$curve->multiplyPoint($curve->getBasePoint(), $components['dA']);
|
||||||
|
|
||||||
|
|
||||||
|
return $components;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an ECDSA public key to the appropriate format
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\Curves\Ed25519 $curve
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function savePublicKey(Ed25519 $curve, array $publicKey)
|
||||||
|
{
|
||||||
|
return $curve->encodePoint($publicKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a private key to the appropriate format.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer $privateKey
|
||||||
|
* @param \phpseclib\Crypt\ECDSA\Curves\Ed25519 $curve
|
||||||
|
* @param \phpseclib\Math\Common\FiniteField\Integer[] $publicKey
|
||||||
|
* @param string $password optional
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function savePrivateKey(Integer $privateKey, Ed25519 $curve, array $publicKey, $password = '')
|
||||||
|
{
|
||||||
|
if (!isset($privateKey->secret)) {
|
||||||
|
throw new \RuntimeException('Private Key does not have a secret set');
|
||||||
|
}
|
||||||
|
if (strlen($privateKey->secret) != 32) {
|
||||||
|
throw new \RuntimeException('Private Key secret is not of the correct length');
|
||||||
|
}
|
||||||
|
return $privateKey->secret . $curve->encodePoint($publicKey);
|
||||||
|
}
|
||||||
|
}
|
68
phpseclib/Crypt/ECDSA/Signature/ASN1.php
Normal file
68
phpseclib/Crypt/ECDSA/Signature/ASN1.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ASN1 Signature Handler
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* Handles signatures in the format described in
|
||||||
|
* https://tools.ietf.org/html/rfc3279#section-2.2.3
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package Common
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2016 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Signature;
|
||||||
|
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\File\ASN1 as Encoder;
|
||||||
|
use phpseclib\File\ASN1\Maps\EcdsaSigValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ASN1 Signature Handler
|
||||||
|
*
|
||||||
|
* @package Common
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
abstract class ASN1
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Loads a signature
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $key
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function load($sig)
|
||||||
|
{
|
||||||
|
if (!is_string($sig)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoded = Encoder::decodeBER($sig);
|
||||||
|
if (empty($decoded)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$components = Encoder::asn1map($decoded[0], EcdsaSigValue::MAP);
|
||||||
|
|
||||||
|
return $components;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a signature in the appropriate format
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \phpseclib\Math\BigInteger $r
|
||||||
|
* @param \phpseclib\Math\BigInteger $s
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function save(BigInteger $r, BigInteger $s)
|
||||||
|
{
|
||||||
|
return Encoder::encodeDER(compact('r', 's'), EcdsaSigValue::MAP);
|
||||||
|
}
|
||||||
|
}
|
29
phpseclib/Crypt/ECDSA/Signature/Raw.php
Normal file
29
phpseclib/Crypt/ECDSA/Signature/Raw.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw ECDSA Signature Handler
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package DSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2016 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Signature;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Common\Signature\Raw as Progenitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw DSA Signature Handler
|
||||||
|
*
|
||||||
|
* @package ECDSA
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
abstract class Raw extends Progenitor
|
||||||
|
{
|
||||||
|
}
|
95
phpseclib/Crypt/ECDSA/Signature/SSH2.php
Normal file
95
phpseclib/Crypt/ECDSA/Signature/SSH2.php
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SSH2 Signature Handler
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* Handles signatures in the format used by SSH2
|
||||||
|
*
|
||||||
|
* @category Crypt
|
||||||
|
* @package Common
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2016 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib\Crypt\ECDSA\Signature;
|
||||||
|
|
||||||
|
use phpseclib\Math\BigInteger;
|
||||||
|
use phpseclib\Common\Functions\Strings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SSH2 Signature Handler
|
||||||
|
*
|
||||||
|
* @package Common
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
abstract class SSH2
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Loads a signature
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $sig
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function load($sig)
|
||||||
|
{
|
||||||
|
if (!is_string($sig)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = Strings::unpackSSH2('ss', $sig);
|
||||||
|
if ($result === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
list($type, $blob) = $result;
|
||||||
|
switch ($type) {
|
||||||
|
// see https://tools.ietf.org/html/rfc5656#section-3.1.2
|
||||||
|
case 'ecdsa-sha2-nistp256':
|
||||||
|
case 'ecdsa-sha2-nistp384':
|
||||||
|
case 'ecdsa-sha2-nistp521':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = ceil(substr($type, 16) / 8);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'r' => new BigInteger(substr($blob, 0, $length), 256),
|
||||||
|
's' => new BigInteger(substr($blob, $length), 256)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a signature in the appropriate format
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \phpseclib\Math\BigInteger $r
|
||||||
|
* @param \phpseclib\Math\BigInteger $s
|
||||||
|
* @param string $curve
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function save(BigInteger $r, BigInteger $s, $curve)
|
||||||
|
{
|
||||||
|
switch ($curve) {
|
||||||
|
case 'nistp256':
|
||||||
|
case 'nistp384':
|
||||||
|
case 'nistp521':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = ceil(substr($curve, 5) / 8);
|
||||||
|
|
||||||
|
return Strings::packSSH2('ss', 'ecdsa-sha2-' . $curve,
|
||||||
|
str_pad($r->toBytes(), $length, "\0", STR_PAD_LEFT) .
|
||||||
|
str_pad($s->toBytes(), $length, "\0", STR_PAD_LEFT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -45,7 +45,6 @@
|
|||||||
|
|
||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
use ParagonIE\ConstantTime\Base64;
|
|
||||||
use phpseclib\File\ASN1;
|
use phpseclib\File\ASN1;
|
||||||
use phpseclib\Math\BigInteger;
|
use phpseclib\Math\BigInteger;
|
||||||
use phpseclib\Common\Functions\Strings;
|
use phpseclib\Common\Functions\Strings;
|
||||||
@ -203,14 +202,6 @@ class RSA extends AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
private $sLen;
|
private $sLen;
|
||||||
|
|
||||||
/**
|
|
||||||
* Comment
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
private $comment;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash function for the Mask Generation Function
|
* Hash function for the Mask Generation Function
|
||||||
*
|
*
|
||||||
@ -332,40 +323,11 @@ class RSA extends AsymmetricKey
|
|||||||
* @return array
|
* @return array
|
||||||
* @access public
|
* @access public
|
||||||
* @param int $bits
|
* @param int $bits
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public static function createKey($bits = 2048)
|
public static function createKey($bits = 2048)
|
||||||
{
|
{
|
||||||
self::initialize_static_variables();
|
self::initialize_static_variables();
|
||||||
|
|
||||||
if (!isset(self::$engine)) {
|
|
||||||
self::setPreferredEngine(self::ENGINE_OPENSSL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum
|
|
||||||
|
|
||||||
if (self::$engine == self::ENGINE_OPENSSL && $bits >= 384 && self::$defaultExponent == 65537) {
|
|
||||||
$config = [];
|
|
||||||
if (isset(self::$configFile)) {
|
|
||||||
$config['config'] = self::$configFile;
|
|
||||||
}
|
|
||||||
$rsa = openssl_pkey_new(['private_key_bits' => $bits] + $config);
|
|
||||||
openssl_pkey_export($rsa, $privatekeystr, null, $config);
|
|
||||||
$privatekey = new RSA();
|
|
||||||
$privatekey->load($privatekeystr);
|
|
||||||
|
|
||||||
$publickeyarr = openssl_pkey_get_details($rsa);
|
|
||||||
$publickey = new RSA();
|
|
||||||
$publickey->load($publickeyarr['key']);
|
|
||||||
$publickey->setPublicKey();
|
|
||||||
|
|
||||||
// clear the buffer of error strings stemming from a minimalistic openssl.cnf
|
|
||||||
while (openssl_error_string() !== false) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return compact('privatekey', 'publickey');
|
|
||||||
}
|
|
||||||
|
|
||||||
static $e;
|
static $e;
|
||||||
if (!isset($e)) {
|
if (!isset($e)) {
|
||||||
$e = new BigInteger(self::$defaultExponent);
|
$e = new BigInteger(self::$defaultExponent);
|
||||||
@ -488,7 +450,8 @@ class RSA extends AsymmetricKey
|
|||||||
$this->isPublic = $key->isPublic;
|
$this->isPublic = $key->isPublic;
|
||||||
|
|
||||||
if (is_object($key->hash)) {
|
if (is_object($key->hash)) {
|
||||||
$this->hash = new Hash($key->hash->getHash());
|
$this->hashName = $key->hash->getHash();
|
||||||
|
$this->hash = new Hash($this->hashName);
|
||||||
}
|
}
|
||||||
if (is_object($key->mgfHash)) {
|
if (is_object($key->mgfHash)) {
|
||||||
$this->mgfHash = new Hash($key->mgfHash->getHash());
|
$this->mgfHash = new Hash($key->mgfHash->getHash());
|
||||||
@ -531,6 +494,7 @@ class RSA extends AsymmetricKey
|
|||||||
$this->exponents = null;
|
$this->exponents = null;
|
||||||
$this->coefficients = null;
|
$this->coefficients = null;
|
||||||
$this->publicExponent = null;
|
$this->publicExponent = null;
|
||||||
|
$this->isPublic = false;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -652,6 +616,19 @@ class RSA extends AsymmetricKey
|
|||||||
return !isset($this->modulus) ? 0 : $this->modulus->getLength();
|
return !isset($this->modulus) ? 0 : $this->modulus->getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current engine being used
|
||||||
|
*
|
||||||
|
* @see self::useInternalEngine()
|
||||||
|
* @see self::useBestEngine()
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getEngine()
|
||||||
|
{
|
||||||
|
return 'PHP';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the public key
|
* Defines the public key
|
||||||
*
|
*
|
||||||
@ -704,15 +681,25 @@ class RSA extends AsymmetricKey
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does the key self-identify as being a public key or not?
|
* Is the key a public key?
|
||||||
*
|
*
|
||||||
* @see self::isPublicKey()
|
|
||||||
* @access public
|
* @access public
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isPublicKey()
|
public function isPublicKey()
|
||||||
{
|
{
|
||||||
return $this->isPublic();
|
return $this->isPublic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the key a private key?
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPrivateKey()
|
||||||
|
{
|
||||||
|
return !$this->isPublic && isset($this->modulus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -735,6 +722,7 @@ class RSA extends AsymmetricKey
|
|||||||
{
|
{
|
||||||
if ($key === false && !empty($this->publicExponent)) {
|
if ($key === false && !empty($this->publicExponent)) {
|
||||||
$this->publicExponent = false;
|
$this->publicExponent = false;
|
||||||
|
$this->isPublic = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -743,6 +731,7 @@ class RSA extends AsymmetricKey
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$rsa->publicExponent = false;
|
$rsa->publicExponent = false;
|
||||||
|
$rsa->isPublic = false;
|
||||||
|
|
||||||
// don't overwrite the old key if the new key is invalid
|
// don't overwrite the old key if the new key is invalid
|
||||||
$this->load($rsa);
|
$this->load($rsa);
|
||||||
@ -761,8 +750,14 @@ class RSA extends AsymmetricKey
|
|||||||
* @param string $type optional
|
* @param string $type optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getPublicKey($type = 'PKCS8')
|
public function getPublicKey($type = null)
|
||||||
{
|
{
|
||||||
|
$returnObj = false;
|
||||||
|
if ($type === null) {
|
||||||
|
$returnObj = true;
|
||||||
|
$type = 'PKCS8';
|
||||||
|
}
|
||||||
|
|
||||||
$type = self::validatePlugin('Keys', $type, 'savePublicKey');
|
$type = self::validatePlugin('Keys', $type, 'savePublicKey');
|
||||||
if ($type === false) {
|
if ($type === false) {
|
||||||
return false;
|
return false;
|
||||||
@ -772,7 +767,15 @@ class RSA extends AsymmetricKey
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $type::savePublicKey($this->modulus, $this->publicExponent);
|
$key = $type::savePublicKey($this->modulus, $this->publicExponent);
|
||||||
|
if (!$returnObj) {
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
$public = clone $this;
|
||||||
|
$public->load($key, 'PKCS8');
|
||||||
|
|
||||||
|
return $public;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1704,17 +1707,17 @@ class RSA extends AsymmetricKey
|
|||||||
static $oids;
|
static $oids;
|
||||||
if (!isset($oids)) {
|
if (!isset($oids)) {
|
||||||
$oids = [
|
$oids = [
|
||||||
'1.2.840.113549.2.2' => 'md2',
|
'md2' => '1.2.840.113549.2.2',
|
||||||
'1.2.840.113549.2.4' => 'md4', // from PKCS1 v1.5
|
'md4' => '1.2.840.113549.2.4', // from PKCS1 v1.5
|
||||||
'1.2.840.113549.2.5' => 'md5',
|
'md5' => '1.2.840.113549.2.5',
|
||||||
'1.3.14.3.2.26' => 'id-sha1',
|
'id-sha1' => '1.3.14.3.2.26',
|
||||||
'2.16.840.1.101.3.4.2.1' => 'id-sha256',
|
'id-sha256' => '2.16.840.1.101.3.4.2.1',
|
||||||
'2.16.840.1.101.3.4.2.2' => 'id-sha384',
|
'id-sha384' => '2.16.840.1.101.3.4.2.2',
|
||||||
'2.16.840.1.101.3.4.2.3' => 'id-sha512',
|
'id-sha512' => '2.16.840.1.101.3.4.2.3',
|
||||||
// from PKCS1 v2.2
|
// from PKCS1 v2.2
|
||||||
'2.16.840.1.101.3.4.2.4' => 'id-sha224',
|
'id-sha224' => '2.16.840.1.101.3.4.2.4',
|
||||||
'2.16.840.1.101.3.4.2.5' => 'id-sha512/224',
|
'id-sha512/224' => '2.16.840.1.101.3.4.2.5',
|
||||||
'2.16.840.1.101.3.4.2.6' => 'id-sha512/256',
|
'id-sha512/256' => '2.16.840.1.101.3.4.2.6',
|
||||||
];
|
];
|
||||||
ASN1::loadOIDs($oids);
|
ASN1::loadOIDs($oids);
|
||||||
}
|
}
|
||||||
@ -1724,7 +1727,7 @@ class RSA extends AsymmetricKey
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in_array($decoded['digestAlgorithm']['algorithm'], $oids)) {
|
if (!isset($oids[$decoded['digestAlgorithm']['algorithm']])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,18 +71,21 @@ abstract class MSBLOB
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return array|bool
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function load($key, $password = '')
|
public static function load($key, $password = '')
|
||||||
{
|
{
|
||||||
if (!is_string($key)) {
|
if (!is_string($key)) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
$key = Base64::decode($key);
|
$key = Base64::decode($key);
|
||||||
|
|
||||||
if (!is_string($key) || strlen($key) < 20) {
|
if (!is_string($key)) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Base64 decoding produced an error');
|
||||||
|
}
|
||||||
|
if (strlen($key) < 20) {
|
||||||
|
throw new \UnexpectedValueException('Key appears to be malformed');
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUBLICKEYSTRUC publickeystruc
|
// PUBLICKEYSTRUC publickeystruc
|
||||||
@ -103,7 +106,7 @@ abstract class MSBLOB
|
|||||||
$publickey = false;
|
$publickey = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
throw new \UnexpectedValueException('Key appears to be malformed');
|
||||||
}
|
}
|
||||||
|
|
||||||
$components = ['isPublicKey' => $publickey];
|
$components = ['isPublicKey' => $publickey];
|
||||||
@ -114,7 +117,7 @@ abstract class MSBLOB
|
|||||||
case self::CALG_RSA_SIGN:
|
case self::CALG_RSA_SIGN:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
throw new \UnexpectedValueException('Key appears to be malformed');
|
||||||
}
|
}
|
||||||
|
|
||||||
// RSAPUBKEY rsapubkey
|
// RSAPUBKEY rsapubkey
|
||||||
@ -132,12 +135,12 @@ abstract class MSBLOB
|
|||||||
case self::RSA1:
|
case self::RSA1:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
throw new \UnexpectedValueException('Key appears to be malformed');
|
||||||
}
|
}
|
||||||
|
|
||||||
$baseLength = $bitlen / 16;
|
$baseLength = $bitlen / 16;
|
||||||
if (strlen($key) != 2 * $baseLength && strlen($key) != 9 * $baseLength) {
|
if (strlen($key) != 2 * $baseLength && strlen($key) != 9 * $baseLength) {
|
||||||
return false;
|
throw new \UnexpectedValueException('Key appears to be malformed');
|
||||||
}
|
}
|
||||||
|
|
||||||
$components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(strrev($pubexp), 256);
|
$components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(strrev($pubexp), 256);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user