mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-24 11:05:30 +00:00
undo merging of master to 2.0 branch
This commit is contained in:
parent
b3171cc63f
commit
8fb4c3363d
@ -1,6 +1,6 @@
|
|||||||
# phpseclib - PHP Secure Communications Library
|
# phpseclib - PHP Secure Communications Library
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/phpseclib/phpseclib.svg?branch=master)](https://travis-ci.org/phpseclib/phpseclib)
|
[![Build Status](https://travis-ci.org/phpseclib/phpseclib.svg?branch=2.0)](https://travis-ci.org/phpseclib/phpseclib)
|
||||||
|
|
||||||
MIT-licensed pure-PHP implementations of an arbitrary-precision integer
|
MIT-licensed pure-PHP implementations of an arbitrary-precision integer
|
||||||
arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael,
|
arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael,
|
||||||
@ -8,7 +8,7 @@ AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
|
|||||||
|
|
||||||
* [Download (1.0.1)](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.1.zip/download)
|
* [Download (1.0.1)](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.1.zip/download)
|
||||||
* [Browse Git](https://github.com/phpseclib/phpseclib)
|
* [Browse Git](https://github.com/phpseclib/phpseclib)
|
||||||
* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/master/latest/)
|
* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/2.0/latest/)
|
||||||
|
|
||||||
<img src="http://phpseclib.sourceforge.net/pear-icon.png" alt="PEAR Channel" width="16" height="16">
|
<img src="http://phpseclib.sourceforge.net/pear-icon.png" alt="PEAR Channel" width="16" height="16">
|
||||||
PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.htm)
|
PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.htm)
|
||||||
@ -16,7 +16,7 @@ PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.
|
|||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
* [Documentation / Manual](http://phpseclib.sourceforge.net/)
|
* [Documentation / Manual](http://phpseclib.sourceforge.net/)
|
||||||
* [API Documentation](http://phpseclib.bantux.org/api/master/) (generated by Sami)
|
* [API Documentation](http://phpseclib.bantux.org/api/2.0/) (generated by Sami)
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
|
@ -51,7 +51,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"paragonie/random_compat": "^1.4|^2.0",
|
|
||||||
"php": ">=5.3.3"
|
"php": ">=5.3.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
55
composer.lock
generated
55
composer.lock
generated
@ -4,58 +4,9 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"hash": "deb73cf7e6004dbc2550a38c4082df2d",
|
"hash": "8599992bf6058a9da82372eb8bcae2c2",
|
||||||
"content-hash": "39f9dd8d2c209ff69eebbb83e367257e",
|
"content-hash": "fde47c84178c55c06de858a2128e3d07",
|
||||||
"packages": [
|
"packages": [],
|
||||||
{
|
|
||||||
"name": "paragonie/random_compat",
|
|
||||||
"version": "v2.0.2",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/paragonie/random_compat.git",
|
|
||||||
"reference": "088c04e2f261c33bed6ca5245491cfca69195ccf"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/088c04e2f261c33bed6ca5245491cfca69195ccf",
|
|
||||||
"reference": "088c04e2f261c33bed6ca5245491cfca69195ccf",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.2.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "4.*|5.*"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"lib/random.php"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Paragon Initiative Enterprises",
|
|
||||||
"email": "security@paragonie.com",
|
|
||||||
"homepage": "https://paragonie.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
|
|
||||||
"keywords": [
|
|
||||||
"csprng",
|
|
||||||
"pseudorandom",
|
|
||||||
"random"
|
|
||||||
],
|
|
||||||
"time": "2016-04-03 06:00:07"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
"name": "doctrine/instantiator",
|
"name": "doctrine/instantiator",
|
||||||
|
@ -49,6 +49,8 @@
|
|||||||
|
|
||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Rijndael;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of AES.
|
* Pure-PHP implementation of AES.
|
||||||
*
|
*
|
||||||
@ -66,32 +68,30 @@ class AES extends Rijndael
|
|||||||
* @see \phpseclib\Crypt\Rijndael::setBlockLength()
|
* @see \phpseclib\Crypt\Rijndael::setBlockLength()
|
||||||
* @access public
|
* @access public
|
||||||
* @param int $length
|
* @param int $length
|
||||||
* @throws \BadMethodCallException anytime it's called
|
|
||||||
*/
|
*/
|
||||||
function setBlockLength($length)
|
function setBlockLength($length)
|
||||||
{
|
{
|
||||||
throw new \BadMethodCallException('The block length cannot be set for AES.');
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the key length
|
* Sets the key length
|
||||||
*
|
*
|
||||||
* Valid key lengths are 128, 192, and 256. Set the link to bool(false) to disable a fixed key length
|
* Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to
|
||||||
|
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
|
||||||
*
|
*
|
||||||
* @see \phpseclib\Crypt\Rijndael:setKeyLength()
|
* @see \phpseclib\Crypt\Rijndael:setKeyLength()
|
||||||
* @access public
|
* @access public
|
||||||
* @param int $length
|
* @param int $length
|
||||||
* @throws \LengthException if the key length isn't supported
|
|
||||||
*/
|
*/
|
||||||
function setKeyLength($length)
|
function setKeyLength($length)
|
||||||
{
|
{
|
||||||
switch ($length) {
|
switch ($length) {
|
||||||
case 128:
|
case 160:
|
||||||
case 192:
|
$length = 192;
|
||||||
case 256:
|
|
||||||
break;
|
break;
|
||||||
default:
|
case 224:
|
||||||
throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 128, 192 or 256 supported');
|
$length = 256;
|
||||||
}
|
}
|
||||||
parent::setKeyLength($length);
|
parent::setKeyLength($length);
|
||||||
}
|
}
|
||||||
@ -105,19 +105,24 @@ class AES extends Rijndael
|
|||||||
* @see setKeyLength()
|
* @see setKeyLength()
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @throws \LengthException if the key length isn't supported
|
|
||||||
*/
|
*/
|
||||||
function setKey($key)
|
function setKey($key)
|
||||||
{
|
{
|
||||||
switch (strlen($key)) {
|
|
||||||
case 16:
|
|
||||||
case 24:
|
|
||||||
case 32:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::setKey($key);
|
parent::setKey($key);
|
||||||
|
|
||||||
|
if (!$this->explicit_key_length) {
|
||||||
|
$length = strlen($key);
|
||||||
|
switch (true) {
|
||||||
|
case $length <= 16:
|
||||||
|
$this->key_length = 16;
|
||||||
|
break;
|
||||||
|
case $length <= 24:
|
||||||
|
$this->key_length = 24;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->key_length = 32;
|
||||||
|
}
|
||||||
|
$this->_setEngine();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
|
|
||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Hash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Class for all \phpseclib\Crypt\* cipher classes
|
* Base Class for all \phpseclib\Crypt\* cipher classes
|
||||||
*
|
*
|
||||||
@ -139,7 +141,7 @@ abstract class Base
|
|||||||
* @var string
|
* @var string
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $key = false;
|
var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Initialization Vector
|
* The Initialization Vector
|
||||||
@ -148,7 +150,7 @@ abstract class Base
|
|||||||
* @var string
|
* @var string
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $iv = false;
|
var $iv;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A "sliding" Initialization Vector
|
* A "sliding" Initialization Vector
|
||||||
@ -429,15 +431,6 @@ abstract class Base
|
|||||||
*/
|
*/
|
||||||
var $openssl_options;
|
var $openssl_options;
|
||||||
|
|
||||||
/**
|
|
||||||
* Don't truncate / null pad key
|
|
||||||
*
|
|
||||||
* @see self::_clearBuffers()
|
|
||||||
* @var bool
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $skip_key_adjustment = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Has the key length explicitly been set or should it be derived from the key, itself?
|
* Has the key length explicitly been set or should it be derived from the key, itself?
|
||||||
*
|
*
|
||||||
@ -447,9 +440,20 @@ abstract class Base
|
|||||||
*/
|
*/
|
||||||
var $explicit_key_length = false;
|
var $explicit_key_length = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't truncate / null pad key
|
||||||
|
*
|
||||||
|
* @see self::_clearBuffers()
|
||||||
|
* @var bool
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $skip_key_adjustment = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
|
* Determines whether or not the mcrypt extension should be used.
|
||||||
|
*
|
||||||
* $mode could be:
|
* $mode could be:
|
||||||
*
|
*
|
||||||
* - self::MODE_ECB
|
* - self::MODE_ECB
|
||||||
@ -462,29 +466,32 @@ abstract class Base
|
|||||||
*
|
*
|
||||||
* - self::MODE_OFB
|
* - self::MODE_OFB
|
||||||
*
|
*
|
||||||
|
* If not explicitly set, self::MODE_CBC will be used.
|
||||||
|
*
|
||||||
* @param int $mode
|
* @param int $mode
|
||||||
* @access public
|
* @access public
|
||||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
|
||||||
*/
|
*/
|
||||||
function __construct($mode)
|
function __construct($mode = self::MODE_CBC)
|
||||||
{
|
{
|
||||||
// $mode dependent settings
|
// $mode dependent settings
|
||||||
switch ($mode) {
|
switch ($mode) {
|
||||||
case self::MODE_ECB:
|
case self::MODE_ECB:
|
||||||
case self::MODE_CBC:
|
|
||||||
$this->paddable = true;
|
$this->paddable = true;
|
||||||
|
$this->mode = self::MODE_ECB;
|
||||||
break;
|
break;
|
||||||
case self::MODE_CTR:
|
case self::MODE_CTR:
|
||||||
case self::MODE_CFB:
|
case self::MODE_CFB:
|
||||||
case self::MODE_OFB:
|
case self::MODE_OFB:
|
||||||
case self::MODE_STREAM:
|
case self::MODE_STREAM:
|
||||||
$this->paddable = false;
|
$this->mode = $mode;
|
||||||
break;
|
break;
|
||||||
|
case self::MODE_CBC:
|
||||||
default:
|
default:
|
||||||
throw new \InvalidArgumentException('No valid mode has been specified');
|
$this->paddable = true;
|
||||||
|
$this->mode = self::MODE_CBC;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->mode = $mode;
|
$this->_setEngine();
|
||||||
|
|
||||||
// Determining whether inline crypting can be used by the cipher
|
// Determining whether inline crypting can be used by the cipher
|
||||||
if ($this->use_inline_crypt !== false && function_exists('create_function')) {
|
if ($this->use_inline_crypt !== false && function_exists('create_function')) {
|
||||||
@ -493,28 +500,19 @@ abstract class Base
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the initialization vector.
|
* Sets the initialization vector. (optional)
|
||||||
*
|
*
|
||||||
* setIV() is not required when self::MODE_ECB (or ie for AES: \phpseclib\Crypt\AES::MODE_ECB) is being used.
|
* SetIV is not required when self::MODE_ECB (or ie for AES: \phpseclib\Crypt\AES::MODE_ECB) is being used. If not explicitly set, it'll be assumed
|
||||||
|
* to be all zero's.
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $iv
|
* @param string $iv
|
||||||
* @throws \LengthException if the IV length isn't equal to the block size
|
|
||||||
* @throws \InvalidArgumentException if an IV is provided when one shouldn't be
|
|
||||||
* @internal Can be overwritten by a sub class, but does not have to be
|
* @internal Can be overwritten by a sub class, but does not have to be
|
||||||
*/
|
*/
|
||||||
function setIV($iv)
|
function setIV($iv)
|
||||||
{
|
{
|
||||||
if ($this->mode == self::MODE_ECB) {
|
if ($this->mode == self::MODE_ECB) {
|
||||||
throw new \InvalidArgumentException('This mode does not require an IV.');
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->mode == self::MODE_STREAM && $this->usesIV()) {
|
|
||||||
throw new \InvalidArgumentException('This algorithm does not use an IV.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen($iv) != $this->block_size) {
|
|
||||||
throw new \LengthException('Received initialization vector of size ' . strlen($iv) . ', but size ' . $this->block_size . ' is required');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->iv = $iv;
|
$this->iv = $iv;
|
||||||
@ -522,14 +520,18 @@ abstract class Base
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether or not the algorithm uses an IV
|
* Sets the key length.
|
||||||
|
*
|
||||||
|
* Keys with explicitly set lengths need to be treated accordingly
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @return bool
|
* @param int $length
|
||||||
*/
|
*/
|
||||||
function usesIV()
|
function setKeyLength($length)
|
||||||
{
|
{
|
||||||
return true;
|
$this->explicit_key_length = true;
|
||||||
|
$this->changed = true;
|
||||||
|
$this->_setEngine();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -554,24 +556,6 @@ abstract class Base
|
|||||||
return $this->block_size << 3;
|
return $this->block_size << 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the key length.
|
|
||||||
*
|
|
||||||
* Keys with explicitly set lengths need to be treated accordingly
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param int $length
|
|
||||||
*/
|
|
||||||
function setKeyLength($length)
|
|
||||||
{
|
|
||||||
$this->explicit_key_length = $length >> 3;
|
|
||||||
|
|
||||||
if (is_string($this->key) && strlen($this->key) != $this->explicit_key_length) {
|
|
||||||
$this->key = false;
|
|
||||||
throw new \LengthException('Key has already been set and is not ' .$this->explicit_key_length . ' bytes long');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the key.
|
* Sets the key.
|
||||||
*
|
*
|
||||||
@ -588,12 +572,12 @@ abstract class Base
|
|||||||
*/
|
*/
|
||||||
function setKey($key)
|
function setKey($key)
|
||||||
{
|
{
|
||||||
if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) {
|
if (!$this->explicit_key_length) {
|
||||||
throw new \LengthException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes');
|
$this->setKeyLength(strlen($key) << 3);
|
||||||
|
$this->explicit_key_length = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->key = $key;
|
$this->key = $key;
|
||||||
$this->key_length = strlen($key);
|
|
||||||
$this->changed = true;
|
$this->changed = true;
|
||||||
$this->_setEngine();
|
$this->_setEngine();
|
||||||
}
|
}
|
||||||
@ -610,7 +594,6 @@ abstract class Base
|
|||||||
* @see Crypt/Hash.php
|
* @see Crypt/Hash.php
|
||||||
* @param string $password
|
* @param string $password
|
||||||
* @param string $method
|
* @param string $method
|
||||||
* @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length
|
|
||||||
* @return bool
|
* @return bool
|
||||||
* @access public
|
* @access public
|
||||||
* @internal Could, but not must, extend by the child Crypt_* class
|
* @internal Could, but not must, extend by the child Crypt_* class
|
||||||
@ -637,8 +620,7 @@ abstract class Base
|
|||||||
if (isset($func_args[5])) {
|
if (isset($func_args[5])) {
|
||||||
$dkLen = $func_args[5];
|
$dkLen = $func_args[5];
|
||||||
} else {
|
} else {
|
||||||
$key_length = $this->explicit_key_length !== false ? $this->explicit_key_length : $this->key_length;
|
$dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length;
|
||||||
$dkLen = $method == 'pbkdf1' ? 2 * $key_length : $key_length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
@ -646,7 +628,8 @@ abstract class Base
|
|||||||
$hashObj = new Hash();
|
$hashObj = new Hash();
|
||||||
$hashObj->setHash($hash);
|
$hashObj->setHash($hash);
|
||||||
if ($dkLen > $hashObj->getLength()) {
|
if ($dkLen > $hashObj->getLength()) {
|
||||||
throw new \LengthException('Derived key length cannot be longer than the hash length');
|
user_error('Derived key too long');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
$t = $password . $salt;
|
$t = $password . $salt;
|
||||||
for ($i = 0; $i < $count; ++$i) {
|
for ($i = 0; $i < $count; ++$i) {
|
||||||
@ -793,7 +776,7 @@ abstract class Base
|
|||||||
$this->changed = false;
|
$this->changed = false;
|
||||||
}
|
}
|
||||||
if ($this->enchanged) {
|
if ($this->enchanged) {
|
||||||
mcrypt_generic_init($this->enmcrypt, $this->key, $this->_getIV($this->encryptIV));
|
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
||||||
$this->enchanged = false;
|
$this->enchanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -856,7 +839,7 @@ abstract class Base
|
|||||||
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
|
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
|
||||||
|
|
||||||
if (!$this->continuousBuffer) {
|
if (!$this->continuousBuffer) {
|
||||||
mcrypt_generic_init($this->enmcrypt, $this->key, $this->_getIV($this->encryptIV));
|
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ciphertext;
|
return $ciphertext;
|
||||||
@ -1005,13 +988,14 @@ abstract class Base
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $ciphertext
|
* @param string $ciphertext
|
||||||
* @return string $plaintext
|
* @return string $plaintext
|
||||||
* @throws \LengthException if we're inside a block cipher and the ciphertext length is not a multiple of the block size
|
|
||||||
* @internal Could, but not must, extend by the child Crypt_* class
|
* @internal Could, but not must, extend by the child Crypt_* class
|
||||||
*/
|
*/
|
||||||
function decrypt($ciphertext)
|
function decrypt($ciphertext)
|
||||||
{
|
{
|
||||||
if ($this->paddable && strlen($ciphertext) % $this->block_size) {
|
if ($this->paddable) {
|
||||||
throw new \LengthException('The ciphertext length (' . strlen($ciphertext) . ') needs to be a multiple of the block size (' . $this->block_size . ')');
|
// we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}:
|
||||||
|
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||||
|
$ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->engine === self::ENGINE_OPENSSL) {
|
if ($this->engine === self::ENGINE_OPENSSL) {
|
||||||
@ -1104,7 +1088,7 @@ abstract class Base
|
|||||||
$this->changed = false;
|
$this->changed = false;
|
||||||
}
|
}
|
||||||
if ($this->dechanged) {
|
if ($this->dechanged) {
|
||||||
mcrypt_generic_init($this->demcrypt, $this->key, $this->_getIV($this->decryptIV));
|
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
||||||
$this->dechanged = false;
|
$this->dechanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1149,7 +1133,7 @@ abstract class Base
|
|||||||
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
|
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
|
||||||
|
|
||||||
if (!$this->continuousBuffer) {
|
if (!$this->continuousBuffer) {
|
||||||
mcrypt_generic_init($this->demcrypt, $this->key, $this->_getIV($this->decryptIV));
|
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
||||||
@ -1286,22 +1270,6 @@ abstract class Base
|
|||||||
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the IV
|
|
||||||
*
|
|
||||||
* mcrypt requires an IV even if ECB is used
|
|
||||||
*
|
|
||||||
* @see self::encrypt()
|
|
||||||
* @see self::decrypt()
|
|
||||||
* @param string $iv
|
|
||||||
* @return string
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
function _getIV($iv)
|
|
||||||
{
|
|
||||||
return $this->mode == self::MODE_ECB ? str_repeat("\0", $this->block_size) : $iv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenSSL CTR Processor
|
* OpenSSL CTR Processor
|
||||||
*
|
*
|
||||||
@ -1854,7 +1822,6 @@ abstract class Base
|
|||||||
*
|
*
|
||||||
* @see self::_unpad()
|
* @see self::_unpad()
|
||||||
* @param string $text
|
* @param string $text
|
||||||
* @throws \LengthException if padding is disabled and the plaintext's length is not a multiple of the block size
|
|
||||||
* @access private
|
* @access private
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -1866,7 +1833,8 @@ abstract class Base
|
|||||||
if ($length % $this->block_size == 0) {
|
if ($length % $this->block_size == 0) {
|
||||||
return $text;
|
return $text;
|
||||||
} else {
|
} else {
|
||||||
throw new \LengthException("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size}). Try enabling padding.");
|
user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
|
||||||
|
$this->padding = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1883,7 +1851,6 @@ abstract class Base
|
|||||||
*
|
*
|
||||||
* @see self::_pad()
|
* @see self::_pad()
|
||||||
* @param string $text
|
* @param string $text
|
||||||
* @throws \LengthException if the ciphertext's length is not a multiple of the block size
|
|
||||||
* @access private
|
* @access private
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -1896,7 +1863,7 @@ abstract class Base
|
|||||||
$length = ord($text[strlen($text) - 1]);
|
$length = ord($text[strlen($text) - 1]);
|
||||||
|
|
||||||
if (!$length || $length > $this->block_size) {
|
if (!$length || $length > $this->block_size) {
|
||||||
throw new \LengthException("The ciphertext has an invalid padding length ($length) compared to the block size ({$this->block_size})");
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return substr($text, 0, -$length);
|
return substr($text, 0, -$length);
|
||||||
@ -1909,19 +1876,20 @@ abstract class Base
|
|||||||
* after disableContinuousBuffer() or on cipher $engine (re)init
|
* after disableContinuousBuffer() or on cipher $engine (re)init
|
||||||
* ie after setKey() or setIV()
|
* ie after setKey() or setIV()
|
||||||
*
|
*
|
||||||
* @access private
|
* @access public
|
||||||
* @internal Could, but not must, extend by the child Crypt_* class
|
* @internal Could, but not must, extend by the child Crypt_* class
|
||||||
* @throws \UnexpectedValueException when an IV is required but not defined
|
|
||||||
*/
|
*/
|
||||||
function _clearBuffers()
|
function _clearBuffers()
|
||||||
{
|
{
|
||||||
$this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
|
$this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
|
||||||
|
|
||||||
if ($this->iv === false && !in_array($this->mode, array(self::MODE_STREAM, self::MODE_ECB))) {
|
// mcrypt's handling of invalid's $iv:
|
||||||
throw new \UnexpectedValueException('No IV has been defined');
|
// $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
|
||||||
}
|
$this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
|
||||||
|
|
||||||
$this->encryptIV = $this->decryptIV = $this->iv;
|
if (!$this->skip_key_adjustment) {
|
||||||
|
$this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
|
|
||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of Blowfish.
|
* Pure-PHP implementation of Blowfish.
|
||||||
*
|
*
|
||||||
@ -283,22 +285,6 @@ class Blowfish extends Base
|
|||||||
*/
|
*/
|
||||||
var $key_length = 16;
|
var $key_length = 16;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default Constructor.
|
|
||||||
*
|
|
||||||
* @param int $mode
|
|
||||||
* @access public
|
|
||||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
|
||||||
*/
|
|
||||||
function __construct($mode)
|
|
||||||
{
|
|
||||||
if ($mode == self::MODE_STREAM) {
|
|
||||||
throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the key length.
|
* Sets the key length.
|
||||||
*
|
*
|
||||||
@ -309,12 +295,14 @@ class Blowfish extends Base
|
|||||||
*/
|
*/
|
||||||
function setKeyLength($length)
|
function setKeyLength($length)
|
||||||
{
|
{
|
||||||
if ($length < 32 || $length > 448) {
|
if ($length < 32) {
|
||||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes between 32 and 448 bits are supported');
|
$this->key_length = 7;
|
||||||
|
} elseif ($length > 448) {
|
||||||
|
$this->key_length = 56;
|
||||||
|
} else {
|
||||||
|
$this->key_length = $length >> 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->key_length = $length >> 3;
|
|
||||||
|
|
||||||
parent::setKeyLength($length);
|
parent::setKeyLength($length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
|
|
||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of DES.
|
* Pure-PHP implementation of DES.
|
||||||
*
|
*
|
||||||
@ -578,22 +580,6 @@ class DES extends Base
|
|||||||
0x00000820, 0x00020020, 0x08000000, 0x08020800
|
0x00000820, 0x00020020, 0x08000000, 0x08020800
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Default Constructor.
|
|
||||||
*
|
|
||||||
* @param int $mode
|
|
||||||
* @access public
|
|
||||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
|
||||||
*/
|
|
||||||
function __construct($mode)
|
|
||||||
{
|
|
||||||
if ($mode == self::MODE_STREAM) {
|
|
||||||
throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for engine validity
|
* Test for engine validity
|
||||||
*
|
*
|
||||||
@ -619,18 +605,24 @@ class DES extends Base
|
|||||||
/**
|
/**
|
||||||
* Sets the key.
|
* Sets the key.
|
||||||
*
|
*
|
||||||
* Keys must be 64-bits long or 8 bytes long.
|
* Keys can be of any length. DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we
|
||||||
|
* only use the first eight, if $key has more then eight characters in it, and pad $key with the
|
||||||
|
* null byte if it is less then eight characters long.
|
||||||
*
|
*
|
||||||
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
||||||
*
|
*
|
||||||
|
* If the key is not explicitly set, it'll be assumed to be all zero's.
|
||||||
|
*
|
||||||
* @see \phpseclib\Crypt\Base::setKey()
|
* @see \phpseclib\Crypt\Base::setKey()
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
*/
|
*/
|
||||||
function setKey($key)
|
function setKey($key)
|
||||||
{
|
{
|
||||||
if (!($this instanceof TripleDES) && strlen($key) != 8) {
|
// We check/cut here only up to max length of the key.
|
||||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of size 8 are supported');
|
// Key padding to the proper length will be done in _setupKey()
|
||||||
|
if (strlen($key) > $this->key_length_max) {
|
||||||
|
$key = substr($key, 0, $this->key_length_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the key
|
// Sets the key
|
||||||
|
@ -1,19 +1,26 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around hash() and hash_hmac() functions supporting truncated hashes
|
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
|
||||||
* such as sha256-96. Any hash algorithm returned by hash_algos() (and
|
|
||||||
* truncated versions thereof) are supported.
|
|
||||||
*
|
*
|
||||||
* If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will
|
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
|
||||||
* return the HMAC as opposed to the hash.
|
*
|
||||||
|
* md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
|
||||||
|
*
|
||||||
|
* If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will return the HMAC as opposed to
|
||||||
|
* the hash. If no valid algorithm is provided, sha1 will be used.
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* {@internal The variable names are the same as those in
|
||||||
|
* {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
|
||||||
*
|
*
|
||||||
* Here's a short example of how to use this library:
|
* Here's a short example of how to use this library:
|
||||||
* <code>
|
* <code>
|
||||||
* <?php
|
* <?php
|
||||||
* include 'vendor/autoload.php';
|
* include 'vendor/autoload.php';
|
||||||
*
|
*
|
||||||
* $hash = new \phpseclib\Crypt\Hash('sha512');
|
* $hash = new \phpseclib\Crypt\Hash('sha1');
|
||||||
*
|
*
|
||||||
* $hash->setKey('abcdefg');
|
* $hash->setKey('abcdefg');
|
||||||
*
|
*
|
||||||
@ -24,9 +31,7 @@
|
|||||||
* @category Crypt
|
* @category Crypt
|
||||||
* @package Hash
|
* @package Hash
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @copyright 2015 Jim Wigginton
|
* @copyright 2007 Jim Wigginton
|
||||||
* @author Andreas Fischer <bantu@phpbb.com>
|
|
||||||
* @copyright 2015 Andreas Fischer
|
|
||||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
@ -34,16 +39,34 @@
|
|||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
use phpseclib\Math\BigInteger;
|
use phpseclib\Math\BigInteger;
|
||||||
use phpseclib\Exception\UnsupportedAlgorithmException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
|
||||||
|
*
|
||||||
* @package Hash
|
* @package Hash
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @author Andreas Fischer <bantu@phpbb.com>
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
class Hash
|
class Hash
|
||||||
{
|
{
|
||||||
|
/**#@+
|
||||||
|
* @access private
|
||||||
|
* @see \phpseclib\Crypt\Hash::__construct()
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Toggles the internal implementation
|
||||||
|
*/
|
||||||
|
const MODE_INTERNAL = 1;
|
||||||
|
/**
|
||||||
|
* Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
|
||||||
|
*/
|
||||||
|
const MODE_MHASH = 2;
|
||||||
|
/**
|
||||||
|
* Toggles the hash() implementation, which works on PHP 5.1.2+.
|
||||||
|
*/
|
||||||
|
const MODE_HASH = 3;
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash Parameter
|
* Hash Parameter
|
||||||
*
|
*
|
||||||
@ -53,6 +76,15 @@ class Hash
|
|||||||
*/
|
*/
|
||||||
var $hashParam;
|
var $hashParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte-length of compression blocks / key (Internal HMAC)
|
||||||
|
*
|
||||||
|
* @see self::setAlgorithm()
|
||||||
|
* @var int
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $b;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Byte-length of hash output (Internal HMAC)
|
* Byte-length of hash output (Internal HMAC)
|
||||||
*
|
*
|
||||||
@ -60,7 +92,7 @@ class Hash
|
|||||||
* @var int
|
* @var int
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $length;
|
var $l = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash Algorithm
|
* Hash Algorithm
|
||||||
@ -80,23 +112,10 @@ class Hash
|
|||||||
*/
|
*/
|
||||||
var $key = false;
|
var $key = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Initial Hash
|
|
||||||
*
|
|
||||||
* Used only for sha512/*
|
|
||||||
*
|
|
||||||
* @see self::_sha512()
|
|
||||||
* @var array
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $initial = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Outer XOR (Internal HMAC)
|
* Outer XOR (Internal HMAC)
|
||||||
*
|
*
|
||||||
* Used only for sha512/*
|
* @see self::setKey()
|
||||||
*
|
|
||||||
* @see self::hash()
|
|
||||||
* @var string
|
* @var string
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
@ -105,9 +124,7 @@ class Hash
|
|||||||
/**
|
/**
|
||||||
* Inner XOR (Internal HMAC)
|
* Inner XOR (Internal HMAC)
|
||||||
*
|
*
|
||||||
* Used only for sha512/*
|
* @see self::setKey()
|
||||||
*
|
|
||||||
* @see self::hash()
|
|
||||||
* @var string
|
* @var string
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
@ -117,14 +134,25 @@ class Hash
|
|||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
* @param string $hash
|
* @param string $hash
|
||||||
|
* @return \phpseclib\Crypt\Hash
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function __construct($hash = 'sha256')
|
function __construct($hash = 'sha1')
|
||||||
{
|
{
|
||||||
$this->setHash($hash);
|
if (!defined('CRYPT_HASH_MODE')) {
|
||||||
|
switch (true) {
|
||||||
|
case extension_loaded('hash'):
|
||||||
|
define('CRYPT_HASH_MODE', self::MODE_HASH);
|
||||||
|
break;
|
||||||
|
case extension_loaded('mhash'):
|
||||||
|
define('CRYPT_HASH_MODE', self::MODE_MHASH);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
define('CRYPT_HASH_MODE', self::MODE_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->ipad = str_repeat(chr(0x36), 128);
|
$this->setHash($hash);
|
||||||
$this->opad = str_repeat(chr(0x5C), 128);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,76 +191,101 @@ class Hash
|
|||||||
{
|
{
|
||||||
$this->hashParam = $hash = strtolower($hash);
|
$this->hashParam = $hash = strtolower($hash);
|
||||||
switch ($hash) {
|
switch ($hash) {
|
||||||
case 'md2-96':
|
|
||||||
case 'md5-96':
|
case 'md5-96':
|
||||||
case 'sha1-96':
|
case 'sha1-96':
|
||||||
case 'sha256-96':
|
case 'sha256-96':
|
||||||
case 'sha512-96':
|
case 'sha512-96':
|
||||||
case 'sha512/224-96':
|
|
||||||
case 'sha512/256-96':
|
|
||||||
$hash = substr($hash, 0, -3);
|
$hash = substr($hash, 0, -3);
|
||||||
$this->length = 12; // 96 / 8 = 12
|
$this->l = 12; // 96 / 8 = 12
|
||||||
break;
|
break;
|
||||||
case 'md2':
|
case 'md2':
|
||||||
case 'md5':
|
case 'md5':
|
||||||
$this->length = 16;
|
$this->l = 16;
|
||||||
break;
|
break;
|
||||||
case 'sha1':
|
case 'sha1':
|
||||||
$this->length = 20;
|
$this->l = 20;
|
||||||
break;
|
|
||||||
case 'sha512/224':
|
|
||||||
$this->length = 28;
|
|
||||||
break;
|
break;
|
||||||
case 'sha256':
|
case 'sha256':
|
||||||
case 'sha512/256':
|
$this->l = 32;
|
||||||
$this->length = 32;
|
|
||||||
break;
|
break;
|
||||||
case 'sha384':
|
case 'sha384':
|
||||||
$this->length = 48;
|
$this->l = 48;
|
||||||
break;
|
break;
|
||||||
case 'sha512':
|
case 'sha512':
|
||||||
$this->length = 64;
|
$this->l = 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($hash) {
|
||||||
|
case 'md2':
|
||||||
|
$mode = CRYPT_HASH_MODE == self::MODE_HASH && in_array('md2', hash_algos()) ?
|
||||||
|
self::MODE_HASH : self::MODE_INTERNAL;
|
||||||
|
break;
|
||||||
|
case 'sha384':
|
||||||
|
case 'sha512':
|
||||||
|
$mode = CRYPT_HASH_MODE == self::MODE_MHASH ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// see if the hash isn't "officially" supported see if it can
|
$mode = CRYPT_HASH_MODE;
|
||||||
// be "unofficially" supported and calculate the length
|
}
|
||||||
// accordingly.
|
|
||||||
if (in_array($hash, hash_algos())) {
|
switch ($mode) {
|
||||||
$this->length = strlen(hash($hash, '', true));
|
case self::MODE_MHASH:
|
||||||
break;
|
switch ($hash) {
|
||||||
}
|
case 'md5':
|
||||||
// if the hash algorithm doens't exist maybe it's a truncated
|
$this->hash = MHASH_MD5;
|
||||||
// hash, e.g. whirlpool-12 or some such.
|
|
||||||
if (preg_match('#(-\d+)$#', $hash, $matches)) {
|
|
||||||
$hash = substr($hash, 0, -strlen($matches[1]));
|
|
||||||
if (in_array($hash, hash_algos())) {
|
|
||||||
$this->length = abs($matches[1]) >> 3;
|
|
||||||
break;
|
break;
|
||||||
}
|
case 'sha256':
|
||||||
|
$this->hash = MHASH_SHA256;
|
||||||
|
break;
|
||||||
|
case 'sha1':
|
||||||
|
default:
|
||||||
|
$this->hash = MHASH_SHA1;
|
||||||
}
|
}
|
||||||
throw new UnsupportedAlgorithmException(
|
return;
|
||||||
"$hash is not a supported algorithm"
|
case self::MODE_HASH:
|
||||||
);
|
switch ($hash) {
|
||||||
|
case 'md5':
|
||||||
|
$this->hash = 'md5';
|
||||||
|
return;
|
||||||
|
case 'md2':
|
||||||
|
case 'sha256':
|
||||||
|
case 'sha384':
|
||||||
|
case 'sha512':
|
||||||
|
$this->hash = $hash;
|
||||||
|
return;
|
||||||
|
case 'sha1':
|
||||||
|
default:
|
||||||
|
$this->hash = 'sha1';
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($hash == 'sha512/224' || $hash == 'sha512/256') {
|
switch ($hash) {
|
||||||
// from http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf#page=24
|
case 'md2':
|
||||||
$this->initial = $hash == 'sha512/256' ?
|
$this->b = 16;
|
||||||
array(
|
$this->hash = array($this, '_md2');
|
||||||
'22312194FC2BF72C', '9F555FA3C84C64C2', '2393B86B6F53B151', '963877195940EABD',
|
break;
|
||||||
'96283EE2A88EFFE3', 'BE5E1E2553863992', '2B0199FC2C85B8AA', '0EB72DDC81C52CA2'
|
case 'md5':
|
||||||
) :
|
$this->b = 64;
|
||||||
array(
|
$this->hash = array($this, '_md5');
|
||||||
'8C3D37C819544DA2', '73E1996689DCD4D6', '1DFAB7AE32FF9C82', '679DD514582F9FCF',
|
break;
|
||||||
'0F6D2B697BD44DA8', '77E36F7304C48942', '3F9D85A86A1D36C8', '1112E6AD91D692A1'
|
case 'sha256':
|
||||||
);
|
$this->b = 64;
|
||||||
for ($i = 0; $i < 8; $i++) {
|
$this->hash = array($this, '_sha256');
|
||||||
$this->initial[$i] = new BigInteger($this->initial[$i], 16);
|
break;
|
||||||
$this->initial[$i]->setPrecision(64);
|
case 'sha384':
|
||||||
}
|
case 'sha512':
|
||||||
|
$this->b = 128;
|
||||||
|
$this->hash = array($this, '_sha512');
|
||||||
|
break;
|
||||||
|
case 'sha1':
|
||||||
|
default:
|
||||||
|
$this->b = 64;
|
||||||
|
$this->hash = array($this, '_sha1');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->hash = $hash;
|
$this->ipad = str_repeat(chr(0x36), $this->b);
|
||||||
|
$this->opad = str_repeat(chr(0x5C), $this->b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -244,35 +297,45 @@ class Hash
|
|||||||
*/
|
*/
|
||||||
function hash($text)
|
function hash($text)
|
||||||
{
|
{
|
||||||
switch ($this->hash) {
|
$mode = is_array($this->hash) ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
|
||||||
case 'sha512/224':
|
|
||||||
case 'sha512/256':
|
|
||||||
if (empty($this->key) || !is_string($this->key)) {
|
|
||||||
return substr(self::_sha512($text, $this->initial), 0, $this->length);
|
|
||||||
}
|
|
||||||
/* "Applications that use keys longer than B bytes will first hash the key using H and then use the
|
|
||||||
resultant L byte string as the actual key to HMAC."
|
|
||||||
|
|
||||||
-- http://tools.ietf.org/html/rfc2104#section-2 */
|
if (!empty($this->key) || is_string($this->key)) {
|
||||||
$key = strlen($this->key) > $this->b ? self::_sha512($this->key, $this->initial) : $this->key;
|
switch ($mode) {
|
||||||
|
case self::MODE_MHASH:
|
||||||
|
$output = mhash($this->hash, $text, $this->key);
|
||||||
|
break;
|
||||||
|
case self::MODE_HASH:
|
||||||
|
$output = hash_hmac($this->hash, $text, $this->key, true);
|
||||||
|
break;
|
||||||
|
case self::MODE_INTERNAL:
|
||||||
|
/* "Applications that use keys longer than B bytes will first hash the key using H and then use the
|
||||||
|
resultant L byte string as the actual key to HMAC."
|
||||||
|
|
||||||
$key = str_pad($this->key, 128, chr(0)); // step 1
|
-- http://tools.ietf.org/html/rfc2104#section-2 */
|
||||||
$temp = $this->ipad ^ $this->key; // step 2
|
$key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key;
|
||||||
$temp .= $text; // step 3
|
|
||||||
$temp = self::_sha512($temp, $this->initial); // step 4
|
|
||||||
$output = $this->opad ^ $this->key; // step 5
|
|
||||||
$output.= $temp; // step 6
|
|
||||||
$output = self::_sha512($output, $this->initial); // step 7
|
|
||||||
|
|
||||||
return substr($output, 0, $this->length);
|
$key = str_pad($key, $this->b, chr(0)); // step 1
|
||||||
|
$temp = $this->ipad ^ $key; // step 2
|
||||||
|
$temp .= $text; // step 3
|
||||||
|
$temp = call_user_func($this->hash, $temp); // step 4
|
||||||
|
$output = $this->opad ^ $key; // step 5
|
||||||
|
$output.= $temp; // step 6
|
||||||
|
$output = call_user_func($this->hash, $output); // step 7
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch ($mode) {
|
||||||
|
case self::MODE_MHASH:
|
||||||
|
$output = mhash($this->hash, $text);
|
||||||
|
break;
|
||||||
|
case self::MODE_HASH:
|
||||||
|
$output = hash($this->hash, $text, true);
|
||||||
|
break;
|
||||||
|
case self::MODE_INTERNAL:
|
||||||
|
$output = call_user_func($this->hash, $text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$output = !empty($this->key) || is_string($this->key) ?
|
|
||||||
hash_hmac($this->hash, $text, $this->key, true) :
|
|
||||||
hash($this->hash, $text, true);
|
|
||||||
|
|
||||||
return strlen($output) > $this->length
|
return substr($output, 0, $this->l);
|
||||||
? substr($output, 0, $this->length)
|
|
||||||
: $output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -283,20 +346,243 @@ class Hash
|
|||||||
*/
|
*/
|
||||||
function getLength()
|
function getLength()
|
||||||
{
|
{
|
||||||
return $this->length;
|
return $this->l;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of SHA512
|
* Wrapper for MD5
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @param string $m
|
* @param string $m
|
||||||
*/
|
*/
|
||||||
static function _sha512($m, $hash)
|
function _md5($m)
|
||||||
{
|
{
|
||||||
static $k;
|
return pack('H*', md5($m));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for SHA1
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $m
|
||||||
|
*/
|
||||||
|
function _sha1($m)
|
||||||
|
{
|
||||||
|
return pack('H*', sha1($m));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of MD2
|
||||||
|
*
|
||||||
|
* See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $m
|
||||||
|
*/
|
||||||
|
function _md2($m)
|
||||||
|
{
|
||||||
|
static $s = array(
|
||||||
|
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
|
||||||
|
19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
|
||||||
|
76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
|
||||||
|
138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
|
||||||
|
245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
|
||||||
|
148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
|
||||||
|
39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
|
||||||
|
181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
|
||||||
|
150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
|
||||||
|
112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
|
||||||
|
96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
|
||||||
|
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
|
||||||
|
234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
|
||||||
|
129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
|
||||||
|
8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
|
||||||
|
203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
|
||||||
|
166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
|
||||||
|
31, 26, 219, 153, 141, 51, 159, 17, 131, 20
|
||||||
|
);
|
||||||
|
|
||||||
|
// Step 1. Append Padding Bytes
|
||||||
|
$pad = 16 - (strlen($m) & 0xF);
|
||||||
|
$m.= str_repeat(chr($pad), $pad);
|
||||||
|
|
||||||
|
$length = strlen($m);
|
||||||
|
|
||||||
|
// Step 2. Append Checksum
|
||||||
|
$c = str_repeat(chr(0), 16);
|
||||||
|
$l = chr(0);
|
||||||
|
for ($i = 0; $i < $length; $i+= 16) {
|
||||||
|
for ($j = 0; $j < 16; $j++) {
|
||||||
|
// RFC1319 incorrectly states that C[j] should be set to S[c xor L]
|
||||||
|
//$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
|
||||||
|
// per <http://www.rfc-editor.org/errata_search.php?rfc=1319>, however, C[j] should be set to S[c xor L] xor C[j]
|
||||||
|
$c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j]));
|
||||||
|
$l = $c[$j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$m.= $c;
|
||||||
|
|
||||||
|
$length+= 16;
|
||||||
|
|
||||||
|
// Step 3. Initialize MD Buffer
|
||||||
|
$x = str_repeat(chr(0), 48);
|
||||||
|
|
||||||
|
// Step 4. Process Message in 16-Byte Blocks
|
||||||
|
for ($i = 0; $i < $length; $i+= 16) {
|
||||||
|
for ($j = 0; $j < 16; $j++) {
|
||||||
|
$x[$j + 16] = $m[$i + $j];
|
||||||
|
$x[$j + 32] = $x[$j + 16] ^ $x[$j];
|
||||||
|
}
|
||||||
|
$t = chr(0);
|
||||||
|
for ($j = 0; $j < 18; $j++) {
|
||||||
|
for ($k = 0; $k < 48; $k++) {
|
||||||
|
$x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
|
||||||
|
//$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
|
||||||
|
}
|
||||||
|
$t = chr(ord($t) + $j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5. Output
|
||||||
|
return substr($x, 0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of SHA256
|
||||||
|
*
|
||||||
|
* See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $m
|
||||||
|
*/
|
||||||
|
function _sha256($m)
|
||||||
|
{
|
||||||
|
if (extension_loaded('suhosin')) {
|
||||||
|
return pack('H*', sha256($m));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize variables
|
||||||
|
$hash = array(
|
||||||
|
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||||
|
);
|
||||||
|
// Initialize table of round constants
|
||||||
|
// (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
|
||||||
|
static $k = array(
|
||||||
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||||
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||||
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||||
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||||
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||||
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||||
|
);
|
||||||
|
|
||||||
|
// Pre-processing
|
||||||
|
$length = strlen($m);
|
||||||
|
// to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
|
||||||
|
$m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
|
||||||
|
$m[$length] = chr(0x80);
|
||||||
|
// we don't support hashing strings 512MB long
|
||||||
|
$m.= pack('N2', 0, $length << 3);
|
||||||
|
|
||||||
|
// Process the message in successive 512-bit chunks
|
||||||
|
$chunks = str_split($m, 64);
|
||||||
|
foreach ($chunks as $chunk) {
|
||||||
|
$w = array();
|
||||||
|
for ($i = 0; $i < 16; $i++) {
|
||||||
|
extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
|
||||||
|
$w[] = $temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extend the sixteen 32-bit words into sixty-four 32-bit words
|
||||||
|
for ($i = 16; $i < 64; $i++) {
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
|
$s0 = $this->_rightRotate($w[$i - 15], 7) ^
|
||||||
|
$this->_rightRotate($w[$i - 15], 18) ^
|
||||||
|
$this->_rightShift( $w[$i - 15], 3);
|
||||||
|
$s1 = $this->_rightRotate($w[$i - 2], 17) ^
|
||||||
|
$this->_rightRotate($w[$i - 2], 19) ^
|
||||||
|
$this->_rightShift( $w[$i - 2], 10);
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
|
$w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize hash value for this chunk
|
||||||
|
list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
|
||||||
|
|
||||||
|
// Main loop
|
||||||
|
for ($i = 0; $i < 64; $i++) {
|
||||||
|
$s0 = $this->_rightRotate($a, 2) ^
|
||||||
|
$this->_rightRotate($a, 13) ^
|
||||||
|
$this->_rightRotate($a, 22);
|
||||||
|
$maj = ($a & $b) ^
|
||||||
|
($a & $c) ^
|
||||||
|
($b & $c);
|
||||||
|
$t2 = $this->_add($s0, $maj);
|
||||||
|
|
||||||
|
$s1 = $this->_rightRotate($e, 6) ^
|
||||||
|
$this->_rightRotate($e, 11) ^
|
||||||
|
$this->_rightRotate($e, 25);
|
||||||
|
$ch = ($e & $f) ^
|
||||||
|
($this->_not($e) & $g);
|
||||||
|
$t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
|
||||||
|
|
||||||
|
$h = $g;
|
||||||
|
$g = $f;
|
||||||
|
$f = $e;
|
||||||
|
$e = $this->_add($d, $t1);
|
||||||
|
$d = $c;
|
||||||
|
$c = $b;
|
||||||
|
$b = $a;
|
||||||
|
$a = $this->_add($t1, $t2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this chunk's hash to result so far
|
||||||
|
$hash = array(
|
||||||
|
$this->_add($hash[0], $a),
|
||||||
|
$this->_add($hash[1], $b),
|
||||||
|
$this->_add($hash[2], $c),
|
||||||
|
$this->_add($hash[3], $d),
|
||||||
|
$this->_add($hash[4], $e),
|
||||||
|
$this->_add($hash[5], $f),
|
||||||
|
$this->_add($hash[6], $g),
|
||||||
|
$this->_add($hash[7], $h)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produce the final hash value (big-endian)
|
||||||
|
return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure-PHP implementation of SHA384 and SHA512
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $m
|
||||||
|
*/
|
||||||
|
function _sha512($m)
|
||||||
|
{
|
||||||
|
static $init384, $init512, $k;
|
||||||
|
|
||||||
if (!isset($k)) {
|
if (!isset($k)) {
|
||||||
|
// Initialize variables
|
||||||
|
$init384 = array( // initial values for SHA384
|
||||||
|
'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
|
||||||
|
'67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
|
||||||
|
);
|
||||||
|
$init512 = array( // initial values for SHA512
|
||||||
|
'6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
|
||||||
|
'510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
|
||||||
|
);
|
||||||
|
|
||||||
|
for ($i = 0; $i < 8; $i++) {
|
||||||
|
$init384[$i] = new BigInteger($init384[$i], 16);
|
||||||
|
$init384[$i]->setPrecision(64);
|
||||||
|
$init512[$i] = new BigInteger($init512[$i], 16);
|
||||||
|
$init512[$i]->setPrecision(64);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize table of round constants
|
// Initialize table of round constants
|
||||||
// (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
|
// (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
|
||||||
$k = array(
|
$k = array(
|
||||||
@ -327,6 +613,8 @@ class Hash
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hash = $this->l == 48 ? $init384 : $init512;
|
||||||
|
|
||||||
// Pre-processing
|
// Pre-processing
|
||||||
$length = strlen($m);
|
$length = strlen($m);
|
||||||
// to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
|
// to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
|
||||||
@ -340,7 +628,7 @@ class Hash
|
|||||||
foreach ($chunks as $chunk) {
|
foreach ($chunks as $chunk) {
|
||||||
$w = array();
|
$w = array();
|
||||||
for ($i = 0; $i < 16; $i++) {
|
for ($i = 0; $i < 16; $i++) {
|
||||||
$temp = new BigInteger(self::_string_shift($chunk, 8), 256);
|
$temp = new BigInteger($this->_string_shift($chunk, 8), 256);
|
||||||
$temp->setPrecision(64);
|
$temp->setPrecision(64);
|
||||||
$w[] = $temp;
|
$w[] = $temp;
|
||||||
}
|
}
|
||||||
@ -361,21 +649,21 @@ class Hash
|
|||||||
);
|
);
|
||||||
$s1 = $temp[0]->bitwise_xor($temp[1]);
|
$s1 = $temp[0]->bitwise_xor($temp[1]);
|
||||||
$s1 = $s1->bitwise_xor($temp[2]);
|
$s1 = $s1->bitwise_xor($temp[2]);
|
||||||
$w[$i] = clone $w[$i - 16];
|
$w[$i] = $w[$i - 16]->copy();
|
||||||
$w[$i] = $w[$i]->add($s0);
|
$w[$i] = $w[$i]->add($s0);
|
||||||
$w[$i] = $w[$i]->add($w[$i - 7]);
|
$w[$i] = $w[$i]->add($w[$i - 7]);
|
||||||
$w[$i] = $w[$i]->add($s1);
|
$w[$i] = $w[$i]->add($s1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize hash value for this chunk
|
// Initialize hash value for this chunk
|
||||||
$a = clone $hash[0];
|
$a = $hash[0]->copy();
|
||||||
$b = clone $hash[1];
|
$b = $hash[1]->copy();
|
||||||
$c = clone $hash[2];
|
$c = $hash[2]->copy();
|
||||||
$d = clone $hash[3];
|
$d = $hash[3]->copy();
|
||||||
$e = clone $hash[4];
|
$e = $hash[4]->copy();
|
||||||
$f = clone $hash[5];
|
$f = $hash[5]->copy();
|
||||||
$g = clone $hash[6];
|
$g = $hash[6]->copy();
|
||||||
$h = clone $hash[7];
|
$h = $hash[7]->copy();
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
for ($i = 0; $i < 80; $i++) {
|
for ($i = 0; $i < 80; $i++) {
|
||||||
@ -412,13 +700,13 @@ class Hash
|
|||||||
$t1 = $t1->add($k[$i]);
|
$t1 = $t1->add($k[$i]);
|
||||||
$t1 = $t1->add($w[$i]);
|
$t1 = $t1->add($w[$i]);
|
||||||
|
|
||||||
$h = clone $g;
|
$h = $g->copy();
|
||||||
$g = clone $f;
|
$g = $f->copy();
|
||||||
$f = clone $e;
|
$f = $e->copy();
|
||||||
$e = $d->add($t1);
|
$e = $d->add($t1);
|
||||||
$d = clone $c;
|
$d = $c->copy();
|
||||||
$c = clone $b;
|
$c = $b->copy();
|
||||||
$b = clone $a;
|
$b = $a->copy();
|
||||||
$a = $t1->add($t2);
|
$a = $t1->add($t2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,11 +726,85 @@ class Hash
|
|||||||
// Produce the final hash value (big-endian)
|
// Produce the final hash value (big-endian)
|
||||||
// (\phpseclib\Crypt\Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
|
// (\phpseclib\Crypt\Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
|
||||||
$temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
|
$temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
|
||||||
$hash[4]->toBytes() . $hash[5]->toBytes() . $hash[6]->toBytes() . $hash[7]->toBytes();
|
$hash[4]->toBytes() . $hash[5]->toBytes();
|
||||||
|
if ($this->l != 48) {
|
||||||
|
$temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
|
||||||
|
}
|
||||||
|
|
||||||
return $temp;
|
return $temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Right Rotate
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param int $int
|
||||||
|
* @param int $amt
|
||||||
|
* @see self::_sha256()
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
function _rightRotate($int, $amt)
|
||||||
|
{
|
||||||
|
$invamt = 32 - $amt;
|
||||||
|
$mask = (1 << $invamt) - 1;
|
||||||
|
return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Right Shift
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param int $int
|
||||||
|
* @param int $amt
|
||||||
|
* @see self::_sha256()
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
function _rightShift($int, $amt)
|
||||||
|
{
|
||||||
|
$mask = (1 << (32 - $amt)) - 1;
|
||||||
|
return ($int >> $amt) & $mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param int $int
|
||||||
|
* @see self::_sha256()
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
function _not($int)
|
||||||
|
{
|
||||||
|
return ~$int & 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add
|
||||||
|
*
|
||||||
|
* _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
|
||||||
|
* possibility of overflow exists, care has to be taken. BigInteger could be used but this should be faster.
|
||||||
|
*
|
||||||
|
* @param int $...
|
||||||
|
* @return int
|
||||||
|
* @see self::_sha256()
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _add()
|
||||||
|
{
|
||||||
|
static $mod;
|
||||||
|
if (!isset($mod)) {
|
||||||
|
$mod = pow(2, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = 0;
|
||||||
|
$arguments = func_get_args();
|
||||||
|
foreach ($arguments as $argument) {
|
||||||
|
$result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmod($result, $mod);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String Shift
|
* String Shift
|
||||||
*
|
*
|
||||||
@ -453,7 +815,7 @@ class Hash
|
|||||||
* @return string
|
* @return string
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
static function _string_shift(&$string, $index = 1)
|
function _string_shift(&$string, $index = 1)
|
||||||
{
|
{
|
||||||
$substr = substr($string, 0, $index);
|
$substr = substr($string, 0, $index);
|
||||||
$string = substr($string, $index);
|
$string = substr($string, $index);
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
|
|
||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of RC2.
|
* Pure-PHP implementation of RC2.
|
||||||
*
|
*
|
||||||
@ -259,22 +261,6 @@ class RC2 extends Base
|
|||||||
0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6
|
0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Default Constructor.
|
|
||||||
*
|
|
||||||
* @param int $mode
|
|
||||||
* @access public
|
|
||||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
|
||||||
*/
|
|
||||||
function __construct($mode)
|
|
||||||
{
|
|
||||||
if ($mode == self::MODE_STREAM) {
|
|
||||||
throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for engine validity
|
* Test for engine validity
|
||||||
*
|
*
|
||||||
@ -308,15 +294,19 @@ class RC2 extends Base
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param int $length in bits
|
* @param int $length in bits
|
||||||
* @throws \LengthException if the key length isn't supported
|
|
||||||
*/
|
*/
|
||||||
function setKeyLength($length)
|
function setKeyLength($length)
|
||||||
{
|
{
|
||||||
if ($length < 8 || $length > 1024) {
|
if ($length < 8) {
|
||||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported');
|
$this->default_key_length = 8;
|
||||||
|
} elseif ($length > 1024) {
|
||||||
|
$this->default_key_length = 128;
|
||||||
|
} else {
|
||||||
|
$this->default_key_length = $length;
|
||||||
}
|
}
|
||||||
|
$this->current_key_length = $this->default_key_length;
|
||||||
|
|
||||||
$this->default_key_length = $this->current_key_length = $length;
|
parent::setKeyLength($length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -345,20 +335,16 @@ class RC2 extends Base
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param int $t1 optional Effective key length in bits.
|
* @param int $t1 optional Effective key length in bits.
|
||||||
* @throws \LengthException if the key length isn't supported
|
|
||||||
*/
|
*/
|
||||||
function setKey($key, $t1 = false)
|
function setKey($key, $t1 = 0)
|
||||||
{
|
{
|
||||||
$this->orig_key = $key;
|
$this->orig_key = $key;
|
||||||
|
|
||||||
if ($t1 === false) {
|
if ($t1 <= 0) {
|
||||||
$t1 = $this->default_key_length;
|
$t1 = $this->default_key_length;
|
||||||
|
} elseif ($t1 > 1024) {
|
||||||
|
$t1 = 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($t1 < 1 || $t1 > 1024) {
|
|
||||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->current_key_length = $t1;
|
$this->current_key_length = $t1;
|
||||||
// Key byte count should be 1..128.
|
// Key byte count should be 1..128.
|
||||||
$key = strlen($key) ? substr($key, 0, 128) : "\x00";
|
$key = strlen($key) ? substr($key, 0, 128) : "\x00";
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
|
|
||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of RC4.
|
* Pure-PHP implementation of RC4.
|
||||||
*
|
*
|
||||||
@ -121,6 +123,8 @@ class RC4 extends Base
|
|||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
|
* Determines whether or not the mcrypt extension should be used.
|
||||||
|
*
|
||||||
* @see \phpseclib\Crypt\Base::__construct()
|
* @see \phpseclib\Crypt\Base::__construct()
|
||||||
* @return \phpseclib\Crypt\RC4
|
* @return \phpseclib\Crypt\RC4
|
||||||
* @access public
|
* @access public
|
||||||
@ -163,14 +167,26 @@ class RC4 extends Base
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RC4 does not use an IV
|
* Dummy function.
|
||||||
*
|
*
|
||||||
|
* Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
|
||||||
|
* If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
|
||||||
|
* calling setKey().
|
||||||
|
*
|
||||||
|
* [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
|
||||||
|
* the IV's are relatively easy to predict, an attack described by
|
||||||
|
* {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
|
||||||
|
* can be used to quickly guess at the rest of the key. The following links elaborate:
|
||||||
|
*
|
||||||
|
* {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
|
||||||
|
* {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
|
||||||
|
*
|
||||||
|
* @param string $iv
|
||||||
|
* @see self::setKey()
|
||||||
* @access public
|
* @access public
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
function usesIV()
|
function setIV($iv)
|
||||||
{
|
{
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -180,38 +196,20 @@ class RC4 extends Base
|
|||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param int $length
|
* @param int $length
|
||||||
* @throws \LengthException if the key length is invalid
|
|
||||||
*/
|
*/
|
||||||
function setKeyLength($length)
|
function setKeyLength($length)
|
||||||
{
|
{
|
||||||
if ($length < 8 || $length > 2048) {
|
if ($length < 8) {
|
||||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 256 bytes are supported');
|
$this->key_length = 1;
|
||||||
|
} elseif ($length > 2048) {
|
||||||
|
$this->key_length = 256;
|
||||||
|
} else {
|
||||||
|
$this->key_length = $length >> 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->key_length = $length >> 3;
|
|
||||||
|
|
||||||
parent::setKeyLength($length);
|
parent::setKeyLength($length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the key length
|
|
||||||
*
|
|
||||||
* Keys can be between 1 and 256 bytes long.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param int $length
|
|
||||||
* @throws \LengthException if the key length is invalid
|
|
||||||
*/
|
|
||||||
function setKey($key)
|
|
||||||
{
|
|
||||||
$length = strlen($key);
|
|
||||||
if ($length < 1 || $length > 256) {
|
|
||||||
throw new \LengthException('Key size of ' . $length . ' bytes is not supported by RC4. Keys must be between 1 and 256 bytes long');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::setKey($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts a message.
|
* Encrypts a message.
|
||||||
*
|
*
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,223 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Miccrosoft BLOB Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* More info:
|
|
||||||
*
|
|
||||||
* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375601(v=vs.85).aspx
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Crypt
|
|
||||||
* @package RSA
|
|
||||||
* @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\RSA;
|
|
||||||
|
|
||||||
use phpseclib\Math\BigInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Microsoft BLOB Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* @package RSA
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
class MSBLOB
|
|
||||||
{
|
|
||||||
/**#@+
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Public/Private Key Pair
|
|
||||||
*/
|
|
||||||
const PRIVATEKEYBLOB = 0x7;
|
|
||||||
/**
|
|
||||||
* Public Key
|
|
||||||
*/
|
|
||||||
const PUBLICKEYBLOB = 0x6;
|
|
||||||
/**
|
|
||||||
* Public Key
|
|
||||||
*/
|
|
||||||
const PUBLICKEYBLOBEX = 0xA;
|
|
||||||
/**
|
|
||||||
* RSA public key exchange algorithm
|
|
||||||
*/
|
|
||||||
const CALG_RSA_KEYX = 0x0000A400;
|
|
||||||
/**
|
|
||||||
* RSA public key exchange algorithm
|
|
||||||
*/
|
|
||||||
const CALG_RSA_SIGN = 0x00002400;
|
|
||||||
/**
|
|
||||||
* Public Key
|
|
||||||
*/
|
|
||||||
const RSA1 = 0x31415352;
|
|
||||||
/**
|
|
||||||
* Private Key
|
|
||||||
*/
|
|
||||||
const RSA2 = 0x32415352;
|
|
||||||
/**#@-*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Break a public or private key down into its constituent components
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $key
|
|
||||||
* @param string $password optional
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
static function load($key, $password = '')
|
|
||||||
{
|
|
||||||
if (!is_string($key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$key = base64_decode($key);
|
|
||||||
|
|
||||||
if (!is_string($key) || strlen($key) < 20) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PUBLICKEYSTRUC publickeystruc
|
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx
|
|
||||||
extract(unpack('atype/aversion/vreserved/Valgo', self::_string_shift($key, 8)));
|
|
||||||
switch (ord($type)) {
|
|
||||||
case self::PUBLICKEYBLOB:
|
|
||||||
case self::PUBLICKEYBLOBEX:
|
|
||||||
$publickey = true;
|
|
||||||
break;
|
|
||||||
case self::PRIVATEKEYBLOB:
|
|
||||||
$publickey = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$components = array('isPublicKey' => $publickey);
|
|
||||||
|
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx
|
|
||||||
switch ($algo) {
|
|
||||||
case self::CALG_RSA_KEYX:
|
|
||||||
case self::CALG_RSA_SIGN:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// RSAPUBKEY rsapubkey
|
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa387685(v=vs.85).aspx
|
|
||||||
// could do V for pubexp but that's unsigned 32-bit whereas some PHP installs only do signed 32-bit
|
|
||||||
extract(unpack('Vmagic/Vbitlen/a4pubexp', self::_string_shift($key, 12)));
|
|
||||||
switch ($magic) {
|
|
||||||
case self::RSA2:
|
|
||||||
$components['isPublicKey'] = false;
|
|
||||||
case self::RSA1:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$baseLength = $bitlen / 16;
|
|
||||||
if (strlen($key) != 2 * $baseLength && strlen($key) != 9 * $baseLength) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(strrev($pubexp), 256);
|
|
||||||
// BYTE modulus[rsapubkey.bitlen/8]
|
|
||||||
$components['modulus'] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 8)), 256);
|
|
||||||
|
|
||||||
if ($publickey) {
|
|
||||||
return $components;
|
|
||||||
}
|
|
||||||
|
|
||||||
$components['isPublicKey'] = false;
|
|
||||||
|
|
||||||
// BYTE prime1[rsapubkey.bitlen/16]
|
|
||||||
$components['primes'] = array(1 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256));
|
|
||||||
// BYTE prime2[rsapubkey.bitlen/16]
|
|
||||||
$components['primes'][] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256);
|
|
||||||
// BYTE exponent1[rsapubkey.bitlen/16]
|
|
||||||
$components['exponents'] = array(1 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256));
|
|
||||||
// BYTE exponent2[rsapubkey.bitlen/16]
|
|
||||||
$components['exponents'][] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256);
|
|
||||||
// BYTE coefficient[rsapubkey.bitlen/16]
|
|
||||||
$components['coefficients'] = array(2 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256));
|
|
||||||
if (isset($components['privateExponent'])) {
|
|
||||||
$components['publicExponent'] = $components['privateExponent'];
|
|
||||||
}
|
|
||||||
// BYTE privateExponent[rsapubkey.bitlen/8]
|
|
||||||
$components['privateExponent'] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 8)), 256);
|
|
||||||
|
|
||||||
return $components;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a private key to the appropriate format.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @param \phpseclib\Math\BigInteger $d
|
|
||||||
* @param array $primes
|
|
||||||
* @param array $exponents
|
|
||||||
* @param array $coefficients
|
|
||||||
* @param string $password optional
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '')
|
|
||||||
{
|
|
||||||
$n = strrev($n->toBytes());
|
|
||||||
$e = str_pad(strrev($e->toBytes()), 4, "\0");
|
|
||||||
$key = pack('aavV', chr(self::PRIVATEKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX);
|
|
||||||
$key.= pack('VVa*', self::RSA2, 8 * strlen($n), $e);
|
|
||||||
$key.= $n;
|
|
||||||
$key.= strrev($primes[1]->toBytes());
|
|
||||||
$key.= strrev($primes[2]->toBytes());
|
|
||||||
$key.= strrev($exponents[1]->toBytes());
|
|
||||||
$key.= strrev($exponents[2]->toBytes());
|
|
||||||
$key.= strrev($coefficients[1]->toBytes());
|
|
||||||
$key.= strrev($d->toBytes());
|
|
||||||
|
|
||||||
return base64_encode($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a public key to the appropriate format
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePublicKey(BigInteger $n, BigInteger $e)
|
|
||||||
{
|
|
||||||
$n = strrev($n->toBytes());
|
|
||||||
$e = str_pad(strrev($e->toBytes()), 4, "\0");
|
|
||||||
$key = pack('aavV', chr(self::PUBLICKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX);
|
|
||||||
$key.= pack('VVa*', self::RSA1, 8 * strlen($n), $e);
|
|
||||||
$key.= $n;
|
|
||||||
|
|
||||||
return base64_encode($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String Shift
|
|
||||||
*
|
|
||||||
* Inspired by array_shift
|
|
||||||
*
|
|
||||||
* @param string $string
|
|
||||||
* @param int $index
|
|
||||||
* @return string
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
static function _string_shift(&$string, $index = 1)
|
|
||||||
{
|
|
||||||
$substr = substr($string, 0, $index);
|
|
||||||
$string = substr($string, $index);
|
|
||||||
return $substr;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,140 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* OpenSSH Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* Place in $HOME/.ssh/authorized_keys
|
|
||||||
*
|
|
||||||
* @category Crypt
|
|
||||||
* @package RSA
|
|
||||||
* @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\RSA;
|
|
||||||
|
|
||||||
use phpseclib\Math\BigInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OpenSSH Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* @package RSA
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
class OpenSSH
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Default comment
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
static $comment = 'phpseclib-generated-key';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the default comment
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $comment
|
|
||||||
*/
|
|
||||||
static function setComment($comment)
|
|
||||||
{
|
|
||||||
self::$comment = str_replace(array("\r", "\n"), '', $comment);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Break a public or private key down into its constituent components
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $key
|
|
||||||
* @param string $password optional
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
static function load($key, $password = '')
|
|
||||||
{
|
|
||||||
if (!is_string($key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$parts = explode(' ', $key, 3);
|
|
||||||
|
|
||||||
$key = isset($parts[1]) ? base64_decode($parts[1]) : base64_decode($parts[0]);
|
|
||||||
if ($key === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$comment = isset($parts[2]) ? $parts[2] : false;
|
|
||||||
|
|
||||||
if (substr($key, 0, 11) != "\0\0\0\7ssh-rsa") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
self::_string_shift($key, 11);
|
|
||||||
if (strlen($key) <= 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
extract(unpack('Nlength', self::_string_shift($key, 4)));
|
|
||||||
if (strlen($key) <= $length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$publicExponent = new BigInteger(self::_string_shift($key, $length), -256);
|
|
||||||
if (strlen($key) <= 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
extract(unpack('Nlength', self::_string_shift($key, 4)));
|
|
||||||
if (strlen($key) != $length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$modulus = new BigInteger(self::_string_shift($key, $length), -256);
|
|
||||||
|
|
||||||
return array(
|
|
||||||
'isPublicKey' => true,
|
|
||||||
'modulus' => $modulus,
|
|
||||||
'publicExponent' => $publicExponent,
|
|
||||||
'comment' => $comment
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a public key to the appropriate format
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePublicKey(BigInteger $n, BigInteger $e)
|
|
||||||
{
|
|
||||||
$publicExponent = $e->toBytes(true);
|
|
||||||
$modulus = $n->toBytes(true);
|
|
||||||
|
|
||||||
// from <http://tools.ietf.org/html/rfc4253#page-15>:
|
|
||||||
// string "ssh-rsa"
|
|
||||||
// mpint e
|
|
||||||
// mpint n
|
|
||||||
$RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
|
|
||||||
$RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . self::$comment;
|
|
||||||
|
|
||||||
return $RSAPublicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String Shift
|
|
||||||
*
|
|
||||||
* Inspired by array_shift
|
|
||||||
*
|
|
||||||
* @param string $string
|
|
||||||
* @param int $index
|
|
||||||
* @return string
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
static function _string_shift(&$string, $index = 1)
|
|
||||||
{
|
|
||||||
$substr = substr($string, 0, $index);
|
|
||||||
$string = substr($string, $index);
|
|
||||||
return $substr;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,485 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* PKCS Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Crypt
|
|
||||||
* @package RSA
|
|
||||||
* @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\RSA;
|
|
||||||
|
|
||||||
use phpseclib\Crypt\AES;
|
|
||||||
use phpseclib\Crypt\Base;
|
|
||||||
use phpseclib\Crypt\DES;
|
|
||||||
use phpseclib\Crypt\TripleDES;
|
|
||||||
use phpseclib\Math\BigInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PKCS Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* @package RSA
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
abstract class PKCS
|
|
||||||
{
|
|
||||||
/**#@+
|
|
||||||
* @access private
|
|
||||||
* @see \phpseclib\Crypt\RSA::createKey()
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* ASN1 Integer
|
|
||||||
*/
|
|
||||||
const ASN1_INTEGER = 2;
|
|
||||||
/**
|
|
||||||
* ASN1 Bit String
|
|
||||||
*/
|
|
||||||
const ASN1_BITSTRING = 3;
|
|
||||||
/**
|
|
||||||
* ASN1 Octet String
|
|
||||||
*/
|
|
||||||
const ASN1_OCTETSTRING = 4;
|
|
||||||
/**
|
|
||||||
* ASN1 Object Identifier
|
|
||||||
*/
|
|
||||||
const ASN1_OBJECT = 6;
|
|
||||||
/**
|
|
||||||
* ASN1 Sequence (with the constucted bit set)
|
|
||||||
*/
|
|
||||||
const ASN1_SEQUENCE = 48;
|
|
||||||
/**#@-*/
|
|
||||||
|
|
||||||
/**#@+
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Auto-detect the format
|
|
||||||
*/
|
|
||||||
const MODE_ANY = 0;
|
|
||||||
/**
|
|
||||||
* Require base64-encoded PEM's be supplied
|
|
||||||
*/
|
|
||||||
const MODE_PEM = 1;
|
|
||||||
/**
|
|
||||||
* Require raw DER's be supplied
|
|
||||||
*/
|
|
||||||
const MODE_DER = 2;
|
|
||||||
/**#@-*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the key a base-64 encoded PEM, DER or should it be auto-detected?
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
* @param int
|
|
||||||
*/
|
|
||||||
static $format = self::MODE_ANY;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the mode constant corresponding to the mode string
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $mode
|
|
||||||
* @return int
|
|
||||||
* @throws \UnexpectedValueException if the block cipher mode is unsupported
|
|
||||||
*/
|
|
||||||
static function getEncryptionMode($mode)
|
|
||||||
{
|
|
||||||
switch ($mode) {
|
|
||||||
case 'CBC':
|
|
||||||
return Base::MODE_CBC;
|
|
||||||
case 'ECB':
|
|
||||||
return Base::MODE_ECB;
|
|
||||||
case 'CFB':
|
|
||||||
return Base::MODE_CFB;
|
|
||||||
case 'OFB':
|
|
||||||
return Base::MODE_OFB;
|
|
||||||
case 'CTR':
|
|
||||||
return Base::MODE_CTR;
|
|
||||||
}
|
|
||||||
throw new \UnexpectedValueException('Unsupported block cipher mode of operation');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a cipher object corresponding to a string
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $algo
|
|
||||||
* @return string
|
|
||||||
* @throws \UnexpectedValueException if the encryption algorithm is unsupported
|
|
||||||
*/
|
|
||||||
static function getEncryptionObject($algo)
|
|
||||||
{
|
|
||||||
$modes = '(CBC|ECB|CFB|OFB|CTR)';
|
|
||||||
switch (true) {
|
|
||||||
case preg_match("#^AES-(128|192|256)-$modes$#", $algo, $matches):
|
|
||||||
$cipher = new AES(self::getEncryptionMode($matches[2]));
|
|
||||||
$cipher->setKeyLength($matches[1]);
|
|
||||||
return $cipher;
|
|
||||||
case preg_match("#^DES-EDE3-$modes$#", $algo, $matches):
|
|
||||||
return new TripleDES(self::getEncryptionMode($matches[1]));
|
|
||||||
case preg_match("#^DES-$modes$#", $algo, $matches):
|
|
||||||
return new DES(self::getEncryptionMode($matches[1]));
|
|
||||||
default:
|
|
||||||
throw new \UnexpectedValueException('Unsupported encryption algorithmn');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a symmetric key for PKCS#1 keys
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $password
|
|
||||||
* @param string $iv
|
|
||||||
* @param int $length
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function generateSymmetricKey($password, $iv, $length)
|
|
||||||
{
|
|
||||||
$symkey = '';
|
|
||||||
$iv = substr($iv, 0, 8);
|
|
||||||
while (strlen($symkey) < $length) {
|
|
||||||
$symkey.= pack('H*', md5($symkey . $password . $iv));
|
|
||||||
}
|
|
||||||
return substr($symkey, 0, $length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Break a public or private key down into its constituent components
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $key
|
|
||||||
* @param string $password optional
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
static function load($key, $password = '')
|
|
||||||
{
|
|
||||||
if (!is_string($key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$components = array('isPublicKey' => strpos($key, 'PUBLIC') !== false);
|
|
||||||
|
|
||||||
/* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
|
|
||||||
"outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to
|
|
||||||
protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding
|
|
||||||
two new "fields" to the key - DEK-Info and Proc-Type. These fields are discussed here:
|
|
||||||
|
|
||||||
http://tools.ietf.org/html/rfc1421#section-4.6.1.1
|
|
||||||
http://tools.ietf.org/html/rfc1421#section-4.6.1.3
|
|
||||||
|
|
||||||
DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell.
|
|
||||||
DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation
|
|
||||||
function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's
|
|
||||||
own implementation. ie. the implementation *is* the standard and any bugs that may exist in that
|
|
||||||
implementation are part of the standard, as well.
|
|
||||||
|
|
||||||
* OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */
|
|
||||||
if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) {
|
|
||||||
$iv = pack('H*', trim($matches[2]));
|
|
||||||
// remove the Proc-Type / DEK-Info sections as they're no longer needed
|
|
||||||
$key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key);
|
|
||||||
$ciphertext = self::_extractBER($key);
|
|
||||||
if ($ciphertext === false) {
|
|
||||||
$ciphertext = $key;
|
|
||||||
}
|
|
||||||
$crypto = self::getEncryptionObject($matches[1]);
|
|
||||||
$crypto->setKey(self::generateSymmetricKey($password, $iv, $crypto->getKeyLength() >> 3));
|
|
||||||
$crypto->setIV($iv);
|
|
||||||
$key = $crypto->decrypt($ciphertext);
|
|
||||||
if ($key === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (self::$format != self::MODE_DER) {
|
|
||||||
$decoded = self::_extractBER($key);
|
|
||||||
if ($decoded !== false) {
|
|
||||||
$key = $decoded;
|
|
||||||
} elseif (self::$format == self::MODE_PEM) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (self::_decodeLength($key) != strlen($key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$tag = ord(self::_string_shift($key));
|
|
||||||
/* intended for keys for which OpenSSL's asn1parse returns the following:
|
|
||||||
|
|
||||||
0:d=0 hl=4 l= 631 cons: SEQUENCE
|
|
||||||
4:d=1 hl=2 l= 1 prim: INTEGER :00
|
|
||||||
7:d=1 hl=2 l= 13 cons: SEQUENCE
|
|
||||||
9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
|
|
||||||
20:d=2 hl=2 l= 0 prim: NULL
|
|
||||||
22:d=1 hl=4 l= 609 prim: OCTET STRING
|
|
||||||
|
|
||||||
ie. PKCS8 keys */
|
|
||||||
|
|
||||||
if ($tag == self::ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") {
|
|
||||||
self::_string_shift($key, 3);
|
|
||||||
$tag = self::ASN1_SEQUENCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($tag == self::ASN1_SEQUENCE) {
|
|
||||||
$temp = self::_string_shift($key, self::_decodeLength($key));
|
|
||||||
if (ord(self::_string_shift($temp)) != self::ASN1_OBJECT) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$length = self::_decodeLength($temp);
|
|
||||||
switch (self::_string_shift($temp, $length)) {
|
|
||||||
case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption
|
|
||||||
break;
|
|
||||||
case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC
|
|
||||||
/*
|
|
||||||
PBEParameter ::= SEQUENCE {
|
|
||||||
salt OCTET STRING (SIZE(8)),
|
|
||||||
iterationCount INTEGER }
|
|
||||||
*/
|
|
||||||
if (ord(self::_string_shift($temp)) != self::ASN1_SEQUENCE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (self::_decodeLength($temp) != strlen($temp)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
self::_string_shift($temp); // assume it's an octet string
|
|
||||||
$salt = self::_string_shift($temp, self::_decodeLength($temp));
|
|
||||||
if (ord(self::_string_shift($temp)) != self::ASN1_INTEGER) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
self::_decodeLength($temp);
|
|
||||||
list(, $iterationCount) = unpack('N', str_pad($temp, 4, chr(0), STR_PAD_LEFT));
|
|
||||||
self::_string_shift($key); // assume it's an octet string
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
if (strlen($key) != $length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$crypto = new DES(DES::MODE_CBC);
|
|
||||||
$crypto->setPassword($password, 'pbkdf1', 'md5', $salt, $iterationCount);
|
|
||||||
$key = $crypto->decrypt($key);
|
|
||||||
if ($key === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return self::load($key);
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* intended for keys for which OpenSSL's asn1parse returns the following:
|
|
||||||
|
|
||||||
0:d=0 hl=4 l= 290 cons: SEQUENCE
|
|
||||||
4:d=1 hl=2 l= 13 cons: SEQUENCE
|
|
||||||
6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
|
|
||||||
17:d=2 hl=2 l= 0 prim: NULL
|
|
||||||
19:d=1 hl=4 l= 271 prim: BIT STRING */
|
|
||||||
$tag = ord(self::_string_shift($key)); // skip over the BIT STRING / OCTET STRING tag
|
|
||||||
self::_decodeLength($key); // skip over the BIT STRING / OCTET STRING length
|
|
||||||
// "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of
|
|
||||||
// unused bits in the final subsequent octet. The number shall be in the range zero to seven."
|
|
||||||
// -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf (section 8.6.2.2)
|
|
||||||
if ($tag == self::ASN1_BITSTRING) {
|
|
||||||
self::_string_shift($key);
|
|
||||||
}
|
|
||||||
if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (self::_decodeLength($key) != strlen($key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$tag = ord(self::_string_shift($key));
|
|
||||||
}
|
|
||||||
if ($tag != self::ASN1_INTEGER) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$temp = self::_string_shift($key, $length);
|
|
||||||
if (strlen($temp) != 1 || ord($temp) > 2) {
|
|
||||||
$components['modulus'] = new BigInteger($temp, 256);
|
|
||||||
self::_string_shift($key); // skip over self::ASN1_INTEGER
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(self::_string_shift($key, $length), 256);
|
|
||||||
|
|
||||||
return $components;
|
|
||||||
}
|
|
||||||
if (ord(self::_string_shift($key)) != self::ASN1_INTEGER) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components['modulus'] = new BigInteger(self::_string_shift($key, $length), 256);
|
|
||||||
self::_string_shift($key);
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components['publicExponent'] = new BigInteger(self::_string_shift($key, $length), 256);
|
|
||||||
self::_string_shift($key);
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components['privateExponent'] = new BigInteger(self::_string_shift($key, $length), 256);
|
|
||||||
self::_string_shift($key);
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components['primes'] = array(1 => new BigInteger(self::_string_shift($key, $length), 256));
|
|
||||||
self::_string_shift($key);
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components['primes'][] = new BigInteger(self::_string_shift($key, $length), 256);
|
|
||||||
self::_string_shift($key);
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components['exponents'] = array(1 => new BigInteger(self::_string_shift($key, $length), 256));
|
|
||||||
self::_string_shift($key);
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components['exponents'][] = new BigInteger(self::_string_shift($key, $length), 256);
|
|
||||||
self::_string_shift($key);
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components['coefficients'] = array(2 => new BigInteger(self::_string_shift($key, $length), 256));
|
|
||||||
|
|
||||||
if (!empty($key)) {
|
|
||||||
if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
self::_decodeLength($key);
|
|
||||||
while (!empty($key)) {
|
|
||||||
if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
self::_decodeLength($key);
|
|
||||||
$key = substr($key, 1);
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components['primes'][] = new BigInteger(self::_string_shift($key, $length), 256);
|
|
||||||
self::_string_shift($key);
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components['exponents'][] = new BigInteger(self::_string_shift($key, $length), 256);
|
|
||||||
self::_string_shift($key);
|
|
||||||
$length = self::_decodeLength($key);
|
|
||||||
$components['coefficients'][] = new BigInteger(self::_string_shift($key, $length), 256);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $components;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Require base64-encoded PEM's be supplied
|
|
||||||
*
|
|
||||||
* @see self::load()
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
static function requirePEM()
|
|
||||||
{
|
|
||||||
self::$format = self::MODE_PEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Require raw DER's be supplied
|
|
||||||
*
|
|
||||||
* @see self::load()
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
static function requireDER()
|
|
||||||
{
|
|
||||||
self::$format = self::MODE_DER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accept any format and auto detect the format
|
|
||||||
*
|
|
||||||
* This is the default setting
|
|
||||||
*
|
|
||||||
* @see self::load()
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
static function requireAny()
|
|
||||||
{
|
|
||||||
self::$format = self::MODE_ANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DER-decode the length
|
|
||||||
*
|
|
||||||
* DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
|
|
||||||
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
* @param string $string
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
static function _decodeLength(&$string)
|
|
||||||
{
|
|
||||||
$length = ord(self::_string_shift($string));
|
|
||||||
if ($length & 0x80) { // definite length, long form
|
|
||||||
$length&= 0x7F;
|
|
||||||
$temp = self::_string_shift($string, $length);
|
|
||||||
list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
|
|
||||||
}
|
|
||||||
return $length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DER-encode the length
|
|
||||||
*
|
|
||||||
* DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
|
|
||||||
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
* @param int $length
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function _encodeLength($length)
|
|
||||||
{
|
|
||||||
if ($length <= 0x7F) {
|
|
||||||
return chr($length);
|
|
||||||
}
|
|
||||||
|
|
||||||
$temp = ltrim(pack('N', $length), chr(0));
|
|
||||||
return pack('Ca*', 0x80 | strlen($temp), $temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String Shift
|
|
||||||
*
|
|
||||||
* Inspired by array_shift
|
|
||||||
*
|
|
||||||
* @param string $string
|
|
||||||
* @param int $index
|
|
||||||
* @return string
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
static function _string_shift(&$string, $index = 1)
|
|
||||||
{
|
|
||||||
$substr = substr($string, 0, $index);
|
|
||||||
$string = substr($string, $index);
|
|
||||||
return $substr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract raw BER from Base64 encoding
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
* @param string $str
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function _extractBER($str)
|
|
||||||
{
|
|
||||||
/* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them
|
|
||||||
* above and beyond the ceritificate.
|
|
||||||
* ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line:
|
|
||||||
*
|
|
||||||
* Bag Attributes
|
|
||||||
* localKeyID: 01 00 00 00
|
|
||||||
* subject=/O=organization/OU=org unit/CN=common name
|
|
||||||
* issuer=/O=organization/CN=common name
|
|
||||||
*/
|
|
||||||
$temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
|
|
||||||
// remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
|
|
||||||
$temp = preg_replace('#-+[^-]+-+#', '', $temp);
|
|
||||||
// remove new lines
|
|
||||||
$temp = str_replace(array("\r", "\n", ' '), '', $temp);
|
|
||||||
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
|
|
||||||
return $temp != false ? $temp : $str;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,172 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* PKCS#1 Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* Used by File/X509.php
|
|
||||||
*
|
|
||||||
* Has the following header:
|
|
||||||
*
|
|
||||||
* -----BEGIN RSA PUBLIC KEY-----
|
|
||||||
*
|
|
||||||
* Analogous to ssh-keygen's pem format (as specified by -m)
|
|
||||||
*
|
|
||||||
* @category Crypt
|
|
||||||
* @package RSA
|
|
||||||
* @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\RSA;
|
|
||||||
|
|
||||||
use phpseclib\Crypt\AES;
|
|
||||||
use phpseclib\Crypt\DES;
|
|
||||||
use phpseclib\Crypt\Random;
|
|
||||||
use phpseclib\Crypt\TripleDES;
|
|
||||||
use phpseclib\Math\BigInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PKCS#1 Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* @package RSA
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
class PKCS1 extends PKCS
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Default encryption algorithm
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
static $defaultEncryptionAlgorithm = 'DES-EDE3-CBC';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the default encryption algorithm
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $algo
|
|
||||||
*/
|
|
||||||
static function setEncryptionAlgorithm($algo)
|
|
||||||
{
|
|
||||||
self::$defaultEncryptionAlgorithm = $algo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a private key to the appropriate format.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @param \phpseclib\Math\BigInteger $d
|
|
||||||
* @param array $primes
|
|
||||||
* @param array $exponents
|
|
||||||
* @param array $coefficients
|
|
||||||
* @param string $password optional
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '')
|
|
||||||
{
|
|
||||||
$num_primes = count($primes);
|
|
||||||
$raw = array(
|
|
||||||
'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
|
|
||||||
'modulus' => $n->toBytes(true),
|
|
||||||
'publicExponent' => $e->toBytes(true),
|
|
||||||
'privateExponent' => $d->toBytes(true),
|
|
||||||
'prime1' => $primes[1]->toBytes(true),
|
|
||||||
'prime2' => $primes[2]->toBytes(true),
|
|
||||||
'exponent1' => $exponents[1]->toBytes(true),
|
|
||||||
'exponent2' => $exponents[2]->toBytes(true),
|
|
||||||
'coefficient' => $coefficients[2]->toBytes(true)
|
|
||||||
);
|
|
||||||
|
|
||||||
$components = array();
|
|
||||||
foreach ($raw as $name => $value) {
|
|
||||||
$components[$name] = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($value)), $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
$RSAPrivateKey = implode('', $components);
|
|
||||||
|
|
||||||
if ($num_primes > 2) {
|
|
||||||
$OtherPrimeInfos = '';
|
|
||||||
for ($i = 3; $i <= $num_primes; $i++) {
|
|
||||||
// OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
|
|
||||||
//
|
|
||||||
// OtherPrimeInfo ::= SEQUENCE {
|
|
||||||
// prime INTEGER, -- ri
|
|
||||||
// exponent INTEGER, -- di
|
|
||||||
// coefficient INTEGER -- ti
|
|
||||||
// }
|
|
||||||
$OtherPrimeInfo = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true));
|
|
||||||
$OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true));
|
|
||||||
$OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true));
|
|
||||||
$OtherPrimeInfos.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo);
|
|
||||||
}
|
|
||||||
$RSAPrivateKey.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos);
|
|
||||||
}
|
|
||||||
|
|
||||||
$RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
|
|
||||||
|
|
||||||
if (!empty($password) || is_string($password)) {
|
|
||||||
$cipher = self::getEncryptionObject(self::$defaultEncryptionAlgorithm);
|
|
||||||
$iv = Random::string($cipher->getBlockLength() >> 3);
|
|
||||||
$cipher->setKey(self::generateSymmetricKey($password, $iv, $cipher->getKeyLength() >> 3));
|
|
||||||
$cipher->setIV($iv);
|
|
||||||
$iv = strtoupper(bin2hex($iv));
|
|
||||||
$RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
|
|
||||||
"Proc-Type: 4,ENCRYPTED\r\n" .
|
|
||||||
"DEK-Info: " . self::$defaultEncryptionAlgorithm . ",$iv\r\n" .
|
|
||||||
"\r\n" .
|
|
||||||
chunk_split(base64_encode($cipher->encrypt($RSAPrivateKey)), 64) .
|
|
||||||
'-----END RSA PRIVATE KEY-----';
|
|
||||||
} else {
|
|
||||||
$RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
|
|
||||||
chunk_split(base64_encode($RSAPrivateKey), 64) .
|
|
||||||
'-----END RSA PRIVATE KEY-----';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $RSAPrivateKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a public key to the appropriate format
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePublicKey(BigInteger $n, BigInteger $e)
|
|
||||||
{
|
|
||||||
$modulus = $n->toBytes(true);
|
|
||||||
$publicExponent = $e->toBytes(true);
|
|
||||||
|
|
||||||
// from <http://tools.ietf.org/html/rfc3447#appendix-A.1.1>:
|
|
||||||
// RSAPublicKey ::= SEQUENCE {
|
|
||||||
// modulus INTEGER, -- n
|
|
||||||
// publicExponent INTEGER -- e
|
|
||||||
// }
|
|
||||||
$components = array(
|
|
||||||
'modulus' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($modulus)), $modulus),
|
|
||||||
'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($publicExponent)), $publicExponent)
|
|
||||||
);
|
|
||||||
|
|
||||||
$RSAPublicKey = pack(
|
|
||||||
'Ca*a*a*',
|
|
||||||
self::ASN1_SEQUENCE,
|
|
||||||
self::_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
|
|
||||||
$components['modulus'],
|
|
||||||
$components['publicExponent']
|
|
||||||
);
|
|
||||||
|
|
||||||
$RSAPublicKey = "-----BEGIN RSA PUBLIC KEY-----\r\n" .
|
|
||||||
chunk_split(base64_encode($RSAPublicKey), 64) .
|
|
||||||
'-----END RSA PUBLIC KEY-----';
|
|
||||||
|
|
||||||
return $RSAPublicKey;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,208 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* PKCS#8 Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
|
|
||||||
*
|
|
||||||
* Has the following header:
|
|
||||||
*
|
|
||||||
* -----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 RSA
|
|
||||||
* @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\RSA;
|
|
||||||
|
|
||||||
use phpseclib\Crypt\DES;
|
|
||||||
use phpseclib\Crypt\Random;
|
|
||||||
use phpseclib\Math\BigInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PKCS#8 Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* @package RSA
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
class PKCS8 extends PKCS
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Convert a private key to the appropriate format.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @param \phpseclib\Math\BigInteger $d
|
|
||||||
* @param array $primes
|
|
||||||
* @param array $exponents
|
|
||||||
* @param array $coefficients
|
|
||||||
* @param string $password optional
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '')
|
|
||||||
{
|
|
||||||
$num_primes = count($primes);
|
|
||||||
$raw = array(
|
|
||||||
'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
|
|
||||||
'modulus' => $n->toBytes(true),
|
|
||||||
'publicExponent' => $e->toBytes(true),
|
|
||||||
'privateExponent' => $d->toBytes(true),
|
|
||||||
'prime1' => $primes[1]->toBytes(true),
|
|
||||||
'prime2' => $primes[2]->toBytes(true),
|
|
||||||
'exponent1' => $exponents[1]->toBytes(true),
|
|
||||||
'exponent2' => $exponents[2]->toBytes(true),
|
|
||||||
'coefficient' => $coefficients[2]->toBytes(true)
|
|
||||||
);
|
|
||||||
|
|
||||||
$components = array();
|
|
||||||
foreach ($raw as $name => $value) {
|
|
||||||
$components[$name] = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($value)), $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
$RSAPrivateKey = implode('', $components);
|
|
||||||
|
|
||||||
if ($num_primes > 2) {
|
|
||||||
$OtherPrimeInfos = '';
|
|
||||||
for ($i = 3; $i <= $num_primes; $i++) {
|
|
||||||
// OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
|
|
||||||
//
|
|
||||||
// OtherPrimeInfo ::= SEQUENCE {
|
|
||||||
// prime INTEGER, -- ri
|
|
||||||
// exponent INTEGER, -- di
|
|
||||||
// coefficient INTEGER -- ti
|
|
||||||
// }
|
|
||||||
$OtherPrimeInfo = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true));
|
|
||||||
$OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true));
|
|
||||||
$OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true));
|
|
||||||
$OtherPrimeInfos.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo);
|
|
||||||
}
|
|
||||||
$RSAPrivateKey.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos);
|
|
||||||
}
|
|
||||||
|
|
||||||
$RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
|
|
||||||
|
|
||||||
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
|
|
||||||
$RSAPrivateKey = pack(
|
|
||||||
'Ca*a*Ca*a*',
|
|
||||||
self::ASN1_INTEGER,
|
|
||||||
"\01\00",
|
|
||||||
$rsaOID,
|
|
||||||
4,
|
|
||||||
self::_encodeLength(strlen($RSAPrivateKey)),
|
|
||||||
$RSAPrivateKey
|
|
||||||
);
|
|
||||||
$RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
|
|
||||||
if (!empty($password) || is_string($password)) {
|
|
||||||
$salt = Random::string(8);
|
|
||||||
$iterationCount = 2048;
|
|
||||||
|
|
||||||
$crypto = new DES(DES::MODE_CBC);
|
|
||||||
$crypto->setPassword($password, 'pbkdf1', 'md5', $salt, $iterationCount);
|
|
||||||
$RSAPrivateKey = $crypto->encrypt($RSAPrivateKey);
|
|
||||||
|
|
||||||
$parameters = pack(
|
|
||||||
'Ca*a*Ca*N',
|
|
||||||
self::ASN1_OCTETSTRING,
|
|
||||||
self::_encodeLength(strlen($salt)),
|
|
||||||
$salt,
|
|
||||||
self::ASN1_INTEGER,
|
|
||||||
self::_encodeLength(4),
|
|
||||||
$iterationCount
|
|
||||||
);
|
|
||||||
$pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03";
|
|
||||||
|
|
||||||
$encryptionAlgorithm = pack(
|
|
||||||
'Ca*a*Ca*a*',
|
|
||||||
self::ASN1_OBJECT,
|
|
||||||
self::_encodeLength(strlen($pbeWithMD5AndDES_CBC)),
|
|
||||||
$pbeWithMD5AndDES_CBC,
|
|
||||||
self::ASN1_SEQUENCE,
|
|
||||||
self::_encodeLength(strlen($parameters)),
|
|
||||||
$parameters
|
|
||||||
);
|
|
||||||
|
|
||||||
$RSAPrivateKey = pack(
|
|
||||||
'Ca*a*Ca*a*',
|
|
||||||
self::ASN1_SEQUENCE,
|
|
||||||
self::_encodeLength(strlen($encryptionAlgorithm)),
|
|
||||||
$encryptionAlgorithm,
|
|
||||||
self::ASN1_OCTETSTRING,
|
|
||||||
self::_encodeLength(strlen($RSAPrivateKey)),
|
|
||||||
$RSAPrivateKey
|
|
||||||
);
|
|
||||||
|
|
||||||
$RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
|
|
||||||
|
|
||||||
$RSAPrivateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" .
|
|
||||||
chunk_split(base64_encode($RSAPrivateKey), 64) .
|
|
||||||
'-----END ENCRYPTED PRIVATE KEY-----';
|
|
||||||
} else {
|
|
||||||
$RSAPrivateKey = "-----BEGIN PRIVATE KEY-----\r\n" .
|
|
||||||
chunk_split(base64_encode($RSAPrivateKey), 64) .
|
|
||||||
'-----END PRIVATE KEY-----';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $RSAPrivateKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a public key to the appropriate format
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePublicKey(BigInteger $n, BigInteger $e)
|
|
||||||
{
|
|
||||||
$modulus = $n->toBytes(true);
|
|
||||||
$publicExponent = $e->toBytes(true);
|
|
||||||
|
|
||||||
// from <http://tools.ietf.org/html/rfc3447#appendix-A.1.1>:
|
|
||||||
// RSAPublicKey ::= SEQUENCE {
|
|
||||||
// modulus INTEGER, -- n
|
|
||||||
// publicExponent INTEGER -- e
|
|
||||||
// }
|
|
||||||
$components = array(
|
|
||||||
'modulus' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($modulus)), $modulus),
|
|
||||||
'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($publicExponent)), $publicExponent)
|
|
||||||
);
|
|
||||||
|
|
||||||
$RSAPublicKey = pack(
|
|
||||||
'Ca*a*a*',
|
|
||||||
self::ASN1_SEQUENCE,
|
|
||||||
self::_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
|
|
||||||
$components['modulus'],
|
|
||||||
$components['publicExponent']
|
|
||||||
);
|
|
||||||
|
|
||||||
// sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
|
|
||||||
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
|
|
||||||
$RSAPublicKey = chr(0) . $RSAPublicKey;
|
|
||||||
$RSAPublicKey = chr(3) . self::_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey;
|
|
||||||
|
|
||||||
$RSAPublicKey = pack(
|
|
||||||
'Ca*a*',
|
|
||||||
self::ASN1_SEQUENCE,
|
|
||||||
self::_encodeLength(strlen($rsaOID . $RSAPublicKey)),
|
|
||||||
$rsaOID . $RSAPublicKey
|
|
||||||
);
|
|
||||||
|
|
||||||
$RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
|
|
||||||
chunk_split(base64_encode($RSAPublicKey), 64) .
|
|
||||||
'-----END PUBLIC KEY-----';
|
|
||||||
|
|
||||||
return $RSAPublicKey;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,311 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* PuTTY Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Crypt
|
|
||||||
* @package RSA
|
|
||||||
* @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\RSA;
|
|
||||||
|
|
||||||
use phpseclib\Crypt\AES;
|
|
||||||
use phpseclib\Crypt\Hash;
|
|
||||||
use phpseclib\Math\BigInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PuTTY Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* @package RSA
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
class PuTTY
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Default comment
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
static $comment = 'phpseclib-generated-key';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the default comment
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $comment
|
|
||||||
*/
|
|
||||||
static function setComment($comment)
|
|
||||||
{
|
|
||||||
self::$comment = str_replace(array("\r", "\n"), '', $comment);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a symmetric key for PuTTY keys
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $password
|
|
||||||
* @param string $iv
|
|
||||||
* @param int $length
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function generateSymmetricKey($password, $length)
|
|
||||||
{
|
|
||||||
$symkey = '';
|
|
||||||
$sequence = 0;
|
|
||||||
while (strlen($symkey) < $length) {
|
|
||||||
$temp = pack('Na*', $sequence++, $password);
|
|
||||||
$symkey.= pack('H*', sha1($temp));
|
|
||||||
}
|
|
||||||
return substr($symkey, 0, $length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Break a public or private key down into its constituent components
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $key
|
|
||||||
* @param string $password optional
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
static function load($key, $password = '')
|
|
||||||
{
|
|
||||||
if (!is_string($key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static $one;
|
|
||||||
if (!isset($one)) {
|
|
||||||
$one = new BigInteger(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($key, 'BEGIN SSH2 PUBLIC KEY')) {
|
|
||||||
$data = preg_split('#[\r\n]+#', $key);
|
|
||||||
$data = array_splice($data, 2, -1);
|
|
||||||
$data = implode('', $data);
|
|
||||||
|
|
||||||
$components = OpenSSH::load($data);
|
|
||||||
if ($components === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!preg_match('#Comment: "(.+)"#', $key, $matches)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$components['comment'] = str_replace(array('\\\\', '\"'), array('\\', '"'), $matches[1]);
|
|
||||||
|
|
||||||
return $components;
|
|
||||||
}
|
|
||||||
|
|
||||||
$components = array('isPublicKey' => false);
|
|
||||||
$key = preg_split('#\r\n|\r|\n#', $key);
|
|
||||||
$type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0]));
|
|
||||||
if ($type != 'ssh-rsa') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1]));
|
|
||||||
$components['comment'] = trim(preg_replace('#Comment: (.+)#', '$1', $key[2]));
|
|
||||||
|
|
||||||
$publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3]));
|
|
||||||
$public = base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength))));
|
|
||||||
$public = substr($public, 11);
|
|
||||||
extract(unpack('Nlength', self::_string_shift($public, 4)));
|
|
||||||
$components['publicExponent'] = new BigInteger(self::_string_shift($public, $length), -256);
|
|
||||||
extract(unpack('Nlength', self::_string_shift($public, 4)));
|
|
||||||
$components['modulus'] = new BigInteger(self::_string_shift($public, $length), -256);
|
|
||||||
|
|
||||||
$privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4]));
|
|
||||||
$private = base64_decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength))));
|
|
||||||
|
|
||||||
switch ($encryption) {
|
|
||||||
case 'aes256-cbc':
|
|
||||||
$symkey = static::generateSymmetricKey($password, 32);
|
|
||||||
$crypto = new AES(AES::MODE_CBC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($encryption != 'none') {
|
|
||||||
$crypto->setKey($symkey);
|
|
||||||
$crypto->setIV(str_repeat("\0", $crypto->getBlockLength() >> 3));
|
|
||||||
$crypto->disablePadding();
|
|
||||||
$private = $crypto->decrypt($private);
|
|
||||||
if ($private === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extract(unpack('Nlength', self::_string_shift($private, 4)));
|
|
||||||
if (strlen($private) < $length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$components['privateExponent'] = new BigInteger(self::_string_shift($private, $length), -256);
|
|
||||||
extract(unpack('Nlength', self::_string_shift($private, 4)));
|
|
||||||
if (strlen($private) < $length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$components['primes'] = array(1 => new BigInteger(self::_string_shift($private, $length), -256));
|
|
||||||
extract(unpack('Nlength', self::_string_shift($private, 4)));
|
|
||||||
if (strlen($private) < $length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$components['primes'][] = new BigInteger(self::_string_shift($private, $length), -256);
|
|
||||||
|
|
||||||
$temp = $components['primes'][1]->subtract($one);
|
|
||||||
$components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp));
|
|
||||||
$temp = $components['primes'][2]->subtract($one);
|
|
||||||
$components['exponents'][] = $components['publicExponent']->modInverse($temp);
|
|
||||||
|
|
||||||
extract(unpack('Nlength', self::_string_shift($private, 4)));
|
|
||||||
if (strlen($private) < $length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$components['coefficients'] = array(2 => new BigInteger(self::_string_shift($private, $length), -256));
|
|
||||||
|
|
||||||
return $components;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String Shift
|
|
||||||
*
|
|
||||||
* Inspired by array_shift
|
|
||||||
*
|
|
||||||
* @param string $string
|
|
||||||
* @param int $index
|
|
||||||
* @return string
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
static function _string_shift(&$string, $index = 1)
|
|
||||||
{
|
|
||||||
$substr = substr($string, 0, $index);
|
|
||||||
$string = substr($string, $index);
|
|
||||||
return $substr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a private key to the appropriate format.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @param \phpseclib\Math\BigInteger $d
|
|
||||||
* @param array $primes
|
|
||||||
* @param array $exponents
|
|
||||||
* @param array $coefficients
|
|
||||||
* @param string $password optional
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '')
|
|
||||||
{
|
|
||||||
if (count($primes) != 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$raw = array(
|
|
||||||
'modulus' => $n->toBytes(true),
|
|
||||||
'publicExponent' => $e->toBytes(true),
|
|
||||||
'privateExponent' => $d->toBytes(true),
|
|
||||||
'prime1' => $primes[1]->toBytes(true),
|
|
||||||
'prime2' => $primes[2]->toBytes(true),
|
|
||||||
'exponent1' => $exponents[1]->toBytes(true),
|
|
||||||
'exponent2' => $exponents[2]->toBytes(true),
|
|
||||||
'coefficient' => $coefficients[2]->toBytes(true)
|
|
||||||
);
|
|
||||||
|
|
||||||
$key = "PuTTY-User-Key-File-2: ssh-rsa\r\nEncryption: ";
|
|
||||||
$encryption = (!empty($password) || is_string($password)) ? 'aes256-cbc' : 'none';
|
|
||||||
$key.= $encryption;
|
|
||||||
$key.= "\r\nComment: " . self::$comment . "\r\n";
|
|
||||||
$public = pack(
|
|
||||||
'Na*Na*Na*',
|
|
||||||
strlen('ssh-rsa'),
|
|
||||||
'ssh-rsa',
|
|
||||||
strlen($raw['publicExponent']),
|
|
||||||
$raw['publicExponent'],
|
|
||||||
strlen($raw['modulus']),
|
|
||||||
$raw['modulus']
|
|
||||||
);
|
|
||||||
$source = pack(
|
|
||||||
'Na*Na*Na*Na*',
|
|
||||||
strlen('ssh-rsa'),
|
|
||||||
'ssh-rsa',
|
|
||||||
strlen($encryption),
|
|
||||||
$encryption,
|
|
||||||
strlen(self::$comment),
|
|
||||||
self::$comment,
|
|
||||||
strlen($public),
|
|
||||||
$public
|
|
||||||
);
|
|
||||||
$public = base64_encode($public);
|
|
||||||
$key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
|
|
||||||
$key.= chunk_split($public, 64);
|
|
||||||
$private = pack(
|
|
||||||
'Na*Na*Na*Na*',
|
|
||||||
strlen($raw['privateExponent']),
|
|
||||||
$raw['privateExponent'],
|
|
||||||
strlen($raw['prime1']),
|
|
||||||
$raw['prime1'],
|
|
||||||
strlen($raw['prime2']),
|
|
||||||
$raw['prime2'],
|
|
||||||
strlen($raw['coefficient']),
|
|
||||||
$raw['coefficient']
|
|
||||||
);
|
|
||||||
if (empty($password) && !is_string($password)) {
|
|
||||||
$source.= pack('Na*', strlen($private), $private);
|
|
||||||
$hashkey = 'putty-private-key-file-mac-key';
|
|
||||||
} else {
|
|
||||||
$private.= Random::string(16 - (strlen($private) & 15));
|
|
||||||
$source.= pack('Na*', strlen($private), $private);
|
|
||||||
$crypto = new AES();
|
|
||||||
|
|
||||||
$crypto->setKey(static::generateSymmetricKey($password, 32));
|
|
||||||
$crypto->setIV(str_repeat("\0", $crypto->getBlockLength() >> 3));
|
|
||||||
$crypto->disablePadding();
|
|
||||||
$private = $crypto->encrypt($private);
|
|
||||||
$hashkey = 'putty-private-key-file-mac-key' . $password;
|
|
||||||
}
|
|
||||||
|
|
||||||
$private = base64_encode($private);
|
|
||||||
$key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n";
|
|
||||||
$key.= chunk_split($private, 64);
|
|
||||||
$hash = new Hash('sha1');
|
|
||||||
$hash->setKey(pack('H*', sha1($hashkey)));
|
|
||||||
$key.= 'Private-MAC: ' . bin2hex($hash->hash($source)) . "\r\n";
|
|
||||||
|
|
||||||
return $key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a public key to the appropriate format
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePublicKey(BigInteger $n, BigInteger $e)
|
|
||||||
{
|
|
||||||
$n = $n->toBytes(true);
|
|
||||||
$e = $e->toBytes(true);
|
|
||||||
|
|
||||||
$key = pack(
|
|
||||||
'Na*Na*Na*',
|
|
||||||
strlen('ssh-rsa'),
|
|
||||||
'ssh-rsa',
|
|
||||||
strlen($e),
|
|
||||||
$e,
|
|
||||||
strlen($n),
|
|
||||||
$n
|
|
||||||
);
|
|
||||||
$key = "---- BEGIN SSH2 PUBLIC KEY ----\r\n" .
|
|
||||||
'Comment: "' . str_replace(array('\\', '"'), array('\\\\', '\"'), self::$comment) . "\"\r\n";
|
|
||||||
chunk_split(base64_encode($key), 64) .
|
|
||||||
'---- END SSH2 PUBLIC KEY ----';
|
|
||||||
|
|
||||||
return $key;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Raw RSA Key Handler
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* An array containing two \phpseclib\Math\BigInteger objects.
|
|
||||||
*
|
|
||||||
* The exponent can be indexed with any of the following:
|
|
||||||
*
|
|
||||||
* 0, e, exponent, publicExponent
|
|
||||||
*
|
|
||||||
* The modulus can be indexed with any of the following:
|
|
||||||
*
|
|
||||||
* 1, n, modulo, modulus
|
|
||||||
*
|
|
||||||
* @category Crypt
|
|
||||||
* @package RSA
|
|
||||||
* @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\RSA;
|
|
||||||
|
|
||||||
use phpseclib\Math\BigInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Raw RSA Key Handler
|
|
||||||
*
|
|
||||||
* @package RSA
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
class Raw
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Break a public or private key down into its constituent components
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $key
|
|
||||||
* @param string $password optional
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
static function load($key, $password = '')
|
|
||||||
{
|
|
||||||
if (!is_array($key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (isset($key['isPublicKey']) && isset($key['modulus'])) {
|
|
||||||
if (isset($key['privateExponent']) || isset($key['publicExponent'])) {
|
|
||||||
if (!isset($key['primes'])) {
|
|
||||||
return $key;
|
|
||||||
}
|
|
||||||
if (isset($key['exponents']) && isset($key['coefficients']) && isset($key['publicExponent']) && isset($key['privateExponent'])) {
|
|
||||||
return $key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$components = array('isPublicKey' => true);
|
|
||||||
switch (true) {
|
|
||||||
case isset($key['e']):
|
|
||||||
$components['publicExponent'] = $key['e'];
|
|
||||||
break;
|
|
||||||
case isset($key['exponent']):
|
|
||||||
$components['publicExponent'] = $key['exponent'];
|
|
||||||
break;
|
|
||||||
case isset($key['publicExponent']):
|
|
||||||
$components['publicExponent'] = $key['publicExponent'];
|
|
||||||
break;
|
|
||||||
case isset($key[0]):
|
|
||||||
$components['publicExponent'] = $key[0];
|
|
||||||
}
|
|
||||||
switch (true) {
|
|
||||||
case isset($key['n']):
|
|
||||||
$components['modulus'] = $key['n'];
|
|
||||||
break;
|
|
||||||
case isset($key['modulo']):
|
|
||||||
$components['modulus'] = $key['modulo'];
|
|
||||||
break;
|
|
||||||
case isset($key['modulus']):
|
|
||||||
$components['modulus'] = $key['modulus'];
|
|
||||||
break;
|
|
||||||
case isset($key[1]):
|
|
||||||
$components['modulus'] = $key[1];
|
|
||||||
}
|
|
||||||
return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a public key to the appropriate format
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePublicKey(BigInteger $n, BigInteger $e)
|
|
||||||
{
|
|
||||||
return array('e' => clone $e, 'n' => clone $n);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* XML Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* More info:
|
|
||||||
*
|
|
||||||
* http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
|
|
||||||
* http://en.wikipedia.org/wiki/XML_Signature
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Crypt
|
|
||||||
* @package RSA
|
|
||||||
* @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\RSA;
|
|
||||||
|
|
||||||
use phpseclib\Math\BigInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* XML Formatted RSA Key Handler
|
|
||||||
*
|
|
||||||
* @package RSA
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
class XML
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Break a public or private key down into its constituent components
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $key
|
|
||||||
* @param string $password optional
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
static function load($key, $password = '')
|
|
||||||
{
|
|
||||||
if (!is_string($key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$components = array(
|
|
||||||
'isPublicKey' => false,
|
|
||||||
'primes' => array(),
|
|
||||||
'exponents' => array(),
|
|
||||||
'coefficients' => array()
|
|
||||||
);
|
|
||||||
|
|
||||||
$use_errors = libxml_use_internal_errors(true);
|
|
||||||
|
|
||||||
$dom = new \DOMDocument();
|
|
||||||
if (!$dom->loadXML('<xml>' . $key . '</xml>')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$xpath = new \DOMXPath($dom);
|
|
||||||
$keys = array('modulus', 'exponent', 'p', 'q', 'dp', 'dq', 'inverseq', 'd');
|
|
||||||
foreach ($keys as $key) {
|
|
||||||
// $dom->getElementsByTagName($key) is case-sensitive
|
|
||||||
$temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$key']");
|
|
||||||
if (!$temp->length) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$value = new BigInteger(base64_decode($temp->item(0)->nodeValue), 256);
|
|
||||||
switch ($key) {
|
|
||||||
case 'modulus':
|
|
||||||
$components['modulus'] = $value;
|
|
||||||
break;
|
|
||||||
case 'exponent':
|
|
||||||
$components['publicExponent'] = $value;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
$components['primes'][1] = $value;
|
|
||||||
break;
|
|
||||||
case 'q':
|
|
||||||
$components['primes'][2] = $value;
|
|
||||||
break;
|
|
||||||
case 'dp':
|
|
||||||
$components['exponents'][1] = $value;
|
|
||||||
break;
|
|
||||||
case 'dq':
|
|
||||||
$components['exponents'][2] = $value;
|
|
||||||
break;
|
|
||||||
case 'inverseq':
|
|
||||||
$components['coefficients'][2] = $value;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
$components['privateExponent'] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
libxml_use_internal_errors($use_errors);
|
|
||||||
|
|
||||||
return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a private key to the appropriate format.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @param \phpseclib\Math\BigInteger $d
|
|
||||||
* @param array $primes
|
|
||||||
* @param array $exponents
|
|
||||||
* @param array $coefficients
|
|
||||||
* @param string $password optional
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '')
|
|
||||||
{
|
|
||||||
if (count($primes) != 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return "<RSAKeyValue>\r\n" .
|
|
||||||
' <Modulus>' . base64_encode($n->toBytes()) . "</Modulus>\r\n" .
|
|
||||||
' <Exponent>' . base64_encode($e->toBytes()) . "</Exponent>\r\n" .
|
|
||||||
' <P>' . base64_encode($primes[1]->toBytes()) . "</P>\r\n" .
|
|
||||||
' <Q>' . base64_encode($primes[2]->toBytes()) . "</Q>\r\n" .
|
|
||||||
' <DP>' . base64_encode($exponents[1]->toBytes()) . "</DP>\r\n" .
|
|
||||||
' <DQ>' . base64_encode($exponents[2]->toBytes()) . "</DQ>\r\n" .
|
|
||||||
' <InverseQ>' . base64_encode($coefficients[2]->toBytes()) . "</InverseQ>\r\n" .
|
|
||||||
' <D>' . base64_encode($d->toBytes()) . "</D>\r\n" .
|
|
||||||
'</RSAKeyValue>';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a public key to the appropriate format
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \phpseclib\Math\BigInteger $n
|
|
||||||
* @param \phpseclib\Math\BigInteger $e
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
static function savePublicKey(BigInteger $n, BigInteger $e)
|
|
||||||
{
|
|
||||||
return "<RSAKeyValue>\r\n" .
|
|
||||||
' <Modulus>' . base64_encode($n->toBytes()) . "</Modulus>\r\n" .
|
|
||||||
' <Exponent>' . base64_encode($e->toBytes()) . "</Exponent>\r\n" .
|
|
||||||
'</RSAKeyValue>';
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,6 +24,14 @@
|
|||||||
|
|
||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\AES;
|
||||||
|
use phpseclib\Crypt\Base;
|
||||||
|
use phpseclib\Crypt\Blowfish;
|
||||||
|
use phpseclib\Crypt\DES;
|
||||||
|
use phpseclib\Crypt\RC4;
|
||||||
|
use phpseclib\Crypt\TripleDES;
|
||||||
|
use phpseclib\Crypt\Twofish;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP Random Number Generator
|
* Pure-PHP Random Number Generator
|
||||||
*
|
*
|
||||||
@ -41,22 +49,68 @@ class Random
|
|||||||
* eg. for RSA key generation.
|
* eg. for RSA key generation.
|
||||||
*
|
*
|
||||||
* @param int $length
|
* @param int $length
|
||||||
* @throws \RuntimeException if a symmetric cipher is needed but not loaded
|
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
static function string($length)
|
static function string($length)
|
||||||
{
|
{
|
||||||
try {
|
if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
|
||||||
return \random_bytes($length);
|
try {
|
||||||
} catch (\Exception $e) {
|
return \random_bytes($length);
|
||||||
// random_compat will throw an Exception, which in PHP 5 does not implement Throwable
|
} catch (\Throwable $e) {
|
||||||
} catch (\Throwable $e) {
|
// If a sufficient source of randomness is unavailable, random_bytes() will throw an
|
||||||
// If a sufficient source of randomness is unavailable, random_bytes() will throw an
|
// object that implements the Throwable interface (Exception, TypeError, Error).
|
||||||
// object that implements the Throwable interface (Exception, TypeError, Error).
|
// We don't actually need to do anything here. The string() method should just continue
|
||||||
// We don't actually need to do anything here. The string() method should just continue
|
// as normal. Note, however, that if we don't have a sufficient source of randomness for
|
||||||
// as normal. Note, however, that if we don't have a sufficient source of randomness for
|
// random_bytes(), most of the other calls here will fail too, so we'll end up using
|
||||||
// random_bytes(), most of the other calls here will fail too, so we'll end up using
|
// the PHP implementation.
|
||||||
// the PHP implementation.
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
||||||
|
// method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
|
||||||
|
// ie. class_alias is a function that was introduced in PHP 5.3
|
||||||
|
if (extension_loaded('mcrypt') && function_exists('class_alias')) {
|
||||||
|
return mcrypt_create_iv($length);
|
||||||
|
}
|
||||||
|
// method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
|
||||||
|
// to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
|
||||||
|
// openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
|
||||||
|
// call php_win32_get_random_bytes():
|
||||||
|
//
|
||||||
|
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
|
||||||
|
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
|
||||||
|
//
|
||||||
|
// php_win32_get_random_bytes() is defined thusly:
|
||||||
|
//
|
||||||
|
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
|
||||||
|
//
|
||||||
|
// we're calling it, all the same, in the off chance that the mcrypt extension is not available
|
||||||
|
if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
|
||||||
|
return openssl_random_pseudo_bytes($length);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// method 1. the fastest
|
||||||
|
if (extension_loaded('openssl')) {
|
||||||
|
return openssl_random_pseudo_bytes($length);
|
||||||
|
}
|
||||||
|
// method 2
|
||||||
|
static $fp = true;
|
||||||
|
if ($fp === true) {
|
||||||
|
// warning's will be output unles the error suppression operator is used. errors such as
|
||||||
|
// "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
|
||||||
|
$fp = @fopen('/dev/urandom', 'rb');
|
||||||
|
}
|
||||||
|
if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
|
||||||
|
return fread($fp, $length);
|
||||||
|
}
|
||||||
|
// method 3. pretty much does the same thing as method 2 per the following url:
|
||||||
|
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
|
||||||
|
// surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
|
||||||
|
// not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
|
||||||
|
// restrictions or some such
|
||||||
|
if (extension_loaded('mcrypt')) {
|
||||||
|
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// at this point we have no choice but to use a pure-PHP CSPRNG
|
// at this point we have no choice but to use a pure-PHP CSPRNG
|
||||||
|
|
||||||
@ -94,13 +148,13 @@ class Random
|
|||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
|
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
|
||||||
(isset($_SERVER) ? self::safe_serialize($_SERVER) : '') .
|
(isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') .
|
||||||
(isset($_POST) ? self::safe_serialize($_POST) : '') .
|
(isset($_POST) ? phpseclib_safe_serialize($_POST) : '') .
|
||||||
(isset($_GET) ? self::safe_serialize($_GET) : '') .
|
(isset($_GET) ? phpseclib_safe_serialize($_GET) : '') .
|
||||||
(isset($_COOKIE) ? self::safe_serialize($_COOKIE) : '') .
|
(isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') .
|
||||||
self::safe_serialize($GLOBALS) .
|
phpseclib_safe_serialize($GLOBALS) .
|
||||||
self::safe_serialize($_SESSION) .
|
phpseclib_safe_serialize($_SESSION) .
|
||||||
self::safe_serialize($_OLD_SESSION)
|
phpseclib_safe_serialize($_OLD_SESSION)
|
||||||
));
|
));
|
||||||
if (!isset($_SESSION['count'])) {
|
if (!isset($_SESSION['count'])) {
|
||||||
$_SESSION['count'] = 0;
|
$_SESSION['count'] = 0;
|
||||||
@ -158,7 +212,8 @@ class Random
|
|||||||
$crypto = new RC4();
|
$crypto = new RC4();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \RuntimeException(__CLASS__ . ' requires at least one symmetric cipher be loaded');
|
user_error(__CLASS__ . ' requires at least one symmetric cipher be loaded');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$crypto->setKey($key);
|
$crypto->setKey($key);
|
||||||
@ -185,16 +240,19 @@ class Random
|
|||||||
}
|
}
|
||||||
return substr($result, 0, $length);
|
return substr($result, 0, $length);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('phpseclib_safe_serialize')) {
|
||||||
/**
|
/**
|
||||||
* Safely serialize variables
|
* Safely serialize variables
|
||||||
*
|
*
|
||||||
* If a class has a private __sleep() it'll emit a warning
|
* If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier.
|
||||||
|
* PHP 5.3 will emit a warning.
|
||||||
*
|
*
|
||||||
* @param mixed $arr
|
* @param mixed $arr
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function safe_serialize(&$arr)
|
function phpseclib_safe_serialize(&$arr)
|
||||||
{
|
{
|
||||||
if (is_object($arr)) {
|
if (is_object($arr)) {
|
||||||
return '';
|
return '';
|
||||||
@ -211,7 +269,7 @@ class Random
|
|||||||
foreach (array_keys($arr) as $key) {
|
foreach (array_keys($arr) as $key) {
|
||||||
// do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
|
// do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
|
||||||
if ($key !== '__phpseclib_marker') {
|
if ($key !== '__phpseclib_marker') {
|
||||||
$safearr[$key] = self::safe_serialize($arr[$key]);
|
$safearr[$key] = phpseclib_safe_serialize($arr[$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unset($arr['__phpseclib_marker']);
|
unset($arr['__phpseclib_marker']);
|
||||||
|
@ -54,6 +54,8 @@
|
|||||||
|
|
||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of Rijndael.
|
* Pure-PHP implementation of Rijndael.
|
||||||
*
|
*
|
||||||
@ -168,26 +170,11 @@ class Rijndael extends Base
|
|||||||
*/
|
*/
|
||||||
var $kl;
|
var $kl;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default Constructor.
|
|
||||||
*
|
|
||||||
* @param int $mode
|
|
||||||
* @access public
|
|
||||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
|
||||||
*/
|
|
||||||
function __construct($mode)
|
|
||||||
{
|
|
||||||
if ($mode == self::MODE_STREAM) {
|
|
||||||
throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the key length.
|
* Sets the key length.
|
||||||
*
|
*
|
||||||
* Valid key lengths are 128, 160, 192, 224, and 256.
|
* Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
|
||||||
|
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
|
||||||
*
|
*
|
||||||
* Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
|
* Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
|
||||||
* and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
|
* and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
|
||||||
@ -201,75 +188,49 @@ class Rijndael extends Base
|
|||||||
* This results then in slower encryption.
|
* This results then in slower encryption.
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @throws \LengthException if the key length is invalid
|
|
||||||
* @param int $length
|
* @param int $length
|
||||||
*/
|
*/
|
||||||
function setKeyLength($length)
|
function setKeyLength($length)
|
||||||
{
|
{
|
||||||
switch ($length) {
|
switch (true) {
|
||||||
case 128:
|
case $length <= 128:
|
||||||
case 160:
|
$this->key_length = 16;
|
||||||
case 192:
|
break;
|
||||||
case 224:
|
case $length <= 160:
|
||||||
case 256:
|
$this->key_length = 20;
|
||||||
$this->key_length = $length >> 3;
|
break;
|
||||||
|
case $length <= 192:
|
||||||
|
$this->key_length = 24;
|
||||||
|
break;
|
||||||
|
case $length <= 224:
|
||||||
|
$this->key_length = 28;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported');
|
$this->key_length = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::setKeyLength($length);
|
parent::setKeyLength($length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the key.
|
|
||||||
*
|
|
||||||
* Rijndael supports five different key lengths
|
|
||||||
*
|
|
||||||
* @see setKeyLength()
|
|
||||||
* @access public
|
|
||||||
* @param string $key
|
|
||||||
* @throws \LengthException if the key length isn't supported
|
|
||||||
*/
|
|
||||||
function setKey($key)
|
|
||||||
{
|
|
||||||
switch (strlen($key)) {
|
|
||||||
case 16:
|
|
||||||
case 20:
|
|
||||||
case 24:
|
|
||||||
case 28:
|
|
||||||
case 32:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 20, 24, 28 or 32 are supported');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::setKey($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the block length
|
* Sets the block length
|
||||||
*
|
*
|
||||||
* Valid block lengths are 128, 160, 192, 224, and 256.
|
* Valid block lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
|
||||||
|
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param int $length
|
* @param int $length
|
||||||
*/
|
*/
|
||||||
function setBlockLength($length)
|
function setBlockLength($length)
|
||||||
{
|
{
|
||||||
switch ($length) {
|
$length >>= 5;
|
||||||
case 128:
|
if ($length > 8) {
|
||||||
case 160:
|
$length = 8;
|
||||||
case 192:
|
} elseif ($length < 4) {
|
||||||
case 224:
|
$length = 4;
|
||||||
case 256:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported');
|
|
||||||
}
|
}
|
||||||
|
$this->Nb = $length;
|
||||||
$this->Nb = $length >> 5;
|
$this->block_size = $length << 2;
|
||||||
$this->block_size = $length >> 3;
|
|
||||||
$this->changed = true;
|
$this->changed = true;
|
||||||
$this->_setEngine();
|
$this->_setEngine();
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,9 @@
|
|||||||
|
|
||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Base;
|
||||||
|
use phpseclib\Crypt\DES;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of Triple DES.
|
* Pure-PHP implementation of Triple DES.
|
||||||
*
|
*
|
||||||
@ -128,7 +131,7 @@ class TripleDES extends DES
|
|||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
* Determines whether or not the mcrypt or OpenSSL extensions should be used.
|
* Determines whether or not the mcrypt extension should be used.
|
||||||
*
|
*
|
||||||
* $mode could be:
|
* $mode could be:
|
||||||
*
|
*
|
||||||
@ -142,14 +145,16 @@ class TripleDES extends DES
|
|||||||
*
|
*
|
||||||
* - \phpseclib\Crypt\Base::MODE_OFB
|
* - \phpseclib\Crypt\Base::MODE_OFB
|
||||||
*
|
*
|
||||||
* - \phpseclib\Crypt\TripleDES::MODE_3CB
|
* - \phpseclib\Crypt\TripleDES::MODE_3CBC
|
||||||
|
*
|
||||||
|
* If not explicitly set, \phpseclib\Crypt\Base::MODE_CBC will be used.
|
||||||
*
|
*
|
||||||
* @see \phpseclib\Crypt\DES::__construct()
|
* @see \phpseclib\Crypt\DES::__construct()
|
||||||
* @see \phpseclib\Crypt\Base::__construct()
|
* @see \phpseclib\Crypt\Base::__construct()
|
||||||
* @param int $mode
|
* @param int $mode
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function __construct($mode)
|
function __construct($mode = Base::MODE_CBC)
|
||||||
{
|
{
|
||||||
switch ($mode) {
|
switch ($mode) {
|
||||||
// In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC
|
// In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC
|
||||||
@ -198,9 +203,10 @@ class TripleDES extends DES
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the initialization vector.
|
* Sets the initialization vector. (optional)
|
||||||
*
|
*
|
||||||
* SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used.
|
* SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used. If not explicitly set, it'll be assumed
|
||||||
|
* to be all zero's.
|
||||||
*
|
*
|
||||||
* @see \phpseclib\Crypt\Base::setIV()
|
* @see \phpseclib\Crypt\Base::setIV()
|
||||||
* @access public
|
* @access public
|
||||||
@ -219,23 +225,24 @@ class TripleDES extends DES
|
|||||||
/**
|
/**
|
||||||
* Sets the key length.
|
* Sets the key length.
|
||||||
*
|
*
|
||||||
* Valid key lengths are 128 and 192 bits.
|
* Valid key lengths are 64, 128 and 192
|
||||||
*
|
|
||||||
* If you want to use a 64-bit key use DES.php
|
|
||||||
*
|
*
|
||||||
* @see \phpseclib\Crypt\Base:setKeyLength()
|
* @see \phpseclib\Crypt\Base:setKeyLength()
|
||||||
* @access public
|
* @access public
|
||||||
* @throws \LengthException if the key length is invalid
|
|
||||||
* @param int $length
|
* @param int $length
|
||||||
*/
|
*/
|
||||||
function setKeyLength($length)
|
function setKeyLength($length)
|
||||||
{
|
{
|
||||||
switch ($length) {
|
$length >>= 3;
|
||||||
case 128:
|
switch (true) {
|
||||||
case 192:
|
case $length <= 8:
|
||||||
|
$this->key_length = 8;
|
||||||
|
break;
|
||||||
|
case $length <= 16:
|
||||||
|
$this->key_length = 16;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128 or 192 bits are supported');
|
$this->key_length = 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::setKeyLength($length);
|
parent::setKeyLength($length);
|
||||||
@ -244,38 +251,36 @@ class TripleDES extends DES
|
|||||||
/**
|
/**
|
||||||
* Sets the key.
|
* Sets the key.
|
||||||
*
|
*
|
||||||
* Triple DES can use 128-bit (eg. strlen($key) == 16) or 192-bit (eg. strlen($key) == 24) keys.
|
* Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
|
||||||
|
* 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
|
||||||
*
|
*
|
||||||
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
||||||
*
|
*
|
||||||
|
* If the key is not explicitly set, it'll be assumed to be all null bytes.
|
||||||
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @see \phpseclib\Crypt\DES::setKey()
|
* @see \phpseclib\Crypt\DES::setKey()
|
||||||
* @see \phpseclib\Crypt\Base::setKey()
|
* @see \phpseclib\Crypt\Base::setKey()
|
||||||
* @throws \LengthException if the key length is invalid
|
|
||||||
* @param string $key
|
* @param string $key
|
||||||
*/
|
*/
|
||||||
function setKey($key)
|
function setKey($key)
|
||||||
{
|
{
|
||||||
if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) {
|
$length = $this->explicit_key_length ? $this->key_length : strlen($key);
|
||||||
throw new \LengthException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes');
|
if ($length > 8) {
|
||||||
|
$key = str_pad(substr($key, 0, 24), 24, chr(0));
|
||||||
|
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
|
||||||
|
// http://php.net/function.mcrypt-encrypt#47973
|
||||||
|
$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
|
||||||
|
} else {
|
||||||
|
$key = str_pad($key, 8, chr(0));
|
||||||
}
|
}
|
||||||
|
parent::setKey($key);
|
||||||
|
|
||||||
switch (strlen($key)) {
|
// And in case of self::MODE_3CBC:
|
||||||
case 16:
|
// if key <= 64bits we not need the 3 $des to work,
|
||||||
$key.= substr($key, 0, 8);
|
// because we will then act as regular DES-CBC with just a <= 64bit key.
|
||||||
case 24:
|
// So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des.
|
||||||
break;
|
if ($this->mode_3cbc && $length > 8) {
|
||||||
default:
|
|
||||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16 or 24 are supported');
|
|
||||||
}
|
|
||||||
|
|
||||||
// copied from Base::setKey()
|
|
||||||
$this->key = $key;
|
|
||||||
$this->key_length = strlen($key);
|
|
||||||
$this->changed = true;
|
|
||||||
$this->_setEngine();
|
|
||||||
|
|
||||||
if ($this->mode_3cbc) {
|
|
||||||
$this->des[0]->setKey(substr($key, 0, 8));
|
$this->des[0]->setKey(substr($key, 0, 8));
|
||||||
$this->des[1]->setKey(substr($key, 8, 8));
|
$this->des[1]->setKey(substr($key, 8, 8));
|
||||||
$this->des[2]->setKey(substr($key, 16, 8));
|
$this->des[2]->setKey(substr($key, 16, 8));
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
|
|
||||||
namespace phpseclib\Crypt;
|
namespace phpseclib\Crypt;
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of Twofish.
|
* Pure-PHP implementation of Twofish.
|
||||||
*
|
*
|
||||||
@ -368,22 +370,6 @@ class Twofish extends Base
|
|||||||
*/
|
*/
|
||||||
var $key_length = 16;
|
var $key_length = 16;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default Constructor.
|
|
||||||
*
|
|
||||||
* @param int $mode
|
|
||||||
* @access public
|
|
||||||
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
|
|
||||||
*/
|
|
||||||
function __construct($mode)
|
|
||||||
{
|
|
||||||
if ($mode == self::MODE_STREAM) {
|
|
||||||
throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the key length.
|
* Sets the key length.
|
||||||
*
|
*
|
||||||
@ -394,42 +380,20 @@ class Twofish extends Base
|
|||||||
*/
|
*/
|
||||||
function setKeyLength($length)
|
function setKeyLength($length)
|
||||||
{
|
{
|
||||||
switch ($length) {
|
switch (true) {
|
||||||
case 128:
|
case $length <= 128:
|
||||||
case 192:
|
$this->key_length = 16;
|
||||||
case 256:
|
break;
|
||||||
|
case $length <= 192:
|
||||||
|
$this->key_length = 24;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
|
$this->key_length = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::setKeyLength($length);
|
parent::setKeyLength($length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the key.
|
|
||||||
*
|
|
||||||
* Rijndael supports five different key lengths
|
|
||||||
*
|
|
||||||
* @see setKeyLength()
|
|
||||||
* @access public
|
|
||||||
* @param string $key
|
|
||||||
* @throws \LengthException if the key length isn't supported
|
|
||||||
*/
|
|
||||||
function setKey($key)
|
|
||||||
{
|
|
||||||
switch (strlen($key)) {
|
|
||||||
case 16:
|
|
||||||
case 24:
|
|
||||||
case 32:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::setKey($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup the key (expansion)
|
* Setup the key (expansion)
|
||||||
*
|
*
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BadConfigurationException
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Exception
|
|
||||||
* @package BadConfigurationException
|
|
||||||
* @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\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BadConfigurationException
|
|
||||||
*
|
|
||||||
* @package BadConfigurationException
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
*/
|
|
||||||
class BadConfigurationException extends \RuntimeException
|
|
||||||
{
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FileNotFoundException
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Exception
|
|
||||||
* @package FileNotFoundException
|
|
||||||
* @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\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FileNotFoundException
|
|
||||||
*
|
|
||||||
* @package FileNotFoundException
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
*/
|
|
||||||
class FileNotFoundException extends \RuntimeException
|
|
||||||
{
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NoSupportedAlgorithmsException
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Exception
|
|
||||||
* @package NoSupportedAlgorithmsException
|
|
||||||
* @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\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NoSupportedAlgorithmsException
|
|
||||||
*
|
|
||||||
* @package NoSupportedAlgorithmsException
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
*/
|
|
||||||
class NoSupportedAlgorithmsException extends \RuntimeException
|
|
||||||
{
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UnsupportedAlgorithmException
|
|
||||||
*
|
|
||||||
* PHP version 5
|
|
||||||
*
|
|
||||||
* @category Exception
|
|
||||||
* @package UnsupportedAlgorithmException
|
|
||||||
* @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\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UnsupportedAlgorithmException
|
|
||||||
*
|
|
||||||
* @package UnsupportedAlgorithmException
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
*/
|
|
||||||
class UnsupportedAlgorithmException extends \RuntimeException
|
|
||||||
{
|
|
||||||
}
|
|
@ -793,7 +793,6 @@ class ASN1
|
|||||||
* @param string $mapping
|
* @param string $mapping
|
||||||
* @param int $idx
|
* @param int $idx
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \RuntimeException if the input has an error in it
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _encode_der($source, $mapping, $idx = null, $special = array())
|
function _encode_der($source, $mapping, $idx = null, $special = array())
|
||||||
@ -986,7 +985,7 @@ class ASN1
|
|||||||
case self::TYPE_OBJECT_IDENTIFIER:
|
case self::TYPE_OBJECT_IDENTIFIER:
|
||||||
$oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
|
$oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
|
||||||
if ($oid === false) {
|
if ($oid === false) {
|
||||||
throw new \RuntimeException('Invalid OID');
|
user_error('Invalid OID');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$value = '';
|
$value = '';
|
||||||
@ -1039,7 +1038,7 @@ class ASN1
|
|||||||
$filters = $filters[$part];
|
$filters = $filters[$part];
|
||||||
}
|
}
|
||||||
if ($filters === false) {
|
if ($filters === false) {
|
||||||
throw new \RuntimeException('No filters defined for ' . implode('/', $loc));
|
user_error('No filters defined for ' . implode('/', $loc));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return $this->_encode_der($source, $filters + $mapping, null, $special);
|
return $this->_encode_der($source, $filters + $mapping, null, $special);
|
||||||
@ -1063,7 +1062,7 @@ class ASN1
|
|||||||
$value = $source ? "\xFF" : "\x00";
|
$value = $source ? "\xFF" : "\x00";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \RuntimeException('Mapping provides no type definition for ' . implode('/', $this->location));
|
user_error('Mapping provides no type definition for ' . implode('/', $this->location));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@
|
|||||||
namespace phpseclib\File;
|
namespace phpseclib\File;
|
||||||
|
|
||||||
use phpseclib\Crypt\Hash;
|
use phpseclib\Crypt\Hash;
|
||||||
use phpseclib\Crypt\Random;
|
|
||||||
use phpseclib\Crypt\RSA;
|
use phpseclib\Crypt\RSA;
|
||||||
use phpseclib\Exception\UnsupportedAlgorithmException;
|
use phpseclib\Crypt\Random;
|
||||||
|
use phpseclib\File\ASN1;
|
||||||
use phpseclib\File\ASN1\Element;
|
use phpseclib\File\ASN1\Element;
|
||||||
use phpseclib\Math\BigInteger;
|
use phpseclib\Math\BigInteger;
|
||||||
|
|
||||||
@ -1654,7 +1654,7 @@ class X509
|
|||||||
$map = $this->_getMapping($id);
|
$map = $this->_getMapping($id);
|
||||||
if (is_bool($map)) {
|
if (is_bool($map)) {
|
||||||
if (!$map) {
|
if (!$map) {
|
||||||
//user_error($id . ' is not a currently supported extension');
|
user_error($id . ' is not a currently supported extension');
|
||||||
unset($extensions[$i]);
|
unset($extensions[$i]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1727,7 +1727,7 @@ class X509
|
|||||||
$id = $attributes[$i]['type'];
|
$id = $attributes[$i]['type'];
|
||||||
$map = $this->_getMapping($id);
|
$map = $this->_getMapping($id);
|
||||||
if ($map === false) {
|
if ($map === false) {
|
||||||
//user_error($id . ' is not a currently supported attribute', E_USER_NOTICE);
|
user_error($id . ' is not a currently supported attribute', E_USER_NOTICE);
|
||||||
unset($attributes[$i]);
|
unset($attributes[$i]);
|
||||||
} elseif (is_array($attributes[$i]['value'])) {
|
} elseif (is_array($attributes[$i]['value'])) {
|
||||||
$values = &$attributes[$i]['value'];
|
$values = &$attributes[$i]['value'];
|
||||||
@ -2120,8 +2120,7 @@ class X509
|
|||||||
/**
|
/**
|
||||||
* Validates a signature
|
* Validates a signature
|
||||||
*
|
*
|
||||||
* Returns true if the signature is verified and false if it is not correct.
|
* Returns true if the signature is verified, false if it is not correct or null on error
|
||||||
* If the algorithms are unsupposed an exception is thrown.
|
|
||||||
*
|
*
|
||||||
* @param string $publicKeyAlgorithm
|
* @param string $publicKeyAlgorithm
|
||||||
* @param string $publicKey
|
* @param string $publicKey
|
||||||
@ -2129,15 +2128,14 @@ class X509
|
|||||||
* @param string $signature
|
* @param string $signature
|
||||||
* @param string $signatureSubject
|
* @param string $signatureSubject
|
||||||
* @access private
|
* @access private
|
||||||
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
|
* @return int
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
function _validateSignature($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject)
|
function _validateSignature($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject)
|
||||||
{
|
{
|
||||||
switch ($publicKeyAlgorithm) {
|
switch ($publicKeyAlgorithm) {
|
||||||
case 'rsaEncryption':
|
case 'rsaEncryption':
|
||||||
$rsa = new RSA();
|
$rsa = new RSA();
|
||||||
$rsa->load($publicKey);
|
$rsa->loadKey($publicKey);
|
||||||
|
|
||||||
switch ($signatureAlgorithm) {
|
switch ($signatureAlgorithm) {
|
||||||
case 'md2WithRSAEncryption':
|
case 'md2WithRSAEncryption':
|
||||||
@ -2148,16 +2146,17 @@ class X509
|
|||||||
case 'sha384WithRSAEncryption':
|
case 'sha384WithRSAEncryption':
|
||||||
case 'sha512WithRSAEncryption':
|
case 'sha512WithRSAEncryption':
|
||||||
$rsa->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
|
$rsa->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
|
||||||
if (!@$rsa->verify($signatureSubject, $signature, RSA::PADDING_PKCS1)) {
|
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
|
||||||
|
if (!@$rsa->verify($signatureSubject, $signature)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
|
return null;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedAlgorithmException('Public key algorithm unsupported');
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2812,7 +2811,7 @@ class X509
|
|||||||
switch ($keyinfo['algorithm']['algorithm']) {
|
switch ($keyinfo['algorithm']['algorithm']) {
|
||||||
case 'rsaEncryption':
|
case 'rsaEncryption':
|
||||||
$publicKey = new RSA();
|
$publicKey = new RSA();
|
||||||
$publicKey->load($key);
|
$publicKey->loadKey($key);
|
||||||
$publicKey->setPublicKey();
|
$publicKey->setPublicKey();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2888,7 +2887,7 @@ class X509
|
|||||||
switch ($algorithm) {
|
switch ($algorithm) {
|
||||||
case 'rsaEncryption':
|
case 'rsaEncryption':
|
||||||
$this->publicKey = new RSA();
|
$this->publicKey = new RSA();
|
||||||
$this->publicKey->load($key);
|
$this->publicKey->loadKey($key);
|
||||||
$this->publicKey->setPublicKey();
|
$this->publicKey->setPublicKey();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -3011,7 +3010,7 @@ class X509
|
|||||||
switch ($algorithm) {
|
switch ($algorithm) {
|
||||||
case 'rsaEncryption':
|
case 'rsaEncryption':
|
||||||
$this->publicKey = new RSA();
|
$this->publicKey = new RSA();
|
||||||
$this->publicKey->load($key);
|
$this->publicKey->loadKey($key);
|
||||||
$this->publicKey->setPublicKey();
|
$this->publicKey->setPublicKey();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -3406,7 +3405,7 @@ class X509
|
|||||||
$origPublicKey = $this->publicKey;
|
$origPublicKey = $this->publicKey;
|
||||||
$class = get_class($this->privateKey);
|
$class = get_class($this->privateKey);
|
||||||
$this->publicKey = new $class();
|
$this->publicKey = new $class();
|
||||||
$this->publicKey->load($this->privateKey->getPublicKey());
|
$this->publicKey->loadKey($this->privateKey->getPublicKey());
|
||||||
$this->publicKey->setPublicKey();
|
$this->publicKey->setPublicKey();
|
||||||
if (!($publicKey = $this->_formatSubjectPublicKey())) {
|
if (!($publicKey = $this->_formatSubjectPublicKey())) {
|
||||||
return false;
|
return false;
|
||||||
@ -3464,7 +3463,7 @@ class X509
|
|||||||
$origPublicKey = $this->publicKey;
|
$origPublicKey = $this->publicKey;
|
||||||
$class = get_class($this->privateKey);
|
$class = get_class($this->privateKey);
|
||||||
$this->publicKey = new $class();
|
$this->publicKey = new $class();
|
||||||
$this->publicKey->load($this->privateKey->getPublicKey());
|
$this->publicKey->loadKey($this->privateKey->getPublicKey());
|
||||||
$this->publicKey->setPublicKey();
|
$this->publicKey->setPublicKey();
|
||||||
$publicKey = $this->_formatSubjectPublicKey();
|
$publicKey = $this->_formatSubjectPublicKey();
|
||||||
if (!$publicKey) {
|
if (!$publicKey) {
|
||||||
@ -3652,7 +3651,6 @@ class X509
|
|||||||
* @param \phpseclib\File\X509 $subject
|
* @param \phpseclib\File\X509 $subject
|
||||||
* @param string $signatureAlgorithm
|
* @param string $signatureAlgorithm
|
||||||
* @access public
|
* @access public
|
||||||
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
|
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
function _sign($key, $signatureAlgorithm)
|
function _sign($key, $signatureAlgorithm)
|
||||||
@ -3667,15 +3665,14 @@ class X509
|
|||||||
case 'sha384WithRSAEncryption':
|
case 'sha384WithRSAEncryption':
|
||||||
case 'sha512WithRSAEncryption':
|
case 'sha512WithRSAEncryption':
|
||||||
$key->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
|
$key->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
|
||||||
|
$key->setSignatureMode(RSA::SIGNATURE_PKCS1);
|
||||||
|
|
||||||
$this->currentCert['signature'] = base64_encode("\0" . $key->sign($this->signatureSubject, RSA::PADDING_PKCS1));
|
$this->currentCert['signature'] = base64_encode("\0" . $key->sign($this->signatureSubject));
|
||||||
return $this->currentCert;
|
return $this->currentCert;
|
||||||
default:
|
|
||||||
throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedAlgorithmException('Unsupported public key algorithm');
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4232,7 +4229,7 @@ class X509
|
|||||||
$raw = base64_decode($raw);
|
$raw = base64_decode($raw);
|
||||||
// If the key is private, compute identifier from its corresponding public key.
|
// If the key is private, compute identifier from its corresponding public key.
|
||||||
$key = new RSA();
|
$key = new RSA();
|
||||||
if (!$key->load($raw)) {
|
if (!$key->loadKey($raw)) {
|
||||||
return false; // Not an unencrypted RSA key.
|
return false; // Not an unencrypted RSA key.
|
||||||
}
|
}
|
||||||
if ($key->getPrivateKey() !== false) { // If private.
|
if ($key->getPrivateKey() !== false) { // If private.
|
||||||
@ -4252,7 +4249,7 @@ class X509
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
default: // Should be a key object (i.e.: \phpseclib\Crypt\RSA).
|
default: // Should be a key object (i.e.: \phpseclib\Crypt\RSA).
|
||||||
$key = $key->getPublicKey('PKCS1');
|
$key = $key->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4285,7 +4282,7 @@ class X509
|
|||||||
//return new Element(base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey())));
|
//return new Element(base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey())));
|
||||||
return array(
|
return array(
|
||||||
'algorithm' => array('algorithm' => 'rsaEncryption'),
|
'algorithm' => array('algorithm' => 'rsaEncryption'),
|
||||||
'subjectPublicKey' => $this->publicKey->getPublicKey('PKCS1')
|
'subjectPublicKey' => $this->publicKey->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,8 @@
|
|||||||
|
|
||||||
namespace phpseclib\Net;
|
namespace phpseclib\Net;
|
||||||
|
|
||||||
use phpseclib\Exception\FileNotFoundException;
|
use phpseclib\Net\SSH1;
|
||||||
|
use phpseclib\Net\SSH2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementations of SCP.
|
* Pure-PHP implementations of SCP.
|
||||||
@ -139,7 +140,6 @@ class SCP
|
|||||||
* @param string $data
|
* @param string $data
|
||||||
* @param int $mode
|
* @param int $mode
|
||||||
* @param callable $callback
|
* @param callable $callback
|
||||||
* @throws \phpseclib\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist
|
|
||||||
* @return bool
|
* @return bool
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
@ -168,7 +168,8 @@ class SCP
|
|||||||
$size = strlen($data);
|
$size = strlen($data);
|
||||||
} else {
|
} else {
|
||||||
if (!is_file($data)) {
|
if (!is_file($data)) {
|
||||||
throw new FileNotFoundException("$data is not a valid file");
|
user_error("$data is not a valid file", E_USER_NOTICE);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$fp = @fopen($data, 'rb');
|
$fp = @fopen($data, 'rb');
|
||||||
@ -288,7 +289,6 @@ class SCP
|
|||||||
* Receives a packet from an SSH server
|
* Receives a packet from an SSH server
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \UnexpectedValueException on receipt of an unexpected packet
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _receive()
|
function _receive()
|
||||||
@ -314,7 +314,8 @@ class SCP
|
|||||||
$this->ssh->bitmap = 0;
|
$this->ssh->bitmap = 0;
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
throw new \UnexpectedValueException('Unknown packet received');
|
user_error('Unknown packet received', E_USER_NOTICE);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
namespace phpseclib\Net;
|
namespace phpseclib\Net;
|
||||||
|
|
||||||
use phpseclib\Exception\FileNotFoundException;
|
use phpseclib\Net\SSH2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementations of SFTP.
|
* Pure-PHP implementations of SFTP.
|
||||||
@ -383,7 +383,6 @@ class SFTP extends SSH2
|
|||||||
*
|
*
|
||||||
* @param string $username
|
* @param string $username
|
||||||
* @param string $password
|
* @param string $password
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @return bool
|
* @return bool
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
@ -471,7 +470,8 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->_get_sftp_packet();
|
$response = $this->_get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_VERSION) {
|
if ($this->packet_type != NET_SFTP_VERSION) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_VERSION');
|
user_error('Expected SSH_FXP_VERSION');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Nversion', $this->_string_shift($response, 4)));
|
extract(unpack('Nversion', $this->_string_shift($response, 4)));
|
||||||
@ -610,7 +610,6 @@ class SFTP extends SSH2
|
|||||||
*
|
*
|
||||||
* @see self::chdir()
|
* @see self::chdir()
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
@ -635,7 +634,8 @@ class SFTP extends SSH2
|
|||||||
$this->_logError($response);
|
$this->_logError($response);
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,7 +666,6 @@ class SFTP extends SSH2
|
|||||||
* Changes the current directory
|
* Changes the current directory
|
||||||
*
|
*
|
||||||
* @param string $dir
|
* @param string $dir
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @return bool
|
* @return bool
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
@ -711,7 +710,8 @@ class SFTP extends SSH2
|
|||||||
$this->_logError($response);
|
$this->_logError($response);
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->_close_handle($handle)) {
|
if (!$this->_close_handle($handle)) {
|
||||||
@ -813,7 +813,6 @@ class SFTP extends SSH2
|
|||||||
* @param string $dir
|
* @param string $dir
|
||||||
* @param bool $raw
|
* @param bool $raw
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _list($dir, $raw = true)
|
function _list($dir, $raw = true)
|
||||||
@ -845,7 +844,8 @@ class SFTP extends SSH2
|
|||||||
$this->_logError($response);
|
$this->_logError($response);
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_update_stat_cache($dir, array());
|
$this->_update_stat_cache($dir, array());
|
||||||
@ -899,7 +899,8 @@ class SFTP extends SSH2
|
|||||||
}
|
}
|
||||||
break 2;
|
break 2;
|
||||||
default:
|
default:
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1258,7 +1259,6 @@ class SFTP extends SSH2
|
|||||||
*
|
*
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @param int $type
|
* @param int $type
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
@ -1279,7 +1279,8 @@ class SFTP extends SSH2
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1305,7 +1306,6 @@ class SFTP extends SSH2
|
|||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @param int $time
|
* @param int $time
|
||||||
* @param int $atime
|
* @param int $atime
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @return bool
|
* @return bool
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
@ -1342,7 +1342,8 @@ class SFTP extends SSH2
|
|||||||
$this->_logError($response);
|
$this->_logError($response);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_setstat($filename, $attr, false);
|
return $this->_setstat($filename, $attr, false);
|
||||||
@ -1395,7 +1396,6 @@ class SFTP extends SSH2
|
|||||||
* @param int $mode
|
* @param int $mode
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @param bool $recursive
|
* @param bool $recursive
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
@ -1434,7 +1434,8 @@ class SFTP extends SSH2
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1443,7 +1444,6 @@ class SFTP extends SSH2
|
|||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @param string $attr
|
* @param string $attr
|
||||||
* @param bool $recursive
|
* @param bool $recursive
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @return bool
|
* @return bool
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
@ -1482,7 +1482,8 @@ class SFTP extends SSH2
|
|||||||
*/
|
*/
|
||||||
$response = $this->_get_sftp_packet();
|
$response = $this->_get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||||
@ -1570,7 +1571,6 @@ class SFTP extends SSH2
|
|||||||
* Return the target of a symbolic link
|
* Return the target of a symbolic link
|
||||||
*
|
*
|
||||||
* @param string $link
|
* @param string $link
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
@ -1594,7 +1594,8 @@ class SFTP extends SSH2
|
|||||||
$this->_logError($response);
|
$this->_logError($response);
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Ncount', $this->_string_shift($response, 4)));
|
extract(unpack('Ncount', $this->_string_shift($response, 4)));
|
||||||
@ -1614,7 +1615,6 @@ class SFTP extends SSH2
|
|||||||
*
|
*
|
||||||
* @param string $target
|
* @param string $target
|
||||||
* @param string $link
|
* @param string $link
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @return bool
|
* @return bool
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
@ -1634,7 +1634,8 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->_get_sftp_packet();
|
$response = $this->_get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||||
@ -1686,7 +1687,6 @@ class SFTP extends SSH2
|
|||||||
*
|
*
|
||||||
* @param string $dir
|
* @param string $dir
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _mkdir_helper($dir, $attr)
|
function _mkdir_helper($dir, $attr)
|
||||||
@ -1697,7 +1697,8 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->_get_sftp_packet();
|
$response = $this->_get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||||
@ -1713,7 +1714,6 @@ class SFTP extends SSH2
|
|||||||
* Removes a directory.
|
* Removes a directory.
|
||||||
*
|
*
|
||||||
* @param string $dir
|
* @param string $dir
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @return bool
|
* @return bool
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
@ -1734,7 +1734,8 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->_get_sftp_packet();
|
$response = $this->_get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||||
@ -1794,9 +1795,6 @@ class SFTP extends SSH2
|
|||||||
* @param int $start
|
* @param int $start
|
||||||
* @param int $local_start
|
* @param int $local_start
|
||||||
* @param callable|null $progressCallback
|
* @param callable|null $progressCallback
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @throws \BadFunctionCallException if you're uploading via a callback and the callback function is invalid
|
|
||||||
* @throws \phpseclib\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist
|
|
||||||
* @return bool
|
* @return bool
|
||||||
* @access public
|
* @access public
|
||||||
* @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib\Net\SFTP::setMode().
|
* @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib\Net\SFTP::setMode().
|
||||||
@ -1844,7 +1842,8 @@ class SFTP extends SSH2
|
|||||||
$this->_logError($response);
|
$this->_logError($response);
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
|
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
|
||||||
@ -1852,7 +1851,7 @@ class SFTP extends SSH2
|
|||||||
switch (true) {
|
switch (true) {
|
||||||
case $mode & self::SOURCE_CALLBACK:
|
case $mode & self::SOURCE_CALLBACK:
|
||||||
if (!is_callable($data)) {
|
if (!is_callable($data)) {
|
||||||
throw new \BadFunctionCallException("\$data should be is_callable() if you specify SOURCE_CALLBACK flag");
|
user_error("\$data should be is_callable() if you specify SOURCE_CALLBACK flag");
|
||||||
}
|
}
|
||||||
$dataCallback = $data;
|
$dataCallback = $data;
|
||||||
// do nothing
|
// do nothing
|
||||||
@ -1863,7 +1862,8 @@ class SFTP extends SSH2
|
|||||||
break;
|
break;
|
||||||
case $mode & self::SOURCE_LOCAL_FILE:
|
case $mode & self::SOURCE_LOCAL_FILE:
|
||||||
if (!is_file($data)) {
|
if (!is_file($data)) {
|
||||||
throw new FileNotFoundException("$data is not a valid file");
|
user_error("$data is not a valid file");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
$fp = @fopen($data, 'rb');
|
$fp = @fopen($data, 'rb');
|
||||||
if (!$fp) {
|
if (!$fp) {
|
||||||
@ -1948,7 +1948,6 @@ class SFTP extends SSH2
|
|||||||
*
|
*
|
||||||
* @param int $i
|
* @param int $i
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _read_put_responses($i)
|
function _read_put_responses($i)
|
||||||
@ -1956,7 +1955,8 @@ class SFTP extends SSH2
|
|||||||
while ($i--) {
|
while ($i--) {
|
||||||
$response = $this->_get_sftp_packet();
|
$response = $this->_get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||||
@ -1974,7 +1974,6 @@ class SFTP extends SSH2
|
|||||||
*
|
*
|
||||||
* @param string $handle
|
* @param string $handle
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _close_handle($handle)
|
function _close_handle($handle)
|
||||||
@ -1987,7 +1986,8 @@ class SFTP extends SSH2
|
|||||||
// -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
|
// -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
|
||||||
$response = $this->_get_sftp_packet();
|
$response = $this->_get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||||
@ -2012,7 +2012,6 @@ class SFTP extends SSH2
|
|||||||
* @param string $local_file
|
* @param string $local_file
|
||||||
* @param int $offset
|
* @param int $offset
|
||||||
* @param int $length
|
* @param int $length
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
@ -2041,7 +2040,8 @@ class SFTP extends SSH2
|
|||||||
$this->_logError($response);
|
$this->_logError($response);
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_resource($local_file)) {
|
if (is_resource($local_file)) {
|
||||||
@ -2063,68 +2063,40 @@ class SFTP extends SSH2
|
|||||||
$fclose_check = $local_file !== false && !is_resource($local_file);
|
$fclose_check = $local_file !== false && !is_resource($local_file);
|
||||||
|
|
||||||
$start = $offset;
|
$start = $offset;
|
||||||
$read = 0;
|
$size = $this->max_sftp_packet < $length || $length < 0 ? $this->max_sftp_packet : $length;
|
||||||
while (true) {
|
while (true) {
|
||||||
$i = 0;
|
$packet = pack('Na*N3', strlen($handle), $handle, $offset / 4294967296, $offset, $size);
|
||||||
|
if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) {
|
||||||
|
if ($fclose_check) {
|
||||||
|
fclose($fp);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
while ($i < NET_SFTP_QUEUE_SIZE && ($length < 0 || $read < $length)) {
|
$response = $this->_get_sftp_packet();
|
||||||
$tempoffset = $start + $read;
|
switch ($this->packet_type) {
|
||||||
|
case NET_SFTP_DATA:
|
||||||
$packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet;
|
$temp = substr($response, 4);
|
||||||
|
$offset+= strlen($temp);
|
||||||
$packet = pack('Na*N3', strlen($handle), $handle, $tempoffset / 4294967296, $tempoffset, $packet_size);
|
if ($local_file === false) {
|
||||||
if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) {
|
$content.= $temp;
|
||||||
|
} else {
|
||||||
|
fputs($fp, $temp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NET_SFTP_STATUS:
|
||||||
|
// could, in theory, return false if !strlen($content) but we'll hold off for the time being
|
||||||
|
$this->_logError($response);
|
||||||
|
break 2;
|
||||||
|
default:
|
||||||
|
user_error('Expected SSH_FXP_DATA or SSH_FXP_STATUS');
|
||||||
if ($fclose_check) {
|
if ($fclose_check) {
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
$packet = null;
|
|
||||||
$read+= $packet_size;
|
|
||||||
$i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$i) {
|
if ($length > 0 && $length <= $offset - $start) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$clear_responses = false;
|
|
||||||
while ($i > 0) {
|
|
||||||
$i--;
|
|
||||||
|
|
||||||
if ($clear_responses) {
|
|
||||||
$this->_get_sftp_packet();
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
$response = $this->_get_sftp_packet();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($this->packet_type) {
|
|
||||||
case NET_SFTP_DATA:
|
|
||||||
$temp = substr($response, 4);
|
|
||||||
$offset+= strlen($temp);
|
|
||||||
if ($local_file === false) {
|
|
||||||
$content.= $temp;
|
|
||||||
} else {
|
|
||||||
fputs($fp, $temp);
|
|
||||||
}
|
|
||||||
$temp = null;
|
|
||||||
break;
|
|
||||||
case NET_SFTP_STATUS:
|
|
||||||
// could, in theory, return false if !strlen($content) but we'll hold off for the time being
|
|
||||||
$this->_logError($response);
|
|
||||||
$clear_responses = true; // don't break out of the loop yet, so we can read the remaining responses
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if ($fclose_check) {
|
|
||||||
fclose($fp);
|
|
||||||
}
|
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_DATA or SSH_FXP_STATUS');
|
|
||||||
}
|
|
||||||
$response = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($clear_responses) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2155,7 +2127,6 @@ class SFTP extends SSH2
|
|||||||
* @param string $path
|
* @param string $path
|
||||||
* @param bool $recursive
|
* @param bool $recursive
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function delete($path, $recursive = true)
|
function delete($path, $recursive = true)
|
||||||
@ -2176,7 +2147,8 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->_get_sftp_packet();
|
$response = $this->_get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
||||||
@ -2508,7 +2480,6 @@ class SFTP extends SSH2
|
|||||||
* @param string $oldname
|
* @param string $oldname
|
||||||
* @param string $newname
|
* @param string $newname
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function rename($oldname, $newname)
|
function rename($oldname, $newname)
|
||||||
@ -2531,7 +2502,8 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->_get_sftp_packet();
|
$response = $this->_get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
user_error('Expected SSH_FXP_STATUS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
||||||
@ -2705,13 +2677,13 @@ class SFTP extends SSH2
|
|||||||
if (defined('NET_SFTP_LOGGING')) {
|
if (defined('NET_SFTP_LOGGING')) {
|
||||||
$packet_type = '-> ' . $this->packet_types[$type] .
|
$packet_type = '-> ' . $this->packet_types[$type] .
|
||||||
' (' . round($stop - $start, 4) . 's)';
|
' (' . round($stop - $start, 4) . 's)';
|
||||||
if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
|
if (NET_SFTP_LOGGING == NET_SFTP_LOG_REALTIME) {
|
||||||
echo "<pre>\r\n" . $this->_format_log(array($data), array($packet_type)) . "\r\n</pre>\r\n";
|
echo "<pre>\r\n" . $this->_format_log(array($data), array($packet_type)) . "\r\n</pre>\r\n";
|
||||||
flush();
|
flush();
|
||||||
ob_flush();
|
ob_flush();
|
||||||
} else {
|
} else {
|
||||||
$this->packet_type_log[] = $packet_type;
|
$this->packet_type_log[] = $packet_type;
|
||||||
if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
|
if (NET_SFTP_LOGGING == NET_SFTP_LOG_COMPLEX) {
|
||||||
$this->packet_log[] = $data;
|
$this->packet_log[] = $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2781,13 +2753,13 @@ class SFTP extends SSH2
|
|||||||
if (defined('NET_SFTP_LOGGING')) {
|
if (defined('NET_SFTP_LOGGING')) {
|
||||||
$packet_type = '<- ' . $this->packet_types[$this->packet_type] .
|
$packet_type = '<- ' . $this->packet_types[$this->packet_type] .
|
||||||
' (' . round($stop - $start, 4) . 's)';
|
' (' . round($stop - $start, 4) . 's)';
|
||||||
if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
|
if (NET_SFTP_LOGGING == NET_SFTP_LOG_REALTIME) {
|
||||||
echo "<pre>\r\n" . $this->_format_log(array($packet), array($packet_type)) . "\r\n</pre>\r\n";
|
echo "<pre>\r\n" . $this->_format_log(array($packet), array($packet_type)) . "\r\n</pre>\r\n";
|
||||||
flush();
|
flush();
|
||||||
ob_flush();
|
ob_flush();
|
||||||
} else {
|
} else {
|
||||||
$this->packet_type_log[] = $packet_type;
|
$this->packet_type_log[] = $packet_type;
|
||||||
if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
|
if (NET_SFTP_LOGGING == NET_SFTP_LOG_COMPLEX) {
|
||||||
$this->packet_log[] = $packet;
|
$this->packet_log[] = $packet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2799,7 +2771,7 @@ class SFTP extends SSH2
|
|||||||
/**
|
/**
|
||||||
* Returns a log of the packets that have been sent and received.
|
* Returns a log of the packets that have been sent and received.
|
||||||
*
|
*
|
||||||
* Returns a string if NET_SFTP_LOGGING == self::LOG_COMPLEX, an array if NET_SFTP_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
|
* Returns a string if NET_SFTP_LOGGING == NET_SFTP_LOG_COMPLEX, an array if NET_SFTP_LOGGING == NET_SFTP_LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @return string or Array
|
* @return string or Array
|
||||||
@ -2811,10 +2783,10 @@ class SFTP extends SSH2
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (NET_SFTP_LOGGING) {
|
switch (NET_SFTP_LOGGING) {
|
||||||
case self::LOG_COMPLEX:
|
case NET_SFTP_LOG_COMPLEX:
|
||||||
return $this->_format_log($this->packet_log, $this->packet_type_log);
|
return $this->_format_log($this->packet_log, $this->packet_type_log);
|
||||||
break;
|
break;
|
||||||
//case self::LOG_SIMPLE:
|
//case NET_SFTP_LOG_SIMPLE:
|
||||||
default:
|
default:
|
||||||
return $this->packet_type_log;
|
return $this->packet_type_log;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ namespace phpseclib\Net\SFTP;
|
|||||||
|
|
||||||
use phpseclib\Crypt\RSA;
|
use phpseclib\Crypt\RSA;
|
||||||
use phpseclib\Net\SFTP;
|
use phpseclib\Net\SFTP;
|
||||||
use phpseclib\Net\SSH2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SFTP Stream Wrapper
|
* SFTP Stream Wrapper
|
||||||
@ -178,12 +177,13 @@ class Stream
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preg_match('/^{[a-z0-9]+}$/i', $host)) {
|
if ($host[0] == '$') {
|
||||||
$host = SSH2::getConnectionByResourceId($host);
|
$host = substr($host, 1);
|
||||||
if ($host === false) {
|
global $$host;
|
||||||
|
if (($$host instanceof SFTP) === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->sftp = $host;
|
$this->sftp = $$host;
|
||||||
} else {
|
} else {
|
||||||
if (isset($this->context)) {
|
if (isset($this->context)) {
|
||||||
$context = stream_context_get_options($this->context);
|
$context = stream_context_get_options($this->context);
|
||||||
|
@ -537,15 +537,14 @@ class SSH1
|
|||||||
* Connect to an SSHv1 server
|
* Connect to an SSHv1 server
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @throws \RuntimeException on other errors
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _connect()
|
function _connect()
|
||||||
{
|
{
|
||||||
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
|
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
|
||||||
if (!$this->fsock) {
|
if (!$this->fsock) {
|
||||||
throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr"));
|
user_error(rtrim("Cannot connect to {$this->host}:{$this->port}. Error $errno. $errstr"));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->server_identification = $init_line = fgets($this->fsock, 255);
|
$this->server_identification = $init_line = fgets($this->fsock, 255);
|
||||||
@ -556,17 +555,20 @@ class SSH1
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
|
if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
|
||||||
throw new \RuntimeException('Can only connect to SSH servers');
|
user_error('Can only connect to SSH servers');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if ($parts[1][0] != 1) {
|
if ($parts[1][0] != 1) {
|
||||||
throw new \RuntimeException("Cannot connect to $parts[1] servers");
|
user_error("Cannot connect to SSH $parts[1] servers");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs($this->fsock, $this->identifier."\r\n");
|
fputs($this->fsock, $this->identifier."\r\n");
|
||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
|
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_SMSG_PUBLIC_KEY');
|
user_error('Expected SSH_SMSG_PUBLIC_KEY');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$anti_spoofing_cookie = $this->_string_shift($response[self::RESPONSE_DATA], 8);
|
$anti_spoofing_cookie = $this->_string_shift($response[self::RESPONSE_DATA], 8);
|
||||||
@ -650,7 +652,8 @@ class SSH1
|
|||||||
$data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
|
$data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
|
||||||
|
|
||||||
if (!$this->_send_binary_packet($data)) {
|
if (!$this->_send_binary_packet($data)) {
|
||||||
throw new \RuntimeException('Error sending SSH_CMSG_SESSION_KEY');
|
user_error('Error sending SSH_CMSG_SESSION_KEY');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($cipher) {
|
switch ($cipher) {
|
||||||
@ -658,20 +661,16 @@ class SSH1
|
|||||||
// $this->crypto = new \phpseclib\Crypt\Null();
|
// $this->crypto = new \phpseclib\Crypt\Null();
|
||||||
// break;
|
// break;
|
||||||
case self::CIPHER_DES:
|
case self::CIPHER_DES:
|
||||||
$this->crypto = new DES(DES::MODE_CBC);
|
$this->crypto = new DES();
|
||||||
$this->crypto->disablePadding();
|
$this->crypto->disablePadding();
|
||||||
$this->crypto->enableContinuousBuffer();
|
$this->crypto->enableContinuousBuffer();
|
||||||
$this->crypto->setKey(substr($session_key, 0, 8));
|
$this->crypto->setKey(substr($session_key, 0, 8));
|
||||||
// "The iv (initialization vector) is initialized to all zeroes."
|
|
||||||
$this->crypto->setIV(str_repeat("\0", 8));
|
|
||||||
break;
|
break;
|
||||||
case self::CIPHER_3DES:
|
case self::CIPHER_3DES:
|
||||||
$this->crypto = new TripleDES(TripleDES::MODE_3CBC);
|
$this->crypto = new TripleDES(TripleDES::MODE_3CBC);
|
||||||
$this->crypto->disablePadding();
|
$this->crypto->disablePadding();
|
||||||
$this->crypto->enableContinuousBuffer();
|
$this->crypto->enableContinuousBuffer();
|
||||||
$this->crypto->setKey(substr($session_key, 0, 24));
|
$this->crypto->setKey(substr($session_key, 0, 24));
|
||||||
// "All three initialization vectors are initialized to zero."
|
|
||||||
$this->crypto->setIV(str_repeat("\0", 8));
|
|
||||||
break;
|
break;
|
||||||
//case self::CIPHER_RC4:
|
//case self::CIPHER_RC4:
|
||||||
// $this->crypto = new RC4();
|
// $this->crypto = new RC4();
|
||||||
@ -683,7 +682,8 @@ class SSH1
|
|||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
|
|
||||||
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
|
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS');
|
user_error('Expected SSH_SMSG_SUCCESS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->bitmap = self::MASK_CONNECTED;
|
$this->bitmap = self::MASK_CONNECTED;
|
||||||
@ -697,8 +697,6 @@ class SSH1
|
|||||||
* @param string $username
|
* @param string $username
|
||||||
* @param string $password
|
* @param string $password
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @throws \RuntimeException on other errors
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function login($username, $password = '')
|
function login($username, $password = '')
|
||||||
@ -717,7 +715,8 @@ class SSH1
|
|||||||
$data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username);
|
$data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username);
|
||||||
|
|
||||||
if (!$this->_send_binary_packet($data)) {
|
if (!$this->_send_binary_packet($data)) {
|
||||||
throw new \RuntimeException('Error sending SSH_CMSG_USER');
|
user_error('Error sending SSH_CMSG_USER');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
@ -729,13 +728,15 @@ class SSH1
|
|||||||
$this->bitmap |= self::MASK_LOGIN;
|
$this->bitmap |= self::MASK_LOGIN;
|
||||||
return true;
|
return true;
|
||||||
} elseif ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
|
} elseif ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password);
|
$data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password);
|
||||||
|
|
||||||
if (!$this->_send_binary_packet($data)) {
|
if (!$this->_send_binary_packet($data)) {
|
||||||
throw new \RuntimeException('Error sending SSH_CMSG_AUTH_PASSWORD');
|
user_error('Error sending SSH_CMSG_AUTH_PASSWORD');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the username and password from the last logged packet
|
// remove the username and password from the last logged packet
|
||||||
@ -755,7 +756,8 @@ class SSH1
|
|||||||
} elseif ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
|
} elseif ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,19 +792,20 @@ class SSH1
|
|||||||
* @see self::interactiveWrite()
|
* @see self::interactiveWrite()
|
||||||
* @param string $cmd
|
* @param string $cmd
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws \RuntimeException on error sending command
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function exec($cmd, $block = true)
|
function exec($cmd, $block = true)
|
||||||
{
|
{
|
||||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
user_error('Operation disallowed prior to login()');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd);
|
$data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd);
|
||||||
|
|
||||||
if (!$this->_send_binary_packet($data)) {
|
if (!$this->_send_binary_packet($data)) {
|
||||||
throw new \RuntimeException('Error sending SSH_CMSG_EXEC_CMD');
|
user_error('Error sending SSH_CMSG_EXEC_CMD');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$block) {
|
if (!$block) {
|
||||||
@ -838,8 +841,6 @@ class SSH1
|
|||||||
* @see self::interactiveRead()
|
* @see self::interactiveRead()
|
||||||
* @see self::interactiveWrite()
|
* @see self::interactiveWrite()
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @throws \RuntimeException on other errors
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _initShell()
|
function _initShell()
|
||||||
@ -850,7 +851,8 @@ class SSH1
|
|||||||
$data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, self::TTY_OP_END);
|
$data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, self::TTY_OP_END);
|
||||||
|
|
||||||
if (!$this->_send_binary_packet($data)) {
|
if (!$this->_send_binary_packet($data)) {
|
||||||
throw new \RuntimeException('Error sending SSH_CMSG_REQUEST_PTY');
|
user_error('Error sending SSH_CMSG_REQUEST_PTY');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
@ -859,13 +861,15 @@ class SSH1
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
|
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS');
|
user_error('Expected SSH_SMSG_SUCCESS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = pack('C', NET_SSH1_CMSG_EXEC_SHELL);
|
$data = pack('C', NET_SSH1_CMSG_EXEC_SHELL);
|
||||||
|
|
||||||
if (!$this->_send_binary_packet($data)) {
|
if (!$this->_send_binary_packet($data)) {
|
||||||
throw new \RuntimeException('Error sending SSH_CMSG_EXEC_SHELL');
|
user_error('Error sending SSH_CMSG_EXEC_SHELL');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->bitmap |= self::MASK_SHELL;
|
$this->bitmap |= self::MASK_SHELL;
|
||||||
@ -898,17 +902,18 @@ class SSH1
|
|||||||
* @param string $expect
|
* @param string $expect
|
||||||
* @param int $mode
|
* @param int $mode
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \RuntimeException on connection error
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function read($expect, $mode = self::READ__SIMPLE)
|
function read($expect, $mode = self::READ__SIMPLE)
|
||||||
{
|
{
|
||||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
user_error('Operation disallowed prior to login()');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
user_error('Unable to initiate an interactive shell session');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$match = $expect;
|
$match = $expect;
|
||||||
@ -936,23 +941,25 @@ class SSH1
|
|||||||
* @see self::interactiveRead()
|
* @see self::interactiveRead()
|
||||||
* @param string $cmd
|
* @param string $cmd
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \RuntimeException on connection error
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function interactiveWrite($cmd)
|
function interactiveWrite($cmd)
|
||||||
{
|
{
|
||||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
user_error('Operation disallowed prior to login()');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
user_error('Unable to initiate an interactive shell session');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd);
|
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd);
|
||||||
|
|
||||||
if (!$this->_send_binary_packet($data)) {
|
if (!$this->_send_binary_packet($data)) {
|
||||||
throw new \RuntimeException('Error sending SSH_CMSG_STDIN');
|
user_error('Error sending SSH_CMSG_STDIN');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -969,17 +976,18 @@ class SSH1
|
|||||||
*
|
*
|
||||||
* @see self::interactiveRead()
|
* @see self::interactiveRead()
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \RuntimeException on connection error
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function interactiveRead()
|
function interactiveRead()
|
||||||
{
|
{
|
||||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
user_error('Operation disallowed prior to login()');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
user_error('Unable to initiate an interactive shell session');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$read = array($this->fsock);
|
$read = array($this->fsock);
|
||||||
@ -1305,9 +1313,9 @@ class SSH1
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
$rsa = new RSA();
|
$rsa = new RSA();
|
||||||
$rsa->load($key, 'raw');
|
$rsa->loadKey($key, RSA::PUBLIC_FORMAT_RAW);
|
||||||
$rsa->setHash('sha1');
|
$rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1);
|
||||||
return $rsa->encrypt($m, RSA::PADDING_PKCS1);
|
return $rsa->encrypt($m);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// To quote from protocol-1.5.txt:
|
// To quote from protocol-1.5.txt:
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
*
|
*
|
||||||
* $key = new \phpseclib\Crypt\RSA();
|
* $key = new \phpseclib\Crypt\RSA();
|
||||||
* //$key->setPassword('whatever');
|
* //$key->setPassword('whatever');
|
||||||
* $key->load(file_get_contents('privatekey'));
|
* $key->loadKey(file_get_contents('privatekey'));
|
||||||
*
|
*
|
||||||
* $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
|
* $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
|
||||||
* if (!$ssh->login('username', $key)) {
|
* if (!$ssh->login('username', $key)) {
|
||||||
@ -60,7 +60,6 @@ use phpseclib\Crypt\TripleDES;
|
|||||||
use phpseclib\Crypt\Twofish;
|
use phpseclib\Crypt\Twofish;
|
||||||
use phpseclib\Math\BigInteger; // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
|
use phpseclib\Math\BigInteger; // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
|
||||||
use phpseclib\System\SSH\Agent;
|
use phpseclib\System\SSH\Agent;
|
||||||
use phpseclib\Exception\NoSupportedAlgorithmsException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementation of SSHv2.
|
* Pure-PHP implementation of SSHv2.
|
||||||
@ -867,14 +866,6 @@ class SSH2
|
|||||||
*/
|
*/
|
||||||
var $agent;
|
var $agent;
|
||||||
|
|
||||||
/**
|
|
||||||
* Connection storage to replicates ssh2 extension functionality:
|
|
||||||
* {@link http://php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-examples}
|
|
||||||
*
|
|
||||||
* @var SSH2[]
|
|
||||||
*/
|
|
||||||
static $connections;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
@ -968,8 +959,6 @@ class SSH2
|
|||||||
31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY')
|
31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY')
|
||||||
);
|
);
|
||||||
|
|
||||||
self::$connections[$this->getResourceId()] = $this;
|
|
||||||
|
|
||||||
if (is_resource($host)) {
|
if (is_resource($host)) {
|
||||||
$this->fsock = $host;
|
$this->fsock = $host;
|
||||||
return;
|
return;
|
||||||
@ -1000,8 +989,6 @@ class SSH2
|
|||||||
* Connect to an SSHv2 server
|
* Connect to an SSHv2 server
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @throws \RuntimeException on other errors
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _connect()
|
function _connect()
|
||||||
@ -1021,7 +1008,8 @@ class SSH2
|
|||||||
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout);
|
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout);
|
||||||
if (!$this->fsock) {
|
if (!$this->fsock) {
|
||||||
$host = $this->host . ':' . $this->port;
|
$host = $this->host . ':' . $this->port;
|
||||||
throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr"));
|
user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
$elapsed = microtime(true) - $start;
|
$elapsed = microtime(true) - $start;
|
||||||
|
|
||||||
@ -1072,7 +1060,8 @@ class SSH2
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (feof($this->fsock)) {
|
if (feof($this->fsock)) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->identifier = $this->_generate_identifier();
|
$this->identifier = $this->_generate_identifier();
|
||||||
@ -1088,18 +1077,21 @@ class SSH2
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($matches[1] != '1.99' && $matches[1] != '2.0') {
|
if ($matches[1] != '1.99' && $matches[1] != '2.0') {
|
||||||
throw new \RuntimeException("Cannot connect to SSH $matches[1] servers");
|
user_error("Cannot connect to SSH $matches[1] servers");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs($this->fsock, $this->identifier . "\r\n");
|
fputs($this->fsock, $this->identifier . "\r\n");
|
||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
|
if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT');
|
user_error('Expected SSH_MSG_KEXINIT');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->_key_exchange($response)) {
|
if (!$this->_key_exchange($response)) {
|
||||||
@ -1151,9 +1143,6 @@ class SSH2
|
|||||||
* Key Exchange
|
* Key Exchange
|
||||||
*
|
*
|
||||||
* @param string $kexinit_payload_server
|
* @param string $kexinit_payload_server
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @throws \RuntimeException on other errors
|
|
||||||
* @throws \phpseclib\Exception\NoSupportedAlgorithmsException when none of the algorithms phpseclib has loaded are compatible
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _key_exchange($kexinit_payload_server)
|
function _key_exchange($kexinit_payload_server)
|
||||||
@ -1365,28 +1354,27 @@ class SSH2
|
|||||||
// here ends the second place.
|
// here ends the second place.
|
||||||
|
|
||||||
// we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
|
// we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
|
||||||
|
|
||||||
// we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
|
// we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
|
||||||
// diffie-hellman key exchange as fast as possible
|
// diffie-hellman key exchange as fast as possible
|
||||||
$decrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client);
|
$decrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client);
|
||||||
$decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt);
|
$decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt);
|
||||||
if ($decryptKeyLength === null) {
|
if ($decryptKeyLength === null) {
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('No compatible server to client encryption algorithms found');
|
||||||
throw new NoSupportedAlgorithmsException('No compatible server to client encryption algorithms found');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
$encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server);
|
$encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server);
|
||||||
$encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt);
|
$encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt);
|
||||||
if ($encryptKeyLength === null) {
|
if ($encryptKeyLength === null) {
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('No compatible client to server encryption algorithms found');
|
||||||
throw new NoSupportedAlgorithmsException('No compatible client to server encryption algorithms found');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// through diffie-hellman key exchange a symmetric key is obtained
|
// through diffie-hellman key exchange a symmetric key is obtained
|
||||||
$kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms);
|
$kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms);
|
||||||
if ($kex_algorithm === false) {
|
if ($kex_algorithm === false) {
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('No compatible key exchange algorithms found');
|
||||||
throw new NoSupportedAlgorithmsException('No compatible key exchange algorithms found');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
|
// Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
|
||||||
@ -1495,7 +1483,7 @@ class SSH2
|
|||||||
$max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength
|
$max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength
|
||||||
$max = $max->subtract($one);
|
$max = $max->subtract($one);
|
||||||
|
|
||||||
$x = BigInteger::random($one, $max);
|
$x = $one->random($one, $max);
|
||||||
$e = $g->modPow($x, $prime);
|
$e = $g->modPow($x, $prime);
|
||||||
|
|
||||||
$eBytes = $e->toBytes(true);
|
$eBytes = $e->toBytes(true);
|
||||||
@ -1503,17 +1491,20 @@ class SSH2
|
|||||||
$data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes);
|
$data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes);
|
||||||
|
|
||||||
if (!$this->_send_binary_packet($data)) {
|
if (!$this->_send_binary_packet($data)) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||||
|
|
||||||
if ($type != $serverKexReplyMessage) {
|
if ($type != $serverKexReplyMessage) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_MSG_KEXDH_REPLY');
|
user_error('Expected SSH_MSG_KEXDH_REPLY');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$temp = unpack('Nlength', $this->_string_shift($response, 4));
|
$temp = unpack('Nlength', $this->_string_shift($response, 4));
|
||||||
@ -1573,13 +1564,13 @@ class SSH2
|
|||||||
|
|
||||||
$server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
|
$server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
|
||||||
if ($server_host_key_algorithm === false) {
|
if ($server_host_key_algorithm === false) {
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('No compatible server host key algorithms found');
|
||||||
throw new NoSupportedAlgorithmsException('No compatible server host key algorithms found');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($public_key_format != $server_host_key_algorithm || $this->signature_format != $server_host_key_algorithm) {
|
if ($public_key_format != $server_host_key_algorithm || $this->signature_format != $server_host_key_algorithm) {
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('Server Host Key Algorithm Mismatch');
|
||||||
throw new \RuntimeException('Server Host Key Algorithm Mismatch');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
$packet = pack(
|
$packet = pack(
|
||||||
@ -1594,13 +1585,15 @@ class SSH2
|
|||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
|
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||||
|
|
||||||
if ($type != NET_SSH2_MSG_NEWKEYS) {
|
if ($type != NET_SSH2_MSG_NEWKEYS) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_MSG_NEWKEYS');
|
user_error('Expected SSH_MSG_NEWKEYS');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
|
$keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
|
||||||
@ -1616,13 +1609,11 @@ class SSH2
|
|||||||
$this->encrypt->enableContinuousBuffer();
|
$this->encrypt->enableContinuousBuffer();
|
||||||
$this->encrypt->disablePadding();
|
$this->encrypt->disablePadding();
|
||||||
|
|
||||||
if ($this->encrypt->usesIV()) {
|
$iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id);
|
||||||
$iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id);
|
while ($this->encrypt_block_size > strlen($iv)) {
|
||||||
while ($this->encrypt_block_size > strlen($iv)) {
|
$iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
|
||||||
$iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
|
|
||||||
}
|
|
||||||
$this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size));
|
|
||||||
}
|
}
|
||||||
|
$this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size));
|
||||||
|
|
||||||
$key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id);
|
$key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id);
|
||||||
while ($encryptKeyLength > strlen($key)) {
|
while ($encryptKeyLength > strlen($key)) {
|
||||||
@ -1642,13 +1633,11 @@ class SSH2
|
|||||||
$this->decrypt->enableContinuousBuffer();
|
$this->decrypt->enableContinuousBuffer();
|
||||||
$this->decrypt->disablePadding();
|
$this->decrypt->disablePadding();
|
||||||
|
|
||||||
if ($this->decrypt->usesIV()) {
|
$iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id);
|
||||||
$iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id);
|
while ($this->decrypt_block_size > strlen($iv)) {
|
||||||
while ($this->decrypt_block_size > strlen($iv)) {
|
$iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
|
||||||
$iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
|
|
||||||
}
|
|
||||||
$this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size));
|
|
||||||
}
|
}
|
||||||
|
$this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size));
|
||||||
|
|
||||||
$key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id);
|
$key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id);
|
||||||
while ($decryptKeyLength > strlen($key)) {
|
while ($decryptKeyLength > strlen($key)) {
|
||||||
@ -1673,8 +1662,8 @@ class SSH2
|
|||||||
|
|
||||||
$mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server);
|
$mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server);
|
||||||
if ($mac_algorithm === false) {
|
if ($mac_algorithm === false) {
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('No compatible client to server message authentication algorithms found');
|
||||||
throw new NoSupportedAlgorithmsException('No compatible client to server message authentication algorithms found');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
$createKeyLength = 0; // ie. $mac_algorithm == 'none'
|
$createKeyLength = 0; // ie. $mac_algorithm == 'none'
|
||||||
@ -1702,8 +1691,8 @@ class SSH2
|
|||||||
|
|
||||||
$mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client);
|
$mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client);
|
||||||
if ($mac_algorithm === false) {
|
if ($mac_algorithm === false) {
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('No compatible server to client message authentication algorithms found');
|
||||||
throw new NoSupportedAlgorithmsException('No compatible server to client message authentication algorithms found');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
$checkKeyLength = 0;
|
$checkKeyLength = 0;
|
||||||
@ -1749,15 +1738,15 @@ class SSH2
|
|||||||
|
|
||||||
$compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client);
|
$compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client);
|
||||||
if ($compression_algorithm === false) {
|
if ($compression_algorithm === false) {
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('No compatible server to client compression algorithms found');
|
||||||
throw new NoSupportedAlgorithmsException('No compatible server to client compression algorithms found');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
$this->decompress = $compression_algorithm == 'zlib';
|
$this->decompress = $compression_algorithm == 'zlib';
|
||||||
|
|
||||||
$compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server);
|
$compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server);
|
||||||
if ($compression_algorithm === false) {
|
if ($compression_algorithm === false) {
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('No compatible client to server compression algorithms found');
|
||||||
throw new NoSupportedAlgorithmsException('No compatible client to server compression algorithms found');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
$this->compress = $compression_algorithm == 'zlib';
|
$this->compress = $compression_algorithm == 'zlib';
|
||||||
|
|
||||||
@ -1815,26 +1804,26 @@ class SSH2
|
|||||||
{
|
{
|
||||||
switch ($algorithm) {
|
switch ($algorithm) {
|
||||||
case '3des-cbc':
|
case '3des-cbc':
|
||||||
return new TripleDES(Base::MODE_CBC);
|
return new TripleDES();
|
||||||
case '3des-ctr':
|
case '3des-ctr':
|
||||||
return new TripleDES(Base::MODE_CTR);
|
return new TripleDES(Base::MODE_CTR);
|
||||||
case 'aes256-cbc':
|
case 'aes256-cbc':
|
||||||
case 'aes192-cbc':
|
case 'aes192-cbc':
|
||||||
case 'aes128-cbc':
|
case 'aes128-cbc':
|
||||||
return new Rijndael(Base::MODE_CBC);
|
return new Rijndael();
|
||||||
case 'aes256-ctr':
|
case 'aes256-ctr':
|
||||||
case 'aes192-ctr':
|
case 'aes192-ctr':
|
||||||
case 'aes128-ctr':
|
case 'aes128-ctr':
|
||||||
return new Rijndael(Base::MODE_CTR);
|
return new Rijndael(Base::MODE_CTR);
|
||||||
case 'blowfish-cbc':
|
case 'blowfish-cbc':
|
||||||
return new Blowfish(Base::MODE_CBC);
|
return new Blowfish();
|
||||||
case 'blowfish-ctr':
|
case 'blowfish-ctr':
|
||||||
return new Blowfish(Base::MODE_CTR);
|
return new Blowfish(Base::MODE_CTR);
|
||||||
case 'twofish128-cbc':
|
case 'twofish128-cbc':
|
||||||
case 'twofish192-cbc':
|
case 'twofish192-cbc':
|
||||||
case 'twofish256-cbc':
|
case 'twofish256-cbc':
|
||||||
case 'twofish-cbc':
|
case 'twofish-cbc':
|
||||||
return new Twofish(Base::MODE_CBC);
|
return new Twofish();
|
||||||
case 'twofish128-ctr':
|
case 'twofish128-ctr':
|
||||||
case 'twofish192-ctr':
|
case 'twofish192-ctr':
|
||||||
case 'twofish256-ctr':
|
case 'twofish256-ctr':
|
||||||
@ -1902,8 +1891,6 @@ class SSH2
|
|||||||
* @param string $username
|
* @param string $username
|
||||||
* @param string $password
|
* @param string $password
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @throws \RuntimeException on other errors
|
|
||||||
* @access private
|
* @access private
|
||||||
* @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
|
* @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
|
||||||
* by sending dummy SSH_MSG_IGNORE messages.
|
* by sending dummy SSH_MSG_IGNORE messages.
|
||||||
@ -1928,13 +1915,15 @@ class SSH2
|
|||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||||
|
|
||||||
if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) {
|
if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) {
|
||||||
throw new \UnexpectedValueException('Expected SSH_MSG_SERVICE_ACCEPT');
|
user_error('Expected SSH_MSG_SERVICE_ACCEPT');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
$this->bitmap |= self::MASK_LOGIN_REQ;
|
$this->bitmap |= self::MASK_LOGIN_REQ;
|
||||||
}
|
}
|
||||||
@ -1975,7 +1964,8 @@ class SSH2
|
|||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||||
@ -2029,7 +2019,8 @@ class SSH2
|
|||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||||
@ -2105,7 +2096,6 @@ class SSH2
|
|||||||
*
|
*
|
||||||
* @param string $responses...
|
* @param string $responses...
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \RuntimeException on connection error
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _keyboard_interactive_process()
|
function _keyboard_interactive_process()
|
||||||
@ -2117,7 +2107,8 @@ class SSH2
|
|||||||
} else {
|
} else {
|
||||||
$orig = $response = $this->_get_binary_packet();
|
$orig = $response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2241,7 +2232,6 @@ class SSH2
|
|||||||
* @param string $username
|
* @param string $username
|
||||||
* @param \phpseclib\Crypt\RSA $password
|
* @param \phpseclib\Crypt\RSA $password
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \RuntimeException on connection error
|
|
||||||
* @access private
|
* @access private
|
||||||
* @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
|
* @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
|
||||||
* by sending dummy SSH_MSG_IGNORE messages.
|
* by sending dummy SSH_MSG_IGNORE messages.
|
||||||
@ -2249,7 +2239,7 @@ class SSH2
|
|||||||
function _privatekey_login($username, $privatekey)
|
function _privatekey_login($username, $privatekey)
|
||||||
{
|
{
|
||||||
// see http://tools.ietf.org/html/rfc4253#page-15
|
// see http://tools.ietf.org/html/rfc4253#page-15
|
||||||
$publickey = $privatekey->getPublicKey('Raw');
|
$publickey = $privatekey->getPublicKey(RSA::PUBLIC_FORMAT_RAW);
|
||||||
if ($publickey === false) {
|
if ($publickey === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2287,7 +2277,8 @@ class SSH2
|
|||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||||
@ -2310,8 +2301,8 @@ class SSH2
|
|||||||
}
|
}
|
||||||
|
|
||||||
$packet = $part1 . chr(1) . $part2;
|
$packet = $part1 . chr(1) . $part2;
|
||||||
$privatekey->setHash('sha1');
|
$privatekey->setSignatureMode(RSA::SIGNATURE_PKCS1);
|
||||||
$signature = $privatekey->sign(pack('Na*a*', strlen($this->session_id), $this->session_id, $packet), RSA::PADDING_PKCS1);
|
$signature = $privatekey->sign(pack('Na*a*', strlen($this->session_id), $this->session_id, $packet));
|
||||||
$signature = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($signature), $signature);
|
$signature = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($signature), $signature);
|
||||||
$packet.= pack('Na*', strlen($signature), $signature);
|
$packet.= pack('Na*', strlen($signature), $signature);
|
||||||
|
|
||||||
@ -2321,7 +2312,8 @@ class SSH2
|
|||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||||
@ -2371,7 +2363,6 @@ class SSH2
|
|||||||
* @param string $command
|
* @param string $command
|
||||||
* @param Callback $callback
|
* @param Callback $callback
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \RuntimeException on connection error
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function exec($command, $callback = null)
|
function exec($command, $callback = null)
|
||||||
@ -2439,7 +2430,8 @@ class SSH2
|
|||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
list(, $type) = unpack('C', $this->_string_shift($response, 1));
|
list(, $type) = unpack('C', $this->_string_shift($response, 1));
|
||||||
@ -2449,8 +2441,8 @@ class SSH2
|
|||||||
break;
|
break;
|
||||||
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
||||||
default:
|
default:
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
user_error('Unable to request pseudo-terminal');
|
||||||
throw new \RuntimeException('Unable to request pseudo-terminal');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||||
}
|
}
|
||||||
$this->in_request_pty_exec = true;
|
$this->in_request_pty_exec = true;
|
||||||
}
|
}
|
||||||
@ -2518,8 +2510,6 @@ class SSH2
|
|||||||
* @see self::read()
|
* @see self::read()
|
||||||
* @see self::write()
|
* @see self::write()
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
|
||||||
* @throws \RuntimeException on other errors
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _initShell()
|
function _initShell()
|
||||||
@ -2576,7 +2566,8 @@ class SSH2
|
|||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
list(, $type) = unpack('C', $this->_string_shift($response, 1));
|
list(, $type) = unpack('C', $this->_string_shift($response, 1));
|
||||||
@ -2587,8 +2578,8 @@ class SSH2
|
|||||||
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
user_error('Unable to request pseudo-terminal');
|
||||||
throw new \UnexpectedValueException('Unable to request pseudo-terminal');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
$packet = pack(
|
$packet = pack(
|
||||||
@ -2665,7 +2656,6 @@ class SSH2
|
|||||||
* @param string $expect
|
* @param string $expect
|
||||||
* @param int $mode
|
* @param int $mode
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \RuntimeException on connection error
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function read($expect = '', $mode = self::READ_SIMPLE)
|
function read($expect = '', $mode = self::READ_SIMPLE)
|
||||||
@ -2674,11 +2664,13 @@ class SSH2
|
|||||||
$this->is_timeout = false;
|
$this->is_timeout = false;
|
||||||
|
|
||||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
user_error('Operation disallowed prior to login()');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
user_error('Unable to initiate an interactive shell session');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$channel = $this->_get_interactive_channel();
|
$channel = $this->_get_interactive_channel();
|
||||||
@ -2709,17 +2701,18 @@ class SSH2
|
|||||||
* @see self::read()
|
* @see self::read()
|
||||||
* @param string $cmd
|
* @param string $cmd
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws \RuntimeException on connection error
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function write($cmd)
|
function write($cmd)
|
||||||
{
|
{
|
||||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
user_error('Operation disallowed prior to login()');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
user_error('Unable to initiate an interactive shell session');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_send_channel_packet($this->_get_interactive_channel(), $cmd);
|
return $this->_send_channel_packet($this->_get_interactive_channel(), $cmd);
|
||||||
@ -2843,7 +2836,6 @@ class SSH2
|
|||||||
if (isset($this->realtime_log_file) && is_resource($this->realtime_log_file)) {
|
if (isset($this->realtime_log_file) && is_resource($this->realtime_log_file)) {
|
||||||
fclose($this->realtime_log_file);
|
fclose($this->realtime_log_file);
|
||||||
}
|
}
|
||||||
unset(self::$connections[$this->getResourceId()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2888,14 +2880,14 @@ class SSH2
|
|||||||
*
|
*
|
||||||
* @see self::_send_binary_packet()
|
* @see self::_send_binary_packet()
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \RuntimeException on connection errors
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _get_binary_packet()
|
function _get_binary_packet()
|
||||||
{
|
{
|
||||||
if (!is_resource($this->fsock) || feof($this->fsock)) {
|
if (!is_resource($this->fsock) || feof($this->fsock)) {
|
||||||
|
user_error('Connection closed prematurely');
|
||||||
$this->bitmap = 0;
|
$this->bitmap = 0;
|
||||||
throw new \RuntimeException('Connection closed prematurely');
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$start = microtime(true);
|
$start = microtime(true);
|
||||||
@ -2909,7 +2901,8 @@ class SSH2
|
|||||||
$raw = $this->decrypt->decrypt($raw);
|
$raw = $this->decrypt->decrypt($raw);
|
||||||
}
|
}
|
||||||
if ($raw === false) {
|
if ($raw === false) {
|
||||||
throw new \RuntimeException('Unable to decrypt content');
|
user_error('Unable to decrypt content');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5)));
|
extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5)));
|
||||||
@ -2920,15 +2913,17 @@ class SSH2
|
|||||||
// "implementations SHOULD check that the packet length is reasonable"
|
// "implementations SHOULD check that the packet length is reasonable"
|
||||||
// PuTTY uses 0x9000 as the actual max packet size and so to shall we
|
// PuTTY uses 0x9000 as the actual max packet size and so to shall we
|
||||||
if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
|
if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
|
||||||
throw new \RuntimeException('Invalid size');
|
user_error('Invalid size');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$buffer = '';
|
$buffer = '';
|
||||||
while ($remaining_length > 0) {
|
while ($remaining_length > 0) {
|
||||||
$temp = fread($this->fsock, $remaining_length);
|
$temp = fread($this->fsock, $remaining_length);
|
||||||
if ($temp === false || feof($this->fsock)) {
|
if ($temp === false || feof($this->fsock)) {
|
||||||
|
user_error('Error reading from socket');
|
||||||
$this->bitmap = 0;
|
$this->bitmap = 0;
|
||||||
throw new \RuntimeException('Error reading from socket');
|
return false;
|
||||||
}
|
}
|
||||||
$buffer.= $temp;
|
$buffer.= $temp;
|
||||||
$remaining_length-= strlen($temp);
|
$remaining_length-= strlen($temp);
|
||||||
@ -2944,10 +2939,12 @@ class SSH2
|
|||||||
if ($this->hmac_check !== false) {
|
if ($this->hmac_check !== false) {
|
||||||
$hmac = fread($this->fsock, $this->hmac_size);
|
$hmac = fread($this->fsock, $this->hmac_size);
|
||||||
if ($hmac === false || strlen($hmac) != $this->hmac_size) {
|
if ($hmac === false || strlen($hmac) != $this->hmac_size) {
|
||||||
|
user_error('Error reading socket');
|
||||||
$this->bitmap = 0;
|
$this->bitmap = 0;
|
||||||
throw new \RuntimeException('Error reading socket');
|
return false;
|
||||||
} elseif ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) {
|
} elseif ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) {
|
||||||
throw new \RuntimeException('Invalid HMAC');
|
user_error('Invalid HMAC');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3173,7 +3170,6 @@ class SSH2
|
|||||||
*
|
*
|
||||||
* @param $client_channel
|
* @param $client_channel
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws \RuntimeException on connection error
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _get_channel_packet($client_channel, $skip_extended = false)
|
function _get_channel_packet($client_channel, $skip_extended = false)
|
||||||
@ -3206,7 +3202,8 @@ class SSH2
|
|||||||
|
|
||||||
$response = $this->_get_binary_packet();
|
$response = $this->_get_binary_packet();
|
||||||
if ($response === false) {
|
if ($response === false) {
|
||||||
throw new \RuntimeException('Connection closed by server');
|
user_error('Connection closed by server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if ($client_channel == -1 && $response === true) {
|
if ($client_channel == -1 && $response === true) {
|
||||||
return true;
|
return true;
|
||||||
@ -3255,8 +3252,8 @@ class SSH2
|
|||||||
return $result;
|
return $result;
|
||||||
//case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
|
//case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
|
||||||
default:
|
default:
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
user_error('Unable to open channel');
|
||||||
throw new \RuntimeException('Unable to open channel');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
||||||
@ -3266,8 +3263,8 @@ class SSH2
|
|||||||
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
user_error('Unable to fulfill channel request');
|
||||||
throw new \RuntimeException('Unable to fulfill channel request');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||||
}
|
}
|
||||||
case NET_SSH2_MSG_CHANNEL_CLOSE:
|
case NET_SSH2_MSG_CHANNEL_CLOSE:
|
||||||
return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended);
|
return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended);
|
||||||
@ -3376,8 +3373,8 @@ class SSH2
|
|||||||
case NET_SSH2_MSG_CHANNEL_EOF:
|
case NET_SSH2_MSG_CHANNEL_EOF:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
user_error('Error reading channel data');
|
||||||
throw new \RuntimeException('Error reading channel data');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3396,8 +3393,9 @@ class SSH2
|
|||||||
function _send_binary_packet($data, $logged = null)
|
function _send_binary_packet($data, $logged = null)
|
||||||
{
|
{
|
||||||
if (!is_resource($this->fsock) || feof($this->fsock)) {
|
if (!is_resource($this->fsock) || feof($this->fsock)) {
|
||||||
|
user_error('Connection closed prematurely');
|
||||||
$this->bitmap = 0;
|
$this->bitmap = 0;
|
||||||
throw new \RuntimeException('Connection closed prematurely');
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if ($this->compress) {
|
//if ($this->compress) {
|
||||||
@ -3488,14 +3486,14 @@ class SSH2
|
|||||||
@flush();
|
@flush();
|
||||||
@ob_flush();
|
@ob_flush();
|
||||||
break;
|
break;
|
||||||
// basically the same thing as self::LOG_REALTIME with the caveat that NET_SFTP_LOG_REALTIME_FILENAME
|
// basically the same thing as self::LOG_REALTIME with the caveat that self::LOG_REALTIME_FILE
|
||||||
// needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE.
|
// needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE.
|
||||||
// the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily
|
// the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily
|
||||||
// at the beginning of the file
|
// at the beginning of the file
|
||||||
case self::LOG_REALTIME_FILE:
|
case self::LOG_REALTIME_FILE:
|
||||||
if (!isset($this->realtime_log_file)) {
|
if (!isset($this->realtime_log_file)) {
|
||||||
// PHP doesn't seem to like using constants in fopen()
|
// PHP doesn't seem to like using constants in fopen()
|
||||||
$filename = NET_SSH2_LOG_REALTIME_FILENAME;
|
$filename = self::LOG_REALTIME_FILENAME;
|
||||||
$fp = fopen($filename, 'w');
|
$fp = fopen($filename, 'w');
|
||||||
$this->realtime_log_file = $fp;
|
$this->realtime_log_file = $fp;
|
||||||
}
|
}
|
||||||
@ -3960,8 +3958,6 @@ class SSH2
|
|||||||
* is recommended. Returns false if the server signature is not signed correctly with the public host key.
|
* is recommended. Returns false if the server signature is not signed correctly with the public host key.
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws \RuntimeException on badly formatted keys
|
|
||||||
* @throws \phpseclib\Exception\NoSupportedAlgorithmsException when the key isn't in a supported format
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function getServerPublicHostKey()
|
function getServerPublicHostKey()
|
||||||
@ -4007,8 +4003,8 @@ class SSH2
|
|||||||
padding, unsigned, and in network byte order). */
|
padding, unsigned, and in network byte order). */
|
||||||
$temp = unpack('Nlength', $this->_string_shift($signature, 4));
|
$temp = unpack('Nlength', $this->_string_shift($signature, 4));
|
||||||
if ($temp['length'] != 40) {
|
if ($temp['length'] != 40) {
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('Invalid signature');
|
||||||
throw new \RuntimeException('Invalid signature');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
$r = new BigInteger($this->_string_shift($signature, 20), 256);
|
$r = new BigInteger($this->_string_shift($signature, 20), 256);
|
||||||
@ -4019,8 +4015,8 @@ class SSH2
|
|||||||
case $r->compare($q) >= 0:
|
case $r->compare($q) >= 0:
|
||||||
case $s->equals($zero):
|
case $s->equals($zero):
|
||||||
case $s->compare($q) >= 0:
|
case $s->compare($q) >= 0:
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('Invalid signature');
|
||||||
throw new \RuntimeException('Invalid signature');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
$w = $s->modInverse($q);
|
$w = $s->modInverse($q);
|
||||||
@ -4039,7 +4035,7 @@ class SSH2
|
|||||||
list(, $v) = $v->divide($q);
|
list(, $v) = $v->divide($q);
|
||||||
|
|
||||||
if (!$v->equals($r)) {
|
if (!$v->equals($r)) {
|
||||||
//user_error('Bad server signature');
|
user_error('Bad server signature');
|
||||||
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4058,10 +4054,10 @@ class SSH2
|
|||||||
$signature = $this->_string_shift($signature, $temp['length']);
|
$signature = $this->_string_shift($signature, $temp['length']);
|
||||||
|
|
||||||
$rsa = new RSA();
|
$rsa = new RSA();
|
||||||
$rsa->load(array('e' => $e, 'n' => $n), 'raw');
|
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
|
||||||
$rsa->setHash('sha1');
|
$rsa->loadKey(array('e' => $e, 'n' => $n), RSA::PUBLIC_FORMAT_RAW);
|
||||||
if (!$rsa->verify($this->exchange_hash, $signature, RSA::PADDING_PKCS1)) {
|
if (!$rsa->verify($this->exchange_hash, $signature)) {
|
||||||
//user_error('Bad server signature');
|
user_error('Bad server signature');
|
||||||
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@ -4076,8 +4072,8 @@ class SSH2
|
|||||||
// also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source.
|
// also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source.
|
||||||
|
|
||||||
if ($s->compare(new BigInteger()) < 0 || $s->compare($n->subtract(new BigInteger(1))) > 0) {
|
if ($s->compare(new BigInteger()) < 0 || $s->compare($n->subtract(new BigInteger(1))) > 0) {
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
user_error('Invalid signature');
|
||||||
throw new \RuntimeException('Invalid signature');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
$s = $s->modPow($e, $n);
|
$s = $s->modPow($e, $n);
|
||||||
@ -4087,13 +4083,13 @@ class SSH2
|
|||||||
$h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 2 - strlen($h)) . $h;
|
$h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 2 - strlen($h)) . $h;
|
||||||
|
|
||||||
if ($s != $h) {
|
if ($s != $h) {
|
||||||
//user_error('Bad server signature');
|
user_error('Bad server signature');
|
||||||
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
user_error('Unsupported signature format');
|
||||||
throw new NoSupportedAlgorithmsException('Unsupported signature format');
|
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->signature_format . ' ' . base64_encode($this->server_public_host_key);
|
return $this->signature_format . ' ' . base64_encode($this->server_public_host_key);
|
||||||
@ -4169,47 +4165,4 @@ class SSH2
|
|||||||
$this->windowColumns = $columns;
|
$this->windowColumns = $columns;
|
||||||
$this->windowRows = $rows;
|
$this->windowRows = $rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function __toString()
|
|
||||||
{
|
|
||||||
return $this->getResourceId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We use {} because that symbols should not be in URL according to
|
|
||||||
* {@link http://tools.ietf.org/html/rfc3986#section-2 RFC}.
|
|
||||||
* It will safe us from any conflicts, because otherwise regexp will
|
|
||||||
* match all alphanumeric domains.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function getResourceId()
|
|
||||||
{
|
|
||||||
return '{' . spl_object_hash($this) . '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return existing connection
|
|
||||||
*
|
|
||||||
* @param string $id
|
|
||||||
*
|
|
||||||
* @return bool|SSH2 will return false if no such connection
|
|
||||||
*/
|
|
||||||
static function getConnectionByResourceId($id)
|
|
||||||
{
|
|
||||||
return isset(self::$connections[$id]) ? self::$connections[$id] : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return all excising connections
|
|
||||||
*
|
|
||||||
* @return SSH2[]
|
|
||||||
*/
|
|
||||||
static function getConnections()
|
|
||||||
{
|
|
||||||
return self::$connections;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
namespace phpseclib\System\SSH;
|
namespace phpseclib\System\SSH;
|
||||||
|
|
||||||
use phpseclib\Crypt\RSA;
|
use phpseclib\Crypt\RSA;
|
||||||
use phpseclib\Exception\BadConfigurationException;
|
|
||||||
use phpseclib\System\SSH\Agent\Identity;
|
use phpseclib\System\SSH\Agent\Identity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,8 +115,6 @@ class Agent
|
|||||||
* Default Constructor
|
* Default Constructor
|
||||||
*
|
*
|
||||||
* @return \phpseclib\System\SSH\Agent
|
* @return \phpseclib\System\SSH\Agent
|
||||||
* @throws \phpseclib\Exception\BadConfigurationException if SSH_AUTH_SOCK cannot be found
|
|
||||||
* @throws \RuntimeException on connection errors
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function __construct()
|
function __construct()
|
||||||
@ -130,12 +127,13 @@ class Agent
|
|||||||
$address = $_ENV['SSH_AUTH_SOCK'];
|
$address = $_ENV['SSH_AUTH_SOCK'];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new BadConfigurationException('SSH_AUTH_SOCK not found');
|
user_error('SSH_AUTH_SOCK not found');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
|
$this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
|
||||||
if (!$this->fsock) {
|
if (!$this->fsock) {
|
||||||
throw new \RuntimeException("Unable to connect to ssh-agent (Error $errno: $errstr)");
|
user_error("Unable to connect to ssh-agent (Error $errno: $errstr)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +144,6 @@ class Agent
|
|||||||
* Returns an array containing zero or more \phpseclib\System\SSH\Agent\Identity objects
|
* Returns an array containing zero or more \phpseclib\System\SSH\Agent\Identity objects
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
* @throws \RuntimeException on receipt of unexpected packets
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function requestIdentities()
|
function requestIdentities()
|
||||||
@ -157,13 +154,13 @@ class Agent
|
|||||||
|
|
||||||
$packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES);
|
$packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES);
|
||||||
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
||||||
throw new \RuntimeException('Connection closed while requesting identities');
|
user_error('Connection closed while requesting identities');
|
||||||
}
|
}
|
||||||
|
|
||||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||||
$type = ord(fread($this->fsock, 1));
|
$type = ord(fread($this->fsock, 1));
|
||||||
if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) {
|
if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) {
|
||||||
throw new \RuntimeException('Unable to request identities');
|
user_error('Unable to request identities');
|
||||||
}
|
}
|
||||||
|
|
||||||
$identities = array();
|
$identities = array();
|
||||||
@ -181,7 +178,7 @@ class Agent
|
|||||||
switch ($key_type) {
|
switch ($key_type) {
|
||||||
case 'ssh-rsa':
|
case 'ssh-rsa':
|
||||||
$key = new RSA();
|
$key = new RSA();
|
||||||
$key->load($key_str);
|
$key->loadKey($key_str);
|
||||||
break;
|
break;
|
||||||
case 'ssh-dss':
|
case 'ssh-dss':
|
||||||
// not currently supported
|
// not currently supported
|
||||||
@ -277,7 +274,6 @@ class Agent
|
|||||||
*
|
*
|
||||||
* @param string $data
|
* @param string $data
|
||||||
* @return data from SSH Agent
|
* @return data from SSH Agent
|
||||||
* @throws \RuntimeException on connection errors
|
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
function _forward_data($data)
|
function _forward_data($data)
|
||||||
@ -296,7 +292,7 @@ class Agent
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
|
if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
|
||||||
throw new \RuntimeException('Connection closed attempting to forward data to SSH agent');
|
user_error('Connection closed attempting to forward data to SSH agent');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->socket_buffer = '';
|
$this->socket_buffer = '';
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
|
|
||||||
namespace phpseclib\System\SSH\Agent;
|
namespace phpseclib\System\SSH\Agent;
|
||||||
|
|
||||||
use phpseclib\Crypt\RSA;
|
|
||||||
use phpseclib\Exception\UnsupportedAlgorithmException;
|
|
||||||
use phpseclib\System\SSH\Agent;
|
use phpseclib\System\SSH\Agent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,8 +23,9 @@ use phpseclib\System\SSH\Agent;
|
|||||||
* Instantiation should only be performed by \phpseclib\System\SSH\Agent class.
|
* Instantiation should only be performed by \phpseclib\System\SSH\Agent class.
|
||||||
* This could be thought of as implementing an interface that phpseclib\Crypt\RSA
|
* This could be thought of as implementing an interface that phpseclib\Crypt\RSA
|
||||||
* implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
|
* implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
|
||||||
* The methods in this interface would be getPublicKey and sign since those are the
|
* The methods in this interface would be getPublicKey, setSignatureMode
|
||||||
* methods phpseclib looks for to perform public key authentication.
|
* and sign since those are the methods phpseclib looks for to perform
|
||||||
|
* public key authentication.
|
||||||
*
|
*
|
||||||
* @package SSH\Agent
|
* @package SSH\Agent
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
@ -106,29 +105,26 @@ class Identity
|
|||||||
*
|
*
|
||||||
* Wrapper for $this->key->getPublicKey()
|
* Wrapper for $this->key->getPublicKey()
|
||||||
*
|
*
|
||||||
* @param int $type optional
|
* @param int $format optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function getPublicKey($type = 'PKCS8')
|
function getPublicKey($format = null)
|
||||||
{
|
{
|
||||||
return $this->key->getPublicKey($type);
|
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the hash
|
* Set Signature Mode
|
||||||
*
|
*
|
||||||
* ssh-agent only supports signatures with sha1 hashes but to maintain BC with RSA.php this function exists
|
* Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie.
|
||||||
|
* ssh-agent's only supported mode is \phpseclib\Crypt\RSA::SIGNATURE_PKCS1
|
||||||
*
|
*
|
||||||
* @param string $hash optional
|
* @param int $mode
|
||||||
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function setHash($hash = 'sha1')
|
function setSignatureMode($mode)
|
||||||
{
|
{
|
||||||
if ($hash != 'sha1') {
|
|
||||||
throw new UnsupportedAlgorithmException('ssh-agent can only be used with the sha1 hash');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,29 +133,22 @@ class Identity
|
|||||||
* See "2.6.2 Protocol 2 private key signature request"
|
* See "2.6.2 Protocol 2 private key signature request"
|
||||||
*
|
*
|
||||||
* @param string $message
|
* @param string $message
|
||||||
* @param int $padding optional
|
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \RuntimeException on connection errors
|
|
||||||
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
|
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function sign($message, $padding = RSA::PADDING_PKCS1)
|
function sign($message)
|
||||||
{
|
{
|
||||||
if ($padding != RSA::PADDING_PKCS1 && $padding != RSA::PADDING_RELAXED_PKCS1) {
|
|
||||||
throw new UnsupportedAlgorithmException('ssh-agent can only create PKCS1 signatures');
|
|
||||||
}
|
|
||||||
|
|
||||||
// the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
|
// the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
|
||||||
$packet = pack('CNa*Na*N', Agent::SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0);
|
$packet = pack('CNa*Na*N', Agent::SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0);
|
||||||
$packet = pack('Na*', strlen($packet), $packet);
|
$packet = pack('Na*', strlen($packet), $packet);
|
||||||
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
||||||
throw new \RuntimeException('Connection closed during signing');
|
user_error('Connection closed during signing');
|
||||||
}
|
}
|
||||||
|
|
||||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||||
$type = ord(fread($this->fsock, 1));
|
$type = ord(fread($this->fsock, 1));
|
||||||
if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) {
|
if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) {
|
||||||
throw new \RuntimeException('Unable to retreive signature');
|
user_error('Unable to retreive signature');
|
||||||
}
|
}
|
||||||
|
|
||||||
$signature_blob = fread($this->fsock, $length - 1);
|
$signature_blob = fread($this->fsock, $length - 1);
|
||||||
|
@ -1,18 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bootstrapping File for phpseclib
|
* Bootstrapping File for phpseclib
|
||||||
*
|
*
|
||||||
* composer isn't a requirement for phpseclib 2.0 but this file isn't really required
|
|
||||||
* either. it's a bonus for those using composer but if you're not phpseclib will
|
|
||||||
* still work
|
|
||||||
*
|
|
||||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (extension_loaded('mbstring')) {
|
if (extension_loaded('mbstring')) {
|
||||||
// 2 - MB_OVERLOAD_STRING
|
// 2 - MB_OVERLOAD_STRING
|
||||||
if (ini_get('mbstring.func_overload') & 2) {
|
if (ini_get('mbstring.func_overload') & 2) {
|
||||||
throw new UnexpectedValueException(
|
throw new \UnexpectedValueException(
|
||||||
'Overloading of string functions using mbstring.func_overload ' .
|
'Overloading of string functions using mbstring.func_overload ' .
|
||||||
'is not supported by phpseclib.'
|
'is not supported by phpseclib.'
|
||||||
);
|
);
|
||||||
|
@ -42,19 +42,6 @@ class Functional_Net_SFTPStreamTest extends Functional_Net_SFTPTestCase
|
|||||||
$this->assertTrue(in_array('te#st.txt', $this->sftp->nlist()));
|
$this->assertTrue(in_array('te#st.txt', $this->sftp->nlist()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests connection reuse functionality same as ssh2 extension:
|
|
||||||
* {@link http://php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-examples}
|
|
||||||
*/
|
|
||||||
public function testConnectionReuse()
|
|
||||||
{
|
|
||||||
$originalConnectionsCount = count(\phpseclib\Net\SSH2::getConnections());
|
|
||||||
$session = $this->sftp;
|
|
||||||
$dirs = scandir("sftp://$session/");
|
|
||||||
$this->assertCount($originalConnectionsCount, \phpseclib\Net\SSH2::getConnections());
|
|
||||||
$this->assertEquals(array('.', '..'), array_slice($dirs, 0, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function buildUrl($suffix)
|
protected function buildUrl($suffix)
|
||||||
{
|
{
|
||||||
return sprintf(
|
return sprintf(
|
||||||
|
@ -13,9 +13,6 @@ use phpseclib\Net\SFTP;
|
|||||||
*/
|
*/
|
||||||
abstract class Functional_Net_SFTPTestCase extends PhpseclibFunctionalTestCase
|
abstract class Functional_Net_SFTPTestCase extends PhpseclibFunctionalTestCase
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var SFTP
|
|
||||||
*/
|
|
||||||
protected $sftp;
|
protected $sftp;
|
||||||
protected $scratchDir;
|
protected $scratchDir;
|
||||||
|
|
||||||
|
@ -28,7 +28,9 @@ abstract class PhpseclibFunctionalTestCase extends PhpseclibTestCase
|
|||||||
'Should have gmp or bcmath extension for functional test.'
|
'Should have gmp or bcmath extension for functional test.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
self::ensureConstant('CRYPT_HASH_MODE', Hash::MODE_HASH);
|
||||||
self::reRequireFile('Math/BigInteger.php');
|
self::reRequireFile('Math/BigInteger.php');
|
||||||
|
self::reRequireFile('Crypt/Hash.php');
|
||||||
}
|
}
|
||||||
parent::setUpBeforeClass();
|
parent::setUpBeforeClass();
|
||||||
}
|
}
|
||||||
|
@ -47,13 +47,13 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
|
|||||||
':-):-):-):-):-):-)', // https://github.com/phpseclib/phpseclib/pull/43
|
':-):-):-):-):-):-)', // https://github.com/phpseclib/phpseclib/pull/43
|
||||||
);
|
);
|
||||||
$ivs = array(
|
$ivs = array(
|
||||||
str_repeat("\0", 16),
|
'',
|
||||||
str_pad('test123', 16, "\0"),
|
'test123',
|
||||||
);
|
);
|
||||||
$keys = array(
|
$keys = array(
|
||||||
str_repeat("\0", 16),
|
'',
|
||||||
str_pad(':-8', 16, "\0"), // https://github.com/phpseclib/phpseclib/pull/43
|
':-8', // https://github.com/phpseclib/phpseclib/pull/43
|
||||||
str_pad('FOOBARZ', 16, "\0"),
|
'FOOBARZ',
|
||||||
);
|
);
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
@ -100,11 +100,10 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
|
|||||||
// this test case is from the following URL:
|
// this test case is from the following URL:
|
||||||
// https://web.archive.org/web/20070209120224/http://fp.gladman.plus.com/cryptography_technology/rijndael/aesdvec.zip
|
// https://web.archive.org/web/20070209120224/http://fp.gladman.plus.com/cryptography_technology/rijndael/aesdvec.zip
|
||||||
|
|
||||||
$aes = new Rijndael(Base::MODE_CBC);
|
$aes = new Rijndael();
|
||||||
$aes->setPreferredEngine($this->engine);
|
$aes->setPreferredEngine($this->engine);
|
||||||
$aes->disablePadding();
|
$aes->disablePadding();
|
||||||
$aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. Valid in Rijndael.
|
$aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. Valid in Rijndael.
|
||||||
$aes->setIV(str_repeat("\0", 16));
|
|
||||||
//$this->_checkEngine($aes); // should only work in internal mode
|
//$this->_checkEngine($aes); // should only work in internal mode
|
||||||
$ciphertext = $aes->encrypt(pack('H*', '3243f6a8885a308d313198a2e0370734'));
|
$ciphertext = $aes->encrypt(pack('H*', '3243f6a8885a308d313198a2e0370734'));
|
||||||
$this->assertEquals($ciphertext, pack('H*', '231d844639b31b412211cfe93712b880'));
|
$this->assertEquals($ciphertext, pack('H*', '231d844639b31b412211cfe93712b880'));
|
||||||
@ -112,17 +111,15 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @group github451
|
* @group github451
|
||||||
* @expectedException \LengthException
|
|
||||||
*/
|
*/
|
||||||
public function testKeyPaddingAES()
|
public function testKeyPaddingAES()
|
||||||
{
|
{
|
||||||
// same as the above - just with a different ciphertext
|
// same as the above - just with a different ciphertext
|
||||||
|
|
||||||
$aes = new AES(Base::MODE_CBC);
|
$aes = new AES();
|
||||||
$aes->setPreferredEngine($this->engine);
|
$aes->setPreferredEngine($this->engine);
|
||||||
$aes->disablePadding();
|
$aes->disablePadding();
|
||||||
$aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. supported by Rijndael - not AES
|
$aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. AES should null pad to 192-bits
|
||||||
$aes->setIV(str_repeat("\0", 16));
|
|
||||||
$this->_checkEngine($aes);
|
$this->_checkEngine($aes);
|
||||||
$ciphertext = $aes->encrypt(pack('H*', '3243f6a8885a308d313198a2e0370734'));
|
$ciphertext = $aes->encrypt(pack('H*', '3243f6a8885a308d313198a2e0370734'));
|
||||||
$this->assertEquals($ciphertext, pack('H*', 'c109292b173f841b88e0ee49f13db8c0'));
|
$this->assertEquals($ciphertext, pack('H*', 'c109292b173f841b88e0ee49f13db8c0'));
|
||||||
@ -267,7 +264,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
|
|||||||
// from http://csrc.nist.gov/groups/STM/cavp/documents/aes/AESAVS.pdf#page=16
|
// from http://csrc.nist.gov/groups/STM/cavp/documents/aes/AESAVS.pdf#page=16
|
||||||
public function testGFSBox128()
|
public function testGFSBox128()
|
||||||
{
|
{
|
||||||
$aes = new AES(Base::MODE_CBC);
|
$aes = new AES();
|
||||||
|
|
||||||
$aes->setKey(pack('H*', '00000000000000000000000000000000'));
|
$aes->setKey(pack('H*', '00000000000000000000000000000000'));
|
||||||
$aes->setIV(pack('H*', '00000000000000000000000000000000'));
|
$aes->setIV(pack('H*', '00000000000000000000000000000000'));
|
||||||
@ -294,7 +291,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
|
|||||||
|
|
||||||
public function testGFSBox192()
|
public function testGFSBox192()
|
||||||
{
|
{
|
||||||
$aes = new AES(Base::MODE_CBC);
|
$aes = new AES();
|
||||||
|
|
||||||
$aes->setKey(pack('H*', '000000000000000000000000000000000000000000000000'));
|
$aes->setKey(pack('H*', '000000000000000000000000000000000000000000000000'));
|
||||||
$aes->setIV(pack('H*', '00000000000000000000000000000000'));
|
$aes->setIV(pack('H*', '00000000000000000000000000000000'));
|
||||||
@ -319,7 +316,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
|
|||||||
|
|
||||||
public function testGFSBox256()
|
public function testGFSBox256()
|
||||||
{
|
{
|
||||||
$aes = new AES(Base::MODE_CBC);
|
$aes = new AES();
|
||||||
|
|
||||||
$aes->setKey(pack('H*', '00000000000000000000000000000000' . '00000000000000000000000000000000'));
|
$aes->setKey(pack('H*', '00000000000000000000000000000000' . '00000000000000000000000000000000'));
|
||||||
$aes->setIV(pack('H*', '00000000000000000000000000000000'));
|
$aes->setIV(pack('H*', '00000000000000000000000000000000'));
|
||||||
@ -342,41 +339,33 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
|
|||||||
|
|
||||||
public function testGetKeyLengthDefault()
|
public function testGetKeyLengthDefault()
|
||||||
{
|
{
|
||||||
$aes = new AES(Base::MODE_CBC);
|
$aes = new AES();
|
||||||
$this->assertSame($aes->getKeyLength(), 128);
|
$this->assertSame($aes->getKeyLength(), 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetKeyLengthWith192BitKey()
|
public function testGetKeyLengthWith192BitKey()
|
||||||
{
|
{
|
||||||
$aes = new AES(Base::MODE_CBC);
|
$aes = new AES();
|
||||||
$aes->setKey(str_repeat('a', 24));
|
$aes->setKey(str_repeat('a', 24));
|
||||||
$this->assertSame($aes->getKeyLength(), 192);
|
$this->assertSame($aes->getKeyLength(), 192);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \LengthException
|
|
||||||
*/
|
|
||||||
public function testSetKeyLengthWithLargerKey()
|
public function testSetKeyLengthWithLargerKey()
|
||||||
{
|
{
|
||||||
$aes = new AES(Base::MODE_CBC);
|
$aes = new AES();
|
||||||
$aes->setKeyLength(128);
|
$aes->setKeyLength(128);
|
||||||
$aes->setKey(str_repeat('a', 24));
|
$aes->setKey(str_repeat('a', 24));
|
||||||
$aes->setIV(str_repeat("\0", 16));
|
|
||||||
$this->assertSame($aes->getKeyLength(), 128);
|
$this->assertSame($aes->getKeyLength(), 128);
|
||||||
$ciphertext = bin2hex($aes->encrypt('a'));
|
$ciphertext = bin2hex($aes->encrypt('a'));
|
||||||
$this->assertSame($ciphertext, '82b7b068dfc60ed2a46893b69fecd6c2');
|
$this->assertSame($ciphertext, '82b7b068dfc60ed2a46893b69fecd6c2');
|
||||||
$this->assertSame($aes->getKeyLength(), 128);
|
$this->assertSame($aes->getKeyLength(), 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \LengthException
|
|
||||||
*/
|
|
||||||
public function testSetKeyLengthWithSmallerKey()
|
public function testSetKeyLengthWithSmallerKey()
|
||||||
{
|
{
|
||||||
$aes = new AES(Base::MODE_CBC);
|
$aes = new AES();
|
||||||
$aes->setKeyLength(256);
|
$aes->setKeyLength(256);
|
||||||
$aes->setKey(str_repeat('a', 16));
|
$aes->setKey(str_repeat('a', 16));
|
||||||
$aes->setIV(str_repeat("\0", 16));
|
|
||||||
$this->assertSame($aes->getKeyLength(), 256);
|
$this->assertSame($aes->getKeyLength(), 256);
|
||||||
$ciphertext = bin2hex($aes->encrypt('a'));
|
$ciphertext = bin2hex($aes->encrypt('a'));
|
||||||
$this->assertSame($ciphertext, 'fd4250c0d234aa7e1aa592820aa8406b');
|
$this->assertSame($ciphertext, 'fd4250c0d234aa7e1aa592820aa8406b');
|
||||||
@ -388,7 +377,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
|
|||||||
*/
|
*/
|
||||||
public function testContinuousBuffer()
|
public function testContinuousBuffer()
|
||||||
{
|
{
|
||||||
$aes = new AES(AES::MODE_CBC);
|
$aes = new AES();
|
||||||
$aes->disablePadding();
|
$aes->disablePadding();
|
||||||
$aes->enableContinuousBuffer();
|
$aes->enableContinuousBuffer();
|
||||||
$aes->setIV(pack('H*', '0457bdb4a6712986688349a29eb82535'));
|
$aes->setIV(pack('H*', '0457bdb4a6712986688349a29eb82535'));
|
||||||
|
@ -73,9 +73,8 @@ class Unit_Crypt_BlowfishTest extends PhpseclibTestCase
|
|||||||
*/
|
*/
|
||||||
public function testVectors($engine, $engineName, $key, $plaintext, $expected)
|
public function testVectors($engine, $engineName, $key, $plaintext, $expected)
|
||||||
{
|
{
|
||||||
$bf = new Blowfish(Blowfish::MODE_CBC);
|
$bf = new Blowfish();
|
||||||
$bf->setKey($key);
|
$bf->setKey($key);
|
||||||
$bf->setIV(str_repeat("\0", $bf->getBlockLength() >> 3));
|
|
||||||
if (!$bf->isValidEngine($engine)) {
|
if (!$bf->isValidEngine($engine)) {
|
||||||
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
|
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
|
||||||
}
|
}
|
||||||
|
78
tests/Unit/Crypt/DESTest.php
Normal file
78
tests/Unit/Crypt/DESTest.php
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Andreas Fischer <bantu@phpbb.com>
|
||||||
|
* @copyright MMXIII Andreas Fischer
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Base;
|
||||||
|
use phpseclib\Crypt\DES;
|
||||||
|
|
||||||
|
// the AES tests establish the correctness of the modes of operation. this test is inteded to establish the consistency of
|
||||||
|
// key and iv padding between the multiple engines
|
||||||
|
class Unit_Crypt_DESTest extends PhpseclibTestCase
|
||||||
|
{
|
||||||
|
public function testEncryptPadding()
|
||||||
|
{
|
||||||
|
$des = new DES(Base::MODE_CBC);
|
||||||
|
$des->setKey('d');
|
||||||
|
$des->setIV('d');
|
||||||
|
|
||||||
|
$des->setPreferredEngine(Base::ENGINE_INTERNAL);
|
||||||
|
|
||||||
|
$result = pack('H*', '3e7613642049af1e');
|
||||||
|
|
||||||
|
$internal = $des->encrypt('d');
|
||||||
|
$this->assertEquals($result, $internal, 'Failed asserting that the internal engine produced the correct result');
|
||||||
|
|
||||||
|
$des->setPreferredEngine(Base::ENGINE_MCRYPT);
|
||||||
|
if ($des->getEngine() == Base::ENGINE_MCRYPT) {
|
||||||
|
$mcrypt = $des->encrypt('d');
|
||||||
|
$this->assertEquals($result, $mcrypt, 'Failed asserting that the mcrypt engine produced the correct result');
|
||||||
|
} else {
|
||||||
|
self::markTestSkipped('Unable to initialize mcrypt engine');
|
||||||
|
}
|
||||||
|
|
||||||
|
$des->setPreferredEngine(Base::ENGINE_OPENSSL);
|
||||||
|
if ($des->getEngine() == Base::ENGINE_OPENSSL) {
|
||||||
|
$openssl = $des->encrypt('d');
|
||||||
|
$this->assertEquals($result, $openssl, 'Failed asserting that the OpenSSL engine produced the correct result');
|
||||||
|
} else {
|
||||||
|
self::markTestSkipped('Unable to initialize OpenSSL engine');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpseclib null pads ciphertext's if they're not long enough and you're in ecb / cbc mode. this silent failure mode is consistent
|
||||||
|
// with mcrypt's behavior. maybe throwing an exception would be better but whatever. this test is more intended to establish consistent
|
||||||
|
// behavior between the various engine's
|
||||||
|
public function testDecryptPadding()
|
||||||
|
{
|
||||||
|
$des = new DES(Base::MODE_CBC);
|
||||||
|
$des->disablePadding();
|
||||||
|
// when the key and iv are not specified they should be null padded
|
||||||
|
//$des->setKey();
|
||||||
|
//$des->setIV();
|
||||||
|
|
||||||
|
$des->setPreferredEngine(Base::ENGINE_INTERNAL);
|
||||||
|
$internal = $des->decrypt('d');
|
||||||
|
|
||||||
|
$result = pack('H*', '79b305d1ce555221');
|
||||||
|
$this->assertEquals($result, $internal, 'Failed asserting that the internal engine produced the correct result');
|
||||||
|
|
||||||
|
$des->setPreferredEngine(Base::ENGINE_MCRYPT);
|
||||||
|
if ($des->getEngine() == Base::ENGINE_MCRYPT) {
|
||||||
|
$mcrypt = $des->decrypt('d');
|
||||||
|
$this->assertEquals($result, $mcrypt, 'Failed asserting that the mcrypt engine produced the correct result');
|
||||||
|
} else {
|
||||||
|
self::markTestSkipped('Unable to initialize mcrypt engine');
|
||||||
|
}
|
||||||
|
|
||||||
|
$des->setPreferredEngine(Base::ENGINE_OPENSSL);
|
||||||
|
if ($des->getEngine() == Base::ENGINE_OPENSSL) {
|
||||||
|
$openssl = $des->decrypt('d');
|
||||||
|
$this->assertEquals($result, $openssl, 'Failed asserting that the OpenSSL engine produced the correct result');
|
||||||
|
} else {
|
||||||
|
self::markTestSkipped('Unable to initialize OpenSSL engine');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
tests/Unit/Crypt/Hash/MD5Test.php
Normal file
49
tests/Unit/Crypt/Hash/MD5Test.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Andreas Fischer <bantu@phpbb.com>
|
||||||
|
* @copyright 2012 Andreas Fischer
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Hash;
|
||||||
|
|
||||||
|
class Unit_Crypt_Hash_MD5Test extends Unit_Crypt_Hash_TestCase
|
||||||
|
{
|
||||||
|
public function getInstance()
|
||||||
|
{
|
||||||
|
return new Hash('md5');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider hashData()
|
||||||
|
*/
|
||||||
|
public function testHash($message, $result)
|
||||||
|
{
|
||||||
|
$this->assertHashesTo($this->getInstance(), $message, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function hashData()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('', 'd41d8cd98f00b204e9800998ecf8427e'),
|
||||||
|
array('The quick brown fox jumps over the lazy dog', '9e107d9d372bb6826bd81d3542a419d6'),
|
||||||
|
array('The quick brown fox jumps over the lazy dog.', 'e4d909c290d0fb1ca068ffaddf22cbd0'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider hmacData()
|
||||||
|
*/
|
||||||
|
public function testHMAC($key, $message, $result)
|
||||||
|
{
|
||||||
|
$this->assertHMACsTo($this->getInstance(), $key, $message, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function hmacData()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('', '', '74e6f7298a9c2d168935f58c001bad88'),
|
||||||
|
array('key', 'The quick brown fox jumps over the lazy dog', '80070713463e7749b90c2dc24911e275'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
81
tests/Unit/Crypt/Hash/SHA256Test.php
Normal file
81
tests/Unit/Crypt/Hash/SHA256Test.php
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Andreas Fischer <bantu@phpbb.com>
|
||||||
|
* @copyright 2014 Andreas Fischer
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Hash;
|
||||||
|
|
||||||
|
class Unit_Crypt_Hash_SHA256Test extends Unit_Crypt_Hash_TestCase
|
||||||
|
{
|
||||||
|
public function getInstance()
|
||||||
|
{
|
||||||
|
return new Hash('sha256');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider hashData()
|
||||||
|
*/
|
||||||
|
public function testHash($message, $result)
|
||||||
|
{
|
||||||
|
$this->assertHashesTo($this->getInstance(), $message, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function hashData()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(
|
||||||
|
'',
|
||||||
|
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'The quick brown fox jumps over the lazy dog',
|
||||||
|
'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'The quick brown fox jumps over the lazy dog.',
|
||||||
|
'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider hmacData()
|
||||||
|
*/
|
||||||
|
public function testHMAC($key, $message, $result)
|
||||||
|
{
|
||||||
|
$this->assertHMACsTo($this->getInstance(), $key, $message, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function hmacData()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
// RFC 4231
|
||||||
|
// Test Case 1
|
||||||
|
array(
|
||||||
|
pack('H*', '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'),
|
||||||
|
pack('H*', '4869205468657265'),
|
||||||
|
'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7',
|
||||||
|
),
|
||||||
|
// Test Case 2
|
||||||
|
array(
|
||||||
|
pack('H*', '4a656665'),
|
||||||
|
pack('H*', '7768617420646f2079612077616e7420666f72206e6f7468696e673f'),
|
||||||
|
'5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843',
|
||||||
|
),
|
||||||
|
// Test Case 3
|
||||||
|
array(
|
||||||
|
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
||||||
|
pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'),
|
||||||
|
'773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe',
|
||||||
|
),
|
||||||
|
// Test Case 4
|
||||||
|
array(
|
||||||
|
pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'),
|
||||||
|
pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'),
|
||||||
|
'82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
32
tests/Unit/Crypt/Hash/SHA256_96Test.php
Normal file
32
tests/Unit/Crypt/Hash/SHA256_96Test.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Andreas Fischer <bantu@phpbb.com>
|
||||||
|
* @copyright 2014 Andreas Fischer
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Hash;
|
||||||
|
|
||||||
|
class Unit_Crypt_Hash_SHA256_96Test extends Unit_Crypt_Hash_SHA256Test
|
||||||
|
{
|
||||||
|
public function getInstance()
|
||||||
|
{
|
||||||
|
return new Hash('sha256-96');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider hashData()
|
||||||
|
*/
|
||||||
|
public function testHash($message, $longResult)
|
||||||
|
{
|
||||||
|
parent::testHash($message, substr($longResult, 0, 24));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider hmacData()
|
||||||
|
*/
|
||||||
|
public function testHMAC($key, $message, $longResult)
|
||||||
|
{
|
||||||
|
parent::testHMAC($key, $message, substr($longResult, 0, 24));
|
||||||
|
}
|
||||||
|
}
|
81
tests/Unit/Crypt/Hash/SHA512Test.php
Normal file
81
tests/Unit/Crypt/Hash/SHA512Test.php
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Andreas Fischer <bantu@phpbb.com>
|
||||||
|
* @copyright 2014 Andreas Fischer
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Hash;
|
||||||
|
|
||||||
|
class Unit_Crypt_Hash_SHA512Test extends Unit_Crypt_Hash_TestCase
|
||||||
|
{
|
||||||
|
public function getInstance()
|
||||||
|
{
|
||||||
|
return new Hash('sha512');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider hashData()
|
||||||
|
*/
|
||||||
|
public function testHash($message, $result)
|
||||||
|
{
|
||||||
|
$this->assertHashesTo($this->getInstance(), $message, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function hashData()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(
|
||||||
|
'',
|
||||||
|
'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'The quick brown fox jumps over the lazy dog',
|
||||||
|
'07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'The quick brown fox jumps over the lazy dog.',
|
||||||
|
'91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider hmacData()
|
||||||
|
*/
|
||||||
|
public function testHMAC($key, $message, $result)
|
||||||
|
{
|
||||||
|
$this->assertHMACsTo($this->getInstance(), $key, $message, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function hmacData()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
// RFC 4231
|
||||||
|
// Test Case 1
|
||||||
|
array(
|
||||||
|
pack('H*', '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'),
|
||||||
|
pack('H*', '4869205468657265'),
|
||||||
|
'87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854',
|
||||||
|
),
|
||||||
|
// Test Case 2
|
||||||
|
array(
|
||||||
|
pack('H*', '4a656665'),
|
||||||
|
pack('H*', '7768617420646f2079612077616e7420666f72206e6f7468696e673f'),
|
||||||
|
'164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737',
|
||||||
|
),
|
||||||
|
// Test Case 3
|
||||||
|
array(
|
||||||
|
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
||||||
|
pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'),
|
||||||
|
'fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb',
|
||||||
|
),
|
||||||
|
// Test Case 4
|
||||||
|
array(
|
||||||
|
pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'),
|
||||||
|
pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'),
|
||||||
|
'b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
32
tests/Unit/Crypt/Hash/SHA512_96Test.php
Normal file
32
tests/Unit/Crypt/Hash/SHA512_96Test.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Andreas Fischer <bantu@phpbb.com>
|
||||||
|
* @copyright 2014 Andreas Fischer
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Hash;
|
||||||
|
|
||||||
|
class Unit_Crypt_Hash_SHA512_96Test extends Unit_Crypt_Hash_SHA512Test
|
||||||
|
{
|
||||||
|
public function getInstance()
|
||||||
|
{
|
||||||
|
return new Hash('sha512-96');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider hashData()
|
||||||
|
*/
|
||||||
|
public function testHash($message, $longResult)
|
||||||
|
{
|
||||||
|
parent::testHash($message, substr($longResult, 0, 24));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider hmacData()
|
||||||
|
*/
|
||||||
|
public function testHMAC($key, $message, $longResult)
|
||||||
|
{
|
||||||
|
parent::testHMAC($key, $message, substr($longResult, 0, 24));
|
||||||
|
}
|
||||||
|
}
|
52
tests/Unit/Crypt/Hash/TestCase.php
Normal file
52
tests/Unit/Crypt/Hash/TestCase.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Andreas Fischer <bantu@phpbb.com>
|
||||||
|
* @copyright 2012 Andreas Fischer
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Hash;
|
||||||
|
|
||||||
|
abstract class Unit_Crypt_Hash_TestCase extends PhpseclibTestCase
|
||||||
|
{
|
||||||
|
public static function setUpBeforeClass()
|
||||||
|
{
|
||||||
|
if (!defined('CRYPT_HASH_MODE')) {
|
||||||
|
define('CRYPT_HASH_MODE', Hash::MODE_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
if (defined('CRYPT_HASH_MODE') && CRYPT_HASH_MODE !== Hash::MODE_INTERNAL) {
|
||||||
|
$this->markTestSkipped(
|
||||||
|
'Skipping test because CRYPT_HASH_MODE is not defined as \phpseclib\Crypt\Hash::MODE_INTERNAL.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function assertHashesTo(Hash $hash, $message, $expected)
|
||||||
|
{
|
||||||
|
$this->assertEquals(
|
||||||
|
strtolower($expected),
|
||||||
|
bin2hex($hash->hash($message)),
|
||||||
|
sprintf("Failed asserting that '%s' hashes to '%s'.", $message, $expected)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function assertHMACsTo(Hash $hash, $key, $message, $expected)
|
||||||
|
{
|
||||||
|
$hash->setKey($key);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
strtolower($expected),
|
||||||
|
bin2hex($hash->hash($message)),
|
||||||
|
sprintf(
|
||||||
|
"Failed asserting that '%s' HMACs to '%s' with key '%s'.",
|
||||||
|
$message,
|
||||||
|
$expected,
|
||||||
|
$key
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,423 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @author Andreas Fischer <bantu@phpbb.com>
|
|
||||||
* @copyright 2012 Andreas Fischer
|
|
||||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
use phpseclib\Crypt\Hash;
|
|
||||||
|
|
||||||
class Unit_Crypt_HashTest extends PhpseclibTestCase
|
|
||||||
{
|
|
||||||
protected function assertHashesTo($hash, $message, $expected)
|
|
||||||
{
|
|
||||||
$hash = new Hash($hash);
|
|
||||||
|
|
||||||
$this->assertSame(
|
|
||||||
strtolower($expected),
|
|
||||||
bin2hex($hash->hash($message)),
|
|
||||||
sprintf("Failed asserting that '%s' hashes to '%s'.", $message, $expected)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function assertHMACsTo($hash, $key, $message, $expected)
|
|
||||||
{
|
|
||||||
$hash = new Hash($hash);
|
|
||||||
$hash->setKey($key);
|
|
||||||
|
|
||||||
$this->assertSame(
|
|
||||||
strtolower($expected),
|
|
||||||
bin2hex($hash->hash($message)),
|
|
||||||
sprintf(
|
|
||||||
"Failed asserting that '%s' HMACs to '%s' with key '%s'.",
|
|
||||||
$message,
|
|
||||||
$expected,
|
|
||||||
$key
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function hashData()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array('md5', '', 'd41d8cd98f00b204e9800998ecf8427e'),
|
|
||||||
array('md5', 'The quick brown fox jumps over the lazy dog', '9e107d9d372bb6826bd81d3542a419d6'),
|
|
||||||
array('md5', 'The quick brown fox jumps over the lazy dog.', 'e4d909c290d0fb1ca068ffaddf22cbd0'),
|
|
||||||
array('sha1', 'The quick brown fox jumps over the lazy dog', '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'),
|
|
||||||
array('sha1', 'The quick brown fox jumps over the lazy dog.', '408d94384216f890ff7a0c3528e8bed1e0b01621'),
|
|
||||||
array(
|
|
||||||
'sha256',
|
|
||||||
'',
|
|
||||||
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'sha256',
|
|
||||||
'The quick brown fox jumps over the lazy dog',
|
|
||||||
'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592',
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'sha256',
|
|
||||||
'The quick brown fox jumps over the lazy dog.',
|
|
||||||
'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c',
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'sha384',
|
|
||||||
'',
|
|
||||||
'38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'sha384',
|
|
||||||
'The quick brown fox jumps over the lazy dog',
|
|
||||||
'ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1',
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'sha512',
|
|
||||||
'',
|
|
||||||
'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'sha512',
|
|
||||||
'The quick brown fox jumps over the lazy dog',
|
|
||||||
'07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6',
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'sha512',
|
|
||||||
'The quick brown fox jumps over the lazy dog.',
|
|
||||||
'91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed',
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'whirlpool',
|
|
||||||
'The quick brown fox jumps over the lazy dog.',
|
|
||||||
'87a7ff096082e3ffeb86db10feb91c5af36c2c71bc426fe310ce662e0338223e217def0eab0b02b80eecf875657802bc5965e48f5c0a05467756f0d3f396faba'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'whirlpool',
|
|
||||||
'The quick brown fox jumps over the lazy dog.',
|
|
||||||
'87a7ff096082e3ffeb86db10feb91c5af36c2c71bc426fe310ce662e0338223e217def0eab0b02b80eecf875657802bc5965e48f5c0a05467756f0d3f396faba'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'whirlpool',
|
|
||||||
'The quick brown fox jumps over the lazy dog.',
|
|
||||||
'87a7ff096082e3ffeb86db10feb91c5af36c2c71bc426fe310ce662e0338223e217def0eab0b02b80eecf875657802bc5965e48f5c0a05467756f0d3f396faba'
|
|
||||||
),
|
|
||||||
// from http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA512_224.pdf
|
|
||||||
array(
|
|
||||||
'sha512/224',
|
|
||||||
'abc',
|
|
||||||
'4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'sha512/224',
|
|
||||||
'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu',
|
|
||||||
'23fec5bb94d60b23308192640b0c453335d664734fe40e7268674af9'
|
|
||||||
),
|
|
||||||
// from http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA512_256.pdf
|
|
||||||
array(
|
|
||||||
'sha512/256',
|
|
||||||
'abc',
|
|
||||||
'53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'sha512/256',
|
|
||||||
'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu',
|
|
||||||
'3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a'
|
|
||||||
),
|
|
||||||
// from http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA224.pdf
|
|
||||||
array(
|
|
||||||
'sha224',
|
|
||||||
'abc',
|
|
||||||
'23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'sha224',
|
|
||||||
'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
|
|
||||||
'75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B1952522525'
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider hmacData()
|
|
||||||
*/
|
|
||||||
public function testHMAC($hash, $key, $message, $result)
|
|
||||||
{
|
|
||||||
$this->assertHMACsTo($hash, $key, $message, $result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider hmacData()
|
|
||||||
*/
|
|
||||||
public function testHMAC96($hash, $key, $message, $result)
|
|
||||||
{
|
|
||||||
$this->assertHMACsTo($hash . '-96', $key, $message, substr($result, 0, 24));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function hmacData()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
array('md5', '', '', '74e6f7298a9c2d168935f58c001bad88'),
|
|
||||||
array('md5', 'key', 'The quick brown fox jumps over the lazy dog', '80070713463e7749b90c2dc24911e275'),
|
|
||||||
|
|
||||||
array(
|
|
||||||
'whirlpool',
|
|
||||||
'abcd',
|
|
||||||
'The quick brown fox jumps over the lazy dog',
|
|
||||||
'e71aabb2588d789292fa6fef00b35cc269ec3ea912b1c1cd7127daf95f004a5df5392ee563d322bac7e19d9eab161932fe9c257d63e0d09eca0d91ab4010125e',
|
|
||||||
),
|
|
||||||
|
|
||||||
// from https://tools.ietf.org/rfc/rfc4231.txt
|
|
||||||
// test case 1
|
|
||||||
array(
|
|
||||||
'sha224',
|
|
||||||
str_repeat("\x0b", 20),
|
|
||||||
'Hi There',
|
|
||||||
'896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22',
|
|
||||||
),
|
|
||||||
// test case 2
|
|
||||||
array(
|
|
||||||
'sha224',
|
|
||||||
'Jefe',
|
|
||||||
'what do ya want for nothing?',
|
|
||||||
'a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44',
|
|
||||||
),
|
|
||||||
// test case 3
|
|
||||||
array(
|
|
||||||
'sha224',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'),
|
|
||||||
'7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea',
|
|
||||||
),
|
|
||||||
// test case 4
|
|
||||||
array(
|
|
||||||
'sha224',
|
|
||||||
pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'),
|
|
||||||
pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'),
|
|
||||||
'6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a',
|
|
||||||
),
|
|
||||||
// skip test case 5; truncation is only supported to 96 bits (eg. sha1-96) and that's already unit tested
|
|
||||||
// test case 6
|
|
||||||
array(
|
|
||||||
'sha224',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
'Test Using Larger Than Block-Size Key - Hash Key First',
|
|
||||||
'95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e',
|
|
||||||
),
|
|
||||||
// test case 7
|
|
||||||
array(
|
|
||||||
'sha224',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.',
|
|
||||||
'3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1'
|
|
||||||
),
|
|
||||||
|
|
||||||
// test case 1
|
|
||||||
array(
|
|
||||||
'sha256',
|
|
||||||
str_repeat("\x0b", 20),
|
|
||||||
'Hi There',
|
|
||||||
'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7',
|
|
||||||
),
|
|
||||||
// test case 2
|
|
||||||
array(
|
|
||||||
'sha256',
|
|
||||||
'Jefe',
|
|
||||||
'what do ya want for nothing?',
|
|
||||||
'5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843',
|
|
||||||
),
|
|
||||||
// test case 3
|
|
||||||
array(
|
|
||||||
'sha256',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'),
|
|
||||||
'773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe',
|
|
||||||
),
|
|
||||||
// test case 4
|
|
||||||
array(
|
|
||||||
'sha256',
|
|
||||||
pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'),
|
|
||||||
pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'),
|
|
||||||
'82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b',
|
|
||||||
),
|
|
||||||
// skip test case 5; truncation is only supported to 96 bits (eg. sha1-96) and that's already unit tested
|
|
||||||
// test case 6
|
|
||||||
array(
|
|
||||||
'sha256',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
'Test Using Larger Than Block-Size Key - Hash Key First',
|
|
||||||
'60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54',
|
|
||||||
),
|
|
||||||
// test case 7
|
|
||||||
array(
|
|
||||||
'sha256',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.',
|
|
||||||
'9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2'
|
|
||||||
),
|
|
||||||
|
|
||||||
// test case 1
|
|
||||||
array(
|
|
||||||
'sha384',
|
|
||||||
str_repeat("\x0b", 20),
|
|
||||||
'Hi There',
|
|
||||||
'afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6',
|
|
||||||
),
|
|
||||||
// test case 2
|
|
||||||
array(
|
|
||||||
'sha384',
|
|
||||||
'Jefe',
|
|
||||||
'what do ya want for nothing?',
|
|
||||||
'af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649',
|
|
||||||
),
|
|
||||||
// test case 3
|
|
||||||
array(
|
|
||||||
'sha384',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'),
|
|
||||||
'88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27',
|
|
||||||
),
|
|
||||||
// test case 4
|
|
||||||
array(
|
|
||||||
'sha384',
|
|
||||||
pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'),
|
|
||||||
pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'),
|
|
||||||
'3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb',
|
|
||||||
),
|
|
||||||
// skip test case 5; truncation is only supported to 96 bits (eg. sha1-96) and that's already unit tested
|
|
||||||
// test case 6
|
|
||||||
array(
|
|
||||||
'sha384',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
'Test Using Larger Than Block-Size Key - Hash Key First',
|
|
||||||
'4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952',
|
|
||||||
),
|
|
||||||
// test case 7
|
|
||||||
array(
|
|
||||||
'sha384',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.',
|
|
||||||
'6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e'
|
|
||||||
),
|
|
||||||
|
|
||||||
// test case 1
|
|
||||||
array(
|
|
||||||
'sha512',
|
|
||||||
str_repeat("\x0b", 20),
|
|
||||||
'Hi There',
|
|
||||||
'87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854',
|
|
||||||
),
|
|
||||||
// test case 2
|
|
||||||
array(
|
|
||||||
'sha512',
|
|
||||||
'Jefe',
|
|
||||||
'what do ya want for nothing?',
|
|
||||||
'164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737',
|
|
||||||
),
|
|
||||||
// test case 3
|
|
||||||
array(
|
|
||||||
'sha512',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'),
|
|
||||||
'fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb',
|
|
||||||
),
|
|
||||||
// test case 4
|
|
||||||
array(
|
|
||||||
'sha512',
|
|
||||||
pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'),
|
|
||||||
pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'),
|
|
||||||
'b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd',
|
|
||||||
),
|
|
||||||
// skip test case 5; truncation is only supported to 96 bits (eg. sha1-96) and that's already unit tested
|
|
||||||
// test case 6
|
|
||||||
array(
|
|
||||||
'sha512',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
'Test Using Larger Than Block-Size Key - Hash Key First',
|
|
||||||
'80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598',
|
|
||||||
),
|
|
||||||
// test case 7
|
|
||||||
array(
|
|
||||||
'sha512',
|
|
||||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
||||||
'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.',
|
|
||||||
'e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58'
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider hashData()
|
|
||||||
*/
|
|
||||||
public function testHash($hash, $message, $result)
|
|
||||||
{
|
|
||||||
$this->assertHashesTo($hash, $message, $result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider hashData()
|
|
||||||
*/
|
|
||||||
public function testHash96($hash, $message, $result)
|
|
||||||
{
|
|
||||||
$this->assertHashesTo($hash . '-96', $message, substr($result, 0, 24));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testConstructorDefault()
|
|
||||||
{
|
|
||||||
$hash = new Hash();
|
|
||||||
$this->assertSame($hash->getHash(), 'sha256');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \phpseclib\Exception\UnsupportedAlgorithmException
|
|
||||||
*/
|
|
||||||
public function testConstructorArgumentInvalid()
|
|
||||||
{
|
|
||||||
new Hash('abcdefghijklmnopqrst');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testConstructorArgumentValid()
|
|
||||||
{
|
|
||||||
$hash = new Hash('whirlpool');
|
|
||||||
$this->assertSame($hash->getHash(), 'whirlpool');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \phpseclib\Exception\UnsupportedAlgorithmException
|
|
||||||
*/
|
|
||||||
public function testSetHashInvalid()
|
|
||||||
{
|
|
||||||
$hash = new Hash('md5');
|
|
||||||
$hash->setHash('abcdefghijklmnopqrst-96');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSetHashValid()
|
|
||||||
{
|
|
||||||
$hash = new Hash('md5');
|
|
||||||
$this->assertSame($hash->getHash(), 'md5');
|
|
||||||
$hash->setHash('sha1');
|
|
||||||
$this->assertSame($hash->getHash(), 'sha1');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider lengths
|
|
||||||
*/
|
|
||||||
public function testGetLengthKnown($algorithm, $length)
|
|
||||||
{
|
|
||||||
$hash = new Hash($algorithm);
|
|
||||||
$this->assertSame($hash->getLength(), $length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function lengths()
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
// known
|
|
||||||
array('md5-96', 12),
|
|
||||||
array('md5', 16),
|
|
||||||
array('sha1', 20),
|
|
||||||
array('sha256', 32),
|
|
||||||
array('sha384', 48),
|
|
||||||
array('sha512', 64),
|
|
||||||
// unknown
|
|
||||||
array('whirlpool', 64),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -110,11 +110,10 @@ class Unit_Crypt_RC2Test extends PhpseclibTestCase
|
|||||||
*/
|
*/
|
||||||
public function testVectors($engine, $engineName, $key, $keyLen, $plaintext, $ciphertext)
|
public function testVectors($engine, $engineName, $key, $keyLen, $plaintext, $ciphertext)
|
||||||
{
|
{
|
||||||
$rc2 = new RC2(RC2::MODE_CBC);
|
$rc2 = new RC2();
|
||||||
$rc2->disablePadding();
|
$rc2->disablePadding();
|
||||||
$rc2->setKeyLength($keyLen);
|
$rc2->setKeyLength($keyLen);
|
||||||
$rc2->setKey(pack('H*', $key)); // could also do $rc2->setKey(pack('H*', $key), $keyLen)
|
$rc2->setKey(pack('H*', $key)); // could also do $rc2->setKey(pack('H*', $key), $keyLen)
|
||||||
$rc2->setIV(str_repeat("\0", $rc2->getBlockLength() >> 3));
|
|
||||||
if (!$rc2->isValidEngine($engine)) {
|
if (!$rc2->isValidEngine($engine)) {
|
||||||
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
|
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
|
||||||
}
|
}
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* @author Jim Wigginton <terrafrost@php.net>
|
|
||||||
* @copyright 2015 Jim Wigginton
|
|
||||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
use phpseclib\Crypt\RSA;
|
|
||||||
|
|
||||||
class Unit_Crypt_RSA_CreateKeyTest extends PhpseclibTestCase
|
|
||||||
{
|
|
||||||
public function testCreateKey()
|
|
||||||
{
|
|
||||||
extract(RSA::createKey(768));
|
|
||||||
$this->assertInstanceOf('\phpseclib\Crypt\RSA', $privatekey);
|
|
||||||
$this->assertInstanceOf('\phpseclib\Crypt\RSA', $publickey);
|
|
||||||
$this->assertNotEmpty("$privatekey");
|
|
||||||
$this->assertNotEmpty("$publickey");
|
|
||||||
|
|
||||||
return array($publickey, $privatekey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @depends testCreateKey
|
|
||||||
*/
|
|
||||||
public function testEncryptDecrypt($args)
|
|
||||||
{
|
|
||||||
list($publickey, $privatekey) = $args;
|
|
||||||
$ciphertext = $publickey->encrypt('zzz');
|
|
||||||
$this->assertInternalType('string', $ciphertext);
|
|
||||||
$plaintext = $privatekey->decrypt($ciphertext);
|
|
||||||
$this->assertSame($plaintext, 'zzz');
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,9 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use phpseclib\Crypt\RSA;
|
use phpseclib\Crypt\RSA;
|
||||||
use phpseclib\Crypt\RSA\PKCS1;
|
|
||||||
use phpseclib\Crypt\RSA\PuTTY;
|
|
||||||
use phpseclib\Math\BigInteger;
|
|
||||||
|
|
||||||
class Unit_Crypt_RSA_LoadKeyTest extends PhpseclibTestCase
|
class Unit_Crypt_RSA_LoadKeyTest extends PhpseclibTestCase
|
||||||
{
|
{
|
||||||
@ -18,7 +15,7 @@ class Unit_Crypt_RSA_LoadKeyTest extends PhpseclibTestCase
|
|||||||
|
|
||||||
$key = 'zzzzzzzzzzzzzz';
|
$key = 'zzzzzzzzzzzzzz';
|
||||||
|
|
||||||
$this->assertFalse($rsa->load($key));
|
$this->assertFalse($rsa->loadKey($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPKCS1Key()
|
public function testPKCS1Key()
|
||||||
@ -39,7 +36,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
|
|||||||
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=
|
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=
|
||||||
-----END RSA PRIVATE KEY-----';
|
-----END RSA PRIVATE KEY-----';
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
$this->assertInternalType('string', $rsa->getPrivateKey());
|
$this->assertInternalType('string', $rsa->getPrivateKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +59,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
|
|||||||
-----END RSA PRIVATE KEY-----';
|
-----END RSA PRIVATE KEY-----';
|
||||||
$key = str_replace(array("\r", "\n", "\r\n"), ' ', $key);
|
$key = str_replace(array("\r", "\n", "\r\n"), ' ', $key);
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
$this->assertInternalType('string', $rsa->getPrivateKey());
|
$this->assertInternalType('string', $rsa->getPrivateKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +79,7 @@ X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl
|
|||||||
U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
|
U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
|
||||||
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=';
|
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=';
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
$this->assertInternalType('string', $rsa->getPrivateKey());
|
$this->assertInternalType('string', $rsa->getPrivateKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +99,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
|
|||||||
'U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ' .
|
'U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ' .
|
||||||
'37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=';
|
'37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=';
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
$this->assertInternalType('string', $rsa->getPrivateKey());
|
$this->assertInternalType('string', $rsa->getPrivateKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +120,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
|
|||||||
'37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=';
|
'37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=';
|
||||||
$key = base64_decode($key);
|
$key = base64_decode($key);
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
$this->assertInternalType('string', $rsa->getPrivateKey());
|
$this->assertInternalType('string', $rsa->getPrivateKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +159,7 @@ GF/qoZyC1mbqdtyyeWgHtVbJVUORmpbNnXOII9duEqBUNDiO9VSZNn/8h/VsYeAB
|
|||||||
xryZaRDVmtMuf/OZBQ==
|
xryZaRDVmtMuf/OZBQ==
|
||||||
-----END ENCRYPTED PRIVATE KEY-----';
|
-----END ENCRYPTED PRIVATE KEY-----';
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
$this->assertInternalType('string', $rsa->getPrivateKey());
|
$this->assertInternalType('string', $rsa->getPrivateKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,12 +182,12 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
|
|||||||
-----END RSA PRIVATE KEY-----';
|
-----END RSA PRIVATE KEY-----';
|
||||||
$rsa->setPassword('password');
|
$rsa->setPassword('password');
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
|
|
||||||
$key = $rsa->getPrivateKey('PKCS8');
|
$key = $rsa->getPrivateKey(RSA::PRIVATE_FORMAT_PKCS8);
|
||||||
$this->assertInternalType('string', $key);
|
$this->assertInternalType('string', $key);
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPubKey1()
|
public function testPubKey1()
|
||||||
@ -206,7 +203,7 @@ gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
|
|||||||
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
|
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
|
||||||
-----END RSA PUBLIC KEY-----';
|
-----END RSA PUBLIC KEY-----';
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
$this->assertInternalType('string', $rsa->getPublicKey());
|
$this->assertInternalType('string', $rsa->getPublicKey());
|
||||||
$this->assertFalse($rsa->getPrivateKey());
|
$this->assertFalse($rsa->getPrivateKey());
|
||||||
}
|
}
|
||||||
@ -225,7 +222,7 @@ lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
|
|||||||
ZQIDAQAB
|
ZQIDAQAB
|
||||||
-----END PUBLIC KEY-----';
|
-----END PUBLIC KEY-----';
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
$this->assertInternalType('string', $rsa->getPublicKey());
|
$this->assertInternalType('string', $rsa->getPublicKey());
|
||||||
$this->assertFalse($rsa->getPrivateKey());
|
$this->assertFalse($rsa->getPrivateKey());
|
||||||
}
|
}
|
||||||
@ -239,7 +236,7 @@ ZQIDAQAB
|
|||||||
'GkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZw== ' .
|
'GkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZw== ' .
|
||||||
'phpseclib-generated-key';
|
'phpseclib-generated-key';
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
$this->assertInternalType('string', $rsa->getPublicKey());
|
$this->assertInternalType('string', $rsa->getPublicKey());
|
||||||
$this->assertFalse($rsa->getPrivateKey());
|
$this->assertFalse($rsa->getPrivateKey());
|
||||||
}
|
}
|
||||||
@ -255,7 +252,7 @@ ZQIDAQAB
|
|||||||
'b6wYtY/q/WtUFr3nK+x0lgOtokhnJfRR/6fnmC1CztPnIT4BWK81VGKWONAxuhMyQ5XChyu6S9'.
|
'b6wYtY/q/WtUFr3nK+x0lgOtokhnJfRR/6fnmC1CztPnIT4BWK81VGKWONAxuhMyQ5XChyu6S9'.
|
||||||
'mWG5tUlUI/5';
|
'mWG5tUlUI/5';
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
$this->assertSame($rsa->getPublicKeyFingerprint('md5'), 'bd:2c:2f:31:b9:ef:b8:f8:ad:fc:40:a6:94:4f:28:82');
|
$this->assertSame($rsa->getPublicKeyFingerprint('md5'), 'bd:2c:2f:31:b9:ef:b8:f8:ad:fc:40:a6:94:4f:28:82');
|
||||||
$this->assertSame($rsa->getPublicKeyFingerprint('sha256'), 'N9sV2uSNZEe8TITODku0pRI27l+Zk0IY0TrRTw3ozwM');
|
$this->assertSame($rsa->getPublicKeyFingerprint('sha256'), 'N9sV2uSNZEe8TITODku0pRI27l+Zk0IY0TrRTw3ozwM');
|
||||||
}
|
}
|
||||||
@ -273,7 +270,7 @@ gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
|
|||||||
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
|
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
|
||||||
-----END RSA PUBLIC KEY-----';
|
-----END RSA PUBLIC KEY-----';
|
||||||
|
|
||||||
$this->assertTrue($rsa->load($key));
|
$this->assertTrue($rsa->loadKey($key));
|
||||||
$this->assertTrue($rsa->setPrivateKey());
|
$this->assertTrue($rsa->setPrivateKey());
|
||||||
$this->assertGreaterThanOrEqual(1, strlen("$rsa"));
|
$this->assertGreaterThanOrEqual(1, strlen("$rsa"));
|
||||||
$this->assertFalse($rsa->getPublicKey());
|
$this->assertFalse($rsa->getPublicKey());
|
||||||
@ -293,11 +290,11 @@ Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
|
|||||||
<Exponent>AQAB</Exponent>
|
<Exponent>AQAB</Exponent>
|
||||||
</RSAKeyValue>';
|
</RSAKeyValue>';
|
||||||
|
|
||||||
$rsa->load($key);
|
$rsa->loadKey($key);
|
||||||
$rsa->setPublicKey();
|
$rsa->setPublicKey();
|
||||||
$newkey = $rsa->getPublicKey('XML');
|
$newkey = $rsa->getPublicKey(RSA::PUBLIC_FORMAT_XML);
|
||||||
|
|
||||||
$this->assertSame(strtolower(preg_replace('#\s#', '', $key)), strtolower(preg_replace('#\s#', '', $newkey)));
|
$this->assertSame(preg_replace('#\s#', '', $key), preg_replace('#\s#', '', $newkey));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -314,7 +311,7 @@ JWrQdxx/WNN+ABG426rgYYbeGcIlWLZCw6Bx/1HtN5ef6nVEoiGNChYKIRB4QFOi
|
|||||||
01smFxps1w8ZIQnD6wIDAQAB
|
01smFxps1w8ZIQnD6wIDAQAB
|
||||||
-----END PUBLIC KEY-----';
|
-----END PUBLIC KEY-----';
|
||||||
|
|
||||||
$rsa->load($key);
|
$rsa->loadKey($key);
|
||||||
$rsa->setPublicKey();
|
$rsa->setPublicKey();
|
||||||
$newkey = $rsa->getPublicKey();
|
$newkey = $rsa->getPublicKey();
|
||||||
|
|
||||||
@ -345,162 +342,11 @@ qMnD/pkHR/NFcYSYShUJS0cHyryVl7/eCclsQlZTRdnVTtKF9xPGTQC8fK0G7BDN
|
|||||||
Z2sKniRCcDT1ZP4=
|
Z2sKniRCcDT1ZP4=
|
||||||
-----END PRIVATE KEY-----';
|
-----END PRIVATE KEY-----';
|
||||||
|
|
||||||
$result = $rsa->load($key, 'PKCS8');
|
$result = $rsa->loadKey($key, RSA::PRIVATE_FORMAT_PKCS8);
|
||||||
|
|
||||||
$this->assertTrue($result);
|
$this->assertTrue($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPKCS1EncryptionChange()
|
|
||||||
{
|
|
||||||
$rsa = new RSA();
|
|
||||||
|
|
||||||
$key = 'PuTTY-User-Key-File-2: ssh-rsa
|
|
||||||
Encryption: none
|
|
||||||
Comment: phpseclib-generated-key
|
|
||||||
Public-Lines: 4
|
|
||||||
AAAAB3NzaC1yc2EAAAADAQABAAAAgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4
|
|
||||||
eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RK
|
|
||||||
NUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDy
|
|
||||||
R4e9T04ZZw==
|
|
||||||
Private-Lines: 8
|
|
||||||
AAAAgBYo5KOevqhsjfDNEVcmkQF8/vsU6hwS4d7ceFYDLa0PlhIAo4aE8KNtyjAQ
|
|
||||||
LiRkmJ0ZqAWTN5TH0ynryJAInTxMb2AnZuXWKt106C5JC7+S9qSCFThTAxvihEpw
|
|
||||||
BVe5dnPnJ80TFtPm+n/JkdQic2bsVSy+kNNn7y4uef5m0mMRAAAAQQDeAw6fiIQX
|
|
||||||
GukBI4eMZZt4nscy2o12KyYner3VpoeE+Np2q+Z3pvAMd/aNzQ/W9WaI+NRfcxUJ
|
|
||||||
rmfPwIGm63ilAAAAQQDEIvkdBvZtCvgHKitwxab+EQ/YxnNE5XvfIXjWE+xEL2br
|
|
||||||
oquF470c9Mm6jf/2zmn6yobE6UUvQ0O3hKSiyOAbAAAAQBGoiuSoSjafUhV7i1cE
|
|
||||||
Gpb88h5NBYZzWXGZ37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ
|
|
||||||
4p0=
|
|
||||||
Private-MAC: 03e2cb74e1d67652fbad063d2ed0478f31bdf256
|
|
||||||
';
|
|
||||||
$key = preg_replace('#(?<!\r)\n#', "\r\n", $key);
|
|
||||||
$this->assertTrue($rsa->load($key));
|
|
||||||
|
|
||||||
PKCS1::setEncryptionAlgorithm('AES-256-CBC');
|
|
||||||
$rsa->setPassword('demo');
|
|
||||||
|
|
||||||
$encryptedKey = (string) $rsa;
|
|
||||||
|
|
||||||
$this->assertRegExp('#AES-256-CBC#', $encryptedKey);
|
|
||||||
|
|
||||||
$rsa = new RSA();
|
|
||||||
$rsa->setPassword('demo');
|
|
||||||
$this->assertTrue($rsa->load($encryptedKey));
|
|
||||||
$rsa->setPassword();
|
|
||||||
$rsa->setPrivateKeyFormat('PuTTY');
|
|
||||||
$key2 = (string) $rsa;
|
|
||||||
|
|
||||||
$this->assertSame($key, $key2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testRawKey()
|
|
||||||
{
|
|
||||||
$rsa = new RSA();
|
|
||||||
|
|
||||||
$key = array(
|
|
||||||
'e' => new BigInteger('10001', 16),
|
|
||||||
'n' => new BigInteger('aa18aba43b50deef38598faf87d2ab634e4571c130a9bca7b878267414faab8b471bd8965f5c9fc3' .
|
|
||||||
'818485eaf529c26246f3055064a8de19c8c338be5496cbaeb059dc0b358143b44a35449eb2641131' .
|
|
||||||
'21a455bd7fde3fac919e94b56fb9bb4f651cdb23ead439d6cd523eb08191e75b35fd13a7419b3090' .
|
|
||||||
'f24787bd4f4e1967', 16)
|
|
||||||
);
|
|
||||||
$this->assertTrue($rsa->load($key));
|
|
||||||
$rsa->setPublicKeyFormat('raw');
|
|
||||||
$this->assertEmpty("$rsa");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testRawComment()
|
|
||||||
{
|
|
||||||
$key = 'PuTTY-User-Key-File-2: ssh-rsa
|
|
||||||
Encryption: aes256-cbc
|
|
||||||
Comment: phpseclib-generated-key
|
|
||||||
Public-Lines: 4
|
|
||||||
AAAAB3NzaC1yc2EAAAADAQABAAAAgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4
|
|
||||||
eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RK
|
|
||||||
NUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDy
|
|
||||||
R4e9T04ZZw==
|
|
||||||
Private-Lines: 8
|
|
||||||
llx04QMegql0/nE5RvcJSrGrodxt6ytuv/JX2caeZBUyQwQc2WBNYagLHyHPM9jI
|
|
||||||
9OUWz59FLhjFXZMDNMoUXxVmjwQpOAaVPYNxxFM9AF6/NXFji64K7huD9n4A+kLn
|
|
||||||
sHwMLWPR5a/tZA0r05DZNz9ULA3mQu7Hz4EQ8ifu3uTPJuTmL51x6RmudYKysb20
|
|
||||||
fM8VzC3ukvzzRh0pujUVTr/yQdmciASVFnZlt4xQy+ZEOVUAOfwjd//AFfXTvk6x
|
|
||||||
7A45rNlU/uicHwLgoY1APvRHCFxw7F+uVW5L4mSX7NNzqBKkZ+1qpQTAfQvIfEIb
|
|
||||||
444+CXsgIyOpqt6VxJH2u6elAtE1wau3YaFR8Alm8m97rFYzRi3oDP5NZYkTCWSV
|
|
||||||
EOpSeghXSs7IilJu8I6/sB1w5dakdeBSFkIynrlFXkO0uUw+QJJWjxY8SypzgIuP
|
|
||||||
DzduF6XsQrCyo6dnIpGQCQ==
|
|
||||||
Private-MAC: 35134b7434bf828b21404099861d455e660e8740';
|
|
||||||
$raw = PuTTY::load($key, 'password');
|
|
||||||
$this->assertArrayHasKey('comment', $raw);
|
|
||||||
$this->assertEquals($raw['comment'], 'phpseclib-generated-key');
|
|
||||||
|
|
||||||
$rsa = new RSA();
|
|
||||||
$rsa->load($raw);
|
|
||||||
$this->assertGreaterThanOrEqual(1, strlen("$rsa"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testPrivateMSBlob()
|
|
||||||
{
|
|
||||||
$key = 'BwIAAACkAABSU0EyAAQAAAEAAQAnh6FFs6kYe/gmb9dzqsQKmtjFE9mxNAe9mEU3OwOEEfyI' .
|
|
||||||
'wkAx0/8dwh12fuP4wzNbdZAq4mmqCE6Lo8wTNNIJVNYEhKq5chHg1+hPDgfETFgtEO54JZSg' .
|
|
||||||
'3cBZWEV/Tq3LHEX8CaLvHZxMEfFXbTfliFYMLoJ+YK1mpg9GYcmbrVmMAKSoOgETkkiJJzYm' .
|
|
||||||
'XftO3KOveBtvkAzjHxxSS1yP/Ba10BzeIleH96SbTuQtQRLXwRykdX9uazK+YsiSud9/PyLb' .
|
|
||||||
'gy5TI+o28OHq5P+0y5+a9IaAQ/92UwlrkHUYfhN/xTVlUIxKlTEdUQTIf+iHif8d4ABb3OdY' .
|
|
||||||
'JXZOW6fGeUP10jMyvbnrEoPDsYy9qfNk++0/8UP2NeO1IATszuZYg1nEXOW/5jmUxMCdiFyd' .
|
|
||||||
'p9ES211kpEZ4XcvjGaDlaQ+bLWj05i2m/9aHYcBrfcxxvlMa/9ZvrX4DfPWeydUDDDQ4+ntp' .
|
|
||||||
'T50BunSvmyf7cUk76Bf2sPgLXUQFoufEQ5g1Qo/v1uyhWBJzh6OSUO/DDXN/s8ec/tN05RQQ' .
|
|
||||||
'FZQ0na+v0hOCrV9IuRqtBuj4WAj1I/A1JjwyyP9Y/6yWFPM6EcS/6lyPy30lJPoULh7G29zk' .
|
|
||||||
'n7NVdTEkDtthdDjtX7Qhgd9qWvm5ADlmnvsS9A5m7ToOgQyOxtJoSlLitLbf/09LRycl/cdI' .
|
|
||||||
'zoMOCEdPe3DQcyEKqUPsghAq+DKw3uZpXwHzwTdfqlHSWAnHDggFKV1HZuWc1c4rV4k4b513TqE=';
|
|
||||||
|
|
||||||
$plaintext = 'zzz';
|
|
||||||
|
|
||||||
$privKey = new RSA();
|
|
||||||
$privKey->load($key);
|
|
||||||
|
|
||||||
$this->assertSame($privKey->getLoadedFormat(), 'MSBLOB');
|
|
||||||
|
|
||||||
$this->assertGreaterThanOrEqual(1, strlen("$privKey"));
|
|
||||||
|
|
||||||
$pubKey = new RSA();
|
|
||||||
$pubKey->load($privKey->getPublicKey('msblob'));
|
|
||||||
|
|
||||||
$this->assertGreaterThanOrEqual(1, strlen("$pubKey"));
|
|
||||||
|
|
||||||
$ciphertext = $pubKey->encrypt($plaintext);
|
|
||||||
|
|
||||||
$this->assertSame($privKey->decrypt($ciphertext), $plaintext);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testNakedOpenSSHKey()
|
|
||||||
{
|
|
||||||
$key = 'AAAAB3NzaC1yc2EAAAABIwAAAIEA/NcGSQFZ0ZgN1EbDusV6LLwLnQjs05ljKcVVP7Z6aKIJUyhUDHE30uJa5XfwPPBsZ3L3Q7S0yycVcuuHjdauugmpn9xx+gyoYs7UiV5G5rvxNcA/Tc+MofGhAMiTmNicorNAs5mv6fRoVbkpIONRXPz6WK0kjx/X04EV42Vm9Qk=';
|
|
||||||
|
|
||||||
$rsa = new RSA();
|
|
||||||
$rsa->load($key);
|
|
||||||
|
|
||||||
$this->assertSame($rsa->getLoadedFormat(), 'OpenSSH');
|
|
||||||
|
|
||||||
$this->assertGreaterThanOrEqual(1, strlen("$rsa"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testPuttyPublicKey()
|
|
||||||
{
|
|
||||||
$key = '---- BEGIN SSH2 PUBLIC KEY ----
|
|
||||||
Comment: "rsa-key-20151023"
|
|
||||||
AAAAB3NzaC1yc2EAAAABJQAAAIEAhC/CSqJ+8vgeQ4H7fJru29h/McqAC9zdGzw0
|
|
||||||
9QsifLQ7s5MvXCavhjUPYIfV0KsdLQydNPLJcbKpXmpVD9azo61zLXwsYr8d1eHr
|
|
||||||
C/EwUYl8b0fAwEsEF3myb+ryzgA9ihY08Zs9NZdmt1Maa+I7lQcLX9F/65YdcAch
|
|
||||||
ILaEujU=
|
|
||||||
---- END SSH2 PUBLIC KEY ----';
|
|
||||||
|
|
||||||
$rsa = new RSA();
|
|
||||||
$rsa->load($key);
|
|
||||||
|
|
||||||
$this->assertSame($rsa->getLoadedFormat(), 'PuTTY');
|
|
||||||
|
|
||||||
$this->assertGreaterThanOrEqual(1, strlen("$rsa"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group github960
|
* @group github960
|
||||||
*/
|
*/
|
||||||
@ -527,11 +373,11 @@ Private-MAC: 35134b7434bf828b21404099861d455e660e8740';
|
|||||||
|
|
||||||
$rsa = new RSA();
|
$rsa = new RSA();
|
||||||
$rsa->setPrivateKey($key);
|
$rsa->setPrivateKey($key);
|
||||||
$rsa->load($key);
|
$rsa->loadKey($key);
|
||||||
|
|
||||||
$rsa = new RSA();
|
$rsa = new RSA();
|
||||||
$rsa->load($key);
|
$rsa->loadKey($key);
|
||||||
$rsa->setPrivateKey();
|
$rsa->setPrivateKey();
|
||||||
$rsa->load($rsa);
|
$rsa->loadKey($rsa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use phpseclib\Crypt\RSA;
|
use phpseclib\Crypt\RSA;
|
||||||
use phpseclib\Math\BigInteger;
|
|
||||||
|
|
||||||
class Unit_Crypt_RSA_ModeTest extends PhpseclibTestCase
|
class Unit_Crypt_RSA_ModeTest extends PhpseclibTestCase
|
||||||
{
|
{
|
||||||
@ -29,19 +28,20 @@ X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl
|
|||||||
U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
|
U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
|
||||||
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=
|
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=
|
||||||
-----END RSA PRIVATE KEY-----';
|
-----END RSA PRIVATE KEY-----';
|
||||||
$rsa->load($privatekey);
|
$rsa->loadKey($privatekey);
|
||||||
$rsa->load($rsa->getPublicKey());
|
$rsa->loadKey($rsa->getPublicKey());
|
||||||
|
|
||||||
|
$rsa->setEncryptionMode(RSA::ENCRYPTION_NONE);
|
||||||
$expected = '105b92f59a87a8ad4da52c128b8c99491790ef5a54770119e0819060032fb9e772ed6772828329567f3d7e9472154c1530f8156ba7fd732f52ca1c06' .
|
$expected = '105b92f59a87a8ad4da52c128b8c99491790ef5a54770119e0819060032fb9e772ed6772828329567f3d7e9472154c1530f8156ba7fd732f52ca1c06' .
|
||||||
'5a3f5ed8a96c442e4662e0464c97f133aed31262170201993085a589565d67cc9e727e0d087e3b225c8965203b271e38a499c92fc0d6502297eca712' .
|
'5a3f5ed8a96c442e4662e0464c97f133aed31262170201993085a589565d67cc9e727e0d087e3b225c8965203b271e38a499c92fc0d6502297eca712' .
|
||||||
'4d04bd467f6f1e7c';
|
'4d04bd467f6f1e7c';
|
||||||
$expected = pack('H*', $expected);
|
$expected = pack('H*', $expected);
|
||||||
$result = $rsa->encrypt($plaintext, RSA::PADDING_NONE);
|
$result = $rsa->encrypt($plaintext);
|
||||||
|
|
||||||
$this->assertEquals($result, $expected);
|
$this->assertEquals($result, $expected);
|
||||||
|
|
||||||
$rsa->load($privatekey);
|
$rsa->loadKey($privatekey);
|
||||||
$this->assertEquals(trim($rsa->decrypt($result, RSA::PADDING_NONE), "\0"), $plaintext);
|
$this->assertEquals(trim($rsa->decrypt($result), "\0"), $plaintext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,9 +50,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
|
|||||||
public function testPSSSigs()
|
public function testPSSSigs()
|
||||||
{
|
{
|
||||||
$rsa = new RSA();
|
$rsa = new RSA();
|
||||||
$rsa->setHash('sha1');
|
$rsa->loadKey('-----BEGIN PUBLIC KEY-----
|
||||||
$rsa->setMGFHash('sha1');
|
|
||||||
$rsa->load('-----BEGIN PUBLIC KEY-----
|
|
||||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVx
|
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVx
|
||||||
wTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFnc
|
wTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFnc
|
||||||
CzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0T
|
CzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0T
|
||||||
@ -65,38 +63,4 @@ p0GbMJDyR4e9T04ZZwIDAQAB
|
|||||||
|
|
||||||
$this->assertTrue($rsa->verify('zzzz', $sig));
|
$this->assertTrue($rsa->verify('zzzz', $sig));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \OutOfBoundsException
|
|
||||||
*/
|
|
||||||
public function testSmallModulo()
|
|
||||||
{
|
|
||||||
$plaintext = 'x';
|
|
||||||
$n = new BigInteger(base64_decode('272435F22706FA96DE26E980D22DFF67'), 256);
|
|
||||||
$e = new BigInteger(base64_decode('158753FF2AF4D1E5BBAB574D5AE6B54D'), 256);
|
|
||||||
|
|
||||||
$rsa = new RSA();
|
|
||||||
$rsa->load(array('n' => $n, 'e' => $e));
|
|
||||||
$rsa->encrypt($plaintext);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testPKCS1LooseVerify()
|
|
||||||
{
|
|
||||||
$rsa = new RSA();
|
|
||||||
$rsa->load('-----BEGIN RSA PUBLIC KEY-----
|
|
||||||
MIGJAoGBAMuqkz8ij+ESAaNvgocVGmapjlrIldmhRo4h2NX4e6IXiCLTSxASQtY4
|
|
||||||
iqRnmyxqQSfaan2okTfQ6sP95bl8Qz8lgneW3ClC6RXG/wpJgsx7TXQ2kodlcKBF
|
|
||||||
m4k72G75QXhZ+I40ZG7cjBf1/9egakR0a0X0MpeOrKCzMBLv9+mpAgMBAAE=
|
|
||||||
-----END RSA PUBLIC KEY-----');
|
|
||||||
|
|
||||||
$message = base64_decode('MYIBLjAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNDA1MTUxNDM4MzRaMC8GCSqGSIb3DQEJBDEiBCBLzLIBGdOf0L2WRrIY' .
|
|
||||||
'9KTwiHnReBW48S9C7LNRaPp5mDCBwgYLKoZIhvcNAQkQAi8xgbIwga8wgawwgakEIJDB9ZGwihf+TaiwrHQNkNHkqbN8Nuws0e77QNObkvFZMIGEMHCkbjBs' .
|
|
||||||
'MQswCQYDVQQGEwJJVDEYMBYGA1UECgwPQXJ1YmFQRUMgUy5wLkEuMSEwHwYDVQQLDBhDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eUMxIDAeBgNVBAMMF0FydWJh' .
|
|
||||||
'UEVDIFMucC5BLiBORyBDQSAzAhAv4L3QcFssQNLDYN/Vu40R');
|
|
||||||
|
|
||||||
$sig = base64_decode('XDSZWw6IcUj8ICxRJf04HzF8stzoiFAZSR2a0Rw3ziZxTOT0/NVUYJO5+9TaaREXEgxuCLpgmA+6W2SWrrGoxbbNfaI90ZoKeOAws4IX+9RfiWuooibjKcvt' .
|
|
||||||
'GJYVVOCcjvQYxUUNbQ4EjCUonk3h7ECXfCCmWqbeq2LsyXeeYGE=');
|
|
||||||
|
|
||||||
$this->assertTrue($rsa->verify($message, $sig, RSA::PADDING_RELAXED_PKCS1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -104,13 +104,12 @@ class Unit_Crypt_TripleDESTest extends PhpseclibTestCase
|
|||||||
*/
|
*/
|
||||||
public function testVectors($engine, $engineName, $key, $plaintext, $expected)
|
public function testVectors($engine, $engineName, $key, $plaintext, $expected)
|
||||||
{
|
{
|
||||||
$des = new TripleDES(TripleDES::MODE_CBC);
|
$des = new TripleDES();
|
||||||
if (!$des->isValidEngine($engine)) {
|
if (!$des->isValidEngine($engine)) {
|
||||||
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
|
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
|
||||||
}
|
}
|
||||||
$des->setPreferredEngine($engine);
|
$des->setPreferredEngine($engine);
|
||||||
$des->setKey($key);
|
$des->setKey($key);
|
||||||
$des->setIV(str_repeat("\0", $des->getBlockLength() >> 3));
|
|
||||||
$des->disablePadding();
|
$des->disablePadding();
|
||||||
$result = $des->encrypt($plaintext);
|
$result = $des->encrypt($plaintext);
|
||||||
$plaintext = bin2hex($plaintext);
|
$plaintext = bin2hex($plaintext);
|
||||||
@ -156,7 +155,7 @@ class Unit_Crypt_TripleDESTest extends PhpseclibTestCase
|
|||||||
*/
|
*/
|
||||||
public function testVectorsWithIV($engine, $engineName, $key, $iv, $plaintext, $expected)
|
public function testVectorsWithIV($engine, $engineName, $key, $iv, $plaintext, $expected)
|
||||||
{
|
{
|
||||||
$des = new TripleDES(TripleDES::MODE_CBC);
|
$des = new TripleDES();
|
||||||
if (!$des->isValidEngine($engine)) {
|
if (!$des->isValidEngine($engine)) {
|
||||||
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
|
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
|
||||||
}
|
}
|
||||||
@ -177,7 +176,6 @@ class Unit_Crypt_TripleDESTest extends PhpseclibTestCase
|
|||||||
|
|
||||||
$des = new TripleDES(TripleDES::MODE_3CBC);
|
$des = new TripleDES(TripleDES::MODE_3CBC);
|
||||||
$des->setKey('abcdefghijklmnopqrstuvwx');
|
$des->setKey('abcdefghijklmnopqrstuvwx');
|
||||||
$des->setIV(str_repeat("\0", $des->getBlockLength() >> 3));
|
|
||||||
|
|
||||||
foreach ($this->engines as $engine => $engineName) {
|
foreach ($this->engines as $engine => $engineName) {
|
||||||
$des->setPreferredEngine($engine);
|
$des->setPreferredEngine($engine);
|
||||||
|
@ -19,8 +19,7 @@ class Unit_Crypt_TwofishTest extends PhpseclibTestCase
|
|||||||
);
|
);
|
||||||
|
|
||||||
foreach ($engines as $engine => $name) {
|
foreach ($engines as $engine => $name) {
|
||||||
$tf = new Twofish(Twofish::MODE_CBC);
|
$tf = new Twofish();
|
||||||
$tf->setIV(str_repeat("\0", $tf->getBlockLength() >> 3));
|
|
||||||
$tf->disablePadding();
|
$tf->disablePadding();
|
||||||
|
|
||||||
// tests from https://www.schneier.com/code/ecb_ival.txt
|
// tests from https://www.schneier.com/code/ecb_ival.txt
|
||||||
|
@ -48,9 +48,10 @@ class Unit_File_X509_SPKACTest extends PhpseclibTestCase
|
|||||||
{
|
{
|
||||||
$privKey = new RSA();
|
$privKey = new RSA();
|
||||||
extract($privKey->createKey());
|
extract($privKey->createKey());
|
||||||
|
$privKey->loadKey($privatekey);
|
||||||
|
|
||||||
$x509 = new X509();
|
$x509 = new X509();
|
||||||
$x509->setPrivateKey($privatekey);
|
$x509->setPrivateKey($privKey);
|
||||||
$x509->setChallenge('...');
|
$x509->setChallenge('...');
|
||||||
|
|
||||||
$spkac = $x509->signSPKAC();
|
$spkac = $x509->signSPKAC();
|
||||||
|
@ -154,7 +154,7 @@ IOkKcGQRCMha8X2e7GmlpdWC1ycenlbN0nbVeSv3JUMcafC4+Q==
|
|||||||
public function testSaveNullRSAParam()
|
public function testSaveNullRSAParam()
|
||||||
{
|
{
|
||||||
$privKey = new RSA();
|
$privKey = new RSA();
|
||||||
$privKey->load('-----BEGIN RSA PRIVATE KEY-----
|
$privKey->loadKey('-----BEGIN RSA PRIVATE KEY-----
|
||||||
MIICXQIBAAKBgQDMswfEpAgnUDWA74zZw5XcPsWh1ly1Vk99tsqwoFDkLF7jvXy1
|
MIICXQIBAAKBgQDMswfEpAgnUDWA74zZw5XcPsWh1ly1Vk99tsqwoFDkLF7jvXy1
|
||||||
dDLHYfuquvfxCgcp8k/4fQhx4ubR8bbGgEq9B05YRnViK0R0iBB5Ui4IaxWYYhKE
|
dDLHYfuquvfxCgcp8k/4fQhx4ubR8bbGgEq9B05YRnViK0R0iBB5Ui4IaxWYYhKE
|
||||||
8xqAEH2fL+/7nsqqNFKkEN9KeFwc7WbMY49U2adlMrpBdRjk1DqIEW3QTwIDAQAB
|
8xqAEH2fL+/7nsqqNFKkEN9KeFwc7WbMY49U2adlMrpBdRjk1DqIEW3QTwIDAQAB
|
||||||
@ -171,7 +171,7 @@ aBtsWpliLSex/HHhtRW9AkBGcq67zKmEpJ9kXcYLEjJii3flFS+Ct/rNm+Hhm1l7
|
|||||||
-----END RSA PRIVATE KEY-----');
|
-----END RSA PRIVATE KEY-----');
|
||||||
|
|
||||||
$pubKey = new RSA();
|
$pubKey = new RSA();
|
||||||
$pubKey->load($privKey->getPublicKey());
|
$pubKey->loadKey($privKey->getPublicKey());
|
||||||
$pubKey->setPublicKey();
|
$pubKey->setPublicKey();
|
||||||
|
|
||||||
$subject = new X509();
|
$subject = new X509();
|
||||||
|
@ -273,13 +273,29 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase
|
|||||||
$min = $this->getInstance(0);
|
$min = $this->getInstance(0);
|
||||||
$max = $this->getInstance('18446744073709551616');
|
$max = $this->getInstance('18446744073709551616');
|
||||||
|
|
||||||
$rand1 = \phpseclib\Math\BigInteger::random($min, $max);
|
$rand1 = $min->random($min, $max);
|
||||||
// technically $rand1 can equal $min but with the $min and $max we've
|
// technically $rand1 can equal $min but with the $min and $max we've
|
||||||
// chosen it's just not that likely
|
// chosen it's just not that likely
|
||||||
$this->assertTrue($rand1->compare($min) > 0);
|
$this->assertTrue($rand1->compare($min) > 0);
|
||||||
$this->assertTrue($rand1->compare($max) < 0);
|
$this->assertTrue($rand1->compare($max) < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRandomOneArgument()
|
||||||
|
{
|
||||||
|
$min = $this->getInstance(0);
|
||||||
|
$max = $this->getInstance('18446744073709551616');
|
||||||
|
|
||||||
|
$rand1 = $min->random($max);
|
||||||
|
$this->assertTrue($rand1->compare($min) > 0);
|
||||||
|
$this->assertTrue($rand1->compare($max) < 0);
|
||||||
|
|
||||||
|
$rand2 = $max->random($min);
|
||||||
|
$this->assertTrue($rand2->compare($min) > 0);
|
||||||
|
$this->assertTrue($rand2->compare($max) < 0);
|
||||||
|
|
||||||
|
$this->assertFalse($rand1->equals($rand2));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group github279
|
* @group github279
|
||||||
*/
|
*/
|
||||||
@ -315,8 +331,8 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase
|
|||||||
Code for generation of $alicePrivate and $bobPrivate.
|
Code for generation of $alicePrivate and $bobPrivate.
|
||||||
$one = $this->getInstance(1);
|
$one = $this->getInstance(1);
|
||||||
$max = $one->bitwise_leftShift(512)->subtract($one);
|
$max = $one->bitwise_leftShift(512)->subtract($one);
|
||||||
$alicePrivate = \phpseclib\Math\BigInteger::random($one, $max);
|
$alicePrivate = $one->random($one, $max);
|
||||||
$bobPrivate = \phpseclib\Math\BigInteger::random($one, $max);
|
$bobPrivate = $one->random($one, $max);
|
||||||
var_dump($alicePrivate->toHex(), $bobPrivate->toHex());
|
var_dump($alicePrivate->toHex(), $bobPrivate->toHex());
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -353,21 +369,7 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase
|
|||||||
$num = $this->getInstance(50);
|
$num = $this->getInstance(50);
|
||||||
$str = print_r($num, true);
|
$str = print_r($num, true);
|
||||||
$this->assertContains('[value] => 0x32', $str);
|
$this->assertContains('[value] => 0x32', $str);
|
||||||
}
|
return $str;
|
||||||
|
|
||||||
public function testPrecision()
|
|
||||||
{
|
|
||||||
$a = $this->getInstance(51);
|
|
||||||
$this->assertSame($a->getPrecision(), -1);
|
|
||||||
$b = $a;
|
|
||||||
$c = clone $a;
|
|
||||||
$b->setPrecision(1);
|
|
||||||
$this->assertSame($a->getPrecision(), 1);
|
|
||||||
$this->assertSame("$a", '1');
|
|
||||||
$this->assertSame($b->getPrecision(), 1);
|
|
||||||
$this->assertSame("$b", '1');
|
|
||||||
$this->assertSame($c->getPrecision(), -1);
|
|
||||||
$this->assertSame("$c", '51');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,18 +110,6 @@ class Unit_Net_SSH2Test extends PhpseclibTestCase
|
|||||||
$this->assertFalse($ssh->isQuietModeEnabled());
|
$this->assertFalse($ssh->isQuietModeEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetConnectionByResourceId()
|
|
||||||
{
|
|
||||||
$ssh = new \phpseclib\Net\SSH2('localhost');
|
|
||||||
$this->assertSame($ssh, \phpseclib\Net\SSH2::getConnectionByResourceId($ssh->getResourceId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetResourceId()
|
|
||||||
{
|
|
||||||
$ssh = new \phpseclib\Net\SSH2('localhost');
|
|
||||||
$this->assertSame('{' . spl_object_hash($ssh) . '}', $ssh->getResourceId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \phpseclib\Net\SSH2
|
* @return \phpseclib\Net\SSH2
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user