- [bug] Crypt_Rijndael calculated IVs incorrectly

- [new] renamed Crypt_HMAC to Crypt_Hash and revised the API
- [new] added Crypt_AES
- [new] added AES support to Net_SSH2


git-svn-id: http://phpseclib.svn.sourceforge.net/svnroot/phpseclib/trunk@21 21d32557-59b3-4da0-833f-c5933fad653e
This commit is contained in:
Jim Wigginton 2009-02-16 22:22:13 +00:00
parent c30f3b7e9a
commit 39de68ab48
6 changed files with 240 additions and 150 deletions

View File

@ -2,7 +2,7 @@
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementations of DES.
* Pure-PHP implementation of DES.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
@ -53,7 +53,7 @@
* @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton
* @license http://www.gnu.org/licenses/lgpl.txt
* @version $Id: DES.php,v 1.5 2008-08-04 17:59:12 terrafrost Exp $
* @version $Id: DES.php,v 1.6 2009-02-16 22:22:13 terrafrost Exp $
* @link http://phpseclib.sourceforge.net
*/
@ -154,7 +154,7 @@ class Crypt_DES {
* The Initialization Vector
*
* @see Crypt_DES::setIV()
* @var Integer
* @var String
* @access private
*/
var $iv = "\0\0\0\0\0\0\0\0";
@ -163,7 +163,7 @@ class Crypt_DES {
* A "sliding" Initialization Vector
*
* @see Crypt_DES::enableContinuousBuffer()
* @var Integer
* @var String
* @access private
*/
var $encryptIV = "\0\0\0\0\0\0\0\0";
@ -172,7 +172,7 @@ class Crypt_DES {
* A "sliding" Initialization Vector
*
* @see Crypt_DES::enableContinuousBuffer()
* @var Integer
* @var String
* @access private
*/
var $decryptIV = "\0\0\0\0\0\0\0\0";
@ -215,7 +215,8 @@ class Crypt_DES {
case CRYPT_DES_MODE_MCRYPT:
switch ($mode) {
case CRYPT_DES_MODE_ECB:
$this->mode = MCRYPT_MODE_ECB; break;
$this->mode = MCRYPT_MODE_ECB;
break;
case CRYPT_DES_MODE_CBC:
default:
$this->mode = MCRYPT_MODE_CBC;
@ -274,10 +275,10 @@ class Crypt_DES {
*
* @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
* @access public
* @param Integer $algorithm_directory
* @param Integer $mode_directory
* @param optional Integer $algorithm_directory
* @param optional Integer $mode_directory
*/
function setMCrypt($algorithm_directory, $mode_directory)
function setMCrypt($algorithm_directory = '', $mode_directory = '')
{
$this->mcrypt = array($algorithm_directory, $mode_directory);
}
@ -504,21 +505,26 @@ class Crypt_DES {
*/
function _pad($text)
{
$length = strlen($text);
if (!$this->padding) {
if (strlen($text) & 7 == 0) {
if ($length & 7 == 0) {
return $text;
} else {
user_error("The plaintext's length ($length) is not a multiple of the block size (8)", E_USER_NOTICE);
$this->padding = true;
}
}
$length = 8 - (strlen($text) & 7);
return str_pad($text, strlen($text) + $length, chr($length));
$pad = 8 - ($length & 7);
return str_pad($text, $length + $pad, chr($pad));
}
/**
* Unpads a string
*
* If padding is enabled and the reported padding length exceeds the block size, padding will be, hence forth, disabled.
*
* @see Crypt_DES::_pad()
* @access private
*/
@ -529,6 +535,13 @@ class Crypt_DES {
}
$length = ord($text[strlen($text) - 1]);
if ($length > 8) {
user_error("The number of bytes reported as being padded ($length) exceeds the block size (8)", E_USER_NOTICE);
$this->padding = false;
return $text;
}
return substr($text, 0, -$length);
}
@ -835,5 +848,4 @@ class Crypt_DES {
}
// vim: ts=4:sw=4:et:
// vim6: fdl=1:
?>
// vim6: fdl=1:

View File

@ -2,12 +2,30 @@
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementation of keyed-hash message authentication codes (HMACs).
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
*
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports md5 and sha1.
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports md5, md5-96, sha1, and
* sha1-96. If {@link Crypt_Hash::setKey() setKey()} is called, {@link Crypt_Hash::hash() hash()} will return the HMAC as
* as opposed to the hash. If no valid algorithm is provided, sha1 will be used.
*
* PHP versions 4 and 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:
* <code>
* <?php
* include('Crypt/Hash.php');
*
* $hash = new Crypt_Hash('sha1');
*
* $hash->setKey('abcdefg');
*
* echo base64_encode($hash->hash('abcdefg'));
* ?>
* </code>
*
* LICENSE: This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@ -24,58 +42,54 @@
* MA 02111-1307 USA
*
* @category Crypt
* @package Crypt_HMAC
* @package Crypt_Hash
* @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton
* @license http://www.gnu.org/licenses/lgpl.txt
* @version $Id: HMAC.php,v 1.3 2007-09-23 04:41:39 terrafrost Exp $
* @version $Id: Hash.php,v 1.1 2009-02-16 22:22:13 terrafrost Exp $
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* @access private
* @see Crypt_HMAC::Crypt_HMAC()
* @see Crypt_Hash::Crypt_Hash()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_HMAC_MODE_INTERNAL', 1);
define('CRYPT_HASH_MODE_INTERNAL', 1);
/**
* Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
*/
define('CRYPT_HMAC_MODE_MHASH', 2);
define('CRYPT_HASH_MODE_MHASH', 2);
/**
* Toggles the hash() implementation, which works on PHP 5.1.2+.
*/
define('CRYPT_HMAC_MODE_HASH', 3);
define('CRYPT_HASH_MODE_HASH', 3);
/**#@-*/
/**
* Pure-PHP implementation of keyed-hash message authentication codes (HMACs).
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
*
* @author Jim Wigginton <terrafrost@php.net>
* @version 0.1.0
* @access public
* @package Crypt_HMAC
* @package Crypt_Hash
*/
class Crypt_HMAC {
class Crypt_Hash {
/**
* Byte-length of compression blocks
* Byte-length of compression blocks / key (Internal HMAC)
*
* The following URL provides more information:
*
* {@link http://tools.ietf.org/html/rfc2104#section-2 http://tools.ietf.org/html/rfc2104#section-2}
*
* @see Crypt_HMAC::setHash()
* @see Crypt_Hash::setAlgorithm()
* @var Integer
* @access private
*/
var $b;
/**
* Byte-length of hash outputs
* Byte-length of hash output (Internal HMAC)
*
* @see Crypt_HMAC::setHash()
* @see Crypt_Hash::setHash()
* @var Integer
* @access private
*/
@ -84,7 +98,7 @@ class Crypt_HMAC {
/**
* Hash Algorithm
*
* @see Crypt_HMAC::setHash()
* @see Crypt_Hash::setHash()
* @var String
* @access private
*/
@ -93,65 +107,59 @@ class Crypt_HMAC {
/**
* Key
*
* @see Crypt_HMAC::setKey()
* @see Crypt_Hash::setKey()
* @var String
* @access private
*/
var $key = '';
/**
* Outer XOR
* Outer XOR (Internal HMAC)
*
* @see Crypt_HMAC::setKey()
* @see Crypt_Hash::setKey()
* @var String
* @access private
*/
var $opad;
/**
* Inner XOR
* Inner XOR (Internal HMAC)
*
* @see Crypt_HMAC::setKey()
* @see Crypt_Hash::setKey()
* @var String
* @access private
*/
var $ipad;
/**
* Final HMAC Length
*
* @see Crypt_HMAC::hmac()
* @var String
* @access private
*/
var $length = 0;
/**
* Default Constructor.
*
* @return Crypt_HMAC
* @param optional String $hash
* @return Crypt_Hash
* @access public
*/
function Crypt_HMAC()
function Crypt_Hash($hash = 'sha1')
{
if ( !defined('CRYPT_HMAC_MODE') ) {
if ( !defined('CRYPT_HASH_MODE') ) {
switch (true) {
case extension_loaded('hash'):
define('CRYPT_HMAC_MODE', CRYPT_HMAC_MODE_HASH);
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
break;
case extension_loaded('mhash'):
define('CRYPT_HMAC_MODE', CRYPT_HMAC_MODE_MHASH);
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
break;
default:
define('CRYPT_HMAC_MODE', CRYPT_HMAC_MODE_INTERNAL);
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
}
}
$this->setHash('sha1');
$this->setHash($hash);
}
/**
* Sets the key.
* Sets the key for HMACs
*
* Keys can be of any length.
*
* @access public
* @param String $key
@ -164,8 +172,6 @@ class Crypt_HMAC {
/**
* Sets the hash function.
*
* Currently, only 'sha1' and 'md5' are supported. If you do not supply a valid $hash, 'sha1' will be used.
*
* @access public
* @param String $hash
*/
@ -174,7 +180,13 @@ class Crypt_HMAC {
switch ($hash) {
case 'md5-96':
case 'sha1-96':
$this->length = 12;
$this->l = 12; // 96 / 8 = 12
break;
case 'md5':
$this->l = 16;
break;
case 'sha1':
$this->l = 20;
}
switch (CRYPT_HMAC_MODE) {
@ -208,14 +220,12 @@ class Crypt_HMAC {
case 'md5':
case 'md5-96':
$this->b = 64;
$this->l = 16;
$this->hash = 'md5';
break;
case 'sha1':
case 'sha1-96':
default:
$this->b = 64;
$this->l = 20;
$this->hash = 'sha1';
}
@ -229,28 +239,46 @@ class Crypt_HMAC {
* @access public
* @param String $text
*/
function hmac($text)
function hash($text)
{
switch (CRYPT_HMAC_MODE) {
case CRYPT_HMAC_MODE_MHASH:
$hmac = mhash($this->hash, $text, $this->key);
break;
case CRYPT_HMAC_MODE_HASH:
$hmac = hash_hmac($this->hash, $text, $this->key, true);
break;
case CRYPT_HMAC_MODE_INTERNAL:
$hash = $this->hash;
if (!empty($this->key)) {
switch (CRYPT_HASH_MODE) {
case CRYPT_HASH_MODE_MHASH:
$output = mhash($this->hash, $text, $this->key);
break;
case CRYPT_HASH_MODE_HASH:
$output = hash_hmac($this->hash, $text, $this->key, true);
break;
case CRYPT_HASH_MODE_INTERNAL:
$hash = $this->hash;
/* "Applications that use keys longer than B bytes will first hash the key using H and then use the
resultant L byte string as the actual key to HMAC."
$key = strlen($this->key) > $this->b ? $this->hash($this->key) : $this->key;
$key = str_pad($key, $this->b, chr(0)); // step 1
$temp = $this->ipad ^ $key; // step 2
$temp.= $text; // step 3
$temp = pack('H*', $hash($temp)); // step 4
$hmac = $this->opad ^ $key; // step 5
$hmac.= $temp; // step 6
$hmac = pack('H*', $hash($hmac)); // step 7
-- http://tools.ietf.org/html/rfc2104#section-2 */
$key = strlen($this->key) > $this->b ? $hash($this->key) : $this->key;
$key = str_pad($key, $this->b, chr(0));// step 1
$temp = $this->ipad ^ $key; // step 2
$temp .= $text; // step 3
$temp = pack('H*', $hash($temp)); // step 4
$output = $this->opad ^ $key; // step 5
$output.= $temp; // step 6
$output = pack('H*', $hash($output)); // step 7
}
} else {
switch (CRYPT_HASH_MODE) {
case CRYPT_HASH_MODE_MHASH:
$output = mhash($this->hash, $text);
break;
case CRYPT_HASH_MODE_MHASH:
$output = hash($this->hash, $text, true);
break;
case CRYPT_HASH_MODE_INTERNAL:
$hash = $this->hash;
$output = pack('H*', $hash($output));
}
}
return $this->length ? substr($hmac, 0, $this->length) : $hmac;
return substr($output, 0, $this->l);
}
}

View File

@ -55,7 +55,7 @@
* @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton
* @license http://www.gnu.org/licenses/lgpl.txt
* @version $Id: RC4.php,v 1.3 2007-07-25 21:56:14 terrafrost Exp $
* @version $Id: RC4.php,v 1.4 2009-02-16 22:22:13 terrafrost Exp $
* @link http://phpseclib.sourceforge.net
*/
@ -259,10 +259,10 @@ class Crypt_RC4 {
*
* @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
* @access public
* @param Integer $algorithm_directory
* @param Integer $mode_directory
* @param optional Integer $algorithm_directory
* @param optional Integer $mode_directory
*/
function setMCrypt($algorithm_directory, $mode_directory)
function setMCrypt($algorithm_directory = '', $mode_directory = '')
{
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
$this->mcrypt = array($algorithm_directory, $mode_directory);

View File

@ -4,8 +4,7 @@
/**
* Pure-PHP implementation of Rijndael.
*
* Does not use mcrypt, even when available, since mcrypt doesn't implement Rijndael - it implements a subset of Rijndael
* known as AES.
* Does not use mcrypt, even when available, for reasons that are explained below.
*
* PHP versions 4 and 5
*
@ -15,8 +14,8 @@
* 136-bits it'll be null-padded to 160-bits and 160 bits will be the key length until
* {@link Crypt_Rijndael::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. AES, itself, only
* supports block lengths of 128 and key lengths of 128, 192, and 256.
* 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.
* {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
* algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224. Indeed, 160 and 224
* are first defined as valid key / block lengths in
@ -65,7 +64,7 @@
* @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVIII Jim Wigginton
* @license http://www.gnu.org/licenses/lgpl.txt
* @version $Id: Rijndael.php,v 1.1 2009-02-01 15:37:25 terrafrost Exp $
* @version $Id: Rijndael.php,v 1.2 2009-02-16 22:22:13 terrafrost Exp $
* @link http://phpseclib.sourceforge.net
*/
@ -88,6 +87,20 @@ define('CRYPT_RIJNDAEL_MODE_ECB', 1);
define('CRYPT_RIJNDAEL_MODE_CBC', 2);
/**#@-*/
/**#@+
* @access private
* @see Crypt_AES::Crypt_AES()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_RIJNDAEL_MODE_INTERNAL', 1);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_RIJNDAEL_MODE_MCRYPT', 2);
/**#@-*/
/**
* Pure-PHP implementation of Rijndael.
*
@ -338,6 +351,11 @@ class Crypt_Rijndael {
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
* CRYPT_RIJNDAEL_MODE_ECB or CRYPT_RIJNDAEL_MODE_CBC. If not explictly set, CRYPT_RIJNDAEL_MODE_CBC will be used.
*
* @param optional Integer $mode
* @return Crypt_Rijndael
* @access public
*/
function Crypt_Rijndael($mode = CRYPT_MODE_RIJNDAEL_CBC) {
@ -464,7 +482,7 @@ class Crypt_Rijndael {
*/
function setIV($iv)
{
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));;
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, $this->block_size), $this->block_size, chr(0));;
}
/**
@ -1013,6 +1031,7 @@ class Crypt_Rijndael {
}
$pad = $this->block_size - ($length % $this->block_size);
return str_pad($text, $length + $pad, chr($pad));
}

View File

@ -47,7 +47,7 @@
* @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton
* @license http://www.gnu.org/licenses/lgpl.txt
* @version $Id: TripleDES.php,v 1.4 2008-08-04 17:59:12 terrafrost Exp $
* @version $Id: TripleDES.php,v 1.5 2009-02-16 22:22:13 terrafrost Exp $
* @link http://phpseclib.sourceforge.net
*/
@ -119,7 +119,7 @@ class Crypt_TripleDES {
* The Initialization Vector
*
* @see Crypt_TripleDES::setIV()
* @var Integer
* @var String
* @access private
*/
var $iv = "\0\0\0\0\0\0\0\0";
@ -128,7 +128,7 @@ class Crypt_TripleDES {
* A "sliding" Initialization Vector
*
* @see Crypt_TripleDES::enableContinuousBuffer()
* @var Integer
* @var String
* @access private
*/
var $encryptIV = "\0\0\0\0\0\0\0\0";
@ -137,7 +137,7 @@ class Crypt_TripleDES {
* A "sliding" Initialization Vector
*
* @see Crypt_TripleDES::enableContinuousBuffer()
* @var Integer
* @var String
* @access private
*/
var $decryptIV = "\0\0\0\0\0\0\0\0";
@ -292,10 +292,10 @@ class Crypt_TripleDES {
*
* @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
* @access public
* @param Integer $algorithm_directory
* @param Integer $mode_directory
* @param optional Integer $algorithm_directory
* @param optional Integer $mode_directory
*/
function setMCrypt($algorithm_directory, $mode_directory)
function setMCrypt($algorithm_directory = '', $mode_directory = '')
{
$this->mcrypt = array($algorithm_directory, $mode_directory);
if ( $this->mode == CRYPT_DES_MODE_3CBC ) {
@ -560,21 +560,26 @@ class Crypt_TripleDES {
*/
function _pad($text)
{
$length = strlen($text);
if (!$this->padding) {
if (strlen($text) & 7 == 0) {
if ($length & 7 == 0) {
return $text;
} else {
user_error("The plaintext's length ($length) is not a multiple of the block size (8)", E_USER_NOTICE);
$this->padding = true;
}
}
$length = 8 - (strlen($text) & 7);
return str_pad($text, strlen($text) + $length, chr($length));
$pad = 8 - ($length & 7);
return str_pad($text, $length + $pad, chr($pad));
}
/**
* Unpads a string
*
* If padding is enabled and the reported padding length exceeds the block size, padding will be, hence forth, disabled.
*
* @see Crypt_TripleDES::_pad()
* @access private
*/
@ -585,10 +590,16 @@ class Crypt_TripleDES {
}
$length = ord($text[strlen($text) - 1]);
if ($length > 8) {
user_error("The number of bytes reported as being padded ($length) exceeds the block size (8)", E_USER_NOTICE);
$this->padding = false;
return $text;
}
return substr($text, 0, -$length);
}
}
// vim: ts=4:sw=4:et:
// vim6: fdl=1:
?>
// vim6: fdl=1:

View File

@ -41,7 +41,7 @@
* @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton
* @license http://www.gnu.org/licenses/lgpl.txt
* @version $Id: SSH2.php,v 1.8 2008-05-26 19:42:01 terrafrost Exp $
* @version $Id: SSH2.php,v 1.9 2009-02-16 22:22:13 terrafrost Exp $
* @link http://phpseclib.sourceforge.net
*/
@ -58,20 +58,25 @@ require_once('Math/BigInteger.php');
require_once('Crypt/Random.php');
/**
* Include Crypt_HMAC.php
* Include Crypt_Hash
*/
require_once('Crypt/HMAC.php');
require_once('Crypt/Hash.php');
/**
* Include Crypt_TripleDES.php
* Include Crypt_TripleDES
*/
require_once('Crypt/TripleDES.php');
/**
* Include Crypt_RC4.php
* Include Crypt_RC4
*/
require_once('Crypt/RC4.php');
/**
* Include Crypt_AES
*/
require_once('Crypt/AES.php');
/**#@+
* Execution Bitmap Masks
*
@ -227,13 +232,31 @@ class Net_SSH2 {
var $languages_client_to_server;
/**
* Block Size
* Block Size for Server to Client Encryption
*
* "Note that the length of the concatenation of 'packet_length',
* 'padding_length', 'payload', and 'random padding' MUST be a multiple
* of the cipher block size or 8, whichever is larger. This constraint
* MUST be enforced, even when using stream ciphers."
*
* -- http://tools.ietf.org/html/rfc4253#section-6
*
* @see Net_SSH2::Net_SSH2()
* @see Net_SSH2::_send_binary_packet()
* @var Integer
* @access private
*/
var $block_size = 8;
var $encrypt_block_size = 8;
/**
* Block Size for Client to Server Encryption
*
* @see Net_SSH2::Net_SSH2()
* @see Net_SSH2::_get_binary_packet()
* @var Integer
* @access private
*/
var $decrypt_block_size = 8;
/**
* Server to Client Encryption Object
@ -525,11 +548,11 @@ class Net_SSH2 {
);
static $encryption_algorithms = array(
'3des-cbc', // REQUIRED three-key 3DES in CBC mode
'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key
'aes192-cbc', // OPTIONAL AES with a 192-bit key
'aes128-cbc', // RECOMMENDED AES with a 128-bit key
'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
'3des-cbc', // REQUIRED three-key 3DES in CBC mode
'none' // OPTIONAL no encryption; NOT RECOMMENDED
);
@ -628,9 +651,7 @@ class Net_SSH2 {
$decrypt = $encryption_algorithms[$i];
switch ($decrypt) {
case '3des-cbc':
// uses the default block size
$decryptKeyLength = 24; // eg. 192 / 8
$decryptIVLength = 8; // eg. 64 / 8
break;
case 'aes256-cbc':
$decryptKeyLength = 32; // eg. 256 / 8
@ -643,7 +664,6 @@ class Net_SSH2 {
break;
case 'arcfour':
$decryptKeyLength = 16; // eg. 128 / 8
$decryptIVLength = 0;
break;
case 'none';
$decryptKeyLength = 0;
@ -659,7 +679,6 @@ class Net_SSH2 {
switch ($encrypt) {
case '3des-cbc':
$encryptKeyLength = 24;
$encryptIVLength = 8;
break;
case 'aes256-cbc':
$encryptKeyLength = 32;
@ -672,7 +691,6 @@ class Net_SSH2 {
break;
case 'arcfour':
$encryptKeyLength = 16;
$encryptIVLength = 0;
break;
case 'none';
$encryptKeyLength = 0;
@ -917,15 +935,19 @@ class Net_SSH2 {
switch ($encrypt) {
case '3des-cbc':
$this->encrypt = new Crypt_TripleDES();
// $this->encrypt_block_size = 64 / 8 == the default
break;
case 'aes256-cbc':
//$this->encrypt = new Crypt_AES();
$this->encrypt = new Crypt_AES();
$this->encrypt_block_size = 16; // eg. 128 / 8
break;
case 'aes192-cbc':
//$this->encrypt = new Crypt_AES();
$this->encrypt = new Crypt_AES();
$this->encrypt_block_size = 16;
break;
case 'aes128-cbc':
//$this->encrypt = new Crypt_AES();
$this->encrypt = new Crypt_AES();
$this->encrypt_block_size = 16;
break;
case 'arcfour':
$this->encrypt = new Crypt_RC4();
@ -939,13 +961,16 @@ class Net_SSH2 {
$this->decrypt = new Crypt_TripleDES();
break;
case 'aes256-cbc':
//$this->decrypt = new Crypt_AES();
$this->decrypt = new Crypt_AES();
$this->decrypt_block_size = 16;
break;
case 'aes192-cbc':
//$this->decrypt = new Crypt_AES();
$this->decrypt = new Crypt_AES();
$this->decrypt_block_size = 16;
break;
case 'aes128-cbc':
//$this->decrypt = new Crypt_AES();
$this->decrypt = new Crypt_AES();
$this->decrypt_block_size = 16;
break;
case 'arcfour':
$this->decrypt = new Crypt_RC4();
@ -966,26 +991,22 @@ class Net_SSH2 {
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$this->hmac_create = new Crypt_HMAC();
$createKeyLength = 0; // ie. $mac_algorithms[$i] == 'none'
switch ($mac_algorithms[$i]) {
case 'none':
$this->hmac_create->setHash('none');
$createKeyLength = 0;
break;
case 'hmac-sha1':
$this->hmac_create->setHash('sha1');
$this->hmac_create = new Crypt_Hash('sha1');
$createKeyLength = 20;
break;
case 'hmac-sha1-96':
$this->hmac_create->setHash('sha1-96');
$this->hmac_create = new Crypt_Hash('sha1-96');
$createKeyLength = 20;
break;
case 'hmac-md5':
$this->hmac_create->setHash('md5');
$this->hmac_create = new Crypt_Hash('md5');
$createKeyLength = 16;
break;
case 'hmac-md5-96':
$this->hmac_create->setHash('md5-96');
$this->hmac_create = new Crypt_Hash('md5-96');
$createKeyLength = 16;
}
@ -995,30 +1016,26 @@ class Net_SSH2 {
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
}
$this->hmac_check = new Crypt_HMAC();
$checkKeyLength = 0;
$this->hmac_size = 0;
switch ($mac_algorithms[$i]) {
case 'none':
$this->hmac_check->setHash('none');
$checkKeyLength = 0;
$this->hmac_size = 0;
break;
case 'hmac-sha1':
$this->hmac_check->setHash('sha1');
$this->hmac_check = new Crypt_Hash('sha1');
$checkKeyLength = 20;
$this->hmac_size = 20;
break;
case 'hmac-sha1-96':
$this->hmac_check->setHash('sha1-96');
$this->hmac_check = new Crypt_Hash('sha1-96');
$checkKeyLength = 20;
$this->hmac_size = 12;
break;
case 'hmac-md5':
$this->hmac_check->setHash('md5');
$this->hmac_check = new Crypt_Hash('md5');
$checkKeyLength = 16;
$this->hmac_size = 16;
break;
case 'hmac-md5-96':
$this->hmac_check->setHash('md5-96');
$this->hmac_check = new Crypt_Hash('md5-96');
$checkKeyLength = 16;
$this->hmac_size = 12;
}
@ -1026,16 +1043,16 @@ class Net_SSH2 {
$keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
$iv = pack('H*', $hash($keyBytes . $source . 'A' . $this->session_id));
while ($encryptIVLength > strlen($iv)) {
while ($this->encrypt_block_size > strlen($iv)) {
$iv.= pack('H*', $hash($keyBytes . $source . $iv));
}
$this->encrypt->setIV(substr($iv, 0, $encryptIVLength));
$this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size));
$iv = pack('H*', $hash($keyBytes . $source . 'B' . $this->session_id));
while ($decryptIVLength > strlen($iv)) {
while ($this->decrypt_block_size > strlen($iv)) {
$iv.= pack('H*', $hash($keyBytes . $source . $iv));
}
$this->decrypt->setIV(substr($iv, 0, $decryptIVLength));
$this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size));
$key = pack('H*', $hash($keyBytes . $source . 'C' . $this->session_id));
while ($encryptKeyLength > strlen($key)) {
@ -1331,7 +1348,7 @@ class Net_SSH2 {
return false;
}
$raw = fread($this->fsock, $this->block_size);
$raw = fread($this->fsock, $this->decrypt_block_size);
if ($this->decrypt !== false) {
$raw = $this->decrypt->decrypt($raw);
@ -1341,8 +1358,11 @@ class Net_SSH2 {
$packet_length = $temp['packet_length'];
$padding_length = $temp['padding_length'];
$temp = fread($this->fsock, $packet_length + 4 - $this->block_size);
$raw.= $this->decrypt !== false ? $this->decrypt->decrypt($temp) : $temp;
$remaining_length = $packet_length + 4 - $this->decrypt_block_size;
if ($remaining_length > 0) {
$temp = fread($this->fsock, $remaining_length);
$raw.= $this->decrypt !== false ? $this->decrypt->decrypt($temp) : $temp;
}
$payload = $this->_string_shift($raw, $packet_length - $padding_length - 1);
$padding = $this->_string_shift($raw, $padding_length); // should leave $raw empty
@ -1464,10 +1484,10 @@ class Net_SSH2 {
return false;
}
// 4, for the packet length + 1, for the padding length + 4, for the minimal padding amount
// 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9
$packet_length = strlen($data) + 9;
// round up to the nearest $this->block_size
$packet_length+= (($this->block_size - 1) * $packet_length) % $this->block_size;
// round up to the nearest $this->encrypt_block_size
$packet_length+= (($this->encrypt_block_size - 1) * $packet_length) % $this->encrypt_block_size;
// subtracting strlen($data) is obvious - subtracting 5 is necessary because of packet_length and padding_length
$padding_length = $packet_length - strlen($data) - 5;