Revert "Merge branch '2.0'"

This reverts commit be5f4ef6b19c82f6c898708cc8e1828b05e3d4e8, reversing
changes made to 638fe6971c.
This commit is contained in:
terrafrost 2016-04-10 11:30:59 -05:00
parent 2cc5dcdc89
commit b4cf10fc94
76 changed files with 7105 additions and 5377 deletions

8
.gitattributes vendored
View File

@ -1 +1,9 @@
* text=auto * text=auto
/build/ export-ignore
/tests/ export-ignore
/travis/ export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/CHANGELOG.md export-ignore
/phpunit.xml.dist export-ignore

View File

@ -1,13 +1,12 @@
language: php language: php
# When adding environments here, the number of runs specified in .scrutinizer.yml
# may have to be adjusted.
php: php:
- 5.3.3
- 5.3 - 5.3
- 5.4 - 5.4
- 5.5.9
- 5.5 - 5.5
- 5.6 - 5.6
- 7.0
- hhvm - hhvm
env: env:
@ -19,10 +18,16 @@ env:
before_install: true before_install: true
install: install:
- sudo apt-get install parallel - wget http://ftp.gnu.org/gnu/parallel/parallel-20120522.tar.bz2
- tar -xvjf parallel*
- cd parallel*
- ./configure
- make
- sudo make install
- cd ..
- eval `ssh-agent -s` - eval `ssh-agent -s`
- travis/setup-secure-shell.sh - travis/setup-secure-shell.sh
- sh -c "if [ '$TRAVIS_PHP_VERSION' != 'hhvm' ]; then travis/install-php-extensions.sh; fi" - sh -c "if [ '$TRAVIS_PHP_VERSION' != 'hhvm' -a '$TRAVIS_PHP_VERSION' != '7.0' ]; then travis/install-php-extensions.sh; fi"
- travis/setup-composer.sh - travis/setup-composer.sh
script: script:

View File

@ -3,3 +3,4 @@ phpseclib Lead Developer: TerraFrost (Jim Wigginton)
phpseclib Developers: monnerat (Patrick Monnerat) phpseclib Developers: monnerat (Patrick Monnerat)
bantu (Andreas Fischer) bantu (Andreas Fischer)
petrich (Hans-Jürgen Petrich) petrich (Hans-Jürgen Petrich)
GrahamCampbell (Graham Campbell)

View File

@ -1,5 +1,56 @@
# Changelog # Changelog
## 2.0.1 - 2016-01-18
- RSA: fix regression in PSS mode ([#769](https://github.com/phpseclib/phpseclib/pull/769))
- RSA: fix issue loading PKCS8 specific keys ([#861](https://github.com/phpseclib/phpseclib/pull/861))
- X509: add getOID() method ([#789](https://github.com/phpseclib/phpseclib/pull/789))
- X509: improve base64-encoded detection rules ([#855](https://github.com/phpseclib/phpseclib/pull/855))
- SFTP: fix quirky behavior with put() ([#830](https://github.com/phpseclib/phpseclib/pull/830))
- SFTP: fix E_NOTICE ([#883](https://github.com/phpseclib/phpseclib/pull/883))
- SFTP/Stream: fix issue with filenames with hashes ([#901](https://github.com/phpseclib/phpseclib/pull/901))
- SSH2: add isAuthenticated() method ([#897](https://github.com/phpseclib/phpseclib/pull/897))
- SSH/Agent: fix possible PHP warning ([#923](https://github.com/phpseclib/phpseclib/issues/923))
- BigInteger: add __debugInfo() magic method ([#881](https://github.com/phpseclib/phpseclib/pull/881))
- BigInteger: fix issue with doing bitwise not on 0
- add getBlockLength() method to symmetric ciphers
## 2.0.0 - 2015-08-04
- Classes were renamed and namespaced ([#243](https://github.com/phpseclib/phpseclib/issues/243))
- The use of an autoloader is now required (e.g. Composer)
## 1.0.1 - 2016-01-18
- RSA: fix regression in PSS mode ([#769](https://github.com/phpseclib/phpseclib/pull/769))
- RSA: fix issue loading PKCS8 specific keys ([#861](https://github.com/phpseclib/phpseclib/pull/861))
- X509: add getOID() method ([#789](https://github.com/phpseclib/phpseclib/pull/789))
- X509: improve base64-encoded detection rules ([#855](https://github.com/phpseclib/phpseclib/pull/855))
- SFTP: fix quirky behavior with put() ([#830](https://github.com/phpseclib/phpseclib/pull/830))
- SFTP: fix E_NOTICE ([#883](https://github.com/phpseclib/phpseclib/pull/883))
- SFTP/Stream: fix issue with filenames with hashes ([#901](https://github.com/phpseclib/phpseclib/pull/901))
- SSH2: add isAuthenticated() method ([#897](https://github.com/phpseclib/phpseclib/pull/897))
- SSH/Agent: fix possible PHP warning ([#923](https://github.com/phpseclib/phpseclib/issues/923))
- BigInteger: add __debugInfo() magic method ([#881](https://github.com/phpseclib/phpseclib/pull/881))
- BigInteger: fix issue with doing bitwise not on 0
- add getBlockLength() method to symmetric ciphers
## 1.0.0 - 2015-08-02
- OpenSSL support for symmetric ciphers ([#507](https://github.com/phpseclib/phpseclib/pull/507))
- rewritten vt100 terminal emulator (File_ANSI) ([#689](https://github.com/phpseclib/phpseclib/pull/689))
- agent-forwarding support (System_SSH_Agent) ([#592](https://github.com/phpseclib/phpseclib/pull/592))
- Net_SSH2 improvements
- diffie-hellman-group-exchange-sha1/sha256 support ([#714](https://github.com/phpseclib/phpseclib/pull/714))
- window size handling updates ([#717](https://github.com/phpseclib/phpseclib/pull/717))
- Net_SFTP improvements
- add callback support to put() ([#655](https://github.com/phpseclib/phpseclib/pull/655))
- stat cache fixes ([#743](https://github.com/phpseclib/phpseclib/issues/743), [#730](https://github.com/phpseclib/phpseclib/issues/730), [#709](https://github.com/phpseclib/phpseclib/issues/709), [#726](https://github.com/phpseclib/phpseclib/issues/726))
- add "none" encryption mode to Crypt_RSA ([#692](https://github.com/phpseclib/phpseclib/pull/692))
- misc ASN.1 / X.509 parsing fixes ([#721](https://github.com/phpseclib/phpseclib/pull/721), [#627](https://github.com/phpseclib/phpseclib/pull/627))
- use a random serial number for new X509 certs ([#740](https://github.com/phpseclib/phpseclib/pull/740))
- add getPublicKeyFingerprint() to Crypt_RSA ([#677](https://github.com/phpseclib/phpseclib/pull/677))
## 0.3.10 - 2015-02-04 ## 0.3.10 - 2015-02-04
- simplify SSH2 window size handling ([#538](https://github.com/phpseclib/phpseclib/pull/538)) - simplify SSH2 window size handling ([#538](https://github.com/phpseclib/phpseclib/pull/538))
@ -86,4 +137,4 @@
= add support for AES-128-CBC and DES-EDE3-CFB encrypted RSA private keys = add support for AES-128-CBC and DES-EDE3-CFB encrypted RSA private keys
- add Net_SFTP::stat(), Net_SFTP::lstat() and Net_SFTP::rawlist() - add Net_SFTP::stat(), Net_SFTP::lstat() and Net_SFTP::rawlist()
- logging was added to Net_SSH1 - logging was added to Net_SSH1
- the license was changed to the less restrictive MIT license - the license was changed to the less restrictive MIT license

View File

@ -1,4 +1,4 @@
Copyright 2007-2013 TerraFrost and other contributors Copyright 2007-2016 TerraFrost and other contributors
http://phpseclib.sourceforge.net/ http://phpseclib.sourceforge.net/
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining

View File

@ -1,14 +1,14 @@
# phpseclib - PHP Secure Communications Library # phpseclib - PHP Secure Communications Library
[![Build Status](https://secure.travis-ci.org/phpseclib/phpseclib.png?branch=2.0)](http://travis-ci.org/phpseclib/phpseclib) [![Build Status](https://travis-ci.org/phpseclib/phpseclib.svg?branch=master)](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,
AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509 AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
* [Download (0.3.10)](http://sourceforge.net/projects/phpseclib/files/phpseclib0.3.10.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/php5/latest/) * [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/master/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/2.0/) (generated by Sami) * [API Documentation](http://phpseclib.bantux.org/api/master/) (generated by Sami)
## Support ## Support
@ -40,7 +40,7 @@ Dependencies are managed via Composer.
2. Install Dependencies 2. Install Dependencies
``` sh ``` sh
php composer.phar install --dev php composer.phar install
``` ```
## Contributing ## Contributing

View File

@ -43,9 +43,15 @@
"name": "Hans-Jürgen Petrich", "name": "Hans-Jürgen Petrich",
"email": "petrich@tronic-media.com", "email": "petrich@tronic-media.com",
"role": "Developer" "role": "Developer"
},
{
"name": "Graham Campbell",
"email": "graham@alt-three.com",
"role": "Developer"
} }
], ],
"require": { "require": {
"paragonie/random_compat": "^1.4|^2.0",
"php": ">=5.3.3" "php": ">=5.3.3"
}, },
"require-dev": { "require-dev": {
@ -56,10 +62,10 @@
}, },
"suggest": { "suggest": {
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a wide variety of cryptographic operations.", "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.",
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations." "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations."
}, },
"include-path": ["phpseclib/"],
"autoload": { "autoload": {
"files": [ "files": [
"phpseclib/bootstrap.php" "phpseclib/bootstrap.php"

626
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -11,13 +11,13 @@
* just a wrapper to Rijndael.php you may consider using Rijndael.php instead of * just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
* to save one include_once(). * to save one include_once().
* *
* If {@link \phpseclib\Crypt\AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from * If {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link \phpseclib\Crypt\AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
* it'll be null-padded to 192-bits and 192 bits will be the key length until {@link \phpseclib\Crypt\AES::setKey() setKey()} * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link self::setKey() setKey()}
* is called, again, at which point, it'll be recalculated. * is called, again, at which point, it'll be recalculated.
* *
* Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, some functions are available to be called that, in the context of AES, don't * Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, some functions are available to be called that, in the context of AES, don't
* make a whole lot of sense. {@link \phpseclib\Crypt\AES::setBlockLength() setBlockLength()}, for instance. Calling that function, * make a whole lot of sense. {@link self::setBlockLength() setBlockLength()}, for instance. Calling that function,
* however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one). * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
* *
* Here's a short example of how to use this library: * Here's a short example of how to use this library:
@ -49,8 +49,6 @@
namespace phpseclib\Crypt; namespace phpseclib\Crypt;
use phpseclib\Crypt\Rijndael;
/** /**
* Pure-PHP implementation of AES. * Pure-PHP implementation of AES.
* *
@ -67,31 +65,33 @@ class AES extends Rijndael
* *
* @see \phpseclib\Crypt\Rijndael::setBlockLength() * @see \phpseclib\Crypt\Rijndael::setBlockLength()
* @access public * @access public
* @param Integer $length * @param int $length
* @throws \BadMethodCallException anytime it's called
*/ */
function setBlockLength($length) function setBlockLength($length)
{ {
return; throw new \BadMethodCallException('The block length cannot be set for AES.');
} }
/** /**
* Sets the key length * Sets the key length
* *
* Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to * Valid key lengths are 128, 192, and 256. Set the link to bool(false) to disable a fixed key length
* 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 Integer $length * @param int $length
* @throws \LengthException if the key length isn't supported
*/ */
function setKeyLength($length) function setKeyLength($length)
{ {
switch ($length) { switch ($length) {
case 160: case 128:
$length = 192; case 192:
case 256:
break; break;
case 224: default:
$length = 256; throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 128, 192 or 256 supported');
} }
parent::setKeyLength($length); parent::setKeyLength($length);
} }
@ -104,25 +104,20 @@ class AES extends Rijndael
* @see \phpseclib\Crypt\Rijndael:setKey() * @see \phpseclib\Crypt\Rijndael:setKey()
* @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)
{ {
parent::setKey($key); switch (strlen($key)) {
case 16:
if (!$this->explicit_key_length) { case 24:
$length = strlen($key); case 32:
switch (true) { break;
case $length <= 16: default:
$this->key_size = 16; throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
break;
case $length <= 24:
$this->key_size = 24;
break;
default:
$this->key_size = 32;
}
$this->_setEngine();
} }
parent::setKey($key);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -37,8 +37,6 @@
namespace phpseclib\Crypt; namespace phpseclib\Crypt;
use phpseclib\Crypt\Base;
/** /**
* Pure-PHP implementation of Blowfish. * Pure-PHP implementation of Blowfish.
* *
@ -53,26 +51,16 @@ class Blowfish extends Base
* Block Length of the cipher * Block Length of the cipher
* *
* @see \phpseclib\Crypt\Base::block_size * @see \phpseclib\Crypt\Base::block_size
* @var Integer * @var int
* @access private * @access private
*/ */
var $block_size = 8; var $block_size = 8;
/**
* The default password key_size used by setPassword()
*
* @see \phpseclib\Crypt\Base::password_key_size
* @see \phpseclib\Crypt\Base::setPassword()
* @var Integer
* @access private
*/
var $password_key_size = 56;
/** /**
* The mcrypt specific name of the cipher * The mcrypt specific name of the cipher
* *
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var String * @var string
* @access private * @access private
*/ */
var $cipher_name_mcrypt = 'blowfish'; var $cipher_name_mcrypt = 'blowfish';
@ -81,7 +69,7 @@ class Blowfish extends Base
* Optimizing value while CFB-encrypting * Optimizing value while CFB-encrypting
* *
* @see \phpseclib\Crypt\Base::cfb_init_len * @see \phpseclib\Crypt\Base::cfb_init_len
* @var Integer * @var int
* @access private * @access private
*/ */
var $cfb_init_len = 500; var $cfb_init_len = 500;
@ -94,7 +82,7 @@ class Blowfish extends Base
* @access private * @access private
* @var array * @var array
*/ */
var $sbox0 = array ( var $sbox0 = array(
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
@ -277,53 +265,73 @@ class Blowfish extends Base
/** /**
* Holds the last used key * Holds the last used key
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $kl; var $kl;
/** /**
* Sets the key. * The Key Length (in bytes)
* *
* Keys can be of any length. Blowfish, itself, requires the use of a key between 32 and max. 448-bits long. * @see \phpseclib\Crypt\Base::setKeyLength()
* If the key is less than 32-bits we NOT fill the key to 32bit but let the key as it is to be compatible * @var int
* with mcrypt because mcrypt act this way with blowfish key's < 32 bits. * @access private
* * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
* If the key is more than 448-bits, we trim the excess bits. * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
* * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
* If the key is not explicitly set, or empty, it'll be assumed a 128 bits key to be all null bytes. * of that, we'll just precompute it once.
*
* @access public
* @see \phpseclib\Crypt\Base::setKey()
* @param String $key
*/ */
function setKey($key) var $key_length = 16;
{
$keylength = strlen($key);
if (!$keylength) { /**
$key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; * Default Constructor.
} elseif ($keylength > 56) { *
$key = substr($key, 0, 56); * @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::setKey($key); parent::__construct($mode);
}
/**
* Sets the key length.
*
* Key lengths can be between 32 and 448 bits.
*
* @access public
* @param int $length
*/
function setKeyLength($length)
{
if ($length < 32 || $length > 448) {
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 = $length >> 3;
parent::setKeyLength($length);
} }
/** /**
* Test for engine validity * Test for engine validity
* *
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see \phpseclib\Crypt\Base::isValidEngine() * @see \phpseclib\Crypt\Base::isValidEngine()
* @param Integer $engine * @param int $engine
* @access public * @access public
* @return Boolean * @return bool
*/ */
function isValidEngine($engine) function isValidEngine($engine)
{ {
if ($engine == self::ENGINE_OPENSSL) { if ($engine == self::ENGINE_OPENSSL) {
if (strlen($this->key) != 16) { if ($this->key_length != 16) {
return false; return false;
} }
$this->cipher_name_openssl_ecb = 'bf-ecb'; $this->cipher_name_openssl_ecb = 'bf-ecb';
@ -393,8 +401,8 @@ class Blowfish extends Base
* Encrypts a block * Encrypts a block
* *
* @access private * @access private
* @param String $in * @param string $in
* @return String * @return string
*/ */
function _encryptBlock($in) function _encryptBlock($in)
{ {
@ -429,8 +437,8 @@ class Blowfish extends Base
* Decrypts a block * Decrypts a block
* *
* @access private * @access private
* @param String $in * @param string $in
* @return String * @return string
*/ */
function _decryptBlock($in) function _decryptBlock($in)
{ {
@ -471,9 +479,9 @@ class Blowfish extends Base
$lambda_functions =& self::_getLambdaFunctions(); $lambda_functions =& self::_getLambdaFunctions();
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function. // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for Crypt_Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit) // (Currently, for Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one. // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
// Generation of a unique hash for our generated code // Generation of a unique hash for our generated code
$code_hash = "Crypt_Blowfish, {$this->mode}"; $code_hash = "Crypt_Blowfish, {$this->mode}";

View File

@ -42,8 +42,6 @@
namespace phpseclib\Crypt; namespace phpseclib\Crypt;
use phpseclib\Crypt\Base;
/** /**
* Pure-PHP implementation of DES. * Pure-PHP implementation of DES.
* *
@ -64,7 +62,7 @@ class DES extends Base
const ENCRYPT = 0; const ENCRYPT = 0;
/** /**
* Contains $keys[self::DECRYPT] * Contains $keys[self::DECRYPT]
*/ */
const DECRYPT = 1; const DECRYPT = 1;
/**#@-*/ /**#@-*/
@ -72,36 +70,25 @@ class DES extends Base
* Block Length of the cipher * Block Length of the cipher
* *
* @see \phpseclib\Crypt\Base::block_size * @see \phpseclib\Crypt\Base::block_size
* @var Integer * @var int
* @access private * @access private
*/ */
var $block_size = 8; var $block_size = 8;
/** /**
* The Key * Key Length (in bytes)
* *
* @see \phpseclib\Crypt\Base::key * @see \phpseclib\Crypt\Base::setKeyLength()
* @see setKey() * @var int
* @var String
* @access private * @access private
*/ */
var $key = "\0\0\0\0\0\0\0\0"; var $key_length = 8;
/**
* The default password key_size used by setPassword()
*
* @see \phpseclib\Crypt\Base::password_key_size
* @see \phpseclib\Crypt\Base::setPassword()
* @var Integer
* @access private
*/
var $password_key_size = 8;
/** /**
* The mcrypt specific name of the cipher * The mcrypt specific name of the cipher
* *
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var String * @var string
* @access private * @access private
*/ */
var $cipher_name_mcrypt = 'des'; var $cipher_name_mcrypt = 'des';
@ -110,7 +97,7 @@ class DES extends Base
* The OpenSSL names of the cipher / modes * The OpenSSL names of the cipher / modes
* *
* @see \phpseclib\Crypt\Base::openssl_mode_names * @see \phpseclib\Crypt\Base::openssl_mode_names
* @var Array * @var array
* @access private * @access private
*/ */
var $openssl_mode_names = array( var $openssl_mode_names = array(
@ -125,7 +112,7 @@ class DES extends Base
* Optimizing value while CFB-encrypting * Optimizing value while CFB-encrypting
* *
* @see \phpseclib\Crypt\Base::cfb_init_len * @see \phpseclib\Crypt\Base::cfb_init_len
* @var Integer * @var int
* @access private * @access private
*/ */
var $cfb_init_len = 500; var $cfb_init_len = 500;
@ -135,9 +122,9 @@ class DES extends Base
* *
* Used only if $engine == self::ENGINE_INTERNAL * Used only if $engine == self::ENGINE_INTERNAL
* *
* @see \phpseclib\Crypt\DES::_setupKey() * @see self::_setupKey()
* @see \phpseclib\Crypt\DES::_processBlock() * @see self::_processBlock()
* @var Integer * @var int
* @access private * @access private
*/ */
var $des_rounds = 1; var $des_rounds = 1;
@ -145,17 +132,17 @@ class DES extends Base
/** /**
* max possible size of $key * max possible size of $key
* *
* @see \phpseclib\Crypt\DES::setKey() * @see self::setKey()
* @var String * @var string
* @access private * @access private
*/ */
var $key_size_max = 8; var $key_length_max = 8;
/** /**
* The Key Schedule * The Key Schedule
* *
* @see \phpseclib\Crypt\DES::_setupKey() * @see self::_setupKey()
* @var Array * @var array
* @access private * @access private
*/ */
var $keys; var $keys;
@ -167,9 +154,9 @@ class DES extends Base
* with each byte containing all bits in the same state as the * with each byte containing all bits in the same state as the
* corresponding bit in the index value. * corresponding bit in the index value.
* *
* @see \phpseclib\Crypt\DES::_processBlock() * @see self::_processBlock()
* @see \phpseclib\Crypt\DES::_setupKey() * @see self::_setupKey()
* @var Array * @var array
* @access private * @access private
*/ */
var $shuffle = array( var $shuffle = array(
@ -308,7 +295,7 @@ class DES extends Base
* *
* Indexing this table with each source byte performs the initial bit permutation. * Indexing this table with each source byte performs the initial bit permutation.
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $ipmap = array( var $ipmap = array(
@ -350,7 +337,7 @@ class DES extends Base
* Inverse IP mapping helper table. * Inverse IP mapping helper table.
* Indexing this table with a byte value reverses the bit order. * Indexing this table with a byte value reverses the bit order.
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $invipmap = array( var $invipmap = array(
@ -394,7 +381,7 @@ class DES extends Base
* Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the * Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the
* P table: concatenation can then be replaced by exclusive ORs. * P table: concatenation can then be replaced by exclusive ORs.
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $sbox1 = array( var $sbox1 = array(
@ -419,7 +406,7 @@ class DES extends Base
/** /**
* Pre-permuted S-box2 * Pre-permuted S-box2
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $sbox2 = array( var $sbox2 = array(
@ -444,7 +431,7 @@ class DES extends Base
/** /**
* Pre-permuted S-box3 * Pre-permuted S-box3
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $sbox3 = array( var $sbox3 = array(
@ -469,7 +456,7 @@ class DES extends Base
/** /**
* Pre-permuted S-box4 * Pre-permuted S-box4
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $sbox4 = array( var $sbox4 = array(
@ -494,7 +481,7 @@ class DES extends Base
/** /**
* Pre-permuted S-box5 * Pre-permuted S-box5
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $sbox5 = array( var $sbox5 = array(
@ -519,7 +506,7 @@ class DES extends Base
/** /**
* Pre-permuted S-box6 * Pre-permuted S-box6
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $sbox6 = array( var $sbox6 = array(
@ -544,7 +531,7 @@ class DES extends Base
/** /**
* Pre-permuted S-box7 * Pre-permuted S-box7
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $sbox7 = array( var $sbox7 = array(
@ -569,7 +556,7 @@ class DES extends Base
/** /**
* Pre-permuted S-box8 * Pre-permuted S-box8
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $sbox8 = array( var $sbox8 = array(
@ -591,19 +578,35 @@ 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
* *
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see \phpseclib\Crypt\Base::isValidEngine() * @see \phpseclib\Crypt\Base::isValidEngine()
* @param Integer $engine * @param int $engine
* @access public * @access public
* @return Boolean * @return bool
*/ */
function isValidEngine($engine) function isValidEngine($engine)
{ {
if ($this->key_size_max == 8) { if ($this->key_length_max == 8) {
if ($engine == self::ENGINE_OPENSSL) { if ($engine == self::ENGINE_OPENSSL) {
$this->cipher_name_openssl_ecb = 'des-ecb'; $this->cipher_name_openssl_ecb = 'des-ecb';
$this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode(); $this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode();
@ -616,24 +619,18 @@ class DES extends Base
/** /**
* Sets the key. * Sets the key.
* *
* Keys can be of any length. DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we * Keys must be 64-bits long or 8 bytes long.
* 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)
{ {
// We check/cut here only up to max length of the key. if (!($this instanceof TripleDES) && strlen($key) != 8) {
// Key padding to the proper length will be done in _setupKey() throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of size 8 are supported');
if (strlen($key) > $this->key_size_max) {
$key = substr($key, 0, $this->key_size_max);
} }
// Sets the key // Sets the key
@ -645,10 +642,10 @@ class DES extends Base
* *
* @see \phpseclib\Crypt\Base::_encryptBlock() * @see \phpseclib\Crypt\Base::_encryptBlock()
* @see \phpseclib\Crypt\Base::encrypt() * @see \phpseclib\Crypt\Base::encrypt()
* @see \phpseclib\Crypt\DES::encrypt() * @see self::encrypt()
* @access private * @access private
* @param String $in * @param string $in
* @return String * @return string
*/ */
function _encryptBlock($in) function _encryptBlock($in)
{ {
@ -660,10 +657,10 @@ class DES extends Base
* *
* @see \phpseclib\Crypt\Base::_decryptBlock() * @see \phpseclib\Crypt\Base::_decryptBlock()
* @see \phpseclib\Crypt\Base::decrypt() * @see \phpseclib\Crypt\Base::decrypt()
* @see \phpseclib\Crypt\DES::decrypt() * @see self::decrypt()
* @access private * @access private
* @param String $in * @param string $in
* @return String * @return string
*/ */
function _decryptBlock($in) function _decryptBlock($in)
{ {
@ -677,12 +674,12 @@ class DES extends Base
* {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
* idea of what this function does. * idea of what this function does.
* *
* @see \phpseclib\Crypt\DES::_encryptBlock() * @see self::_encryptBlock()
* @see \phpseclib\Crypt\DES::_decryptBlock() * @see self::_decryptBlock()
* @access private * @access private
* @param String $block * @param string $block
* @param Integer $mode * @param int $mode
* @return String * @return string
*/ */
function _processBlock($block, $mode) function _processBlock($block, $mode)
{ {
@ -1310,8 +1307,8 @@ class DES extends Base
$des_rounds = $this->des_rounds; $des_rounds = $this->des_rounds;
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function. // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for Crypt_DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit) // (Currently, for DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit)
// (Currently, for Crypt_TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit) // (Currently, for TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );

View File

@ -1,26 +1,19 @@
<?php <?php
/** /**
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions. * Wrapper around hash() and hash_hmac() functions supporting truncated hashes
* such as sha256-96. Any hash algorithm returned by hash_algos() (and
* truncated versions thereof) are supported.
* *
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following: * If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will
* * 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 \phpseclib\Crypt\Hash::setKey() setKey()} is called, {@link \phpseclib\Crypt\Hash::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('sha1'); * $hash = new \phpseclib\Crypt\Hash('sha512');
* *
* $hash->setKey('abcdefg'); * $hash->setKey('abcdefg');
* *
@ -31,7 +24,9 @@
* @category Crypt * @category Crypt
* @package Hash * @package Hash
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton * @copyright 2015 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
*/ */
@ -39,66 +34,39 @@
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
* *
* @see \phpseclib\Crypt\Hash::setHash() * @see self::setHash()
* @var Integer * @var int
* @access private * @access private
*/ */
var $hashParam; var $hashParam;
/**
* Byte-length of compression blocks / key (Internal HMAC)
*
* @see \phpseclib\Crypt\Hash::setAlgorithm()
* @var Integer
* @access private
*/
var $b;
/** /**
* Byte-length of hash output (Internal HMAC) * Byte-length of hash output (Internal HMAC)
* *
* @see \phpseclib\Crypt\Hash::setHash() * @see self::setHash()
* @var Integer * @var int
* @access private * @access private
*/ */
var $l = false; var $length;
/** /**
* Hash Algorithm * Hash Algorithm
* *
* @see \phpseclib\Crypt\Hash::setHash() * @see self::setHash()
* @var String * @var string
* @access private * @access private
*/ */
var $hash; var $hash;
@ -106,17 +74,30 @@ class Hash
/** /**
* Key * Key
* *
* @see \phpseclib\Crypt\Hash::setKey() * @see self::setKey()
* @var String * @var string
* @access private * @access private
*/ */
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)
* *
* @see \phpseclib\Crypt\Hash::setKey() * Used only for sha512/*
* @var String *
* @see self::hash()
* @var string
* @access private * @access private
*/ */
var $opad; var $opad;
@ -124,8 +105,10 @@ class Hash
/** /**
* Inner XOR (Internal HMAC) * Inner XOR (Internal HMAC)
* *
* @see \phpseclib\Crypt\Hash::setKey() * Used only for sha512/*
* @var String *
* @see self::hash()
* @var string
* @access private * @access private
*/ */
var $ipad; var $ipad;
@ -133,26 +116,15 @@ class Hash
/** /**
* Default Constructor. * Default Constructor.
* *
* @param optional String $hash * @param string $hash
* @return \phpseclib\Crypt\Hash
* @access public * @access public
*/ */
function __construct($hash = 'sha1') function __construct($hash = 'sha256')
{ {
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->setHash($hash); $this->setHash($hash);
$this->ipad = str_repeat(chr(0x36), 128);
$this->opad = str_repeat(chr(0x5C), 128);
} }
/** /**
@ -161,7 +133,7 @@ class Hash
* Keys can be of any length. * Keys can be of any length.
* *
* @access public * @access public
* @param optional String $key * @param string $key
*/ */
function setKey($key = false) function setKey($key = false)
{ {
@ -174,7 +146,7 @@ class Hash
* As set by the constructor or by the setHash() method. * As set by the constructor or by the setHash() method.
* *
* @access public * @access public
* @return String * @return string
*/ */
function getHash() function getHash()
{ {
@ -185,405 +157,146 @@ class Hash
* Sets the hash function. * Sets the hash function.
* *
* @access public * @access public
* @param String $hash * @param string $hash
*/ */
function setHash($hash) function setHash($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->l = 12; // 96 / 8 = 12 $this->length = 12; // 96 / 8 = 12
break; break;
case 'md2': case 'md2':
case 'md5': case 'md5':
$this->l = 16; $this->length = 16;
break; break;
case 'sha1': case 'sha1':
$this->l = 20; $this->length = 20;
break;
case 'sha512/224':
$this->length = 28;
break; break;
case 'sha256': case 'sha256':
$this->l = 32; case 'sha512/256':
$this->length = 32;
break; break;
case 'sha384': case 'sha384':
$this->l = 48; $this->length = 48;
break; break;
case 'sha512': case 'sha512':
$this->l = 64; $this->length = 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:
$mode = CRYPT_HASH_MODE; // see if the hash isn't "officially" supported see if it can
} // be "unofficially" supported and calculate the length
// accordingly.
switch ($mode) { if (in_array($hash, hash_algos())) {
case self::MODE_MHASH: $this->length = strlen(hash($hash, '', true));
switch ($hash) { break;
case 'md5':
$this->hash = MHASH_MD5;
break;
case 'sha256':
$this->hash = MHASH_SHA256;
break;
case 'sha1':
default:
$this->hash = MHASH_SHA1;
} }
return; // if the hash algorithm doens't exist maybe it's a truncated
case self::MODE_HASH: // hash, e.g. whirlpool-12 or some such.
switch ($hash) { if (preg_match('#(-\d+)$#', $hash, $matches)) {
case 'md5': $hash = substr($hash, 0, -strlen($matches[1]));
$this->hash = 'md5'; if (in_array($hash, hash_algos())) {
return; $this->length = abs($matches[1]) >> 3;
case 'md2': break;
case 'sha256': }
case 'sha384':
case 'sha512':
$this->hash = $hash;
return;
case 'sha1':
default:
$this->hash = 'sha1';
} }
return; throw new UnsupportedAlgorithmException(
"$hash is not a supported algorithm"
);
} }
switch ($hash) { if ($hash == 'sha512/224' || $hash == 'sha512/256') {
case 'md2': // from http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf#page=24
$this->b = 16; $this->initial = $hash == 'sha512/256' ?
$this->hash = array($this, '_md2'); array(
break; '22312194FC2BF72C', '9F555FA3C84C64C2', '2393B86B6F53B151', '963877195940EABD',
case 'md5': '96283EE2A88EFFE3', 'BE5E1E2553863992', '2B0199FC2C85B8AA', '0EB72DDC81C52CA2'
$this->b = 64; ) :
$this->hash = array($this, '_md5'); array(
break; '8C3D37C819544DA2', '73E1996689DCD4D6', '1DFAB7AE32FF9C82', '679DD514582F9FCF',
case 'sha256': '0F6D2B697BD44DA8', '77E36F7304C48942', '3F9D85A86A1D36C8', '1112E6AD91D692A1'
$this->b = 64; );
$this->hash = array($this, '_sha256'); for ($i = 0; $i < 8; $i++) {
break; $this->initial[$i] = new BigInteger($this->initial[$i], 16);
case 'sha384': $this->initial[$i]->setPrecision(64);
case 'sha512': }
$this->b = 128;
$this->hash = array($this, '_sha512');
break;
case 'sha1':
default:
$this->b = 64;
$this->hash = array($this, '_sha1');
} }
$this->ipad = str_repeat(chr(0x36), $this->b); $this->hash = $hash;
$this->opad = str_repeat(chr(0x5C), $this->b);
} }
/** /**
* Compute the HMAC. * Compute the HMAC.
* *
* @access public * @access public
* @param String $text * @param string $text
* @return String * @return string
*/ */
function hash($text) function hash($text)
{ {
$mode = is_array($this->hash) ? self::MODE_INTERNAL : CRYPT_HASH_MODE; switch ($this->hash) {
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."
if (!empty($this->key) || is_string($this->key)) { -- http://tools.ietf.org/html/rfc2104#section-2 */
switch ($mode) { $key = strlen($this->key) > $this->b ? self::_sha512($this->key, $this->initial) : $this->key;
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."
-- http://tools.ietf.org/html/rfc2104#section-2 */ $key = str_pad($this->key, 128, chr(0)); // step 1
$key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key; $temp = $this->ipad ^ $this->key; // step 2
$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
$key = str_pad($key, $this->b, chr(0)); // step 1 return substr($output, 0, $this->length);
$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 substr($output, 0, $this->l); return strlen($output) > $this->length
? substr($output, 0, $this->length)
: $output;
} }
/** /**
* Returns the hash length (in bytes) * Returns the hash length (in bytes)
* *
* @access public * @access public
* @return Integer * @return int
*/ */
function getLength() function getLength()
{ {
return $this->l; return $this->length;
} }
/** /**
* Wrapper for MD5 * Pure-PHP implementation of SHA512
* *
* @access private * @access private
* @param String $m * @param string $m
*/ */
function _md5($m) static function _sha512($m, $hash)
{ {
return pack('H*', md5($m)); static $k;
}
/**
* 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(
@ -614,8 +327,6 @@ 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
@ -629,7 +340,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($this->_string_shift($chunk, 8), 256); $temp = new BigInteger(self::_string_shift($chunk, 8), 256);
$temp->setPrecision(64); $temp->setPrecision(64);
$w[] = $temp; $w[] = $temp;
} }
@ -650,21 +361,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] = $w[$i - 16]->copy(); $w[$i] = clone $w[$i - 16];
$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 = $hash[0]->copy(); $a = clone $hash[0];
$b = $hash[1]->copy(); $b = clone $hash[1];
$c = $hash[2]->copy(); $c = clone $hash[2];
$d = $hash[3]->copy(); $d = clone $hash[3];
$e = $hash[4]->copy(); $e = clone $hash[4];
$f = $hash[5]->copy(); $f = clone $hash[5];
$g = $hash[6]->copy(); $g = clone $hash[6];
$h = $hash[7]->copy(); $h = clone $hash[7];
// Main loop // Main loop
for ($i = 0; $i < 80; $i++) { for ($i = 0; $i < 80; $i++) {
@ -701,13 +412,13 @@ class Hash
$t1 = $t1->add($k[$i]); $t1 = $t1->add($k[$i]);
$t1 = $t1->add($w[$i]); $t1 = $t1->add($w[$i]);
$h = $g->copy(); $h = clone $g;
$g = $f->copy(); $g = clone $f;
$f = $e->copy(); $f = clone $e;
$e = $d->add($t1); $e = $d->add($t1);
$d = $c->copy(); $d = clone $c;
$c = $b->copy(); $c = clone $b;
$b = $a->copy(); $b = clone $a;
$a = $t1->add($t2); $a = $t1->add($t2);
} }
@ -727,96 +438,22 @@ 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[4]->toBytes() . $hash[5]->toBytes() . $hash[6]->toBytes() . $hash[7]->toBytes();
if ($this->l != 48) {
$temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
}
return $temp; return $temp;
} }
/**
* Right Rotate
*
* @access private
* @param Integer $int
* @param Integer $amt
* @see _sha256()
* @return Integer
*/
function _rightRotate($int, $amt)
{
$invamt = 32 - $amt;
$mask = (1 << $invamt) - 1;
return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
}
/**
* Right Shift
*
* @access private
* @param Integer $int
* @param Integer $amt
* @see _sha256()
* @return Integer
*/
function _rightShift($int, $amt)
{
$mask = (1 << (32 - $amt)) - 1;
return ($int >> $amt) & $mask;
}
/**
* Not
*
* @access private
* @param Integer $int
* @see _sha256()
* @return Integer
*/
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 Integer $...
* @return Integer
* @see _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
* *
* Inspired by array_shift * Inspired by array_shift
* *
* @param String $string * @param string $string
* @param optional Integer $index * @param int $index
* @return String * @return string
* @access private * @access private
*/ */
function _string_shift(&$string, $index = 1) static function _string_shift(&$string, $index = 1)
{ {
$substr = substr($string, 0, $index); $substr = substr($string, 0, $index);
$string = substr($string, $index); $string = substr($string, $index);

View File

@ -35,8 +35,6 @@
namespace phpseclib\Crypt; namespace phpseclib\Crypt;
use phpseclib\Crypt\Base;
/** /**
* Pure-PHP implementation of RC2. * Pure-PHP implementation of RC2.
* *
@ -49,7 +47,7 @@ class RC2 extends Base
* Block Length of the cipher * Block Length of the cipher
* *
* @see \phpseclib\Crypt\Base::block_size * @see \phpseclib\Crypt\Base::block_size
* @var Integer * @var int
* @access private * @access private
*/ */
var $block_size = 8; var $block_size = 8;
@ -58,8 +56,8 @@ class RC2 extends Base
* The Key * The Key
* *
* @see \phpseclib\Crypt\Base::key * @see \phpseclib\Crypt\Base::key
* @see setKey() * @see self::setKey()
* @var String * @var string
* @access private * @access private
*/ */
var $key; var $key;
@ -68,29 +66,37 @@ class RC2 extends Base
* The Original (unpadded) Key * The Original (unpadded) Key
* *
* @see \phpseclib\Crypt\Base::key * @see \phpseclib\Crypt\Base::key
* @see setKey() * @see self::setKey()
* @see encrypt() * @see self::encrypt()
* @see decrypt() * @see self::decrypt()
* @var String * @var string
* @access private * @access private
*/ */
var $orig_key; var $orig_key;
/** /**
* The default password key_size used by setPassword() * Don't truncate / null pad key
* *
* @see \phpseclib\Crypt\Base::password_key_size * @see \phpseclib\Crypt\Base::_clearBuffers()
* @see \phpseclib\Crypt\Base::setPassword() * @var bool
* @var Integer
* @access private * @access private
*/ */
var $password_key_size = 16; // = 128 bits var $skip_key_adjustment = true;
/**
* Key Length (in bytes)
*
* @see \phpseclib\Crypt\RC2::setKeyLength()
* @var int
* @access private
*/
var $key_length = 16; // = 128 bits
/** /**
* The mcrypt specific name of the cipher * The mcrypt specific name of the cipher
* *
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var String * @var string
* @access private * @access private
*/ */
var $cipher_name_mcrypt = 'rc2'; var $cipher_name_mcrypt = 'rc2';
@ -99,7 +105,7 @@ class RC2 extends Base
* Optimizing value while CFB-encrypting * Optimizing value while CFB-encrypting
* *
* @see \phpseclib\Crypt\Base::cfb_init_len * @see \phpseclib\Crypt\Base::cfb_init_len
* @var Integer * @var int
* @access private * @access private
*/ */
var $cfb_init_len = 500; var $cfb_init_len = 500;
@ -107,9 +113,9 @@ class RC2 extends Base
/** /**
* The key length in bits. * The key length in bits.
* *
* @see \phpseclib\Crypt\RC2::setKeyLength() * @see self::setKeyLength()
* @see \phpseclib\Crypt\RC2::setKey() * @see self::setKey()
* @var Integer * @var int
* @access private * @access private
* @internal Should be in range [1..1024]. * @internal Should be in range [1..1024].
* @internal Changing this value after setting the key has no effect. * @internal Changing this value after setting the key has no effect.
@ -119,9 +125,9 @@ class RC2 extends Base
/** /**
* The key length in bits. * The key length in bits.
* *
* @see \phpseclib\Crypt\RC2::isValidEnine() * @see self::isValidEnine()
* @see \phpseclib\Crypt\RC2::setKey() * @see self::setKey()
* @var Integer * @var int
* @access private * @access private
* @internal Should be in range [1..1024]. * @internal Should be in range [1..1024].
*/ */
@ -130,8 +136,8 @@ class RC2 extends Base
/** /**
* The Key Schedule * The Key Schedule
* *
* @see \phpseclib\Crypt\RC2::_setupKey() * @see self::_setupKey()
* @var Array * @var array
* @access private * @access private
*/ */
var $keys; var $keys;
@ -140,8 +146,8 @@ class RC2 extends Base
* Key expansion randomization table. * Key expansion randomization table.
* Twice the same 256-value sequence to save a modulus in key expansion. * Twice the same 256-value sequence to save a modulus in key expansion.
* *
* @see \phpseclib\Crypt\RC2::setKey() * @see self::setKey()
* @var Array * @var array
* @access private * @access private
*/ */
var $pitable = array( var $pitable = array(
@ -214,8 +220,8 @@ class RC2 extends Base
/** /**
* Inverse key expansion randomization table. * Inverse key expansion randomization table.
* *
* @see \phpseclib\Crypt\RC2::setKey() * @see self::setKey()
* @var Array * @var array
* @access private * @access private
*/ */
var $invpitable = array( var $invpitable = array(
@ -253,21 +259,37 @@ 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
* *
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see \phpseclib\Crypt\Base::Crypt_Base() * @see \phpseclib\Crypt\Base::__construct()
* @param Integer $engine * @param int $engine
* @access public * @access public
* @return Boolean * @return bool
*/ */
function isValidEngine($engine) function isValidEngine($engine)
{ {
switch ($engine) { switch ($engine) {
case self::ENGINE_OPENSSL: case self::ENGINE_OPENSSL:
if ($this->current_key_length != 128 || strlen($this->orig_key) != 16) { if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) {
return false; return false;
} }
$this->cipher_name_openssl_ecb = 'rc2-ecb'; $this->cipher_name_openssl_ecb = 'rc2-ecb';
@ -278,26 +300,40 @@ class RC2 extends Base
} }
/** /**
* Sets the key length * Sets the key length.
* *
* Valid key lengths are 1 to 1024. * Valid key lengths are 8 to 1024.
* Calling this function after setting the key has no effect until the next * Calling this function after setting the key has no effect until the next
* \phpseclib\Crypt\RC2::setKey() call. * \phpseclib\Crypt\RC2::setKey() call.
* *
* @access public * @access public
* @param Integer $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 >= 1 && $length <= 1024) { if ($length < 8 || $length > 1024) {
$this->default_key_length = $length; 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 = $this->current_key_length = $length;
}
/**
* Returns the current key length
*
* @access public
* @return int
*/
function getKeyLength()
{
return $this->current_key_length;
} }
/** /**
* Sets the key. * Sets the key.
* *
* Keys can be of any length. RC2, itself, uses 1 to 1024 bit keys (eg. * Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg.
* strlen($key) <= 128), however, we only use the first 128 bytes if $key * strlen($key) <= 128), however, we only use the first 128 bytes if $key
* has more then 128 bytes in it, and set $key to a single null byte if * has more then 128 bytes in it, and set $key to a single null byte if
* it is empty. * it is empty.
@ -307,18 +343,22 @@ class RC2 extends Base
* *
* @see \phpseclib\Crypt\Base::setKey() * @see \phpseclib\Crypt\Base::setKey()
* @access public * @access public
* @param String $key * @param string $key
* @param Integer $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 = 0) function setKey($key, $t1 = false)
{ {
$this->orig_key = $key; $this->orig_key = $key;
if ($t1 <= 0) { if ($t1 === false) {
$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";
@ -349,18 +389,19 @@ class RC2 extends Base
// Prepare the key for mcrypt. // Prepare the key for mcrypt.
$l[0] = $this->invpitable[$l[0]]; $l[0] = $this->invpitable[$l[0]];
array_unshift($l, 'C*'); array_unshift($l, 'C*');
parent::setKey(call_user_func_array('pack', $l)); parent::setKey(call_user_func_array('pack', $l));
} }
/** /**
* Encrypts a message. * Encrypts a message.
* *
* Mostly a wrapper for Crypt_Base::encrypt, with some additional OpenSSL handling code * Mostly a wrapper for \phpseclib\Crypt\Base::encrypt, with some additional OpenSSL handling code
* *
* @see decrypt() * @see self::decrypt()
* @access public * @access public
* @param String $plaintext * @param string $plaintext
* @return String $ciphertext * @return string $ciphertext
*/ */
function encrypt($plaintext) function encrypt($plaintext)
{ {
@ -378,12 +419,12 @@ class RC2 extends Base
/** /**
* Decrypts a message. * Decrypts a message.
* *
* Mostly a wrapper for Crypt_Base::decrypt, with some additional OpenSSL handling code * Mostly a wrapper for \phpseclib\Crypt\Base::decrypt, with some additional OpenSSL handling code
* *
* @see encrypt() * @see self::encrypt()
* @access public * @access public
* @param String $ciphertext * @param string $ciphertext
* @return String $plaintext * @return string $plaintext
*/ */
function decrypt($ciphertext) function decrypt($ciphertext)
{ {
@ -395,7 +436,7 @@ class RC2 extends Base
return $result; return $result;
} }
return parent::encrypt($ciphertext); return parent::decrypt($ciphertext);
} }
/** /**
@ -404,8 +445,8 @@ class RC2 extends Base
* @see \phpseclib\Crypt\Base::_encryptBlock() * @see \phpseclib\Crypt\Base::_encryptBlock()
* @see \phpseclib\Crypt\Base::encrypt() * @see \phpseclib\Crypt\Base::encrypt()
* @access private * @access private
* @param String $in * @param string $in
* @return String * @return string
*/ */
function _encryptBlock($in) function _encryptBlock($in)
{ {
@ -449,8 +490,8 @@ class RC2 extends Base
* @see \phpseclib\Crypt\Base::_decryptBlock() * @see \phpseclib\Crypt\Base::_decryptBlock()
* @see \phpseclib\Crypt\Base::decrypt() * @see \phpseclib\Crypt\Base::decrypt()
* @access private * @access private
* @param String $in * @param string $in
* @return String * @return string
*/ */
function _decryptBlock($in) function _decryptBlock($in)
{ {
@ -538,7 +579,7 @@ class RC2 extends Base
// for the mixing rounds, for better inline crypt performance [~20% faster]. // for the mixing rounds, for better inline crypt performance [~20% faster].
// But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10. // But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
// (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit) // (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit)
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
// Generation of a uniqe hash for our generated code // Generation of a uniqe hash for our generated code
$code_hash = "Crypt_RC2, {$this->mode}"; $code_hash = "Crypt_RC2, {$this->mode}";

View File

@ -44,8 +44,6 @@
namespace phpseclib\Crypt; namespace phpseclib\Crypt;
use phpseclib\Crypt\Base;
/** /**
* Pure-PHP implementation of RC4. * Pure-PHP implementation of RC4.
* *
@ -70,26 +68,25 @@ class RC4 extends Base
* so we the block_size to 0 * so we the block_size to 0
* *
* @see \phpseclib\Crypt\Base::block_size * @see \phpseclib\Crypt\Base::block_size
* @var Integer * @var int
* @access private * @access private
*/ */
var $block_size = 0; var $block_size = 0;
/** /**
* The default password key_size used by setPassword() * Key Length (in bytes)
* *
* @see \phpseclib\Crypt\Base::password_key_size * @see \phpseclib\Crypt\RC4::setKeyLength()
* @see \phpseclib\Crypt\Base::setPassword() * @var int
* @var Integer
* @access private * @access private
*/ */
var $password_key_size = 128; // = 1024 bits var $key_length = 128; // = 1024 bits
/** /**
* The mcrypt specific name of the cipher * The mcrypt specific name of the cipher
* *
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var String * @var string
* @access private * @access private
*/ */
var $cipher_name_mcrypt = 'arcfour'; var $cipher_name_mcrypt = 'arcfour';
@ -106,8 +103,8 @@ class RC4 extends Base
/** /**
* The Key * The Key
* *
* @see \phpseclib\Crypt\RC4::setKey() * @see self::setKey()
* @var String * @var string
* @access private * @access private
*/ */
var $key = "\0"; var $key = "\0";
@ -115,8 +112,8 @@ class RC4 extends Base
/** /**
* The Key Stream for decryption and encryption * The Key Stream for decryption and encryption
* *
* @see \phpseclib\Crypt\RC4::setKey() * @see self::setKey()
* @var Array * @var array
* @access private * @access private
*/ */
var $stream; var $stream;
@ -124,8 +121,6 @@ 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
@ -138,12 +133,12 @@ class RC4 extends Base
/** /**
* Test for engine validity * Test for engine validity
* *
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see Crypt_Base::Crypt_Base() * @see \phpseclib\Crypt\Base::__construct()
* @param Integer $engine * @param int $engine
* @access public * @access public
* @return Boolean * @return bool
*/ */
function isValidEngine($engine) function isValidEngine($engine)
{ {
@ -168,51 +163,63 @@ class RC4 extends Base
} }
/** /**
* Dummy function. * RC4 does not use an IV
* *
* 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 \phpseclib\Crypt\RC4::setKey()
* @access public * @access public
* @return bool
*/ */
function setIV($iv) function usesIV()
{ {
return false;
} }
/** /**
* Sets the key. * Sets the key length
* *
* Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will * Keys can be between 1 and 256 bytes long.
* be used. If no key is explicitly set, it'll be assumed to be a single null byte.
* *
* @access public * @access public
* @see \phpseclib\Crypt\Base::setKey() * @param int $length
* @param String $key * @throws \LengthException if the key length is invalid
*/
function setKeyLength($length)
{
if ($length < 8 || $length > 2048) {
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 = $length >> 3;
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) function setKey($key)
{ {
parent::setKey(substr($key, 0, 256)); $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.
* *
* @see \phpseclib\Crypt\Base::decrypt() * @see \phpseclib\Crypt\Base::decrypt()
* @see \phpseclib\Crypt\RC4::_crypt() * @see self::_crypt()
* @access public * @access public
* @param String $plaintext * @param string $plaintext
* @return String $ciphertext * @return string $ciphertext
*/ */
function encrypt($plaintext) function encrypt($plaintext)
{ {
@ -229,10 +236,10 @@ class RC4 extends Base
* At least if the continuous buffer is disabled. * At least if the continuous buffer is disabled.
* *
* @see \phpseclib\Crypt\Base::encrypt() * @see \phpseclib\Crypt\Base::encrypt()
* @see \phpseclib\Crypt\RC4::_crypt() * @see self::_crypt()
* @access public * @access public
* @param String $ciphertext * @param string $ciphertext
* @return String $plaintext * @return string $plaintext
*/ */
function decrypt($ciphertext) function decrypt($ciphertext)
{ {
@ -246,7 +253,7 @@ class RC4 extends Base
* Encrypts a block * Encrypts a block
* *
* @access private * @access private
* @param String $in * @param string $in
*/ */
function _encryptBlock($in) function _encryptBlock($in)
{ {
@ -257,7 +264,7 @@ class RC4 extends Base
* Decrypts a block * Decrypts a block
* *
* @access private * @access private
* @param String $in * @param string $in
*/ */
function _decryptBlock($in) function _decryptBlock($in)
{ {
@ -294,12 +301,12 @@ class RC4 extends Base
/** /**
* Encrypts or decrypts a message. * Encrypts or decrypts a message.
* *
* @see \phpseclib\Crypt\RC4::encrypt() * @see self::encrypt()
* @see \phpseclib\Crypt\RC4::decrypt() * @see self::decrypt()
* @access private * @access private
* @param String $text * @param string $text
* @param Integer $mode * @param int $mode
* @return String $text * @return string $text
*/ */
function _crypt($text, $mode) function _crypt($text, $mode)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,223 @@
<?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;
}
}

View File

@ -0,0 +1,485 @@
<?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;
}
}

View File

@ -0,0 +1,172 @@
<?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;
}
}

View File

@ -0,0 +1,208 @@
<?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;
}
}

View File

@ -0,0 +1,311 @@
<?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;
}
}

103
phpseclib/Crypt/RSA/Raw.php Normal file
View File

@ -0,0 +1,103 @@
<?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);
}
}

146
phpseclib/Crypt/RSA/XML.php Normal file
View File

@ -0,0 +1,146 @@
<?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>';
}
}

View File

@ -24,14 +24,6 @@
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
* *
@ -48,56 +40,23 @@ class Random
* microoptimizations because this function has the potential of being called a huge number of times. * microoptimizations because this function has the potential of being called a huge number of times.
* eg. for RSA key generation. * eg. for RSA key generation.
* *
* @param Integer $length * @param int $length
* @return String * @throws \RuntimeException if a symmetric cipher is needed but not loaded
* @return string
*/ */
public static function string($length) static function string($length)
{ {
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { try {
// method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call. return \random_bytes($length);
// ie. class_alias is a function that was introduced in PHP 5.3 } catch (\Exception $e) {
if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) { // random_compat will throw an Exception, which in PHP 5 does not implement Throwable
return mcrypt_create_iv($length); } catch (\Throwable $e) {
} // If a sufficient source of randomness is unavailable, random_bytes() will throw an
// method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was, // object that implements the Throwable interface (Exception, TypeError, Error).
// to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4 // We don't actually need to do anything here. The string() method should just continue
// openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both // as normal. Note, however, that if we don't have a sufficient source of randomness for
// call php_win32_get_random_bytes(): // random_bytes(), most of the other calls here will fail too, so we'll end up using
// // the PHP implementation.
// 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 (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
return openssl_random_pseudo_bytes($length);
}
} else {
// method 1. the fastest
if (function_exists('openssl_random_pseudo_bytes')) {
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 (function_exists('mcrypt_create_iv')) {
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
@ -135,13 +94,13 @@ class Random
session_start(); session_start();
$v = $seed = $_SESSION['seed'] = pack('H*', sha1( $v = $seed = $_SESSION['seed'] = pack('H*', sha1(
serialize($_SERVER) . (isset($_SERVER) ? self::safe_serialize($_SERVER) : '') .
serialize($_POST) . (isset($_POST) ? self::safe_serialize($_POST) : '') .
serialize($_GET) . (isset($_GET) ? self::safe_serialize($_GET) : '') .
serialize($_COOKIE) . (isset($_COOKIE) ? self::safe_serialize($_COOKIE) : '') .
serialize($GLOBALS) . self::safe_serialize($GLOBALS) .
serialize($_SESSION) . self::safe_serialize($_SESSION) .
serialize($_OLD_SESSION) self::safe_serialize($_OLD_SESSION)
)); ));
if (!isset($_SESSION['count'])) { if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0; $_SESSION['count'] = 0;
@ -199,8 +158,7 @@ class Random
$crypto = new RC4(); $crypto = new RC4();
break; break;
default: default:
user_error(__CLASS__ . ' requires at least one symmetric cipher be loaded'); throw new \RuntimeException(__CLASS__ . ' requires at least one symmetric cipher be loaded');
return false;
} }
$crypto->setKey($key); $crypto->setKey($key);
@ -227,4 +185,36 @@ class Random
} }
return substr($result, 0, $length); return substr($result, 0, $length);
} }
/**
* Safely serialize variables
*
* If a class has a private __sleep() it'll emit a warning
*
* @param mixed $arr
* @access public
*/
function safe_serialize(&$arr)
{
if (is_object($arr)) {
return '';
}
if (!is_array($arr)) {
return serialize($arr);
}
// prevent circular array recursion
if (isset($arr['__phpseclib_marker'])) {
return '';
}
$safearr = array();
$arr['__phpseclib_marker'] = true;
foreach (array_keys($arr) as $key) {
// do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
if ($key !== '__phpseclib_marker') {
$safearr[$key] = self::safe_serialize($arr[$key]);
}
}
unset($arr['__phpseclib_marker']);
return serialize($safearr);
}
} }

View File

@ -7,11 +7,11 @@
* *
* PHP version 5 * PHP version 5
* *
* If {@link \phpseclib\Crypt\Rijndael::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If * If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If
* {@link \phpseclib\Crypt\Rijndael::setKeyLength() setKeyLength()} isn't called, it'll be calculated from * {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link \phpseclib\Crypt\Rijndael::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's
* 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
* {@link \phpseclib\Crypt\Rijndael::setKey() setKey()} is called, again, at which point, it'll be recalculated. * {@link self::setKey() setKey()} is called, again, at which point, it'll be recalculated.
* *
* Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length. mcrypt, for example, * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length. mcrypt, for example,
* does not. AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256. * does not. AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
@ -54,8 +54,6 @@
namespace phpseclib\Crypt; namespace phpseclib\Crypt;
use phpseclib\Crypt\Base;
/** /**
* Pure-PHP implementation of Rijndael. * Pure-PHP implementation of Rijndael.
* *
@ -65,28 +63,18 @@ use phpseclib\Crypt\Base;
*/ */
class Rijndael extends Base class Rijndael extends Base
{ {
/**
* The default password key_size used by setPassword()
*
* @see \phpseclib\Crypt\Base::password_key_size
* @see \phpseclib\Crypt\Base::setPassword()
* @var Integer
* @access private
*/
var $password_key_size = 16;
/** /**
* The mcrypt specific name of the cipher * The mcrypt specific name of the cipher
* *
* Mcrypt is useable for 128/192/256-bit $block_size/$key_size. For 160/224 not. * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
* \phpseclib\Crypt\Rijndael determines automatically whether mcrypt is useable * \phpseclib\Crypt\Rijndael determines automatically whether mcrypt is useable
* or not for the current $block_size/$key_size. * or not for the current $block_size/$key_length.
* In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly. * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
* *
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @see \phpseclib\Crypt\Base::engine * @see \phpseclib\Crypt\Base::engine
* @see isValidEngine() * @see self::isValidEngine()
* @var String * @var string
* @access private * @access private
*/ */
var $cipher_name_mcrypt = 'rijndael-128'; var $cipher_name_mcrypt = 'rijndael-128';
@ -96,25 +84,16 @@ class Rijndael extends Base
* *
* @see \phpseclib\Crypt\Base::password_default_salt * @see \phpseclib\Crypt\Base::password_default_salt
* @see \phpseclib\Crypt\Base::setPassword() * @see \phpseclib\Crypt\Base::setPassword()
* @var String * @var string
* @access private * @access private
*/ */
var $password_default_salt = 'phpseclib'; var $password_default_salt = 'phpseclib';
/**
* Has the key length explicitly been set or should it be derived from the key, itself?
*
* @see setKeyLength()
* @var Boolean
* @access private
*/
var $explicit_key_length = false;
/** /**
* The Key Schedule * The Key Schedule
* *
* @see _setup() * @see self::_setup()
* @var Array * @var array
* @access private * @access private
*/ */
var $w; var $w;
@ -122,8 +101,8 @@ class Rijndael extends Base
/** /**
* The Inverse Key Schedule * The Inverse Key Schedule
* *
* @see _setup() * @see self::_setup()
* @var Array * @var array
* @access private * @access private
*/ */
var $dw; var $dw;
@ -131,8 +110,8 @@ class Rijndael extends Base
/** /**
* The Block Length divided by 32 * The Block Length divided by 32
* *
* @see setBlockLength() * @see self::setBlockLength()
* @var Integer * @var int
* @access private * @access private
* @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
* because the encryption / decryption / key schedule creation requires this number and not $block_size. We could * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
@ -142,23 +121,23 @@ class Rijndael extends Base
var $Nb = 4; var $Nb = 4;
/** /**
* The Key Length * The Key Length (in bytes)
* *
* @see setKeyLength() * @see self::setKeyLength()
* @var Integer * @var int
* @access private * @access private
* @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
* because the encryption / decryption / key schedule creation requires this number and not $key_size. We could * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
* derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
* of that, we'll just precompute it once. * of that, we'll just precompute it once.
*/ */
var $key_size = 16; var $key_length = 16;
/** /**
* The Key Length divided by 32 * The Key Length divided by 32
* *
* @see setKeyLength() * @see self::setKeyLength()
* @var Integer * @var int
* @access private * @access private
* @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4 * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
*/ */
@ -167,7 +146,7 @@ class Rijndael extends Base
/** /**
* The Number of Rounds * The Number of Rounds
* *
* @var Integer * @var int
* @access private * @access private
* @internal The max value is 14, the min value is 10. * @internal The max value is 14, the min value is 10.
*/ */
@ -176,7 +155,7 @@ class Rijndael extends Base
/** /**
* Shift offsets * Shift offsets
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $c; var $c;
@ -184,7 +163,7 @@ class Rijndael extends Base
/** /**
* Holds the last used key- and block_size information * Holds the last used key- and block_size information
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $kl; var $kl;
@ -192,72 +171,23 @@ class Rijndael extends Base
/** /**
* Default Constructor. * Default Constructor.
* *
* Determines whether or not the mcrypt extension should be used. * @param int $mode
*
* $mode could be:
*
* - \phpseclib\Crypt\Base::MODE_ECB
*
* - \phpseclib\Crypt\Base::MODE_CBC
*
* - \phpseclib\Crypt\Base::MODE_CTR
*
* - \phpseclib\Crypt\Base::MODE_CFB
*
* - \phpseclib\Crypt\Base::MODE_OFB
*
* If not explictly set, \phpseclib\Crypt\Base::MODE_CBC will be used.
*
* @see \phpseclib\Crypt\Base::Crypt_Base()
* @param optional Integer $mode
* @access public * @access public
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
/**
* Sets the key.
*
* Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
* whose length is a multiple of 32. If the key is less than 256-bits and the key length isn't set, we round the length
* up to the closest valid key length, padding $key with null bytes. If the key is more than 256-bits, we trim the
* excess bits.
*
* If the key is not explicitly set, it'll be assumed to be all null bytes.
*
* Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits.
*
* @see \phpseclib\Crypt\Base:setKey()
* @see setKeyLength()
* @access public
* @param String $key
*/ */
function setKey($key) function __construct($mode)
{ {
if (!$this->explicit_key_length) { if ($mode == self::MODE_STREAM) {
$length = strlen($key); throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
switch (true) {
case $length <= 16:
$this->key_size = 16;
break;
case $length <= 20:
$this->key_size = 20;
break;
case $length <= 24:
$this->key_size = 24;
break;
case $length <= 28:
$this->key_size = 28;
break;
default:
$this->key_size = 32;
}
} }
parent::setKey($key);
parent::__construct($mode);
} }
/** /**
* Sets the key length * Sets the key length.
* *
* Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to * Valid key lengths are 128, 160, 192, 224, and 256.
* 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
@ -271,51 +201,75 @@ class Rijndael extends Base
* This results then in slower encryption. * This results then in slower encryption.
* *
* @access public * @access public
* @param Integer $length * @throws \LengthException if the key length is invalid
* @param int $length
*/ */
function setKeyLength($length) function setKeyLength($length)
{ {
switch (true) { switch ($length) {
case $length == 160: case 128:
$this->key_size = 20; case 160:
break; case 192:
case $length == 224: case 224:
$this->key_size = 28; case 256:
break; $this->key_length = $length >> 3;
case $length <= 128:
$this->key_size = 16;
break;
case $length <= 192:
$this->key_size = 24;
break; break;
default: default:
$this->key_size = 32; 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->explicit_key_length = true; parent::setKeyLength($length);
$this->changed = true; }
$this->_setEngine();
/**
* 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. If the length is less than 128, it will be rounded up to * Valid block lengths are 128, 160, 192, 224, and 256.
* 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 Integer $length * @param int $length
*/ */
function setBlockLength($length) function setBlockLength($length)
{ {
$length >>= 5; switch ($length) {
if ($length > 8) { case 128:
$length = 8; case 160:
} elseif ($length < 4) { case 192:
$length = 4; case 224:
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->block_size = $length << 2; $this->Nb = $length >> 5;
$this->block_size = $length >> 3;
$this->changed = true; $this->changed = true;
$this->_setEngine(); $this->_setEngine();
} }
@ -325,10 +279,10 @@ class Rijndael extends Base
* *
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see \phpseclib\Crypt\Base::Crypt_Base() * @see \phpseclib\Crypt\Base::__construct()
* @param Integer $engine * @param int $engine
* @access public * @access public
* @return Boolean * @return bool
*/ */
function isValidEngine($engine) function isValidEngine($engine)
{ {
@ -337,12 +291,12 @@ class Rijndael extends Base
if ($this->block_size != 16) { if ($this->block_size != 16) {
return false; return false;
} }
$this->cipher_name_openssl_ecb = 'aes-' . ($this->key_size << 3) . '-ecb'; $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
$this->cipher_name_openssl = 'aes-' . ($this->key_size << 3) . '-' . $this->_openssl_translate_mode(); $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode();
break; break;
case self::ENGINE_MCRYPT: case self::ENGINE_MCRYPT:
$this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3); $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
if ($this->key_size % 8) { // is it a 160/224-bit key? if ($this->key_length % 8) { // is it a 160/224-bit key?
// mcrypt is not usable for them, only for 128/192/256-bit keys // mcrypt is not usable for them, only for 128/192/256-bit keys
return false; return false;
} }
@ -351,24 +305,12 @@ class Rijndael extends Base
return parent::isValidEngine($engine); return parent::isValidEngine($engine);
} }
/**
* Setup the \phpseclib\Crypt\Base::ENGINE_MCRYPT $engine
*
* @see \phpseclib\Crypt\Base::_setupMcrypt()
* @access private
*/
function _setupMcrypt()
{
$this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0");
parent::_setupMcrypt();
}
/** /**
* Encrypts a block * Encrypts a block
* *
* @access private * @access private
* @param String $in * @param string $in
* @return String * @return string
*/ */
function _encryptBlock($in) function _encryptBlock($in)
{ {
@ -468,8 +410,8 @@ class Rijndael extends Base
* Decrypts a block * Decrypts a block
* *
* @access private * @access private
* @param String $in * @param string $in
* @return String * @return string
*/ */
function _decryptBlock($in) function _decryptBlock($in)
{ {
@ -573,15 +515,13 @@ class Rijndael extends Base
0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
); );
$this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0"); if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_size === $this->kl['key_size'] && $this->block_size === $this->kl['block_size']) {
// already expanded // already expanded
return; return;
} }
$this->kl = array('key' => $this->key, 'key_size' => $this->key_size, 'block_size' => $this->block_size); $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size);
$this->Nk = $this->key_size >> 2; $this->Nk = $this->key_length >> 2;
// see Rijndael-ammended.pdf#page=44 // see Rijndael-ammended.pdf#page=44
$this->Nr = max($this->Nk, $this->Nb) + 6; $this->Nr = max($this->Nk, $this->Nb) + 6;
@ -673,13 +613,13 @@ class Rijndael extends Base
* Performs S-Box substitutions * Performs S-Box substitutions
* *
* @access private * @access private
* @param Integer $word * @param int $word
*/ */
function _subWord($word) function _subWord($word)
{ {
static $sbox; static $sbox;
if (empty($sbox)) { if (empty($sbox)) {
list(,,,, $sbox) = $this->_getTables(); list(, , , , $sbox) = $this->_getTables();
} }
return $sbox[$word & 0x000000FF] | return $sbox[$word & 0x000000FF] |
@ -691,11 +631,11 @@ class Rijndael extends Base
/** /**
* Provides the mixColumns and sboxes tables * Provides the mixColumns and sboxes tables
* *
* @see Crypt_Rijndael:_encryptBlock() * @see self::_encryptBlock()
* @see Crypt_Rijndael:_setupInlineCrypt() * @see self::_setupInlineCrypt()
* @see Crypt_Rijndael:_subWord() * @see self::_subWord()
* @access private * @access private
* @return Array &$tables * @return array &$tables
*/ */
function &_getTables() function &_getTables()
{ {
@ -780,11 +720,11 @@ class Rijndael extends Base
/** /**
* Provides the inverse mixColumns and inverse sboxes tables * Provides the inverse mixColumns and inverse sboxes tables
* *
* @see Crypt_Rijndael:_decryptBlock() * @see self::_decryptBlock()
* @see Crypt_Rijndael:_setupInlineCrypt() * @see self::_setupInlineCrypt()
* @see Crypt_Rijndael:_setupKey() * @see self::_setupKey()
* @access private * @access private
* @return Array &$tables * @return array &$tables
*/ */
function &_getInvTables() function &_getInvTables()
{ {
@ -878,7 +818,7 @@ class Rijndael extends Base
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function. // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit) // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one. // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
// Generation of a uniqe hash for our generated code // Generation of a uniqe hash for our generated code
$code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}"; $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}";

View File

@ -36,9 +36,6 @@
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.
* *
@ -48,7 +45,6 @@ use phpseclib\Crypt\DES;
*/ */
class TripleDES extends DES class TripleDES extends DES
{ {
/** /**
* Encrypt / decrypt using inner chaining * Encrypt / decrypt using inner chaining
* *
@ -60,26 +56,24 @@ class TripleDES extends DES
* Encrypt / decrypt using outer chaining * Encrypt / decrypt using outer chaining
* *
* Outer chaining is used by SSH-2 and when the mode is set to \phpseclib\Crypt\Base::MODE_CBC. * Outer chaining is used by SSH-2 and when the mode is set to \phpseclib\Crypt\Base::MODE_CBC.
*/ */
const MODE_CBC3 = Base::MODE_CBC; const MODE_CBC3 = Base::MODE_CBC;
/** /**
* The default password key_size used by setPassword() * Key Length (in bytes)
* *
* @see \phpseclib\Crypt\DES::password_key_size * @see \phpseclib\Crypt\TripleDES::setKeyLength()
* @see \phpseclib\Crypt\Base::password_key_size * @var int
* @see \phpseclib\Crypt\Base::setPassword()
* @var Integer
* @access private * @access private
*/ */
var $password_key_size = 24; var $key_length = 24;
/** /**
* The default salt used by setPassword() * The default salt used by setPassword()
* *
* @see \phpseclib\Crypt\Base::password_default_salt * @see \phpseclib\Crypt\Base::password_default_salt
* @see \phpseclib\Crypt\Base::setPassword() * @see \phpseclib\Crypt\Base::setPassword()
* @var String * @var string
* @access private * @access private
*/ */
var $password_default_salt = 'phpseclib'; var $password_default_salt = 'phpseclib';
@ -89,7 +83,7 @@ class TripleDES extends DES
* *
* @see \phpseclib\Crypt\DES::cipher_name_mcrypt * @see \phpseclib\Crypt\DES::cipher_name_mcrypt
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var String * @var string
* @access private * @access private
*/ */
var $cipher_name_mcrypt = 'tripledes'; var $cipher_name_mcrypt = 'tripledes';
@ -98,7 +92,7 @@ class TripleDES extends DES
* Optimizing value while CFB-encrypting * Optimizing value while CFB-encrypting
* *
* @see \phpseclib\Crypt\Base::cfb_init_len * @see \phpseclib\Crypt\Base::cfb_init_len
* @var Integer * @var int
* @access private * @access private
*/ */
var $cfb_init_len = 750; var $cfb_init_len = 750;
@ -106,17 +100,17 @@ class TripleDES extends DES
/** /**
* max possible size of $key * max possible size of $key
* *
* @see \phpseclib\Crypt\TripleDES::setKey() * @see self::setKey()
* @see \phpseclib\Crypt\DES::setKey() * @see \phpseclib\Crypt\DES::setKey()
* @var String * @var string
* @access private * @access private
*/ */
var $key_size_max = 24; var $key_length_max = 24;
/** /**
* Internal flag whether using self::MODE_3CBC or not * Internal flag whether using self::MODE_3CBC or not
* *
* @var Boolean * @var bool
* @access private * @access private
*/ */
var $mode_3cbc; var $mode_3cbc;
@ -126,7 +120,7 @@ class TripleDES extends DES
* *
* Used only if $mode_3cbc === true * Used only if $mode_3cbc === true
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $des; var $des;
@ -134,7 +128,7 @@ class TripleDES extends DES
/** /**
* Default Constructor. * Default Constructor.
* *
* Determines whether or not the mcrypt extension should be used. * Determines whether or not the mcrypt or OpenSSL extensions should be used.
* *
* $mode could be: * $mode could be:
* *
@ -148,16 +142,14 @@ class TripleDES extends DES
* *
* - \phpseclib\Crypt\Base::MODE_OFB * - \phpseclib\Crypt\Base::MODE_OFB
* *
* - \phpseclib\Crypt\TripleDES::MODE_3CBC * - \phpseclib\Crypt\TripleDES::MODE_3CB
*
* 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 optional Integer $mode * @param int $mode
* @access public * @access public
*/ */
function __construct($mode = Base::MODE_CBC) function __construct($mode)
{ {
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
@ -189,10 +181,10 @@ class TripleDES extends DES
* *
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see \phpseclib\Crypt\Base::Crypt_Base() * @see \phpseclib\Crypt\Base::__construct()
* @param Integer $engine * @param int $engine
* @access public * @access public
* @return Boolean * @return bool
*/ */
function isValidEngine($engine) function isValidEngine($engine)
{ {
@ -206,14 +198,13 @@ class TripleDES extends DES
} }
/** /**
* Sets the initialization vector. (optional) * Sets the initialization vector.
* *
* SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used. If not explicitly set, it'll be assumed * SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used.
* to be all zero's.
* *
* @see \phpseclib\Crypt\Base::setIV() * @see \phpseclib\Crypt\Base::setIV()
* @access public * @access public
* @param String $iv * @param string $iv
*/ */
function setIV($iv) function setIV($iv)
{ {
@ -225,39 +216,66 @@ class TripleDES extends DES
} }
} }
/**
* Sets the key length.
*
* Valid key lengths are 128 and 192 bits.
*
* If you want to use a 64-bit key use DES.php
*
* @see \phpseclib\Crypt\Base:setKeyLength()
* @access public
* @throws \LengthException if the key length is invalid
* @param int $length
*/
function setKeyLength($length)
{
switch ($length) {
case 128:
case 192:
break;
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');
}
parent::setKeyLength($length);
}
/** /**
* Sets the key. * Sets the key.
* *
* Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or * Triple DES can use 128-bit (eg. strlen($key) == 16) or 192-bit (eg. strlen($key) == 24) keys.
* 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()
* @param String $key * @throws \LengthException if the key length is invalid
* @param string $key
*/ */
function setKey($key) function setKey($key)
{ {
$length = strlen($key); if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) {
if ($length > 8) { throw new \LengthException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes');
$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);
// And in case of self::MODE_3CBC: switch (strlen($key)) {
// if key <= 64bits we not need the 3 $des to work, case 16:
// because we will then act as regular DES-CBC with just a <= 64bit key. $key.= substr($key, 0, 8);
// So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des. case 24:
if ($this->mode_3cbc && $length > 8) { break;
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));
@ -269,8 +287,8 @@ class TripleDES extends DES
* *
* @see \phpseclib\Crypt\Base::encrypt() * @see \phpseclib\Crypt\Base::encrypt()
* @access public * @access public
* @param String $plaintext * @param string $plaintext
* @return String $cipertext * @return string $cipertext
*/ */
function encrypt($plaintext) function encrypt($plaintext)
{ {
@ -296,8 +314,8 @@ class TripleDES extends DES
* *
* @see \phpseclib\Crypt\Base::decrypt() * @see \phpseclib\Crypt\Base::decrypt()
* @access public * @access public
* @param String $ciphertext * @param string $ciphertext
* @return String $plaintext * @return string $plaintext
*/ */
function decrypt($ciphertext) function decrypt($ciphertext)
{ {
@ -351,7 +369,7 @@ class TripleDES extends DES
* however, they are also less intuitive and more likely to cause you problems. * however, they are also less intuitive and more likely to cause you problems.
* *
* @see \phpseclib\Crypt\Base::enableContinuousBuffer() * @see \phpseclib\Crypt\Base::enableContinuousBuffer()
* @see \phpseclib\Crypt\TripleDES::disableContinuousBuffer() * @see self::disableContinuousBuffer()
* @access public * @access public
*/ */
function enableContinuousBuffer() function enableContinuousBuffer()
@ -370,7 +388,7 @@ class TripleDES extends DES
* The default behavior. * The default behavior.
* *
* @see \phpseclib\Crypt\Base::disableContinuousBuffer() * @see \phpseclib\Crypt\Base::disableContinuousBuffer()
* @see \phpseclib\Crypt\TripleDES::enableContinuousBuffer() * @see self::enableContinuousBuffer()
* @access public * @access public
*/ */
function disableContinuousBuffer() function disableContinuousBuffer()
@ -421,11 +439,11 @@ class TripleDES extends DES
/** /**
* Sets the internal crypt engine * Sets the internal crypt engine
* *
* @see \phpseclib\Crypt\Base::Crypt_Base() * @see \phpseclib\Crypt\Base::__construct()
* @see \phpseclib\Crypt\Base::setPreferredEngine() * @see \phpseclib\Crypt\Base::setPreferredEngine()
* @param Integer $engine * @param int $engine
* @access public * @access public
* @return Integer * @return int
*/ */
function setPreferredEngine($engine) function setPreferredEngine($engine)
{ {

View File

@ -37,8 +37,6 @@
namespace phpseclib\Crypt; namespace phpseclib\Crypt;
use phpseclib\Crypt\Base;
/** /**
* Pure-PHP implementation of Twofish. * Pure-PHP implementation of Twofish.
* *
@ -53,7 +51,7 @@ class Twofish extends Base
* The mcrypt specific name of the cipher * The mcrypt specific name of the cipher
* *
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
* @var String * @var string
* @access private * @access private
*/ */
var $cipher_name_mcrypt = 'twofish'; var $cipher_name_mcrypt = 'twofish';
@ -62,7 +60,7 @@ class Twofish extends Base
* Optimizing value while CFB-encrypting * Optimizing value while CFB-encrypting
* *
* @see \phpseclib\Crypt\Base::cfb_init_len * @see \phpseclib\Crypt\Base::cfb_init_len
* @var Integer * @var int
* @access private * @access private
*/ */
var $cfb_init_len = 800; var $cfb_init_len = 800;
@ -70,10 +68,10 @@ class Twofish extends Base
/** /**
* Q-Table * Q-Table
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $q0 = array ( var $q0 = array(
0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38, 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
@ -111,10 +109,10 @@ class Twofish extends Base
/** /**
* Q-Table * Q-Table
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $q1 = array ( var $q1 = array(
0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
@ -152,10 +150,10 @@ class Twofish extends Base
/** /**
* M-Table * M-Table
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $m0 = array ( var $m0 = array(
0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8, 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8,
0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B,
0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
@ -193,10 +191,10 @@ class Twofish extends Base
/** /**
* M-Table * M-Table
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $m1 = array ( var $m1 = array(
0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4, 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4,
0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A,
0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
@ -234,10 +232,10 @@ class Twofish extends Base
/** /**
* M-Table * M-Table
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $m2 = array ( var $m2 = array(
0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA, 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA,
0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7,
0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
@ -275,10 +273,10 @@ class Twofish extends Base
/** /**
* M-Table * M-Table
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $m3 = array ( var $m3 = array(
0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF, 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF,
0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836,
0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
@ -316,7 +314,7 @@ class Twofish extends Base
/** /**
* The Key Schedule Array * The Key Schedule Array
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $K = array(); var $K = array();
@ -324,7 +322,7 @@ class Twofish extends Base
/** /**
* The Key depended S-Table 0 * The Key depended S-Table 0
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $S0 = array(); var $S0 = array();
@ -332,7 +330,7 @@ class Twofish extends Base
/** /**
* The Key depended S-Table 1 * The Key depended S-Table 1
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $S1 = array(); var $S1 = array();
@ -340,7 +338,7 @@ class Twofish extends Base
/** /**
* The Key depended S-Table 2 * The Key depended S-Table 2
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $S2 = array(); var $S2 = array();
@ -348,7 +346,7 @@ class Twofish extends Base
/** /**
* The Key depended S-Table 3 * The Key depended S-Table 3
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $S3 = array(); var $S3 = array();
@ -356,40 +354,79 @@ class Twofish extends Base
/** /**
* Holds the last used key * Holds the last used key
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $kl; var $kl;
/** /**
* Sets the key. * The Key Length (in bytes)
* *
* Keys can be of any length. Twofish, itself, requires the use of a key that's 128, 192 or 256-bits long. * @see Crypt_Twofish::setKeyLength()
* If the key is less than 256-bits we round the length up to the closest valid key length, * @var int
* padding $key with null bytes. If the key is more than 256-bits, we trim the excess bits. * @access private
*/
var $key_length = 16;
/**
* Default Constructor.
* *
* If the key is not explicitly set, it'll be assumed a 128 bits key to be all null bytes. * @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.
*
* Valid key lengths are 128, 192 or 256 bits
* *
* @access public * @access public
* @see \phpseclib\Crypt\Base::setKey() * @param int $length
* @param String $key */
function setKeyLength($length)
{
switch ($length) {
case 128:
case 192:
case 256:
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::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) function setKey($key)
{ {
$keylength = strlen($key); switch (strlen($key)) {
switch (true) { case 16:
case $keylength <= 16: case 24:
$key = str_pad($key, 16, "\0"); case 32:
break; break;
case $keylength <= 24: default:
$key = str_pad($key, 24, "\0"); throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
break;
case $keylength < 32:
$key = str_pad($key, 32, "\0");
break;
case $keylength > 32:
$key = substr($key, 0, 32);
} }
parent::setKey($key); parent::setKey($key);
} }
@ -421,9 +458,9 @@ class Twofish extends Base
switch (strlen($this->key)) { switch (strlen($this->key)) {
case 16: case 16:
list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]); list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]); list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]);
for ($i = 0, $j = 1; $i < 40; $i+= 2,$j+= 2) { for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
$A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^ $A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^ $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^
$m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^ $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^
@ -444,9 +481,9 @@ class Twofish extends Base
} }
break; break;
case 24: case 24:
list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]); list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]); list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]);
list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]); list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]);
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) { for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
$A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^ $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
@ -468,10 +505,10 @@ class Twofish extends Base
} }
break; break;
default: // 32 default: // 32
list ($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]); list($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]); list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]);
list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]); list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]);
list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]); list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]);
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) { for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
$A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^ $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
@ -504,9 +541,9 @@ class Twofish extends Base
* _mdsrem function using by the twofish cipher algorithm * _mdsrem function using by the twofish cipher algorithm
* *
* @access private * @access private
* @param String $A * @param string $A
* @param String $B * @param string $B
* @return Array * @return array
*/ */
function _mdsrem($A, $B) function _mdsrem($A, $B)
{ {
@ -552,8 +589,8 @@ class Twofish extends Base
* Encrypts a block * Encrypts a block
* *
* @access private * @access private
* @param String $in * @param string $in
* @return String * @return string
*/ */
function _encryptBlock($in) function _encryptBlock($in)
{ {
@ -608,8 +645,8 @@ class Twofish extends Base
* Decrypts a block * Decrypts a block
* *
* @access private * @access private
* @param String $in * @param string $in
* @return String * @return string
*/ */
function _decryptBlock($in) function _decryptBlock($in)
{ {
@ -672,7 +709,7 @@ class Twofish extends Base
// Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one. // Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
// (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit) // (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit)
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
// Generation of a uniqe hash for our generated code // Generation of a uniqe hash for our generated code
$code_hash = "Crypt_Twofish, {$this->mode}"; $code_hash = "Crypt_Twofish, {$this->mode}";

View File

@ -0,0 +1,26 @@
<?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
{
}

View File

@ -0,0 +1,26 @@
<?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
{
}

View File

@ -0,0 +1,26 @@
<?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
{
}

View File

@ -0,0 +1,26 @@
<?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
{
}

View File

@ -32,7 +32,7 @@ class ANSI
/** /**
* Max Width * Max Width
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $max_x; var $max_x;
@ -40,7 +40,7 @@ class ANSI
/** /**
* Max Height * Max Height
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $max_y; var $max_y;
@ -48,7 +48,7 @@ class ANSI
/** /**
* Max History * Max History
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $max_history; var $max_history;
@ -56,7 +56,7 @@ class ANSI
/** /**
* History * History
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $history; var $history;
@ -64,7 +64,7 @@ class ANSI
/** /**
* History Attributes * History Attributes
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $history_attrs; var $history_attrs;
@ -72,7 +72,7 @@ class ANSI
/** /**
* Current Column * Current Column
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $x; var $x;
@ -80,7 +80,7 @@ class ANSI
/** /**
* Current Row * Current Row
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $y; var $y;
@ -88,7 +88,7 @@ class ANSI
/** /**
* Old Column * Old Column
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $old_x; var $old_x;
@ -96,7 +96,7 @@ class ANSI
/** /**
* Old Row * Old Row
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $old_y; var $old_y;
@ -104,7 +104,7 @@ class ANSI
/** /**
* An empty attribute cell * An empty attribute cell
* *
* @var Object * @var object
* @access private * @access private
*/ */
var $base_attr_cell; var $base_attr_cell;
@ -112,7 +112,7 @@ class ANSI
/** /**
* The current attribute cell * The current attribute cell
* *
* @var Object * @var object
* @access private * @access private
*/ */
var $attr_cell; var $attr_cell;
@ -120,7 +120,7 @@ class ANSI
/** /**
* An empty attribute row * An empty attribute row
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $attr_row; var $attr_row;
@ -128,7 +128,7 @@ class ANSI
/** /**
* The current screen text * The current screen text
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $screen; var $screen;
@ -136,7 +136,7 @@ class ANSI
/** /**
* The current screen attributes * The current screen attributes
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $attrs; var $attrs;
@ -144,7 +144,7 @@ class ANSI
/** /**
* Current ANSI code * Current ANSI code
* *
* @var String * @var string
* @access private * @access private
*/ */
var $ansi; var $ansi;
@ -152,7 +152,7 @@ class ANSI
/** /**
* Tokenization * Tokenization
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $tokenization; var $tokenization;
@ -184,8 +184,8 @@ class ANSI
* *
* Resets the screen as well * Resets the screen as well
* *
* @param Integer $x * @param int $x
* @param Integer $y * @param int $y
* @access public * @access public
*/ */
function setDimensions($x, $y) function setDimensions($x, $y)
@ -203,8 +203,8 @@ class ANSI
/** /**
* Set the number of lines that should be logged past the terminal height * Set the number of lines that should be logged past the terminal height
* *
* @param Integer $x * @param int $x
* @param Integer $y * @param int $y
* @access public * @access public
*/ */
function setHistory($history) function setHistory($history)
@ -215,7 +215,7 @@ class ANSI
/** /**
* Load a string * Load a string
* *
* @param String $source * @param string $source
* @access public * @access public
*/ */
function loadString($source) function loadString($source)
@ -227,7 +227,7 @@ class ANSI
/** /**
* Appdend a string * Appdend a string
* *
* @param String $source * @param string $source
* @access public * @access public
*/ */
function appendString($source) function appendString($source)
@ -458,7 +458,7 @@ class ANSI
* Returns the current coordinate without preformating * Returns the current coordinate without preformating
* *
* @access private * @access private
* @return String * @return string
*/ */
function _processCoordinate($last_attr, $cur_attr, $char) function _processCoordinate($last_attr, $cur_attr, $char)
{ {
@ -515,7 +515,7 @@ class ANSI
* Returns the current screen without preformating * Returns the current screen without preformating
* *
* @access private * @access private
* @return String * @return string
*/ */
function _getScreen() function _getScreen()
{ {
@ -539,7 +539,7 @@ class ANSI
* Returns the current screen * Returns the current screen
* *
* @access public * @access public
* @return String * @return string
*/ */
function getScreen() function getScreen()
{ {
@ -550,7 +550,7 @@ class ANSI
* Returns the current screen and the x previous lines * Returns the current screen and the x previous lines
* *
* @access public * @access public
* @return String * @return string
*/ */
function getHistory() function getHistory()
{ {

View File

@ -104,7 +104,7 @@ class ASN1
/** /**
* ASN.1 object identifier * ASN.1 object identifier
* *
* @var Array * @var array
* @access private * @access private
* @link http://en.wikipedia.org/wiki/Object_identifier * @link http://en.wikipedia.org/wiki/Object_identifier
*/ */
@ -113,7 +113,7 @@ class ASN1
/** /**
* Default date format * Default date format
* *
* @var String * @var string
* @access private * @access private
* @link http://php.net/class.datetime * @link http://php.net/class.datetime
*/ */
@ -122,10 +122,10 @@ class ASN1
/** /**
* Default date format * Default date format
* *
* @var Array * @var array
* @access private * @access private
* @see \phpseclib\File\ASN1::setTimeFormat() * @see self::setTimeFormat()
* @see \phpseclib\File\ASN1::asn1map() * @see self::asn1map()
* @link http://php.net/class.datetime * @link http://php.net/class.datetime
*/ */
var $encoded; var $encoded;
@ -135,9 +135,9 @@ class ASN1
* *
* If the mapping type is self::TYPE_ANY what do we actually encode it as? * If the mapping type is self::TYPE_ANY what do we actually encode it as?
* *
* @var Array * @var array
* @access private * @access private
* @see \phpseclib\File\ASN1::_encode_der() * @see self::_encode_der()
*/ */
var $filters; var $filters;
@ -148,7 +148,7 @@ class ASN1
* Unambiguous types get the direct mapping (int/real/bool). * Unambiguous types get the direct mapping (int/real/bool).
* Others are mapped as a choice, with an extra indexing level. * Others are mapped as a choice, with an extra indexing level.
* *
* @var Array * @var array
* @access public * @access public
*/ */
var $ANYmap = array( var $ANYmap = array(
@ -182,7 +182,7 @@ class ASN1
* Non-convertable types are absent from this table. * Non-convertable types are absent from this table.
* size == 0 indicates variable length encoding. * size == 0 indicates variable length encoding.
* *
* @var Array * @var array
* @access public * @access public
*/ */
var $stringTypeSize = array( var $stringTypeSize = array(
@ -200,8 +200,8 @@ class ASN1
* *
* Serves a similar purpose to openssl's asn1parse * Serves a similar purpose to openssl's asn1parse
* *
* @param String $encoded * @param string $encoded
* @return Array * @return array
* @access public * @access public
*/ */
function decodeBER($encoded) function decodeBER($encoded)
@ -222,9 +222,9 @@ class ASN1
* $encoded is passed by reference for the recursive calls done for self::TYPE_BIT_STRING and * $encoded is passed by reference for the recursive calls done for self::TYPE_BIT_STRING and
* self::TYPE_OCTET_STRING. In those cases, the indefinite length is used. * self::TYPE_OCTET_STRING. In those cases, the indefinite length is used.
* *
* @param String $encoded * @param string $encoded
* @param Integer $start * @param int $start
* @return Array * @return array
* @access private * @access private
*/ */
function _decode_ber($encoded, $start = 0) function _decode_ber($encoded, $start = 0)
@ -482,10 +482,10 @@ class ASN1
* *
* "Special" mappings may be applied on a per tag-name basis via $special. * "Special" mappings may be applied on a per tag-name basis via $special.
* *
* @param Array $decoded * @param array $decoded
* @param Array $mapping * @param array $mapping
* @param Array $special * @param array $special
* @return Array * @return array
* @access public * @access public
*/ */
function asn1map($decoded, $mapping, $special = array()) function asn1map($decoded, $mapping, $special = array())
@ -616,7 +616,7 @@ class ASN1
} }
// Fail mapping if all input items have not been consumed. // Fail mapping if all input items have not been consumed.
return $i < $n? null: $map; return $i < $n ? null: $map;
// the main diff between sets and sequences is the encapsulation of the foreach in another for loop // the main diff between sets and sequences is the encapsulation of the foreach in another for loop
case self::TYPE_SET: case self::TYPE_SET:
@ -774,10 +774,10 @@ class ASN1
* *
* "Special" mappings can be applied via $special. * "Special" mappings can be applied via $special.
* *
* @param String $source * @param string $source
* @param String $mapping * @param string $mapping
* @param Integer $idx * @param int $idx
* @return String * @return string
* @access public * @access public
*/ */
function encodeDER($source, $mapping, $special = array()) function encodeDER($source, $mapping, $special = array())
@ -789,10 +789,11 @@ class ASN1
/** /**
* ASN.1 Encode (Helper function) * ASN.1 Encode (Helper function)
* *
* @param String $source * @param string $source
* @param String $mapping * @param string $mapping
* @param Integer $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())
@ -985,7 +986,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) {
user_error('Invalid OID'); throw new \RuntimeException('Invalid OID');
return false; return false;
} }
$value = ''; $value = '';
@ -1038,7 +1039,7 @@ class ASN1
$filters = $filters[$part]; $filters = $filters[$part];
} }
if ($filters === false) { if ($filters === false) {
user_error('No filters defined for ' . implode('/', $loc)); throw new \RuntimeException('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);
@ -1062,7 +1063,7 @@ class ASN1
$value = $source ? "\xFF" : "\x00"; $value = $source ? "\xFF" : "\x00";
break; break;
default: default:
user_error('Mapping provides no type definition for ' . implode('/', $this->location)); throw new \RuntimeException('Mapping provides no type definition for ' . implode('/', $this->location));
return false; return false;
} }
@ -1089,8 +1090,8 @@ class ASN1
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. * {@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 * @access private
* @param Integer $length * @param int $length
* @return String * @return string
*/ */
function _encodeLength($length) function _encodeLength($length)
{ {
@ -1108,9 +1109,9 @@ class ASN1
* Called by _decode_ber() and in the case of implicit tags asn1map(). * Called by _decode_ber() and in the case of implicit tags asn1map().
* *
* @access private * @access private
* @param String $content * @param string $content
* @param Integer $tag * @param int $tag
* @return String * @return string
*/ */
function _decodeTime($content, $tag) function _decodeTime($content, $tag)
{ {
@ -1157,7 +1158,7 @@ class ASN1
* Sets the time / date format for asn1map(). * Sets the time / date format for asn1map().
* *
* @access public * @access public
* @param String $format * @param string $format
*/ */
function setTimeFormat($format) function setTimeFormat($format)
{ {
@ -1170,7 +1171,7 @@ class ASN1
* Load the relevant OIDs for a particular ASN.1 semantic mapping. * Load the relevant OIDs for a particular ASN.1 semantic mapping.
* *
* @access public * @access public
* @param Array $oids * @param array $oids
*/ */
function loadOIDs($oids) function loadOIDs($oids)
{ {
@ -1183,7 +1184,7 @@ class ASN1
* See \phpseclib\File\X509, etc, for an example. * See \phpseclib\File\X509, etc, for an example.
* *
* @access public * @access public
* @param Array $filters * @param array $filters
*/ */
function loadFilters($filters) function loadFilters($filters)
{ {
@ -1195,9 +1196,9 @@ class ASN1
* *
* Inspired by array_shift * Inspired by array_shift
* *
* @param String $string * @param string $string
* @param optional Integer $index * @param int $index
* @return String * @return string
* @access private * @access private
*/ */
function _string_shift(&$string, $index = 1) function _string_shift(&$string, $index = 1)
@ -1213,10 +1214,10 @@ class ASN1
* This is a lazy conversion, dealing only with character size. * This is a lazy conversion, dealing only with character size.
* No real conversion table is used. * No real conversion table is used.
* *
* @param String $in * @param string $in
* @param optional Integer $from * @param int $from
* @param optional Integer $to * @param int $to
* @return String * @return string
* @access public * @access public
*/ */
function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING) function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING)

View File

@ -28,7 +28,7 @@ class Element
/** /**
* Raw element value * Raw element value
* *
* @var String * @var string
* @access private * @access private
*/ */
var $element; var $element;
@ -36,7 +36,7 @@ class Element
/** /**
* Constructor * Constructor
* *
* @param String $encoded * @param string $encoded
* @return \phpseclib\File\ASN1\Element * @return \phpseclib\File\ASN1\Element
* @access public * @access public
*/ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@
* exit('bad login'); * exit('bad login');
* } * }
* $scp = new \phpseclib\Net\SCP($ssh); * $scp = new \phpseclib\Net\SCP($ssh);
*
* $scp->put('abcd', str_repeat('x', 1024*1024)); * $scp->put('abcd', str_repeat('x', 1024*1024));
* ?> * ?>
* </code> * </code>
@ -32,8 +32,7 @@
namespace phpseclib\Net; namespace phpseclib\Net;
use phpseclib\Net\SSH1; use phpseclib\Exception\FileNotFoundException;
use phpseclib\Net\SSH2;
/** /**
* Pure-PHP implementations of SCP. * Pure-PHP implementations of SCP.
@ -54,7 +53,7 @@ class SCP
const SOURCE_LOCAL_FILE = 1; const SOURCE_LOCAL_FILE = 1;
/** /**
* Reads data from a string. * Reads data from a string.
*/ */
const SOURCE_STRING = 2; const SOURCE_STRING = 2;
/**#@-*/ /**#@-*/
@ -65,18 +64,18 @@ class SCP
*/ */
/** /**
* SSH1 is being used. * SSH1 is being used.
*/ */
const MODE_SSH1 = 1; const MODE_SSH1 = 1;
/** /**
* SSH2 is being used. * SSH2 is being used.
*/ */
const MODE_SSH2 = 2; const MODE_SSH2 = 2;
/**#@-*/ /**#@-*/
/** /**
* SSH Object * SSH Object
* *
* @var Object * @var object
* @access private * @access private
*/ */
var $ssh; var $ssh;
@ -84,7 +83,7 @@ class SCP
/** /**
* Packet Size * Packet Size
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $packet_size; var $packet_size;
@ -92,7 +91,7 @@ class SCP
/** /**
* Mode * Mode
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $mode; var $mode;
@ -102,9 +101,9 @@ class SCP
* *
* Connects to an SSH server * Connects to an SSH server
* *
* @param String $host * @param string $host
* @param optional Integer $port * @param int $port
* @param optional Integer $timeout * @param int $timeout
* @return \phpseclib\Net\SCP * @return \phpseclib\Net\SCP
* @access public * @access public
*/ */
@ -136,11 +135,12 @@ class SCP
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
* care of that, yourself. * care of that, yourself.
* *
* @param String $remote_file * @param string $remote_file
* @param String $data * @param string $data
* @param optional Integer $mode * @param int $mode
* @param optional Callable $callback * @param callable $callback
* @return Boolean * @throws \phpseclib\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist
* @return bool
* @access public * @access public
*/ */
function put($remote_file, $data, $mode = self::SOURCE_STRING, $callback = null) function put($remote_file, $data, $mode = self::SOURCE_STRING, $callback = null)
@ -168,8 +168,7 @@ class SCP
$size = strlen($data); $size = strlen($data);
} else { } else {
if (!is_file($data)) { if (!is_file($data)) {
user_error("$data is not a valid file", E_USER_NOTICE); throw new FileNotFoundException("$data is not a valid file");
return false;
} }
$fp = @fopen($data, 'rb'); $fp = @fopen($data, 'rb');
@ -212,9 +211,9 @@ class SCP
* the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
* operation * operation
* *
* @param String $remote_file * @param string $remote_file
* @param optional String $local_file * @param string $local_file
* @return Mixed * @return mixed
* @access public * @access public
*/ */
function get($remote_file, $local_file = false) function get($remote_file, $local_file = false)
@ -270,7 +269,7 @@ class SCP
/** /**
* Sends a packet to an SSH server * Sends a packet to an SSH server
* *
* @param String $data * @param string $data
* @access private * @access private
*/ */
function _send($data) function _send($data)
@ -288,7 +287,8 @@ 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,8 +314,7 @@ class SCP
$this->ssh->bitmap = 0; $this->ssh->bitmap = 0;
return false; return false;
default: default:
user_error('Unknown packet received', E_USER_NOTICE); throw new \UnexpectedValueException('Unknown packet received');
return false;
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,7 @@ 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
@ -34,14 +35,14 @@ class Stream
* *
* Rather than re-create the connection we re-use instances if possible * Rather than re-create the connection we re-use instances if possible
* *
* @var Array * @var array
*/ */
static $instances; static $instances;
/** /**
* SFTP instance * SFTP instance
* *
* @var Object * @var object
* @access private * @access private
*/ */
var $sftp; var $sftp;
@ -49,7 +50,7 @@ class Stream
/** /**
* Path * Path
* *
* @var String * @var string
* @access private * @access private
*/ */
var $path; var $path;
@ -57,7 +58,7 @@ class Stream
/** /**
* Mode * Mode
* *
* @var String * @var string
* @access private * @access private
*/ */
var $mode; var $mode;
@ -65,7 +66,7 @@ class Stream
/** /**
* Position * Position
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $pos; var $pos;
@ -73,7 +74,7 @@ class Stream
/** /**
* Size * Size
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $size; var $size;
@ -81,7 +82,7 @@ class Stream
/** /**
* Directory entries * Directory entries
* *
* @var Array * @var array
* @access private * @access private
*/ */
var $entries; var $entries;
@ -89,7 +90,7 @@ class Stream
/** /**
* EOF flag * EOF flag
* *
* @var Boolean * @var bool
* @access private * @access private
*/ */
var $eof; var $eof;
@ -99,7 +100,7 @@ class Stream
* *
* Technically this needs to be publically accessible so PHP can set it directly * Technically this needs to be publically accessible so PHP can set it directly
* *
* @var Resource * @var resource
* @access public * @access public
*/ */
var $context; var $context;
@ -107,7 +108,7 @@ class Stream
/** /**
* Notification callback function * Notification callback function
* *
* @var Callable * @var callable
* @access public * @access public
*/ */
var $notification; var $notification;
@ -115,8 +116,8 @@ class Stream
/** /**
* Registers this class as a URL wrapper. * Registers this class as a URL wrapper.
* *
* @param optional String $protocol The wrapper name to be registered. * @param string $protocol The wrapper name to be registered.
* @return Boolean True on success, false otherwise. * @return bool True on success, false otherwise.
* @access public * @access public
*/ */
static function register($protocol = 'sftp') static function register($protocol = 'sftp')
@ -147,13 +148,24 @@ class Stream
* If "notification" is set as a context parameter the message code for successful login is * If "notification" is set as a context parameter the message code for successful login is
* NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE. * NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE.
* *
* @param String $path * @param string $path
* @return String * @return string
* @access private * @access private
*/ */
function _parse_path($path) function _parse_path($path)
{ {
$orig = $path;
extract(parse_url($path) + array('port' => 22)); extract(parse_url($path) + array('port' => 22));
if (isset($query)) {
$path.= '?' . $query;
} elseif (preg_match('/(\?|\?#)$/', $orig)) {
$path.= '?';
}
if (isset($fragment)) {
$path.= '#' . $fragment;
} elseif ($orig[strlen($orig) - 1] == '#') {
$path.= '#';
}
if (!isset($host)) { if (!isset($host)) {
return false; return false;
@ -166,13 +178,12 @@ class Stream
} }
} }
if ($host[0] == '$') { if (preg_match('/^{[a-z0-9]+}$/i', $host)) {
$host = substr($host, 1); $host = SSH2::getConnectionByResourceId($host);
global $$host; if ($host === false) {
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);
@ -239,11 +250,11 @@ class Stream
/** /**
* Opens file or URL * Opens file or URL
* *
* @param String $path * @param string $path
* @param String $mode * @param string $mode
* @param Integer $options * @param int $options
* @param String $opened_path * @param string $opened_path
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _stream_open($path, $mode, $options, &$opened_path) function _stream_open($path, $mode, $options, &$opened_path)
@ -284,8 +295,8 @@ class Stream
/** /**
* Read from stream * Read from stream
* *
* @param Integer $count * @param int $count
* @return Mixed * @return mixed
* @access public * @access public
*/ */
function _stream_read($count) function _stream_read($count)
@ -326,8 +337,8 @@ class Stream
/** /**
* Write to stream * Write to stream
* *
* @param String $data * @param string $data
* @return Mixed * @return mixed
* @access public * @access public
*/ */
function _stream_write($data) function _stream_write($data)
@ -361,7 +372,7 @@ class Stream
/** /**
* Retrieve the current position of a stream * Retrieve the current position of a stream
* *
* @return Integer * @return int
* @access public * @access public
*/ */
function _stream_tell() function _stream_tell()
@ -379,7 +390,7 @@ class Stream
* will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof() * will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof()
* will return false. do fread($fp, 1) and feof() will then return true. * will return false. do fread($fp, 1) and feof() will then return true.
* *
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _stream_eof() function _stream_eof()
@ -390,9 +401,9 @@ class Stream
/** /**
* Seeks to specific location in a stream * Seeks to specific location in a stream
* *
* @param Integer $offset * @param int $offset
* @param Integer $whence * @param int $whence
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _stream_seek($offset, $whence) function _stream_seek($offset, $whence)
@ -418,10 +429,10 @@ class Stream
/** /**
* Change stream options * Change stream options
* *
* @param String $path * @param string $path
* @param Integer $option * @param int $option
* @param Mixed $var * @param mixed $var
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _stream_metadata($path, $option, $var) function _stream_metadata($path, $option, $var)
@ -452,8 +463,8 @@ class Stream
/** /**
* Retrieve the underlaying resource * Retrieve the underlaying resource
* *
* @param Integer $cast_as * @param int $cast_as
* @return Resource * @return resource
* @access public * @access public
*/ */
function _stream_cast($cast_as) function _stream_cast($cast_as)
@ -464,8 +475,8 @@ class Stream
/** /**
* Advisory file locking * Advisory file locking
* *
* @param Integer $operation * @param int $operation
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _stream_lock($operation) function _stream_lock($operation)
@ -480,9 +491,9 @@ class Stream
* If newname exists, it will be overwritten. This is a departure from what \phpseclib\Net\SFTP * If newname exists, it will be overwritten. This is a departure from what \phpseclib\Net\SFTP
* does. * does.
* *
* @param String $path_from * @param string $path_from
* @param String $path_to * @param string $path_to
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _rename($path_from, $path_to) function _rename($path_from, $path_to)
@ -532,9 +543,9 @@ class Stream
* string longname * string longname
* ATTRS attrs * ATTRS attrs
* *
* @param String $path * @param string $path
* @param Integer $options * @param int $options
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _dir_opendir($path, $options) function _dir_opendir($path, $options)
@ -551,7 +562,7 @@ class Stream
/** /**
* Read entry from directory handle * Read entry from directory handle
* *
* @return Mixed * @return mixed
* @access public * @access public
*/ */
function _dir_readdir() function _dir_readdir()
@ -565,7 +576,7 @@ class Stream
/** /**
* Rewind directory handle * Rewind directory handle
* *
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _dir_rewinddir() function _dir_rewinddir()
@ -577,7 +588,7 @@ class Stream
/** /**
* Close directory handle * Close directory handle
* *
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _dir_closedir() function _dir_closedir()
@ -590,10 +601,10 @@ class Stream
* *
* Only valid $options is STREAM_MKDIR_RECURSIVE * Only valid $options is STREAM_MKDIR_RECURSIVE
* *
* @param String $path * @param string $path
* @param Integer $mode * @param int $mode
* @param Integer $options * @param int $options
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _mkdir($path, $mode, $options) function _mkdir($path, $mode, $options)
@ -614,10 +625,10 @@ class Stream
* STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as * STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as
* $options. What does 8 correspond to? * $options. What does 8 correspond to?
* *
* @param String $path * @param string $path
* @param Integer $mode * @param int $mode
* @param Integer $options * @param int $options
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _rmdir($path, $options) function _rmdir($path, $options)
@ -635,7 +646,7 @@ class Stream
* *
* See <http://php.net/fflush>. Always returns true because \phpseclib\Net\SFTP doesn't cache stuff before writing * See <http://php.net/fflush>. Always returns true because \phpseclib\Net\SFTP doesn't cache stuff before writing
* *
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _stream_flush() function _stream_flush()
@ -646,7 +657,7 @@ class Stream
/** /**
* Retrieve information about a file resource * Retrieve information about a file resource
* *
* @return Mixed * @return mixed
* @access public * @access public
*/ */
function _stream_stat() function _stream_stat()
@ -661,8 +672,8 @@ class Stream
/** /**
* Delete a file * Delete a file
* *
* @param String $path * @param string $path
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _unlink($path) function _unlink($path)
@ -682,9 +693,9 @@ class Stream
* might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll * might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll
* cross that bridge when and if it's reached * cross that bridge when and if it's reached
* *
* @param String $path * @param string $path
* @param Integer $flags * @param int $flags
* @return Mixed * @return mixed
* @access public * @access public
*/ */
function _url_stat($path, $flags) function _url_stat($path, $flags)
@ -705,8 +716,8 @@ class Stream
/** /**
* Truncate stream * Truncate stream
* *
* @param Integer $new_size * @param int $new_size
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _stream_truncate($new_size) function _stream_truncate($new_size)
@ -727,10 +738,10 @@ class Stream
* STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't. * STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't.
* The other two aren't supported because of limitations in \phpseclib\Net\SFTP. * The other two aren't supported because of limitations in \phpseclib\Net\SFTP.
* *
* @param Integer $option * @param int $option
* @param Integer $arg1 * @param int $arg1
* @param Integer $arg2 * @param int $arg2
* @return Boolean * @return bool
* @access public * @access public
*/ */
function _stream_set_option($option, $arg1, $arg2) function _stream_set_option($option, $arg1, $arg2)
@ -757,9 +768,9 @@ class Stream
* If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not * If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not
* NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method. * NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method.
* *
* @param String * @param string
* @param Array * @param array
* @return Mixed * @return mixed
* @access public * @access public
*/ */
function __call($name, $arguments) function __call($name, $arguments)

View File

@ -78,24 +78,24 @@ class SSH1
* IDEA in CFB mode * IDEA in CFB mode
* *
* Not supported. * Not supported.
*/ */
const CIPHER_IDEA = 1; const CIPHER_IDEA = 1;
/** /**
* DES in CBC mode * DES in CBC mode
*/ */
const CIPHER_DES = 2; const CIPHER_DES = 2;
/** /**
* Triple-DES in CBC mode * Triple-DES in CBC mode
* *
* All implementations are required to support this * All implementations are required to support this
*/ */
const CIPHER_3DES = 3; const CIPHER_3DES = 3;
/** /**
* TRI's Simple Stream encryption CBC * TRI's Simple Stream encryption CBC
* *
* Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, does define it (see cipher.h), * Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, does define it (see cipher.h),
* although it doesn't use it (see cipher.c) * although it doesn't use it (see cipher.c)
*/ */
const CIPHER_BROKEN_TSS = 4; const CIPHER_BROKEN_TSS = 4;
/** /**
* RC4 * RC4
@ -111,14 +111,14 @@ class SSH1
* *
* This library currently only supports encryption when the same key is being used for both directions. This is * This library currently only supports encryption when the same key is being used for both directions. This is
* because there's only one $crypto object. Two could be added ($encrypt and $decrypt, perhaps). * because there's only one $crypto object. Two could be added ($encrypt and $decrypt, perhaps).
*/ */
const CIPHER_RC4 = 5; const CIPHER_RC4 = 5;
/** /**
* Blowfish * Blowfish
* *
* Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, defines it (see cipher.h) and * Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, defines it (see cipher.h) and
* uses it (see cipher.c) * uses it (see cipher.c)
*/ */
const CIPHER_BLOWFISH = 6; const CIPHER_BLOWFISH = 6;
/**#@-*/ /**#@-*/
@ -130,21 +130,21 @@ class SSH1
*/ */
/** /**
* .rhosts or /etc/hosts.equiv * .rhosts or /etc/hosts.equiv
*/ */
const AUTH_RHOSTS = 1; const AUTH_RHOSTS = 1;
/** /**
* pure RSA authentication * pure RSA authentication
*/ */
const AUTH_RSA = 2; const AUTH_RSA = 2;
/** /**
* password authentication * password authentication
* *
* This is the only method that is supported by this library. * This is the only method that is supported by this library.
*/ */
const AUTH_PASSWORD = 3; const AUTH_PASSWORD = 3;
/** /**
* .rhosts with RSA host authentication * .rhosts with RSA host authentication
*/ */
const AUTH_RHOSTS_RSA = 4; const AUTH_RHOSTS_RSA = 4;
/**#@-*/ /**#@-*/
@ -162,7 +162,7 @@ class SSH1
* *
* @see \phpseclib\Net\SSH1::_get_binary_packet() * @see \phpseclib\Net\SSH1::_get_binary_packet()
* @access private * @access private
*/ */
const RESPONSE_TYPE = 1; const RESPONSE_TYPE = 1;
/** /**
@ -170,7 +170,7 @@ class SSH1
* *
* @see \phpseclib\Net\SSH1::_get_binary_packet() * @see \phpseclib\Net\SSH1::_get_binary_packet()
* @access private * @access private
*/ */
const RESPONSE_DATA = 2; const RESPONSE_DATA = 2;
/**#@+ /**#@+
@ -191,19 +191,19 @@ class SSH1
*/ */
/** /**
* Returns the message numbers * Returns the message numbers
*/ */
const LOG_SIMPLE = 1; const LOG_SIMPLE = 1;
/** /**
* Returns the message content * Returns the message content
*/ */
const LOG_COMPLEX = 2; const LOG_COMPLEX = 2;
/** /**
* Outputs the content real-time * Outputs the content real-time
*/ */
const LOG_REALTIME = 3; const LOG_REALTIME = 3;
/** /**
* Dumps the content real-time to a file * Dumps the content real-time to a file
*/ */
const LOG_REALTIME_FILE = 4; const LOG_REALTIME_FILE = 4;
/**#@-*/ /**#@-*/
@ -213,18 +213,18 @@ class SSH1
*/ */
/** /**
* Returns when a string matching $expect exactly is found * Returns when a string matching $expect exactly is found
*/ */
const READ_SIMPLE = 1; const READ_SIMPLE = 1;
/** /**
* Returns when a string matching the regular expression $expect is found * Returns when a string matching the regular expression $expect is found
*/ */
const READ_REGEX = 2; const READ_REGEX = 2;
/**#@-*/ /**#@-*/
/** /**
* The SSH identifier * The SSH identifier
* *
* @var String * @var string
* @access private * @access private
*/ */
var $identifier = 'SSH-1.5-phpseclib'; var $identifier = 'SSH-1.5-phpseclib';
@ -232,7 +232,7 @@ class SSH1
/** /**
* The Socket Object * The Socket Object
* *
* @var Object * @var object
* @access private * @access private
*/ */
var $fsock; var $fsock;
@ -240,7 +240,7 @@ class SSH1
/** /**
* The cryptography object * The cryptography object
* *
* @var Object * @var object
* @access private * @access private
*/ */
var $crypto = false; var $crypto = false;
@ -251,7 +251,7 @@ class SSH1
* The bits that are set represent functions that have been called already. This is used to determine * The bits that are set represent functions that have been called already. This is used to determine
* if a requisite function has been successfully executed. If not, an error should be thrown. * if a requisite function has been successfully executed. If not, an error should be thrown.
* *
* @var Integer * @var int
* @access private * @access private
*/ */
var $bitmap = 0; var $bitmap = 0;
@ -261,8 +261,8 @@ class SSH1
* *
* Logged for debug purposes * Logged for debug purposes
* *
* @see \phpseclib\Net\SSH1::getServerKeyPublicExponent() * @see self::getServerKeyPublicExponent()
* @var String * @var string
* @access private * @access private
*/ */
var $server_key_public_exponent; var $server_key_public_exponent;
@ -272,8 +272,8 @@ class SSH1
* *
* Logged for debug purposes * Logged for debug purposes
* *
* @see \phpseclib\Net\SSH1::getServerKeyPublicModulus() * @see self::getServerKeyPublicModulus()
* @var String * @var string
* @access private * @access private
*/ */
var $server_key_public_modulus; var $server_key_public_modulus;
@ -283,8 +283,8 @@ class SSH1
* *
* Logged for debug purposes * Logged for debug purposes
* *
* @see \phpseclib\Net\SSH1::getHostKeyPublicExponent() * @see self::getHostKeyPublicExponent()
* @var String * @var string
* @access private * @access private
*/ */
var $host_key_public_exponent; var $host_key_public_exponent;
@ -294,8 +294,8 @@ class SSH1
* *
* Logged for debug purposes * Logged for debug purposes
* *
* @see \phpseclib\Net\SSH1::getHostKeyPublicModulus() * @see self::getHostKeyPublicModulus()
* @var String * @var string
* @access private * @access private
*/ */
var $host_key_public_modulus; var $host_key_public_modulus;
@ -305,8 +305,8 @@ class SSH1
* *
* Logged for debug purposes * Logged for debug purposes
* *
* @see \phpseclib\Net\SSH1::getSupportedCiphers() * @see self::getSupportedCiphers()
* @var Array * @var array
* @access private * @access private
*/ */
var $supported_ciphers = array( var $supported_ciphers = array(
@ -324,8 +324,8 @@ class SSH1
* *
* Logged for debug purposes * Logged for debug purposes
* *
* @see \phpseclib\Net\SSH1::getSupportedAuthentications() * @see self::getSupportedAuthentications()
* @var Array * @var array
* @access private * @access private
*/ */
var $supported_authentications = array( var $supported_authentications = array(
@ -338,8 +338,8 @@ class SSH1
/** /**
* Server Identification * Server Identification
* *
* @see \phpseclib\Net\SSH1::getServerIdentification() * @see self::getServerIdentification()
* @var String * @var string
* @access private * @access private
*/ */
var $server_identification = ''; var $server_identification = '';
@ -347,8 +347,8 @@ class SSH1
/** /**
* Protocol Flags * Protocol Flags
* *
* @see \phpseclib\Net\SSH1::__construct() * @see self::__construct()
* @var Array * @var array
* @access private * @access private
*/ */
var $protocol_flags = array(); var $protocol_flags = array();
@ -356,8 +356,8 @@ class SSH1
/** /**
* Protocol Flag Log * Protocol Flag Log
* *
* @see \phpseclib\Net\SSH1::getLog() * @see self::getLog()
* @var Array * @var array
* @access private * @access private
*/ */
var $protocol_flag_log = array(); var $protocol_flag_log = array();
@ -365,8 +365,8 @@ class SSH1
/** /**
* Message Log * Message Log
* *
* @see \phpseclib\Net\SSH1::getLog() * @see self::getLog()
* @var Array * @var array
* @access private * @access private
*/ */
var $message_log = array(); var $message_log = array();
@ -374,8 +374,8 @@ class SSH1
/** /**
* Real-time log file pointer * Real-time log file pointer
* *
* @see \phpseclib\Net\SSH1::_append_log() * @see self::_append_log()
* @var Resource * @var resource
* @access private * @access private
*/ */
var $realtime_log_file; var $realtime_log_file;
@ -383,8 +383,8 @@ class SSH1
/** /**
* Real-time log file size * Real-time log file size
* *
* @see \phpseclib\Net\SSH1::_append_log() * @see self::_append_log()
* @var Integer * @var int
* @access private * @access private
*/ */
var $realtime_log_size; var $realtime_log_size;
@ -392,8 +392,8 @@ class SSH1
/** /**
* Real-time log file wrap boolean * Real-time log file wrap boolean
* *
* @see \phpseclib\Net\SSH1::_append_log() * @see self::_append_log()
* @var Boolean * @var bool
* @access private * @access private
*/ */
var $realtime_log_wrap; var $realtime_log_wrap;
@ -401,8 +401,8 @@ class SSH1
/** /**
* Interactive Buffer * Interactive Buffer
* *
* @see \phpseclib\Net\SSH1::read() * @see self::read()
* @var Array * @var array
* @access private * @access private
*/ */
var $interactiveBuffer = ''; var $interactiveBuffer = '';
@ -410,7 +410,7 @@ class SSH1
/** /**
* Timeout * Timeout
* *
* @see \phpseclib\Net\SSH1::setTimeout() * @see self::setTimeout()
* @access private * @access private
*/ */
var $timeout; var $timeout;
@ -418,7 +418,7 @@ class SSH1
/** /**
* Current Timeout * Current Timeout
* *
* @see \phpseclib\Net\SSH1::_get_channel_packet() * @see self::_get_channel_packet()
* @access private * @access private
*/ */
var $curTimeout; var $curTimeout;
@ -426,7 +426,7 @@ class SSH1
/** /**
* Log Boundary * Log Boundary
* *
* @see \phpseclib\Net\SSH1::_format_log * @see self::_format_log()
* @access private * @access private
*/ */
var $log_boundary = ':'; var $log_boundary = ':';
@ -434,7 +434,7 @@ class SSH1
/** /**
* Log Long Width * Log Long Width
* *
* @see \phpseclib\Net\SSH1::_format_log * @see self::_format_log()
* @access private * @access private
*/ */
var $log_long_width = 65; var $log_long_width = 65;
@ -442,7 +442,7 @@ class SSH1
/** /**
* Log Short Width * Log Short Width
* *
* @see \phpseclib\Net\SSH1::_format_log * @see self::_format_log()
* @access private * @access private
*/ */
var $log_short_width = 16; var $log_short_width = 16;
@ -450,9 +450,9 @@ class SSH1
/** /**
* Hostname * Hostname
* *
* @see \phpseclib\Net\SSH1::__construct() * @see self::__construct()
* @see \phpseclib\Net\SSH1::_connect() * @see self::_connect()
* @var String * @var string
* @access private * @access private
*/ */
var $host; var $host;
@ -460,9 +460,9 @@ class SSH1
/** /**
* Port Number * Port Number
* *
* @see \phpseclib\Net\SSH1::__construct() * @see self::__construct()
* @see \phpseclib\Net\SSH1::_connect() * @see self::_connect()
* @var Integer * @var int
* @access private * @access private
*/ */
var $port; var $port;
@ -475,9 +475,9 @@ class SSH1
* however, is non-optional. There will be a timeout, whether or not you set it. If you don't it'll be * however, is non-optional. There will be a timeout, whether or not you set it. If you don't it'll be
* 10 seconds. It is used by fsockopen() in that function. * 10 seconds. It is used by fsockopen() in that function.
* *
* @see \phpseclib\Net\SSH1::__construct() * @see self::__construct()
* @see \phpseclib\Net\SSH1::_connect() * @see self::_connect()
* @var Integer * @var int
* @access private * @access private
*/ */
var $connectionTimeout; var $connectionTimeout;
@ -485,9 +485,9 @@ class SSH1
/** /**
* Default cipher * Default cipher
* *
* @see \phpseclib\Net\SSH1::__construct() * @see self::__construct()
* @see \phpseclib\Net\SSH1::_connect() * @see self::_connect()
* @var Integer * @var int
* @access private * @access private
*/ */
var $cipher; var $cipher;
@ -497,10 +497,10 @@ class SSH1
* *
* Connects to an SSHv1 server * Connects to an SSHv1 server
* *
* @param String $host * @param string $host
* @param optional Integer $port * @param int $port
* @param optional Integer $timeout * @param int $timeout
* @param optional Integer $cipher * @param int $cipher
* @return \phpseclib\Net\SSH1 * @return \phpseclib\Net\SSH1
* @access public * @access public
*/ */
@ -536,15 +536,16 @@ class SSH1
/** /**
* Connect to an SSHv1 server * Connect to an SSHv1 server
* *
* @return Boolean * @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) {
user_error(rtrim("Cannot connect to {$this->host}:{$this->port}. Error $errno. $errstr")); throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr"));
return false;
} }
$this->server_identification = $init_line = fgets($this->fsock, 255); $this->server_identification = $init_line = fgets($this->fsock, 255);
@ -555,20 +556,17 @@ class SSH1
} }
if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) { if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
user_error('Can only connect to SSH servers'); throw new \RuntimeException('Can only connect to SSH servers');
return false;
} }
if ($parts[1][0] != 1) { if ($parts[1][0] != 1) {
user_error("Cannot connect to SSH $parts[1] servers"); throw new \RuntimeException("Cannot connect to $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) {
user_error('Expected SSH_SMSG_PUBLIC_KEY'); throw new \UnexpectedValueException('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);
@ -652,8 +650,7 @@ 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)) {
user_error('Error sending SSH_CMSG_SESSION_KEY'); throw new \RuntimeException('Error sending SSH_CMSG_SESSION_KEY');
return false;
} }
switch ($cipher) { switch ($cipher) {
@ -661,16 +658,20 @@ 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(); $this->crypto = new DES(DES::MODE_CBC);
$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();
@ -682,8 +683,7 @@ 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) {
user_error('Expected SSH_SMSG_SUCCESS'); throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS');
return false;
} }
$this->bitmap = self::MASK_CONNECTED; $this->bitmap = self::MASK_CONNECTED;
@ -694,9 +694,11 @@ class SSH1
/** /**
* Login * Login
* *
* @param String $username * @param string $username
* @param optional String $password * @param string $password
* @return Boolean * @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 = '')
@ -715,8 +717,7 @@ 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)) {
user_error('Error sending SSH_CMSG_USER'); throw new \RuntimeException('Error sending SSH_CMSG_USER');
return false;
} }
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
@ -728,15 +729,13 @@ 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) {
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); throw new \UnexpectedValueException('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)) {
user_error('Error sending SSH_CMSG_AUTH_PASSWORD'); throw new \RuntimeException('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
@ -756,8 +755,7 @@ 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 {
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
return false;
} }
} }
@ -767,7 +765,7 @@ class SSH1
* $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout. * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout.
* Setting $timeout to false or 0 will mean there is no timeout. * Setting $timeout to false or 0 will mean there is no timeout.
* *
* @param Mixed $timeout * @param mixed $timeout
*/ */
function setTimeout($timeout) function setTimeout($timeout)
{ {
@ -788,24 +786,23 @@ class SSH1
* *
* Returns false on failure and the output, otherwise. * Returns false on failure and the output, otherwise.
* *
* @see \phpseclib\Net\SSH1::interactiveRead() * @see self::interactiveRead()
* @see \phpseclib\Net\SSH1::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)) {
user_error('Operation disallowed prior to login()'); throw new \RuntimeException('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)) {
user_error('Error sending SSH_CMSG_EXEC_CMD'); throw new \RuntimeException('Error sending SSH_CMSG_EXEC_CMD');
return false;
} }
if (!$block) { if (!$block) {
@ -838,9 +835,11 @@ class SSH1
/** /**
* Creates an interactive shell * Creates an interactive shell
* *
* @see \phpseclib\Net\SSH1::interactiveRead() * @see self::interactiveRead()
* @see \phpseclib\Net\SSH1::interactiveWrite() * @see self::interactiveWrite()
* @return Boolean * @return bool
* @throws \UnexpectedValueException on receipt of unexpected packets
* @throws \RuntimeException on other errors
* @access private * @access private
*/ */
function _initShell() function _initShell()
@ -851,8 +850,7 @@ 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)) {
user_error('Error sending SSH_CMSG_REQUEST_PTY'); throw new \RuntimeException('Error sending SSH_CMSG_REQUEST_PTY');
return false;
} }
$response = $this->_get_binary_packet(); $response = $this->_get_binary_packet();
@ -861,15 +859,13 @@ class SSH1
return false; return false;
} }
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) { if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
user_error('Expected SSH_SMSG_SUCCESS'); throw new \UnexpectedValueException('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)) {
user_error('Error sending SSH_CMSG_EXEC_SHELL'); throw new \RuntimeException('Error sending SSH_CMSG_EXEC_SHELL');
return false;
} }
$this->bitmap |= self::MASK_SHELL; $this->bitmap |= self::MASK_SHELL;
@ -882,9 +878,9 @@ class SSH1
/** /**
* Inputs a command into an interactive shell. * Inputs a command into an interactive shell.
* *
* @see \phpseclib\Net\SSH1::interactiveWrite() * @see self::interactiveWrite()
* @param String $cmd * @param string $cmd
* @return Boolean * @return bool
* @access public * @access public
*/ */
function write($cmd) function write($cmd)
@ -898,22 +894,21 @@ class SSH1
* $expect can take the form of a string literal or, if $mode == self::READ__REGEX, * $expect can take the form of a string literal or, if $mode == self::READ__REGEX,
* a regular expression. * a regular expression.
* *
* @see \phpseclib\Net\SSH1::write() * @see self::write()
* @param String $expect * @param string $expect
* @param Integer $mode * @param int $mode
* @return Boolean * @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)) {
user_error('Operation disallowed prior to login()'); throw new \RuntimeException('Operation disallowed prior to login()');
return false;
} }
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) { if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
user_error('Unable to initiate an interactive shell session'); throw new \RuntimeException('Unable to initiate an interactive shell session');
return false;
} }
$match = $expect; $match = $expect;
@ -938,28 +933,26 @@ class SSH1
/** /**
* Inputs a command into an interactive shell. * Inputs a command into an interactive shell.
* *
* @see \phpseclib\Net\SSH1::interactiveRead() * @see self::interactiveRead()
* @param String $cmd * @param string $cmd
* @return Boolean * @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)) {
user_error('Operation disallowed prior to login()'); throw new \RuntimeException('Operation disallowed prior to login()');
return false;
} }
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) { if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
user_error('Unable to initiate an interactive shell session'); throw new \RuntimeException('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)) {
user_error('Error sending SSH_CMSG_STDIN'); throw new \RuntimeException('Error sending SSH_CMSG_STDIN');
return false;
} }
return true; return true;
@ -974,20 +967,19 @@ class SSH1
* does not support ANSI escape sequences in Win32 Console applications", so if you're a Windows user, * does not support ANSI escape sequences in Win32 Console applications", so if you're a Windows user,
* there's not going to be much recourse. * there's not going to be much recourse.
* *
* @see \phpseclib\Net\SSH1::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)) {
user_error('Operation disallowed prior to login()'); throw new \RuntimeException('Operation disallowed prior to login()');
return false;
} }
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) { if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
user_error('Unable to initiate an interactive shell session'); throw new \RuntimeException('Unable to initiate an interactive shell session');
return false;
} }
$read = array($this->fsock); $read = array($this->fsock);
@ -1026,7 +1018,7 @@ class SSH1
/** /**
* Disconnect * Disconnect
* *
* @param String $msg * @param string $msg
* @access private * @access private
*/ */
function _disconnect($msg = 'Client Quit') function _disconnect($msg = 'Client Quit')
@ -1063,8 +1055,8 @@ class SSH1
* Also, this function could be improved upon by adding detection for the following exploit: * Also, this function could be improved upon by adding detection for the following exploit:
* http://www.securiteam.com/securitynews/5LP042K3FY.html * http://www.securiteam.com/securitynews/5LP042K3FY.html
* *
* @see \phpseclib\Net\SSH1::_send_binary_packet() * @see self::_send_binary_packet()
* @return Array * @return array
* @access private * @access private
*/ */
function _get_binary_packet() function _get_binary_packet()
@ -1139,9 +1131,9 @@ class SSH1
* *
* Returns true on success, false on failure. * Returns true on success, false on failure.
* *
* @see \phpseclib\Net\SSH1::_get_binary_packet() * @see self::_get_binary_packet()
* @param String $data * @param string $data
* @return Boolean * @return bool
* @access private * @access private
*/ */
function _send_binary_packet($data) function _send_binary_packet($data)
@ -1186,10 +1178,10 @@ class SSH1
* we've reimplemented it. A more detailed discussion of the differences can be found after * we've reimplemented it. A more detailed discussion of the differences can be found after
* $crc_lookup_table's initialization. * $crc_lookup_table's initialization.
* *
* @see \phpseclib\Net\SSH1::_get_binary_packet() * @see self::_get_binary_packet()
* @see \phpseclib\Net\SSH1::_send_binary_packet() * @see self::_send_binary_packet()
* @param String $data * @param string $data
* @return Integer * @return int
* @access private * @access private
*/ */
function _crc($data) function _crc($data)
@ -1284,9 +1276,9 @@ class SSH1
* *
* Inspired by array_shift * Inspired by array_shift
* *
* @param String $string * @param string $string
* @param optional Integer $index * @param int $index
* @return String * @return string
* @access private * @access private
*/ */
function _string_shift(&$string, $index = 1) function _string_shift(&$string, $index = 1)
@ -1303,9 +1295,9 @@ class SSH1
* should be a number with the property that gcd($e, ($p - 1) * ($q - 1)) == 1. Could just make anything that * should be a number with the property that gcd($e, ($p - 1) * ($q - 1)) == 1. Could just make anything that
* calls this call modexp, instead, but I think this makes things clearer, maybe... * calls this call modexp, instead, but I think this makes things clearer, maybe...
* *
* @see \phpseclib\Net\SSH1::__construct() * @see self::__construct()
* @param BigInteger $m * @param BigInteger $m
* @param Array $key * @param array $key
* @return BigInteger * @return BigInteger
* @access private * @access private
*/ */
@ -1313,9 +1305,9 @@ class SSH1
{ {
/* /*
$rsa = new RSA(); $rsa = new RSA();
$rsa->loadKey($key, RSA::PUBLIC_FORMAT_RAW); $rsa->load($key, 'raw');
$rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1); $rsa->setHash('sha1');
return $rsa->encrypt($m); return $rsa->encrypt($m, RSA::PADDING_PKCS1);
*/ */
// To quote from protocol-1.5.txt: // To quote from protocol-1.5.txt:
@ -1354,7 +1346,7 @@ class SSH1
* named constants from it, using the value as the name of the constant and the index as the value of the constant. * named constants from it, using the value as the name of the constant and the index as the value of the constant.
* If any of the constants that would be defined already exists, none of the constants will be defined. * If any of the constants that would be defined already exists, none of the constants will be defined.
* *
* @param Array $array * @param array $array
* @access private * @access private
*/ */
function _define_array() function _define_array()
@ -1377,7 +1369,7 @@ class SSH1
* Returns a string if NET_SSH1_LOGGING == self::LOG_COMPLEX, an array if NET_SSH1_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH1_LOGGING') * Returns a string if NET_SSH1_LOGGING == self::LOG_COMPLEX, an array if NET_SSH1_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH1_LOGGING')
* *
* @access public * @access public
* @return String or Array * @return array|false|string
*/ */
function getLog() function getLog()
{ {
@ -1400,10 +1392,10 @@ class SSH1
/** /**
* Formats a log for printing * Formats a log for printing
* *
* @param Array $message_log * @param array $message_log
* @param Array $message_number_log * @param array $message_number_log
* @access private * @access private
* @return String * @return string
*/ */
function _format_log($message_log, $message_number_log) function _format_log($message_log, $message_number_log)
{ {
@ -1436,9 +1428,9 @@ class SSH1
* *
* For use with preg_replace_callback() * For use with preg_replace_callback()
* *
* @param Array $matches * @param array $matches
* @access private * @access private
* @return String * @return string
*/ */
function _format_log_helper($matches) function _format_log_helper($matches)
{ {
@ -1451,8 +1443,8 @@ class SSH1
* Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
* the raw bytes. This behavior is similar to PHP's md5() function. * the raw bytes. This behavior is similar to PHP's md5() function.
* *
* @param optional Boolean $raw_output * @param bool $raw_output
* @return String * @return string
* @access public * @access public
*/ */
function getServerKeyPublicExponent($raw_output = false) function getServerKeyPublicExponent($raw_output = false)
@ -1466,8 +1458,8 @@ class SSH1
* Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
* the raw bytes. This behavior is similar to PHP's md5() function. * the raw bytes. This behavior is similar to PHP's md5() function.
* *
* @param optional Boolean $raw_output * @param bool $raw_output
* @return String * @return string
* @access public * @access public
*/ */
function getServerKeyPublicModulus($raw_output = false) function getServerKeyPublicModulus($raw_output = false)
@ -1481,8 +1473,8 @@ class SSH1
* Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
* the raw bytes. This behavior is similar to PHP's md5() function. * the raw bytes. This behavior is similar to PHP's md5() function.
* *
* @param optional Boolean $raw_output * @param bool $raw_output
* @return String * @return string
* @access public * @access public
*/ */
function getHostKeyPublicExponent($raw_output = false) function getHostKeyPublicExponent($raw_output = false)
@ -1496,8 +1488,8 @@ class SSH1
* Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead,
* the raw bytes. This behavior is similar to PHP's md5() function. * the raw bytes. This behavior is similar to PHP's md5() function.
* *
* @param optional Boolean $raw_output * @param bool $raw_output
* @return String * @return string
* @access public * @access public
*/ */
function getHostKeyPublicModulus($raw_output = false) function getHostKeyPublicModulus($raw_output = false)
@ -1512,8 +1504,8 @@ class SSH1
* is set to true, returns, instead, an array of constants. ie. instead of array('Triple-DES in CBC mode'), you'll * is set to true, returns, instead, an array of constants. ie. instead of array('Triple-DES in CBC mode'), you'll
* get array(self::CIPHER_3DES). * get array(self::CIPHER_3DES).
* *
* @param optional Boolean $raw_output * @param bool $raw_output
* @return Array * @return array
* @access public * @access public
*/ */
function getSupportedCiphers($raw_output = false) function getSupportedCiphers($raw_output = false)
@ -1528,8 +1520,8 @@ class SSH1
* is set to true, returns, instead, an array of constants. ie. instead of array('password authentication'), you'll * is set to true, returns, instead, an array of constants. ie. instead of array('password authentication'), you'll
* get array(self::AUTH_PASSWORD). * get array(self::AUTH_PASSWORD).
* *
* @param optional Boolean $raw_output * @param bool $raw_output
* @return Array * @return array
* @access public * @access public
*/ */
function getSupportedAuthentications($raw_output = false) function getSupportedAuthentications($raw_output = false)
@ -1540,7 +1532,7 @@ class SSH1
/** /**
* Return the server identification. * Return the server identification.
* *
* @return String * @return string
* @access public * @access public
*/ */
function getServerIdentification() function getServerIdentification()
@ -1553,7 +1545,7 @@ class SSH1
* *
* Makes sure that only the last 1MB worth of packets will be logged * Makes sure that only the last 1MB worth of packets will be logged
* *
* @param String $data * @param string $data
* @access private * @access private
*/ */
function _append_log($protocol_flags, $message) function _append_log($protocol_flags, $message)

File diff suppressed because it is too large Load Diff

View File

@ -34,6 +34,7 @@
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;
/** /**
@ -83,7 +84,7 @@ class Agent
/** /**
* Socket Resource * Socket Resource
* *
* @var Resource * @var resource
* @access private * @access private
*/ */
var $fsock; var $fsock;
@ -115,6 +116,8 @@ 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()
@ -127,13 +130,12 @@ class Agent
$address = $_ENV['SSH_AUTH_SOCK']; $address = $_ENV['SSH_AUTH_SOCK'];
break; break;
default: default:
user_error('SSH_AUTH_SOCK not found'); throw new \BadConfigurationException('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) {
user_error("Unable to connect to ssh-agent (Error $errno: $errstr)"); throw new \RuntimeException("Unable to connect to ssh-agent (Error $errno: $errstr)");
} }
} }
@ -143,7 +145,8 @@ class Agent
* See "2.5.2 Requesting a list of protocol 2 keys" * See "2.5.2 Requesting a list of protocol 2 keys"
* 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()
@ -154,13 +157,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)) {
user_error('Connection closed while requesting identities'); throw new \RuntimeException('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) {
user_error('Unable to request identities'); throw new \RuntimeException('Unable to request identities');
} }
$identities = array(); $identities = array();
@ -169,13 +172,15 @@ class Agent
$length = current(unpack('N', fread($this->fsock, 4))); $length = current(unpack('N', fread($this->fsock, 4)));
$key_blob = fread($this->fsock, $length); $key_blob = fread($this->fsock, $length);
$length = current(unpack('N', fread($this->fsock, 4))); $length = current(unpack('N', fread($this->fsock, 4)));
$key_comment = fread($this->fsock, $length); if ($length) {
$key_comment = fread($this->fsock, $length);
}
$length = current(unpack('N', substr($key_blob, 0, 4))); $length = current(unpack('N', substr($key_blob, 0, 4)));
$key_type = substr($key_blob, 4, $length); $key_type = substr($key_blob, 4, $length);
switch ($key_type) { switch ($key_type) {
case 'ssh-rsa': case 'ssh-rsa':
$key = new RSA(); $key = new RSA();
$key->loadKey('ssh-rsa ' . base64_encode($key_blob) . ' ' . $key_comment); $key->load('ssh-rsa ' . base64_encode($key_blob) . ' ' . $key_comment);
break; break;
case 'ssh-dss': case 'ssh-dss':
// not currently supported // not currently supported
@ -199,7 +204,7 @@ class Agent
* be requested when a channel is opened * be requested when a channel is opened
* *
* @param Net_SSH2 $ssh * @param Net_SSH2 $ssh
* @return Boolean * @return bool
* @access public * @access public
*/ */
function startSSHForwarding($ssh) function startSSHForwarding($ssh)
@ -213,7 +218,7 @@ class Agent
* Request agent forwarding of remote server * Request agent forwarding of remote server
* *
* @param Net_SSH2 $ssh * @param Net_SSH2 $ssh
* @return Boolean * @return bool
* @access private * @access private
*/ */
function _request_forwarding($ssh) function _request_forwarding($ssh)
@ -269,8 +274,9 @@ class Agent
/** /**
* Forward data to SSH Agent and return data reply * Forward data to SSH Agent and return data reply
* *
* @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)
@ -289,7 +295,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)) {
user_error('Connection closed attempting to forward data to SSH agent'); throw new \RuntimeException('Connection closed attempting to forward data to SSH agent');
} }
$this->socket_buffer = ''; $this->socket_buffer = '';

View File

@ -15,6 +15,8 @@
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;
/** /**
@ -23,9 +25,8 @@ 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, setSignatureMode * The methods in this interface would be getPublicKey and sign since those are the
* and sign since those are the methods phpseclib looks for to perform * methods phpseclib looks for to perform public key authentication.
* public key authentication.
* *
* @package SSH\Agent * @package SSH\Agent
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
@ -38,32 +39,32 @@ class Identity
* *
* @var \phpseclib\Crypt\RSA * @var \phpseclib\Crypt\RSA
* @access private * @access private
* @see \phpseclib\System\SSH\Agent\Identity::getPublicKey() * @see self::getPublicKey()
*/ */
var $key; var $key;
/** /**
* Key Blob * Key Blob
* *
* @var String * @var string
* @access private * @access private
* @see \phpseclib\System\SSH\Agent\Identity::sign() * @see self::sign()
*/ */
var $key_blob; var $key_blob;
/** /**
* Socket Resource * Socket Resource
* *
* @var Resource * @var resource
* @access private * @access private
* @see \phpseclib\System\SSH\Agent\Identity::sign() * @see self::sign()
*/ */
var $fsock; var $fsock;
/** /**
* Default Constructor. * Default Constructor.
* *
* @param Resource $fsock * @param resource $fsock
* @return \phpseclib\System\SSH\Agent\Identity * @return \phpseclib\System\SSH\Agent\Identity
* @access private * @access private
*/ */
@ -92,7 +93,7 @@ class Identity
* Called by \phpseclib\System\SSH\Agent::requestIdentities(). The key blob could be extracted from $this->key * Called by \phpseclib\System\SSH\Agent::requestIdentities(). The key blob could be extracted from $this->key
* but this saves a small amount of computation. * but this saves a small amount of computation.
* *
* @param String $key_blob * @param string $key_blob
* @access private * @access private
*/ */
function setPublicKeyBlob($key_blob) function setPublicKeyBlob($key_blob)
@ -105,26 +106,29 @@ class Identity
* *
* Wrapper for $this->key->getPublicKey() * Wrapper for $this->key->getPublicKey()
* *
* @param Integer $format optional * @param int $type optional
* @return Mixed * @return mixed
* @access public * @access public
*/ */
function getPublicKey($format = null) function getPublicKey($type = 'PKCS8')
{ {
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format); return $this->key->getPublicKey($type);
} }
/** /**
* Set Signature Mode * Sets the hash
* *
* Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie. * ssh-agent only supports signatures with sha1 hashes but to maintain BC with RSA.php this function exists
* ssh-agent's only supported mode is \phpseclib\Crypt\RSA::SIGNATURE_PKCS1
* *
* @param Integer $mode * @param string $hash optional
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
* @access public * @access public
*/ */
function setSignatureMode($mode) function setHash($hash = 'sha1')
{ {
if ($hash != 'sha1') {
throw new UnsupportedAlgorithmException('ssh-agent can only be used with the sha1 hash');
}
} }
/** /**
@ -132,23 +136,30 @@ 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
* @return String * @param int $padding optional
* @return string
* @throws \RuntimeException on connection errors
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
* @access public * @access public
*/ */
function sign($message) function sign($message, $padding = RSA::PADDING_PKCS1)
{ {
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)) {
user_error('Connection closed during signing'); throw new \RuntimeException('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) {
user_error('Unable to retreive signature'); throw new \RuntimeException('Unable to retreive signature');
} }
$signature_blob = fread($this->fsock, $length - 1); $signature_blob = fread($this->fsock, $length - 1);

View File

@ -27,6 +27,34 @@ class Functional_Net_SFTPStreamTest extends Functional_Net_SFTPTestCase
$this->assertSame(0, $this->sftp->size('fooo.txt')); $this->assertSame(0, $this->sftp->size('fooo.txt'));
} }
/**
* @group github778
*/
public function testFilenameWithHash()
{
$context = stream_context_create(array(
'sftp' => array('session' => $this->sftp),
));
$fp = fopen($this->buildUrl('te#st.txt'), 'wb', false, $context);
fputs($fp, 'zzzz');
fclose($fp);
$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(

View File

@ -13,6 +13,9 @@ 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;

View File

@ -171,8 +171,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testStatOnDir * @depends testStatOnDir
*/ */
public function testPutSizeGetFileCallback($sftp) public function testPutSizeGetFileCallback($sftp)
{ {
self::$buffer = self::$exampleData; self::$buffer = self::$exampleData;
@ -240,6 +240,20 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
/** /**
* @depends testTruncate * @depends testTruncate
* @group github850
*/
public function testChModOnFile($sftp)
{
$this->assertNotFalse(
$sftp->chmod(0755, 'file1.txt'),
'Failed asserting that chmod() was successful.'
);
return $sftp;
}
/**
* @depends testChModOnFile
*/ */
public function testChDirOnFile($sftp) public function testChDirOnFile($sftp)
{ {
@ -651,5 +665,28 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
$this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK); $this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK);
$sftp->enableStatCache(); $sftp->enableStatCache();
return $sftp;
}
/**
* @depends testStatVsLstat
* @group github830
*/
public function testUploadOffsets($sftp)
{
$sftp->put('offset.txt', 'res.txt', SFTP::SOURCE_LOCAL_FILE, 0, 10);
$this->assertSame(
substr(self::$exampleData, 10),
$sftp->get('offset.txt'),
'Failed asserting that portions of a file could be uploaded.'
);
$sftp->put('offset.txt', 'res.txt', SFTP::SOURCE_LOCAL_FILE, self::$exampleDataLength - 100);
$this->assertSame(
substr(self::$exampleData, 10, -90) . self::$exampleData,
$sftp->get('offset.txt'),
'Failed asserting that you could upload into the middle of a file.'
);
} }
} }

View File

@ -34,6 +34,11 @@ class Functional_Net_SSH2Test extends PhpseclibFunctionalTestCase
'Failed asserting that SSH2 is not connected after construction.' 'Failed asserting that SSH2 is not connected after construction.'
); );
$this->assertFalse(
$ssh->isAuthenticated(),
'Failed asserting that SSH2 is not authenticated after construction.'
);
$this->assertNotEmpty( $this->assertNotEmpty(
$ssh->getServerPublicHostKey(), $ssh->getServerPublicHostKey(),
'Failed asserting that a non-empty public host key was fetched.' 'Failed asserting that a non-empty public host key was fetched.'
@ -55,6 +60,31 @@ class Functional_Net_SSH2Test extends PhpseclibFunctionalTestCase
/** /**
* @depends testPreLogin * @depends testPreLogin
*/ */
public function testBadPassword($ssh)
{
$username = $this->getEnv('SSH_USERNAME');
$password = $this->getEnv('SSH_PASSWORD');
$this->assertFalse(
$ssh->login($username, 'zzz' . $password),
'SSH2 login using password succeeded.'
);
$this->assertTrue(
$ssh->isConnected(),
'Failed asserting that SSH2 is connected after bad login attempt.'
);
$this->assertFalse(
$ssh->isAuthenticated(),
'Failed asserting that SSH2 is not authenticated after bad login attempt.'
);
return $ssh;
}
/**
* @depends testBadPassword
*/
public function testPasswordLogin($ssh) public function testPasswordLogin($ssh)
{ {
$username = $this->getEnv('SSH_USERNAME'); $username = $this->getEnv('SSH_USERNAME');
@ -64,6 +94,11 @@ class Functional_Net_SSH2Test extends PhpseclibFunctionalTestCase
'SSH2 login using password failed.' 'SSH2 login using password failed.'
); );
$this->assertTrue(
$ssh->isAuthenticated(),
'Failed asserting that SSH2 is authenticated after good login attempt.'
);
return $ssh; return $ssh;
} }

View File

@ -28,9 +28,7 @@ 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();
} }

View File

@ -59,7 +59,7 @@ abstract class PhpseclibTestCase extends PHPUnit_Framework_TestCase
$value = constant($constant); $value = constant($constant);
if ($value !== $expected) { if ($value !== $expected) {
if (function_exists('runkit_constant_redefine')) { if (extension_loaded('runkit')) {
if (!runkit_constant_redefine($constant, $expected)) { if (!runkit_constant_redefine($constant, $expected)) {
self::markTestSkipped(sprintf( self::markTestSkipped(sprintf(
"Failed to redefine constant %s to %s", "Failed to redefine constant %s to %s",
@ -82,15 +82,15 @@ abstract class PhpseclibTestCase extends PHPUnit_Framework_TestCase
} }
/** /**
* @param string $filename * @param string $filename Filename relative to library directory.
* *
* @return null * @return null
*/ */
protected static function reRequireFile($filename) protected static function reRequireFile($filename)
{ {
if (function_exists('runkit_import')) { if (extension_loaded('runkit')) {
$result = runkit_import( $result = runkit_import(
$filename, sprintf('%s/../phpseclib/%s', __DIR__, $filename),
RUNKIT_IMPORT_FUNCTIONS | RUNKIT_IMPORT_FUNCTIONS |
RUNKIT_IMPORT_CLASS_METHODS | RUNKIT_IMPORT_CLASS_METHODS |
RUNKIT_IMPORT_OVERRIDE RUNKIT_IMPORT_OVERRIDE

View File

@ -47,24 +47,26 @@ 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),
'test123', str_pad('test123', 16, "\0"),
); );
$keys = array( $keys = array(
'', str_repeat("\0", 16),
':-8', // https://github.com/phpseclib/phpseclib/pull/43 str_pad(':-8', 16, "\0"), // https://github.com/phpseclib/phpseclib/pull/43
'FOOBARZ', str_pad('FOOBARZ', 16, "\0"),
); );
$result = array(); $result = array();
// @codingStandardsIgnoreStart foreach ($modes as $mode) {
foreach ($modes as $mode) foreach ($plaintexts as $plaintext) {
foreach ($plaintexts as $plaintext) foreach ($ivs as $iv) {
foreach ($ivs as $iv) foreach ($keys as $key) {
foreach ($keys as $key) $result[] = array($mode, $plaintext, $iv, $key);
$result[] = array($mode, $plaintext, $iv, $key); }
// @codingStandardsIgnoreEnd }
}
}
return $result; return $result;
} }
@ -98,10 +100,11 @@ 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(); $aes = new Rijndael(Base::MODE_CBC);
$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'));
@ -109,25 +112,27 @@ 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(); $aes = new AES(Base::MODE_CBC);
$aes->setPreferredEngine($this->engine); $aes->setPreferredEngine($this->engine);
$aes->disablePadding(); $aes->disablePadding();
$aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. AES should null pad to 192-bits $aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. supported by Rijndael - not AES
$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'));
} }
/** /**
* Produces all combinations of test values. * Produces all combinations of test values.
* *
* @return array * @return array
*/ */
public function continuousBufferBatteryCombos() public function continuousBufferBatteryCombos()
{ {
$modes = array( $modes = array(
@ -155,19 +160,20 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
$result = array(); $result = array();
// @codingStandardsIgnoreStart foreach ($modes as $mode) {
foreach ($modes as $mode) foreach ($combos as $combo) {
foreach ($combos as $combo) foreach (array('encrypt', 'decrypt') as $op) {
foreach (array('encrypt', 'decrypt') as $op) $result[] = array($op, $mode, $combo);
$result[] = array($op, $mode, $combo); }
// @codingStandardsIgnoreEnd }
}
return $result; return $result;
} }
/** /**
* @dataProvider continuousBufferBatteryCombos * @dataProvider continuousBufferBatteryCombos
*/ */
public function testContinuousBufferBattery($op, $mode, $test) public function testContinuousBufferBattery($op, $mode, $test)
{ {
$iv = str_repeat('x', 16); $iv = str_repeat('x', 16);
@ -211,9 +217,10 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
} }
/** /**
* @dataProvider continuousBufferBatteryCombos * Pretty much the same as testContinuousBufferBattery with the caveat that continuous mode is not enabled.
*/ *
// pretty much the same as testContinuousBufferBattery with the caveat that continuous mode is not enabled * @dataProvider continuousBufferBatteryCombos
*/
public function testNonContinuousBufferBattery($op, $mode, $test) public function testNonContinuousBufferBattery($op, $mode, $test)
{ {
if (count($test) == 1) { if (count($test) == 1) {
@ -260,7 +267,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(); $aes = new AES(Base::MODE_CBC);
$aes->setKey(pack('H*', '00000000000000000000000000000000')); $aes->setKey(pack('H*', '00000000000000000000000000000000'));
$aes->setIV(pack('H*', '00000000000000000000000000000000')); $aes->setIV(pack('H*', '00000000000000000000000000000000'));
@ -287,7 +294,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
public function testGFSBox192() public function testGFSBox192()
{ {
$aes = new AES(); $aes = new AES(Base::MODE_CBC);
$aes->setKey(pack('H*', '000000000000000000000000000000000000000000000000')); $aes->setKey(pack('H*', '000000000000000000000000000000000000000000000000'));
$aes->setIV(pack('H*', '00000000000000000000000000000000')); $aes->setIV(pack('H*', '00000000000000000000000000000000'));
@ -312,7 +319,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
public function testGFSBox256() public function testGFSBox256()
{ {
$aes = new AES(); $aes = new AES(Base::MODE_CBC);
$aes->setKey(pack('H*', '00000000000000000000000000000000' . '00000000000000000000000000000000')); $aes->setKey(pack('H*', '00000000000000000000000000000000' . '00000000000000000000000000000000'));
$aes->setIV(pack('H*', '00000000000000000000000000000000')); $aes->setIV(pack('H*', '00000000000000000000000000000000'));
@ -332,4 +339,63 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
$result = bin2hex($aes->encrypt(pack('H*', '91fbef2d15a97816060bee1feaa49afe'))); $result = bin2hex($aes->encrypt(pack('H*', '91fbef2d15a97816060bee1feaa49afe')));
$this->assertSame($result, '1bc704f1bce135ceb810341b216d7abe'); $this->assertSame($result, '1bc704f1bce135ceb810341b216d7abe');
} }
public function testGetKeyLengthDefault()
{
$aes = new AES(Base::MODE_CBC);
$this->assertSame($aes->getKeyLength(), 128);
}
public function testGetKeyLengthWith192BitKey()
{
$aes = new AES(Base::MODE_CBC);
$aes->setKey(str_repeat('a', 24));
$this->assertSame($aes->getKeyLength(), 192);
}
/**
* @expectedException \LengthException
*/
public function testSetKeyLengthWithLargerKey()
{
$aes = new AES(Base::MODE_CBC);
$aes->setKeyLength(128);
$aes->setKey(str_repeat('a', 24));
$aes->setIV(str_repeat("\0", 16));
$this->assertSame($aes->getKeyLength(), 128);
$ciphertext = bin2hex($aes->encrypt('a'));
$this->assertSame($ciphertext, '82b7b068dfc60ed2a46893b69fecd6c2');
$this->assertSame($aes->getKeyLength(), 128);
}
/**
* @expectedException \LengthException
*/
public function testSetKeyLengthWithSmallerKey()
{
$aes = new AES(Base::MODE_CBC);
$aes->setKeyLength(256);
$aes->setKey(str_repeat('a', 16));
$aes->setIV(str_repeat("\0", 16));
$this->assertSame($aes->getKeyLength(), 256);
$ciphertext = bin2hex($aes->encrypt('a'));
$this->assertSame($ciphertext, 'fd4250c0d234aa7e1aa592820aa8406b');
$this->assertSame($aes->getKeyLength(), 256);
}
/**
* @group github938
*/
public function testContinuousBuffer()
{
$aes = new AES(AES::MODE_CBC);
$aes->disablePadding();
$aes->enableContinuousBuffer();
$aes->setIV(pack('H*', '0457bdb4a6712986688349a29eb82535'));
$aes->setKey(pack('H*', '00d596e2c8189b2592fac358e7396ad2'));
$aes->decrypt(pack('H*', '9aa234ea7c750a8109a0f32d768b964e'));
$plaintext = $aes->decrypt(pack('H*', '0457bdb4a6712986688349a29eb82535'));
$expected = pack('H*', '6572617574689e1be8d2d8d43c594cf3');
$this->assertSame($plaintext, $expected);
}
} }

View File

@ -56,22 +56,26 @@ class Unit_Crypt_BlowfishTest extends PhpseclibTestCase
array(pack('H*', '0123456789ABCDEF'), pack('H*', '0000000000000000'), pack('H*', '245946885754369A')), array(pack('H*', '0123456789ABCDEF'), pack('H*', '0000000000000000'), pack('H*', '245946885754369A')),
array(pack('H*', 'FEDCBA9876543210'), pack('H*', 'FFFFFFFFFFFFFFFF'), pack('H*', '6B5C5A9C5D9E0A5A')) array(pack('H*', 'FEDCBA9876543210'), pack('H*', 'FFFFFFFFFFFFFFFF'), pack('H*', '6B5C5A9C5D9E0A5A'))
); );
$result = array(); $result = array();
// @codingStandardsIgnoreStart
foreach ($engines as $engine => $engineName) foreach ($engines as $engine => $engineName) {
foreach ($tests as $test) foreach ($tests as $test) {
$result[] = array($engine, $engineName, $test[0], $test[1], $test[2]); $result[] = array($engine, $engineName, $test[0], $test[1], $test[2]);
// @codingStandardsIgnoreEnd }
}
return $result; return $result;
} }
/** /**
* @dataProvider engineVectors * @dataProvider engineVectors
*/ */
public function testVectors($engine, $engineName, $key, $plaintext, $expected) public function testVectors($engine, $engineName, $key, $plaintext, $expected)
{ {
$bf = new Blowfish(); $bf = new Blowfish(Blowfish::MODE_CBC);
$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');
} }

View File

@ -1,78 +0,0 @@
<?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');
}
}
}

View File

@ -1,49 +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_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'),
);
}
}

View File

@ -1,81 +0,0 @@
<?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',
),
);
}
}

View File

@ -1,32 +0,0 @@
<?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));
}
}

View File

@ -1,81 +0,0 @@
<?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',
),
);
}
}

View File

@ -1,32 +0,0 @@
<?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));
}
}

View File

@ -1,52 +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;
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
)
);
}
}

View File

@ -0,0 +1,423 @@
<?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),
);
}
}

View File

@ -30,12 +30,15 @@ class Unit_Crypt_RC2Test extends PhpseclibTestCase
array('88bca90e90875a7f0f79c384627bafb2', 128, '0000000000000000', '2269552ab0f85ca6'), array('88bca90e90875a7f0f79c384627bafb2', 128, '0000000000000000', '2269552ab0f85ca6'),
array('88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e', 129, '0000000000000000', '5b78d3a43dfff1f1') array('88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e', 129, '0000000000000000', '5b78d3a43dfff1f1')
); );
$result = array(); $result = array();
// @codingStandardsIgnoreStart
foreach ($this->engines as $engine => $engineName) foreach ($this->engines as $engine => $engineName) {
foreach ($tests as $test) foreach ($tests as $test) {
$result[] = array($engine, $engineName, $test[0], $test[1], $test[2], $test[3]); $result[] = array($engine, $engineName, $test[0], $test[1], $test[2], $test[3]);
// @codingStandardsIgnoreEnd }
}
return $result; return $result;
} }
@ -103,14 +106,15 @@ class Unit_Crypt_RC2Test extends PhpseclibTestCase
} }
/** /**
* @dataProvider engineVectors * @dataProvider engineVectors
*/ */
public function testVectors($engine, $engineName, $key, $keyLen, $plaintext, $ciphertext) public function testVectors($engine, $engineName, $key, $keyLen, $plaintext, $ciphertext)
{ {
$rc2 = new RC2(); $rc2 = new RC2(RC2::MODE_CBC);
$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');
} }
@ -118,5 +122,8 @@ class Unit_Crypt_RC2Test extends PhpseclibTestCase
$result = bin2hex($rc2->encrypt(pack('H*', $plaintext))); $result = bin2hex($rc2->encrypt(pack('H*', $plaintext)));
$this->assertEquals($result, $ciphertext, "Failed asserting that $plaintext yielded expected output in $engineName engine"); $this->assertEquals($result, $ciphertext, "Failed asserting that $plaintext yielded expected output in $engineName engine");
$result = bin2hex($rc2->decrypt(pack('H*', $ciphertext)));
$this->assertEquals($result, $plaintext, "Failed asserting that decrypted result yielded $plaintext as a result in $engineName engine");
} }
} }

View File

@ -181,19 +181,23 @@ class Unit_Crypt_RC4Test extends PhpseclibTestCase
) )
) )
); );
$result = array(); $result = array();
// @codingStandardsIgnoreStart
foreach ($engines as $engine => $engineName) foreach ($engines as $engine => $engineName) {
foreach ($tests as $test) foreach ($tests as $test) {
foreach ($test['output'] as $output) foreach ($test['output'] as $output) {
$result[] = array($engine, $engineName, $test['key'], $output['offset'], $output['result']); $result[] = array($engine, $engineName, $test['key'], $output['offset'], $output['result']);
// @codingStandardsIgnoreEnd }
}
}
return $result; return $result;
} }
/** /**
* @dataProvider engineVectors * @dataProvider engineVectors
*/ */
public function testVectors($engine, $engineName, $key, $offset, $expected) public function testVectors($engine, $engineName, $key, $offset, $expected)
{ {
$rc4 = new RC4(); $rc4 = new RC4();

View File

@ -0,0 +1,34 @@
<?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');
}
}

View File

@ -6,6 +6,9 @@
*/ */
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
{ {
@ -15,7 +18,7 @@ class Unit_Crypt_RSA_LoadKeyTest extends PhpseclibTestCase
$key = 'zzzzzzzzzzzzzz'; $key = 'zzzzzzzzzzzzzz';
$this->assertFalse($rsa->loadKey($key)); $this->assertFalse($rsa->load($key));
} }
public function testPKCS1Key() public function testPKCS1Key()
@ -36,7 +39,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0= 37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=
-----END RSA PRIVATE KEY-----'; -----END RSA PRIVATE KEY-----';
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($key));
$this->assertInternalType('string', $rsa->getPrivateKey()); $this->assertInternalType('string', $rsa->getPrivateKey());
} }
@ -59,7 +62,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->loadKey($key)); $this->assertTrue($rsa->load($key));
$this->assertInternalType('string', $rsa->getPrivateKey()); $this->assertInternalType('string', $rsa->getPrivateKey());
} }
@ -79,7 +82,7 @@ X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl
U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0='; 37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=';
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($key));
$this->assertInternalType('string', $rsa->getPrivateKey()); $this->assertInternalType('string', $rsa->getPrivateKey());
} }
@ -99,7 +102,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
'U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ' . 'U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ' .
'37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0='; '37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=';
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($key));
$this->assertInternalType('string', $rsa->getPrivateKey()); $this->assertInternalType('string', $rsa->getPrivateKey());
} }
@ -120,7 +123,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
'37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0='; '37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=';
$key = base64_decode($key); $key = base64_decode($key);
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($key));
$this->assertInternalType('string', $rsa->getPrivateKey()); $this->assertInternalType('string', $rsa->getPrivateKey());
} }
@ -159,7 +162,7 @@ GF/qoZyC1mbqdtyyeWgHtVbJVUORmpbNnXOII9duEqBUNDiO9VSZNn/8h/VsYeAB
xryZaRDVmtMuf/OZBQ== xryZaRDVmtMuf/OZBQ==
-----END ENCRYPTED PRIVATE KEY-----'; -----END ENCRYPTED PRIVATE KEY-----';
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($key));
$this->assertInternalType('string', $rsa->getPrivateKey()); $this->assertInternalType('string', $rsa->getPrivateKey());
} }
@ -182,12 +185,12 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
-----END RSA PRIVATE KEY-----'; -----END RSA PRIVATE KEY-----';
$rsa->setPassword('password'); $rsa->setPassword('password');
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($key));
$key = $rsa->getPrivateKey(RSA::PRIVATE_FORMAT_PKCS8); $key = $rsa->getPrivateKey('PKCS8');
$this->assertInternalType('string', $key); $this->assertInternalType('string', $key);
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($key));
} }
public function testPubKey1() public function testPubKey1()
@ -203,7 +206,7 @@ gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END RSA PUBLIC KEY-----'; -----END RSA PUBLIC KEY-----';
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($key));
$this->assertInternalType('string', $rsa->getPublicKey()); $this->assertInternalType('string', $rsa->getPublicKey());
$this->assertFalse($rsa->getPrivateKey()); $this->assertFalse($rsa->getPrivateKey());
} }
@ -222,7 +225,7 @@ lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB ZQIDAQAB
-----END PUBLIC KEY-----'; -----END PUBLIC KEY-----';
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($key));
$this->assertInternalType('string', $rsa->getPublicKey()); $this->assertInternalType('string', $rsa->getPublicKey());
$this->assertFalse($rsa->getPrivateKey()); $this->assertFalse($rsa->getPrivateKey());
} }
@ -236,7 +239,7 @@ ZQIDAQAB
'GkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZw== ' . 'GkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZw== ' .
'phpseclib-generated-key'; 'phpseclib-generated-key';
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($key));
$this->assertInternalType('string', $rsa->getPublicKey()); $this->assertInternalType('string', $rsa->getPublicKey());
$this->assertFalse($rsa->getPrivateKey()); $this->assertFalse($rsa->getPrivateKey());
} }
@ -252,7 +255,7 @@ ZQIDAQAB
'b6wYtY/q/WtUFr3nK+x0lgOtokhnJfRR/6fnmC1CztPnIT4BWK81VGKWONAxuhMyQ5XChyu6S9'. 'b6wYtY/q/WtUFr3nK+x0lgOtokhnJfRR/6fnmC1CztPnIT4BWK81VGKWONAxuhMyQ5XChyu6S9'.
'mWG5tUlUI/5'; 'mWG5tUlUI/5';
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($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');
} }
@ -270,7 +273,7 @@ gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END RSA PUBLIC KEY-----'; -----END RSA PUBLIC KEY-----';
$this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->load($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());
@ -290,11 +293,11 @@ Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
<Exponent>AQAB</Exponent> <Exponent>AQAB</Exponent>
</RSAKeyValue>'; </RSAKeyValue>';
$rsa->loadKey($key); $rsa->load($key);
$rsa->setPublicKey(); $rsa->setPublicKey();
$newkey = $rsa->getPublicKey(RSA::PUBLIC_FORMAT_XML); $newkey = $rsa->getPublicKey('XML');
$this->assertSame(preg_replace('#\s#', '', $key), preg_replace('#\s#', '', $newkey)); $this->assertSame(strtolower(preg_replace('#\s#', '', $key)), strtolower(preg_replace('#\s#', '', $newkey)));
} }
/** /**
@ -311,10 +314,224 @@ JWrQdxx/WNN+ABG426rgYYbeGcIlWLZCw6Bx/1HtN5ef6nVEoiGNChYKIRB4QFOi
01smFxps1w8ZIQnD6wIDAQAB 01smFxps1w8ZIQnD6wIDAQAB
-----END PUBLIC KEY-----'; -----END PUBLIC KEY-----';
$rsa->loadKey($key); $rsa->load($key);
$rsa->setPublicKey(); $rsa->setPublicKey();
$newkey = $rsa->getPublicKey(); $newkey = $rsa->getPublicKey();
$this->assertSame(preg_replace('#\s#', '', $key), preg_replace('#\s#', '', $newkey)); $this->assertSame(preg_replace('#\s#', '', $key), preg_replace('#\s#', '', $newkey));
} }
/**
* @group github861
*/
public function testPKCS8Only()
{
$rsa = new RSA();
$key = '-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKB0yPMAbUHKqJxP
5sjG9AOrQSAYNDc34NsnZ1tsi7fZ9lHlBaKZ6gjm2U9q+/qCKv2BuGINxWo2CMJp
DHNY0QTt7hThr3B4U62z1CWWGnfLhFtHKH6jNYYOGc4x0jgT88uSrKFvUOLhjkjW
bURmJMpN+OjLJuZQZ7uwoqtT3IEDAgMBAAECgYBaElS/fEzYst/Fp2DA8lYGPTs4
vf2JxbdWrp7phlxEH3mTbUGljkr/Jj90wnSiojFpz0jm2h4oyh5Oq9OOaJwkCYcu
2lcHJvFlhR2XEJpd1bHHcvDwZHdUjSpnO8kvwQtjuTnho2ntRzAA4wIJVSd7Tynj
0IFEKmzhSKIvIIeN8QJBANLa10R1vs+YqpLdpAuc6Z9GYhHuh1TysBPw2xNtw3Xf
tGPx4/53eQ0RwiHdw9Opgt8CBHErD6KzziflfxUrIXkCQQDCz4t01qYWT43kxS6k
TcnZb/obho6akGc8C1hSxFIIGUa9hAhMpY2W6GXeGpv5TZtEJZIJE1VHTLvcLSGm
ILNbAkEAgq9mWqULxYket3Yt1ZDEb5Zk9C49rJXaMhHHBoyyZ51mJcfngnE0Erid
9PWJCOf4GBYdALMqtrHwpWOlV05rKQJAd6Tz50w1MRqm8MvRe4Ny5qIJH4Kibncl
kBD/q8V7BBJSCe7fEgPTU81jUudQx+pL46yXZg+DnoiYD/9/3QHUZQJBAMBiKiZ7
qMnD/pkHR/NFcYSYShUJS0cHyryVl7/eCclsQlZTRdnVTtKF9xPGTQC8fK0G7BDN
Z2sKniRCcDT1ZP4=
-----END PRIVATE KEY-----';
$result = $rsa->load($key, 'PKCS8');
$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
*/
public function testSetLoad()
{
$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';
$rsa = new RSA();
$rsa->setPrivateKey($key);
$rsa->load($key);
$rsa = new RSA();
$rsa->load($key);
$rsa->setPrivateKey();
$rsa->load($rsa);
}
} }

View File

@ -6,6 +6,7 @@
*/ */
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
{ {
@ -28,19 +29,74 @@ X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl
U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0= 37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=
-----END RSA PRIVATE KEY-----'; -----END RSA PRIVATE KEY-----';
$rsa->loadKey($privatekey); $rsa->load($privatekey);
$rsa->loadKey($rsa->getPublicKey()); $rsa->load($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); $result = $rsa->encrypt($plaintext, RSA::PADDING_NONE);
$this->assertEquals($result, $expected); $this->assertEquals($result, $expected);
$rsa->loadKey($privatekey); $rsa->load($privatekey);
$this->assertEquals(trim($rsa->decrypt($result), "\0"), $plaintext); $this->assertEquals(trim($rsa->decrypt($result, RSA::PADDING_NONE), "\0"), $plaintext);
}
/**
* @group github768
*/
public function testPSSSigs()
{
$rsa = new RSA();
$rsa->setHash('sha1');
$rsa->setMGFHash('sha1');
$rsa->load('-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVx
wTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFnc
CzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0T
p0GbMJDyR4e9T04ZZwIDAQAB
-----END PUBLIC KEY-----');
$sig = pack('H*', '1bd29a1d704a906cd7f726370ce1c63d8fb7b9a620871a05f3141a311c0d6e75fefb5d36dfb50d3ea2d37cd67992471419bfadd35da6e13b494' .
'058ddc9b568d4cfea13ddc3c62b86a6256f5f296980d1131d3eaec6089069a3de79983f73eae20198a18721338b4a66e9cfe80e4f8e4fcef7a5bead5cbb' .
'b8ac4c76adffbc178c');
$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));
} }
} }

View File

@ -87,26 +87,30 @@ class Unit_Crypt_TripleDESTest extends PhpseclibTestCase
array(str_repeat("\x01", 24), pack('H*', '0000000000000002'), pack('H*', '06E7EA22CE92708F')), array(str_repeat("\x01", 24), pack('H*', '0000000000000002'), pack('H*', '06E7EA22CE92708F')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000001'), pack('H*', '166B40B44ABA4BD6')) array(str_repeat("\x01", 24), pack('H*', '0000000000000001'), pack('H*', '166B40B44ABA4BD6'))
); );
$result = array(); $result = array();
// @codingStandardsIgnoreStart
foreach ($this->engines as $engine => $engineName) foreach ($this->engines as $engine => $engineName) {
foreach ($tests as $test) foreach ($tests as $test) {
$result[] = array($engine, $engineName, $test[0], $test[1], $test[2]); $result[] = array($engine, $engineName, $test[0], $test[1], $test[2]);
// @codingStandardsIgnoreEnd }
}
return $result; return $result;
} }
/** /**
* @dataProvider engineVectors * @dataProvider engineVectors
*/ */
public function testVectors($engine, $engineName, $key, $plaintext, $expected) public function testVectors($engine, $engineName, $key, $plaintext, $expected)
{ {
$des = new TripleDES(); $des = new TripleDES(TripleDES::MODE_CBC);
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);
@ -135,21 +139,24 @@ class Unit_Crypt_TripleDESTest extends PhpseclibTestCase
pack('H*', '84401f78fe6c10876d8ea23094ea5309'), pack('H*', '84401f78fe6c10876d8ea23094ea5309'),
pack('H*', '7b1f7c7e3b1c948ebd04a75ffba7d2f5')) pack('H*', '7b1f7c7e3b1c948ebd04a75ffba7d2f5'))
); );
$result = array(); $result = array();
// @codingStandardsIgnoreStart
foreach ($engines as $engine => $engineName) foreach ($engines as $engine => $engineName) {
foreach ($tests as $test) foreach ($tests as $test) {
$result[] = array($engine, $engineName, $test[0], $test[1], $test[2], $test[3]); $result[] = array($engine, $engineName, $test[0], $test[1], $test[2], $test[3]);
// @codingStandardsIgnoreEnd }
}
return $result; return $result;
} }
/** /**
* @dataProvider engineIVVectors * @dataProvider engineIVVectors
*/ */
public function testVectorsWithIV($engine, $engineName, $key, $iv, $plaintext, $expected) public function testVectorsWithIV($engine, $engineName, $key, $iv, $plaintext, $expected)
{ {
$des = new TripleDES(); $des = new TripleDES(TripleDES::MODE_CBC);
if (!$des->isValidEngine($engine)) { if (!$des->isValidEngine($engine)) {
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine'); self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
} }
@ -170,6 +177,7 @@ 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);

View File

@ -19,7 +19,8 @@ class Unit_Crypt_TwofishTest extends PhpseclibTestCase
); );
foreach ($engines as $engine => $name) { foreach ($engines as $engine => $name) {
$tf = new Twofish(); $tf = new Twofish(Twofish::MODE_CBC);
$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

View File

@ -18,7 +18,7 @@ class Unit_File_ASN1Test extends PhpseclibTestCase
$KDC_REP = array( $KDC_REP = array(
'type' => ASN1::TYPE_SEQUENCE, 'type' => ASN1::TYPE_SEQUENCE,
'children' => array( 'children' => array(
'pvno' => array( 'pvno' => array(
'constant' => 0, 'constant' => 0,
'optional' => true, 'optional' => true,
'explicit' => true, 'explicit' => true,

View File

@ -68,4 +68,29 @@ draiRBZruwMPwPIP
$this->assertInternalType('array', $csr); $this->assertInternalType('array', $csr);
} }
public function testCSRDER()
{
$csr = 'MIICdzCCAV8CAQEwDDEKMAgGA1UEAwwBeDCCASIwDQYJKoZIhvcNAQEBBQADggEP' .
'ADCCAQoCggEBALtcrFDD2AHe3x2bR00wPDsPH6FJLxr5uc1ybb+ldDB5xNVImC8P' .
'LU6VXDZ5z68KjSovs1q0OWJWfCjlAuGLzqO35s86LI1CFuTFdkScVHMwh8zUVFoP' .
'pG7/9rKaNxCgaHs4evxjxQP2+Ny7tBqPLb/KV0exm6Twocf963jC/Tyn57G5erRf' .
'zpFrfK7DozhxY7znumJ4FuSn0TVkD6PPwZFn9VoTjv2ZoJmacGK+0r5yNKG799F5' .
'K8EgDrOCfbzCZjX6GJctyn2SNPTeBuXS9piH21FGnJAryv80zG+zUqFdEyoLUGJt' .
'4Vy6+tDP9cW68fiwTZS1Oc1VeFdL1G/CrjkCAwEAAaAmMCQGCSqGSIb3DQEJDjEX' .
'MBUwEwYKKwYBBAGCqlsBCQQFMAOCAQEwDQYJKoZIhvcNAQELBQADggEBAF4XOd+1' .
'jkJOYRInNpHfhzSD/ktDY50gpLPuDvl4f/ZBlKrb1eDYQG5F3bnYzoZWHN4n+6Zs' .
'CkljXs5ZPUZ5LuVpASumoG/aHXGz8c8NC3asJ1V73ljEPAfIXwqoIUoaP9jLL+Ee' .
'zy/ZCi2NKWVo2D7ocnn79oblAem9ksSeQl4z3Gvhuug6MsMqn96NU/ZY/vjYzAjb' .
'MAvJIVRY0rbCxbFa0K+XNJtF7GLyBxyPNFWCvADhvm9C4uPmoypYg7MY6EewJInN' .
'xzMH7I4xDLjNu0VBa6lAxTvflp0joQHKlTYX0SDIKPbQivjZMuObPuxDtkVZ0rQl' .
'AjmgMowaN5otTXM=';
$csr = base64_decode($csr);
$x509 = new X509();
$csr = $x509->loadCSR($csr);
$this->assertInternalType('array', $csr);
}
} }

View File

@ -48,10 +48,9 @@ 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($privKey); $x509->setPrivateKey($privatekey);
$x509->setChallenge('...'); $x509->setChallenge('...');
$spkac = $x509->signSPKAC(); $spkac = $x509->signSPKAC();
@ -94,6 +93,5 @@ class Unit_File_X509_SPKACTest extends PhpseclibTestCase
$x509->validateSignature(), $x509->validateSignature(),
'Failed asserting that the signature is invalid' 'Failed asserting that the signature is invalid'
); );
} }
} }

View File

@ -12,6 +12,55 @@ use phpseclib\Crypt\RSA;
class Unit_File_X509_X509Test extends PhpseclibTestCase class Unit_File_X509_X509Test extends PhpseclibTestCase
{ {
public function testExtensionMapping()
{
$test = '-----BEGIN CERTIFICATE-----
MIIG1jCCBL6gAwIBAgITUAAAAA0qg8bE6DhrLAAAAAAADTANBgkqhkiG9w0BAQsF
ADAiMSAwHgYDVQQDExcuU2VjdXJlIEVudGVycHJpc2UgQ0EgMTAeFw0xNTAyMjMx
NTE1MDdaFw0xNjAyMjMxNTE1MDdaMD8xFjAUBgoJkiaJk/IsZAEZFgZzZWN1cmUx
DjAMBgNVBAMTBVVzZXJzMRUwEwYDVQQDEwxtZXRhY2xhc3NpbmcwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMdG1CzR/gTalbLN9J+2cvMGeD7wsR7S78
HU5hdwE+kECROjRAcjFBOR57ezSDrkmhkTzo28tj0oAHjOh8N9vuXtASfZSCXugx
H+ImJ+E7PA4aXBp+0H2hohW9sXNNCFiVNmJLX66O4bxIeKtVRq/+eSNijV4OOEkC
zMyTHAUbOFP0t6KoJtM1syNoQ1+fKdfcjz5XtiEzSVcp2zf0MwNFSeZSgGQ0jh8A
Kd6YVKA8ZnrqOWZxKETT+bBNTjIT0ggjQfzcE4zW2RzrN7zWabUowoU92+DAp4s3
sAEywX9ISSge62DEzTnZZSf9bpoScAfT8raRFA3BkoJ/s4c4CgfPAgMBAAGjggLm
MIIC4jAdBgNVHQ4EFgQULlIyJL9+ZwAI/SkVdsJMxFOVp+EwHwYDVR0jBBgwFoAU
5nEIMEUT5mMd1WepmviwgK7dIzwwggEKBgNVHR8EggEBMIH+MIH7oIH4oIH1hoG5
bGRhcDovLy9DTj0uU2VjdXJlJTIwRW50ZXJwcmlzZSUyMENBJTIwMSxDTj1hdXRo
LENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxD
Tj1Db25maWd1cmF0aW9uLERDPXNlY3VyZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25M
aXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnSGN2h0dHA6
Ly9jcmwuc2VjdXJlb2JzY3VyZS5jb20vP2FjdGlvbj1jcmwmY2E9ZW50ZXJwcmlz
ZTEwgccGCCsGAQUFBwEBBIG6MIG3MIG0BggrBgEFBQcwAoaBp2xkYXA6Ly8vQ049
LlNlY3VyZSUyMEVudGVycHJpc2UlMjBDQSUyMDEsQ049QUlBLENOPVB1YmxpYyUy
MEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9
c2VjdXJlP2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0
aW9uQXV0aG9yaXR5MBcGCSsGAQQBgjcUAgQKHggAVQBzAGUAcjAOBgNVHQ8BAf8E
BAMCBaAwKQYDVR0lBCIwIAYKKwYBBAGCNwoDBAYIKwYBBQUHAwQGCCsGAQUFBwMC
MC4GA1UdEQQnMCWgIwYKKwYBBAGCNxQCA6AVDBNtZXRhY2xhc3NpbmdAc2VjdXJl
MEQGCSqGSIb3DQEJDwQ3MDUwDgYIKoZIhvcNAwICAgCAMA4GCCqGSIb3DQMEAgIA
gDAHBgUrDgMCBzAKBggqhkiG9w0DBzANBgkqhkiG9w0BAQsFAAOCAgEAKNmjYh+h
cObJEM0CWgz50jOYKZ4M5iIxoAWgrYY9Pv+0O9aPjvPLzjd5bY322L8lxh5wy5my
DKmip+irzjdVdxzQfoyy+ceODmCbX9L6MfEDn0RBzdwjLe1/eOxE1na0sZztrVCc
yt5nI91NNGZJUcVqVQsIA/25FWlkvo/FTfuqTuXdQiEVM5MCKJI915anmTdugy+G
0CmBJALIxtyz5P7sZhaHZFNdpKnx82QsauErqjP9H0RXc6VXX5qt+tEDvYfSlFcc
0lv3aQnV/eIdfm7APJkQ3lmNWWQwdkVf7adXJ7KAAPHSt1yvSbVxThJR/jmIkyeQ
XW/TOP5m7JI/GrmvdlzI1AgwJ+zO8fOmCDuif99pDb1CvkzQ65RZ8p5J1ZV6hzlb
VvOhn4LDnT1jnTcEqigmx1gxM/5ifvMorXn/ItMjKPlb72vHpeF7OeKE8GHsvZAm
osHcKyJXbTIcXchmpZX1efbmCMJBqHgJ/qBTBMl9BX0+YqbTZyabRJSs9ezbTRn0
oRYl21Q8EnvS71CemxEUkSsKJmfJKkQNCsOjc8AbX/V/X9R7LJkH3UEx6K2zQQKK
k6m17mi63YW/+iPCGOWZ2qXmY5HPEyyF2L4L4IDryFJ+8xLyw3pH9/yp5aHZDtp6
833K6qyjgHJT+fUzSEYpiwF5rSBJIGClOCY=
-----END CERTIFICATE-----';
$x509 = new X509();
$cert = $x509->loadX509($test);
$this->assertInternalType('array', $cert['tbsCertificate']['extensions'][3]['extnValue']);
}
public function testLoadUnsupportedExtension() public function testLoadUnsupportedExtension()
{ {
$test = '-----BEGIN CERTIFICATE----- $test = '-----BEGIN CERTIFICATE-----
@ -105,7 +154,7 @@ IOkKcGQRCMha8X2e7GmlpdWC1ycenlbN0nbVeSv3JUMcafC4+Q==
public function testSaveNullRSAParam() public function testSaveNullRSAParam()
{ {
$privKey = new RSA(); $privKey = new RSA();
$privKey->loadKey('-----BEGIN RSA PRIVATE KEY----- $privKey->load('-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDMswfEpAgnUDWA74zZw5XcPsWh1ly1Vk99tsqwoFDkLF7jvXy1 MIICXQIBAAKBgQDMswfEpAgnUDWA74zZw5XcPsWh1ly1Vk99tsqwoFDkLF7jvXy1
dDLHYfuquvfxCgcp8k/4fQhx4ubR8bbGgEq9B05YRnViK0R0iBB5Ui4IaxWYYhKE dDLHYfuquvfxCgcp8k/4fQhx4ubR8bbGgEq9B05YRnViK0R0iBB5Ui4IaxWYYhKE
8xqAEH2fL+/7nsqqNFKkEN9KeFwc7WbMY49U2adlMrpBdRjk1DqIEW3QTwIDAQAB 8xqAEH2fL+/7nsqqNFKkEN9KeFwc7WbMY49U2adlMrpBdRjk1DqIEW3QTwIDAQAB
@ -122,7 +171,7 @@ aBtsWpliLSex/HHhtRW9AkBGcq67zKmEpJ9kXcYLEjJii3flFS+Ct/rNm+Hhm1l7
-----END RSA PRIVATE KEY-----'); -----END RSA PRIVATE KEY-----');
$pubKey = new RSA(); $pubKey = new RSA();
$pubKey->loadKey($privKey->getPublicKey()); $pubKey->load($privKey->getPublicKey());
$pubKey->setPublicKey(); $pubKey->setPublicKey();
$subject = new X509(); $subject = new X509();
@ -168,4 +217,47 @@ aBtsWpliLSex/HHhtRW9AkBGcq67zKmEpJ9kXcYLEjJii3flFS+Ct/rNm+Hhm1l7
} }
return $value; return $value;
} }
public function testGetOID()
{
$x509 = new X509();
$this->assertEquals($x509->getOID('2.16.840.1.101.3.4.2.1'), '2.16.840.1.101.3.4.2.1');
$this->assertEquals($x509->getOID('id-sha256'), '2.16.840.1.101.3.4.2.1');
$this->assertEquals($x509->getOID('zzz'), 'zzz');
}
public function testIPAddressSubjectAltNamesDecoding()
{
$test = '-----BEGIN CERTIFICATE-----
MIIEcTCCAlmgAwIBAgIBDjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBQuU2Vj
dXJlIElzc3VpbmcgQ0EgMTAeFw0xNjAxMjUyMzIwMjZaFw0yMTAxMjYyMzIwMjZa
MBoxGDAWBgNVBAMMDzIwNC4xNTIuMjAwLjI1MDCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAM9lMPiYQ26L5qXR1rlUXM0Z3DeRhDsJ/9NadLFJnvxKCV5L
M9rlrThpK6V5VbgPgEwKVLXGtJoGSEUkLd4roJ25ZTH08GcYszWyp8nLPQRovYnN
+aeE1aefnHcpt524f0Es9NFXh0uwRWV3ZCWSwN+mo9Qo6507KZq+q34if7/q9+De
O5RJumVQWc9OCjCt6pQBnBua9oCAca+SIHftOdgWXqVw+Xvl6/dLeF70jJD43P00
+bdAnGDgBdgO+p+K+XrOCaCWMcCsRX5xiK4hUG54UM5ayBST+McyfjsKxpO2djPg
FlSL0RLg+Nj8WehANUUuaNU874Pp3FV5GTI0ZbUCAwEAAaOBvDCBuTAMBgNVHRMB
Af8EAjAAMAsGA1UdDwQEAwIF4DATBgNVHSUEDDAKBggrBgEFBQcDATAhBgNVHREE
GjAYhwTMmMj6hxAgAQRw8wkACQAAAAAAAAADMEMGA1UdHwQ8MDowOKA2oDSGMmh0
dHA6Ly9jcmwuc2VjdXJlb2JzY3VyZS5jb20vP2FjdGlvbj1jcmwmY2E9aXNzdWUx
MB8GA1UdIwQYMBaAFOJWVCX4poZSBzemgihf9dAhFNHJMA0GCSqGSIb3DQEBCwUA
A4ICAQAce9whx4InRtzk1to6oeRxTCbeNDjNFuTkotphSws4hDoaz3nyFLSYyMT4
aKFnNP9AmMS5nEXphtP4HP9wAluTcAFMuip0rDJjiRA/khIE27KurO6cg1faFWHl
6lh6xnEf9UFZZzTLsXt2miBiMb8olgPrBuVFWjPZ/ConesJRZRFqMd5mfntXC+2V
zRcXdtwp9h/Am/WuvjsG/gBAPdeRNKffCokIcgfvffd2oklSDD0T9baG2MTgaxnX
oG6e5saWjoN8bLWuCJpvjA7aErXQwXUyXx1nrTWQ1TCR2N+M62X7e07jZLKSAECP
v6SqZ9/LDmCacVQbfg4wDC/gbpjDSKaD5fkusH6leXleWQ7X8Z03LsKvVq43a71z
jO61kkiFAh3CegWsY+TSYjZxDq58xGMiE7y/fK+SHQXDLyY7HU4eky2l3DSy8bXQ
p64vTJ/OmAcXVNUASfBCNw0kpxuFjlxers/+6zheowB1RIKo0xvSRC4cEDRl/jFA
b7WUT/MIe6B1r0v1gxHnFG2bFI/MhTT9V+tICOLo7+69z4jf/OFkzjYvqq2QWPgc
sE3f2TNnmKFRJx67bEMoaaWLIR94Yuq/TWB6dTiWwk9meZkGG3OjQg/YbO6vl/Am
NDEuGt30Vl2de7G1glnhaceB6Q9KfH7p2gAwNP9JMTtx3PtEcA==
-----END CERTIFICATE-----';
$x509 = new X509();
$cert = $x509->loadX509($test);
$this->assertEquals($cert['tbsCertificate']['extensions'][3]['extnValue'][0]['iPAddress'], '204.152.200.250');
$this->assertEquals($cert['tbsCertificate']['extensions'][3]['extnValue'][1]['iPAddress'], '2001:470:f309:9::3');
}
} }

View File

@ -9,7 +9,7 @@ class Unit_Math_BigInteger_InternalOpenSSLTest extends Unit_Math_BigInteger_Test
{ {
public static function setUpBeforeClass() public static function setUpBeforeClass()
{ {
if (!function_exists('openssl_public_encrypt')) { if (!extension_loaded('openssl')) {
self::markTestSkipped('openssl_public_encrypt() function is not available.'); self::markTestSkipped('openssl_public_encrypt() function is not available.');
} }

View File

@ -9,10 +9,7 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase
{ {
public static function setUpBeforeClass() public static function setUpBeforeClass()
{ {
include_once 'Math/BigInteger.php';
parent::setUpBeforeClass(); parent::setUpBeforeClass();
self::reRequireFile('Math/BigInteger.php'); self::reRequireFile('Math/BigInteger.php');
} }
@ -52,7 +49,7 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase
public function testToHex() public function testToHex()
{ {
$this->assertSame('41', $this->getInstance('65')->toHex()); $this->assertSame('41', $this->getInstance('65')->toHex());
} }
public function testToBits() public function testToBits()
@ -220,6 +217,11 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase
$z = $this->getInstance('11111111111111111111111', 16); $z = $this->getInstance('11111111111111111111111', 16);
$this->assertSame($z->toHex(), $x->bitwise_NOT()->toHex()); $this->assertSame($z->toHex(), $x->bitwise_NOT()->toHex());
$a = $this->getInstance(0);
$a->bitwise_not();
$this->assertSame($a->toString(), '0');
} }
public function testBitwiseLeftShift() public function testBitwiseLeftShift()
@ -271,29 +273,13 @@ 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 = $min->random($min, $max); $rand1 = \phpseclib\Math\BigInteger::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
*/ */
@ -329,8 +315,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 = $one->random($one, $max); $alicePrivate = \phpseclib\Math\BigInteger::random($one, $max);
$bobPrivate = $one->random($one, $max); $bobPrivate = \phpseclib\Math\BigInteger::random($one, $max);
var_dump($alicePrivate->toHex(), $bobPrivate->toHex()); var_dump($alicePrivate->toHex(), $bobPrivate->toHex());
*/ */
@ -358,4 +344,40 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase
'Failed asserting that Alice and Bob share the same BigInteger.' 'Failed asserting that Alice and Bob share the same BigInteger.'
); );
} }
/**
* @requires PHP 5.6
*/
public function testDebugInfo()
{
$num = $this->getInstance(50);
$str = print_r($num, true);
$this->assertContains('[value] => 0x32', $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');
}
/**
* @group github954
*/
public function testSlidingWindow()
{
$e = $this->getInstance(str_repeat('1', 1794), 2);
$x = $this->getInstance(1);
$n = $this->getInstance(2);
$x->powMod($e, $n);
}
} }

View File

@ -110,6 +110,18 @@ 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
*/ */

View File

@ -10,7 +10,7 @@ date_default_timezone_set('UTC');
$loader_path = __DIR__ . '/../vendor/autoload.php'; $loader_path = __DIR__ . '/../vendor/autoload.php';
if (!file_exists($loader_path)) { if (!file_exists($loader_path)) {
echo "Dependencies must be installed using composer:\n\n"; echo "Dependencies must be installed using composer:\n\n";
echo "php composer.phar install --dev\n\n"; echo "php composer.phar install\n\n";
echo "See http://getcomposer.org for help with installing composer\n"; echo "See http://getcomposer.org for help with installing composer\n";
exit(1); exit(1);
} }

View File

@ -21,10 +21,5 @@ function install_php_extension
} }
# runkit # runkit
if [ "$TRAVIS_PHP_VERSION" == "5.6" ] git clone https://github.com/zenovich/runkit.git
then
git clone https://github.com/adrianguenter/runkit.git
else
git clone https://github.com/zenovich/runkit.git
fi
install_php_extension 'runkit' install_php_extension 'runkit'

View File

@ -20,7 +20,7 @@ then
PHPUNIT_ARGS="$PHPUNIT_ARGS -d zend.enable_gc=0" PHPUNIT_ARGS="$PHPUNIT_ARGS -d zend.enable_gc=0"
fi fi
if [ "$TRAVIS_PHP_VERSION" = 'hhvm' ] if [ "$TRAVIS_PHP_VERSION" = 'hhvm' -o "$TRAVIS_PHP_VERSION" = '7.0' ]
then then
find tests -type f -name "*Test.php" | \ find tests -type f -name "*Test.php" | \
parallel --gnu --keep-order \ parallel --gnu --keep-order \