updating phpseclib to latest cvs - fixes a bunch of key generation issues
This commit is contained in:
parent
c5bb41176e
commit
520faaf67d
@ -56,7 +56,7 @@
|
|||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @copyright MMVIII Jim Wigginton
|
* @copyright MMVIII Jim Wigginton
|
||||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
* @version $Id: AES.php,v 1.5 2009/11/23 19:06:06 terrafrost Exp $
|
* @version $Id: AES.php,v 1.7 2010/02/09 06:10:25 terrafrost Exp $
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -70,6 +70,14 @@ require_once 'Rijndael.php';
|
|||||||
* @see Crypt_AES::encrypt()
|
* @see Crypt_AES::encrypt()
|
||||||
* @see Crypt_AES::decrypt()
|
* @see Crypt_AES::decrypt()
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* Encrypt / decrypt using the Counter mode.
|
||||||
|
*
|
||||||
|
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
|
||||||
|
*
|
||||||
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
|
||||||
|
*/
|
||||||
|
define('CRYPT_AES_MODE_CTR', -1);
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Electronic Code Book mode.
|
* Encrypt / decrypt using the Electronic Code Book mode.
|
||||||
*
|
*
|
||||||
@ -108,13 +116,28 @@ define('CRYPT_AES_MODE_MCRYPT', 2);
|
|||||||
*/
|
*/
|
||||||
class Crypt_AES extends Crypt_Rijndael {
|
class Crypt_AES extends Crypt_Rijndael {
|
||||||
/**
|
/**
|
||||||
* MCrypt parameters
|
* mcrypt resource for encryption
|
||||||
*
|
*
|
||||||
* @see Crypt_AES::setMCrypt()
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
* @var Array
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::encrypt()
|
||||||
|
* @var String
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $mcrypt = array('', '');
|
var $enmcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mcrypt resource for decryption
|
||||||
|
*
|
||||||
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::decrypt()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $demcrypt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
@ -147,6 +170,13 @@ class Crypt_AES extends Crypt_Rijndael {
|
|||||||
case CRYPT_AES_MODE_ECB:
|
case CRYPT_AES_MODE_ECB:
|
||||||
$this->mode = MCRYPT_MODE_ECB;
|
$this->mode = MCRYPT_MODE_ECB;
|
||||||
break;
|
break;
|
||||||
|
case CRYPT_AES_MODE_CTR:
|
||||||
|
// ctr doesn't have a constant associated with it even though it appears to be fairly widely
|
||||||
|
// supported. in lieu of knowing just how widely supported it is, i've, for now, opted not to
|
||||||
|
// include a compatibility layer. the layer has been implemented but, for now, is commented out.
|
||||||
|
$this->mode = 'ctr';
|
||||||
|
//$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_AES_MODE_CTR;
|
||||||
|
break;
|
||||||
case CRYPT_AES_MODE_CBC:
|
case CRYPT_AES_MODE_CBC:
|
||||||
default:
|
default:
|
||||||
$this->mode = MCRYPT_MODE_CBC;
|
$this->mode = MCRYPT_MODE_CBC;
|
||||||
@ -158,6 +188,9 @@ class Crypt_AES extends Crypt_Rijndael {
|
|||||||
case CRYPT_AES_MODE_ECB:
|
case CRYPT_AES_MODE_ECB:
|
||||||
$this->mode = CRYPT_RIJNDAEL_MODE_ECB;
|
$this->mode = CRYPT_RIJNDAEL_MODE_ECB;
|
||||||
break;
|
break;
|
||||||
|
case CRYPT_AES_MODE_CTR:
|
||||||
|
$this->mode = CRYPT_RIJNDAEL_MODE_CTR;
|
||||||
|
break;
|
||||||
case CRYPT_AES_MODE_CBC:
|
case CRYPT_AES_MODE_CBC:
|
||||||
default:
|
default:
|
||||||
$this->mode = CRYPT_RIJNDAEL_MODE_CBC;
|
$this->mode = CRYPT_RIJNDAEL_MODE_CBC;
|
||||||
@ -203,18 +236,26 @@ class Crypt_AES extends Crypt_Rijndael {
|
|||||||
{
|
{
|
||||||
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
|
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
|
||||||
$this->_mcryptSetup();
|
$this->_mcryptSetup();
|
||||||
$plaintext = $this->_pad($plaintext);
|
/*
|
||||||
|
if ($this->mode == CRYPT_AES_MODE_CTR) {
|
||||||
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
|
$iv = $this->encryptIV;
|
||||||
mcrypt_generic_init($td, $this->key, $this->encryptIV);
|
$xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($plaintext), $iv));
|
||||||
|
$ciphertext = $plaintext ^ $xor;
|
||||||
$ciphertext = mcrypt_generic($td, $plaintext);
|
|
||||||
|
|
||||||
mcrypt_generic_deinit($td);
|
|
||||||
mcrypt_module_close($td);
|
|
||||||
|
|
||||||
if ($this->continuousBuffer) {
|
if ($this->continuousBuffer) {
|
||||||
$this->encryptIV = substr($ciphertext, -16);
|
$this->encryptIV = $iv;
|
||||||
|
}
|
||||||
|
return $ciphertext;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ($this->mode != 'ctr') {
|
||||||
|
$plaintext = $this->_pad($plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
|
||||||
|
|
||||||
|
if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ciphertext;
|
return $ciphertext;
|
||||||
@ -234,46 +275,38 @@ class Crypt_AES extends Crypt_Rijndael {
|
|||||||
*/
|
*/
|
||||||
function decrypt($ciphertext)
|
function decrypt($ciphertext)
|
||||||
{
|
{
|
||||||
|
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
|
||||||
|
$this->_mcryptSetup();
|
||||||
|
/*
|
||||||
|
if ($this->mode == CRYPT_AES_MODE_CTR) {
|
||||||
|
$iv = $this->decryptIV;
|
||||||
|
$xor = mcrypt_generic($this->enmcrypt, $this->_generate_xor(strlen($ciphertext), $iv));
|
||||||
|
$plaintext = $ciphertext ^ $xor;
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->decryptIV = $iv;
|
||||||
|
}
|
||||||
|
return $plaintext;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ($this->mode != 'ctr') {
|
||||||
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
||||||
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||||
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0));
|
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0));
|
||||||
|
|
||||||
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
|
|
||||||
$this->_mcryptSetup();
|
|
||||||
|
|
||||||
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
|
|
||||||
mcrypt_generic_init($td, $this->key, $this->decryptIV);
|
|
||||||
|
|
||||||
$plaintext = mdecrypt_generic($td, $ciphertext);
|
|
||||||
|
|
||||||
mcrypt_generic_deinit($td);
|
|
||||||
mcrypt_module_close($td);
|
|
||||||
|
|
||||||
if ($this->continuousBuffer) {
|
|
||||||
$this->decryptIV = substr($ciphertext, -16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_unpad($plaintext);
|
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
|
||||||
|
|
||||||
|
if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::decrypt($ciphertext);
|
return parent::decrypt($ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets MCrypt parameters. (optional)
|
|
||||||
*
|
|
||||||
* If MCrypt is being used, empty strings will be used, unless otherwise specified.
|
|
||||||
*
|
|
||||||
* @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
|
|
||||||
* @access public
|
|
||||||
* @param optional Integer $algorithm_directory
|
|
||||||
* @param optional Integer $mode_directory
|
|
||||||
*/
|
|
||||||
function setMCrypt($algorithm_directory = '', $mode_directory = '')
|
|
||||||
{
|
|
||||||
$this->mcrypt = array($algorithm_directory, $mode_directory);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup mcrypt
|
* Setup mcrypt
|
||||||
*
|
*
|
||||||
@ -315,6 +348,17 @@ class Crypt_AES extends Crypt_Rijndael {
|
|||||||
$this->key = substr($this->key, 0, $this->key_size);
|
$this->key = substr($this->key, 0, $this->key_size);
|
||||||
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
|
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
|
||||||
|
|
||||||
|
if (!isset($this->enmcrypt)) {
|
||||||
|
$mode = $this->mode;
|
||||||
|
//$mode = $this->mode == CRYPT_AES_MODE_CTR ? MCRYPT_MODE_ECB : $this->mode;
|
||||||
|
|
||||||
|
$this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
|
||||||
|
$this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
|
||||||
|
} // else should mcrypt_generic_deinit be called?
|
||||||
|
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
|
||||||
|
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
|
||||||
|
|
||||||
$this->changed = false;
|
$this->changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,12 +376,19 @@ class Crypt_AES extends Crypt_Rijndael {
|
|||||||
{
|
{
|
||||||
$state = unpack('N*word', $in);
|
$state = unpack('N*word', $in);
|
||||||
|
|
||||||
|
$Nr = $this->Nr;
|
||||||
|
$w = $this->w;
|
||||||
|
$t0 = $this->t0;
|
||||||
|
$t1 = $this->t1;
|
||||||
|
$t2 = $this->t2;
|
||||||
|
$t3 = $this->t3;
|
||||||
|
|
||||||
// addRoundKey and reindex $state
|
// addRoundKey and reindex $state
|
||||||
$state = array(
|
$state = array(
|
||||||
$state['word1'] ^ $this->w[0][0],
|
$state['word1'] ^ $w[0][0],
|
||||||
$state['word2'] ^ $this->w[0][1],
|
$state['word2'] ^ $w[0][1],
|
||||||
$state['word3'] ^ $this->w[0][2],
|
$state['word3'] ^ $w[0][2],
|
||||||
$state['word4'] ^ $this->w[0][3]
|
$state['word4'] ^ $w[0][3]
|
||||||
);
|
);
|
||||||
|
|
||||||
// shiftRows + subWord + mixColumns + addRoundKey
|
// shiftRows + subWord + mixColumns + addRoundKey
|
||||||
@ -345,10 +396,10 @@ class Crypt_AES extends Crypt_Rijndael {
|
|||||||
// only a marginal improvement. since that also, imho, hinders the readability of the code, i've opted not to do it.
|
// only a marginal improvement. since that also, imho, hinders the readability of the code, i've opted not to do it.
|
||||||
for ($round = 1; $round < $this->Nr; $round++) {
|
for ($round = 1; $round < $this->Nr; $round++) {
|
||||||
$state = array(
|
$state = array(
|
||||||
$this->t0[$state[0] & 0xFF000000] ^ $this->t1[$state[1] & 0x00FF0000] ^ $this->t2[$state[2] & 0x0000FF00] ^ $this->t3[$state[3] & 0x000000FF] ^ $this->w[$round][0],
|
$t0[$state[0] & 0xFF000000] ^ $t1[$state[1] & 0x00FF0000] ^ $t2[$state[2] & 0x0000FF00] ^ $t3[$state[3] & 0x000000FF] ^ $w[$round][0],
|
||||||
$this->t0[$state[1] & 0xFF000000] ^ $this->t1[$state[2] & 0x00FF0000] ^ $this->t2[$state[3] & 0x0000FF00] ^ $this->t3[$state[0] & 0x000000FF] ^ $this->w[$round][1],
|
$t0[$state[1] & 0xFF000000] ^ $t1[$state[2] & 0x00FF0000] ^ $t2[$state[3] & 0x0000FF00] ^ $t3[$state[0] & 0x000000FF] ^ $w[$round][1],
|
||||||
$this->t0[$state[2] & 0xFF000000] ^ $this->t1[$state[3] & 0x00FF0000] ^ $this->t2[$state[0] & 0x0000FF00] ^ $this->t3[$state[1] & 0x000000FF] ^ $this->w[$round][2],
|
$t0[$state[2] & 0xFF000000] ^ $t1[$state[3] & 0x00FF0000] ^ $t2[$state[0] & 0x0000FF00] ^ $t3[$state[1] & 0x000000FF] ^ $w[$round][2],
|
||||||
$this->t0[$state[3] & 0xFF000000] ^ $this->t1[$state[0] & 0x00FF0000] ^ $this->t2[$state[1] & 0x0000FF00] ^ $this->t3[$state[2] & 0x000000FF] ^ $this->w[$round][3]
|
$t0[$state[3] & 0xFF000000] ^ $t1[$state[0] & 0x00FF0000] ^ $t2[$state[1] & 0x0000FF00] ^ $t3[$state[2] & 0x000000FF] ^ $w[$round][3]
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -386,31 +437,38 @@ class Crypt_AES extends Crypt_Rijndael {
|
|||||||
{
|
{
|
||||||
$state = unpack('N*word', $in);
|
$state = unpack('N*word', $in);
|
||||||
|
|
||||||
|
$Nr = $this->Nr;
|
||||||
|
$dw = $this->dw;
|
||||||
|
$dt0 = $this->dt0;
|
||||||
|
$dt1 = $this->dt1;
|
||||||
|
$dt2 = $this->dt2;
|
||||||
|
$dt3 = $this->dt3;
|
||||||
|
|
||||||
// addRoundKey and reindex $state
|
// addRoundKey and reindex $state
|
||||||
$state = array(
|
$state = array(
|
||||||
$state['word1'] ^ $this->dw[$this->Nr][0],
|
$state['word1'] ^ $dw[$this->Nr][0],
|
||||||
$state['word2'] ^ $this->dw[$this->Nr][1],
|
$state['word2'] ^ $dw[$this->Nr][1],
|
||||||
$state['word3'] ^ $this->dw[$this->Nr][2],
|
$state['word3'] ^ $dw[$this->Nr][2],
|
||||||
$state['word4'] ^ $this->dw[$this->Nr][3]
|
$state['word4'] ^ $dw[$this->Nr][3]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// invShiftRows + invSubBytes + invMixColumns + addRoundKey
|
// invShiftRows + invSubBytes + invMixColumns + addRoundKey
|
||||||
for ($round = $this->Nr - 1; $round > 0; $round--) {
|
for ($round = $this->Nr - 1; $round > 0; $round--) {
|
||||||
$state = array(
|
$state = array(
|
||||||
$this->dt0[$state[0] & 0xFF000000] ^ $this->dt1[$state[3] & 0x00FF0000] ^ $this->dt2[$state[2] & 0x0000FF00] ^ $this->dt3[$state[1] & 0x000000FF] ^ $this->dw[$round][0],
|
$dt0[$state[0] & 0xFF000000] ^ $dt1[$state[3] & 0x00FF0000] ^ $dt2[$state[2] & 0x0000FF00] ^ $dt3[$state[1] & 0x000000FF] ^ $dw[$round][0],
|
||||||
$this->dt0[$state[1] & 0xFF000000] ^ $this->dt1[$state[0] & 0x00FF0000] ^ $this->dt2[$state[3] & 0x0000FF00] ^ $this->dt3[$state[2] & 0x000000FF] ^ $this->dw[$round][1],
|
$dt0[$state[1] & 0xFF000000] ^ $dt1[$state[0] & 0x00FF0000] ^ $dt2[$state[3] & 0x0000FF00] ^ $dt3[$state[2] & 0x000000FF] ^ $dw[$round][1],
|
||||||
$this->dt0[$state[2] & 0xFF000000] ^ $this->dt1[$state[1] & 0x00FF0000] ^ $this->dt2[$state[0] & 0x0000FF00] ^ $this->dt3[$state[3] & 0x000000FF] ^ $this->dw[$round][2],
|
$dt0[$state[2] & 0xFF000000] ^ $dt1[$state[1] & 0x00FF0000] ^ $dt2[$state[0] & 0x0000FF00] ^ $dt3[$state[3] & 0x000000FF] ^ $dw[$round][2],
|
||||||
$this->dt0[$state[3] & 0xFF000000] ^ $this->dt1[$state[2] & 0x00FF0000] ^ $this->dt2[$state[1] & 0x0000FF00] ^ $this->dt3[$state[0] & 0x000000FF] ^ $this->dw[$round][3]
|
$dt0[$state[3] & 0xFF000000] ^ $dt1[$state[2] & 0x00FF0000] ^ $dt2[$state[1] & 0x0000FF00] ^ $dt3[$state[0] & 0x000000FF] ^ $dw[$round][3]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// invShiftRows + invSubWord + addRoundKey
|
// invShiftRows + invSubWord + addRoundKey
|
||||||
$state = array(
|
$state = array(
|
||||||
$this->_invSubWord(($state[0] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[1] & 0x000000FF)) ^ $this->dw[0][0],
|
$this->_invSubWord(($state[0] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[1] & 0x000000FF)) ^ $dw[0][0],
|
||||||
$this->_invSubWord(($state[1] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[2] & 0x000000FF)) ^ $this->dw[0][1],
|
$this->_invSubWord(($state[1] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[2] & 0x000000FF)) ^ $dw[0][1],
|
||||||
$this->_invSubWord(($state[2] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[3] & 0x000000FF)) ^ $this->dw[0][2],
|
$this->_invSubWord(($state[2] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[3] & 0x000000FF)) ^ $dw[0][2],
|
||||||
$this->_invSubWord(($state[3] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[0] & 0x000000FF)) ^ $this->dw[0][3]
|
$this->_invSubWord(($state[3] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[0] & 0x000000FF)) ^ $dw[0][3]
|
||||||
);
|
);
|
||||||
|
|
||||||
return pack('N*', $state[0], $state[1], $state[2], $state[3]);
|
return pack('N*', $state[0], $state[1], $state[2], $state[3]);
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @copyright MMVII Jim Wigginton
|
* @copyright MMVII Jim Wigginton
|
||||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
* @version $Id: DES.php,v 1.9 2009/11/23 19:06:06 terrafrost Exp $
|
* @version $Id: DES.php,v 1.12 2010/02/09 06:10:26 terrafrost Exp $
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -77,6 +77,14 @@ define('CRYPT_DES_DECRYPT', 1);
|
|||||||
* @see Crypt_DES::encrypt()
|
* @see Crypt_DES::encrypt()
|
||||||
* @see Crypt_DES::decrypt()
|
* @see Crypt_DES::decrypt()
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* Encrypt / decrypt using the Counter mode.
|
||||||
|
*
|
||||||
|
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
|
||||||
|
*
|
||||||
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
|
||||||
|
*/
|
||||||
|
define('CRYPT_DES_MODE_CTR', -1);
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Electronic Code Book mode.
|
* Encrypt / decrypt using the Electronic Code Book mode.
|
||||||
*
|
*
|
||||||
@ -178,13 +186,38 @@ class Crypt_DES {
|
|||||||
var $decryptIV = "\0\0\0\0\0\0\0\0";
|
var $decryptIV = "\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MCrypt parameters
|
* mcrypt resource for encryption
|
||||||
*
|
*
|
||||||
* @see Crypt_DES::setMCrypt()
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
* @var Array
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::encrypt()
|
||||||
|
* @var String
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
var $mcrypt = array('', '');
|
var $enmcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mcrypt resource for decryption
|
||||||
|
*
|
||||||
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::decrypt()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $demcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the (en|de)mcrypt resource need to be (re)initialized?
|
||||||
|
*
|
||||||
|
* @see setKey()
|
||||||
|
* @see setIV()
|
||||||
|
* @var Boolean
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $changed = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
@ -217,6 +250,10 @@ class Crypt_DES {
|
|||||||
case CRYPT_DES_MODE_ECB:
|
case CRYPT_DES_MODE_ECB:
|
||||||
$this->mode = MCRYPT_MODE_ECB;
|
$this->mode = MCRYPT_MODE_ECB;
|
||||||
break;
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$this->mode = 'ctr';
|
||||||
|
//$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_DES_MODE_CTR;
|
||||||
|
break;
|
||||||
case CRYPT_DES_MODE_CBC:
|
case CRYPT_DES_MODE_CBC:
|
||||||
default:
|
default:
|
||||||
$this->mode = MCRYPT_MODE_CBC;
|
$this->mode = MCRYPT_MODE_CBC;
|
||||||
@ -226,6 +263,7 @@ class Crypt_DES {
|
|||||||
default:
|
default:
|
||||||
switch ($mode) {
|
switch ($mode) {
|
||||||
case CRYPT_DES_MODE_ECB:
|
case CRYPT_DES_MODE_ECB:
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
case CRYPT_DES_MODE_CBC:
|
case CRYPT_DES_MODE_CBC:
|
||||||
$this->mode = $mode;
|
$this->mode = $mode;
|
||||||
break;
|
break;
|
||||||
@ -252,6 +290,7 @@ class Crypt_DES {
|
|||||||
function setKey($key)
|
function setKey($key)
|
||||||
{
|
{
|
||||||
$this->keys = ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) ? substr($key, 0, 8) : $this->_prepareKey($key);
|
$this->keys = ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) ? substr($key, 0, 8) : $this->_prepareKey($key);
|
||||||
|
$this->changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -265,22 +304,46 @@ class Crypt_DES {
|
|||||||
*/
|
*/
|
||||||
function setIV($iv)
|
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, 8), 8, chr(0));
|
||||||
|
$this->changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets MCrypt parameters. (optional)
|
* Generate CTR XOR encryption key
|
||||||
*
|
*
|
||||||
* If MCrypt is being used, empty strings will be used, unless otherwise specified.
|
* Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
|
||||||
|
* plaintext / ciphertext in CTR mode.
|
||||||
*
|
*
|
||||||
* @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
|
* @see Crypt_DES::decrypt()
|
||||||
|
* @see Crypt_DES::encrypt()
|
||||||
* @access public
|
* @access public
|
||||||
* @param optional Integer $algorithm_directory
|
* @param Integer $length
|
||||||
* @param optional Integer $mode_directory
|
* @param String $iv
|
||||||
*/
|
*/
|
||||||
function setMCrypt($algorithm_directory = '', $mode_directory = '')
|
function _generate_xor($length, &$iv)
|
||||||
{
|
{
|
||||||
$this->mcrypt = array($algorithm_directory, $mode_directory);
|
$xor = '';
|
||||||
|
$num_blocks = ($length + 7) >> 3;
|
||||||
|
for ($i = 0; $i < $num_blocks; $i++) {
|
||||||
|
$xor.= $iv;
|
||||||
|
for ($j = 4; $j <= 8; $j+=4) {
|
||||||
|
$temp = substr($iv, -$j, 4);
|
||||||
|
switch ($temp) {
|
||||||
|
case "\xFF\xFF\xFF\xFF":
|
||||||
|
$iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
|
||||||
|
break;
|
||||||
|
case "\x7F\xFF\xFF\xFF":
|
||||||
|
$iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
|
||||||
|
break 2;
|
||||||
|
default:
|
||||||
|
extract(unpack('Ncount', $temp));
|
||||||
|
$iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $xor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -302,19 +365,23 @@ class Crypt_DES {
|
|||||||
*/
|
*/
|
||||||
function encrypt($plaintext)
|
function encrypt($plaintext)
|
||||||
{
|
{
|
||||||
|
if ($this->mode != CRYPT_DES_MODE_CTR && $this->mode != 'ctr') {
|
||||||
$plaintext = $this->_pad($plaintext);
|
$plaintext = $this->_pad($plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||||
$td = mcrypt_module_open(MCRYPT_DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
|
if ($this->changed) {
|
||||||
mcrypt_generic_init($td, $this->keys, $this->encryptIV);
|
if (!isset($this->enmcrypt)) {
|
||||||
|
$this->enmcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
|
||||||
|
}
|
||||||
|
mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV);
|
||||||
|
$this->changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
$ciphertext = mcrypt_generic($td, $plaintext);
|
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
|
||||||
|
|
||||||
mcrypt_generic_deinit($td);
|
if (!$this->continuousBuffer) {
|
||||||
mcrypt_module_close($td);
|
mcrypt_generic_init($this->enmcrypt, $this->keys, $this->encryptIV);
|
||||||
|
|
||||||
if ($this->continuousBuffer) {
|
|
||||||
$this->encryptIV = substr($ciphertext, -8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ciphertext;
|
return $ciphertext;
|
||||||
@ -342,6 +409,17 @@ class Crypt_DES {
|
|||||||
if ($this->continuousBuffer) {
|
if ($this->continuousBuffer) {
|
||||||
$this->encryptIV = $xor;
|
$this->encryptIV = $xor;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$xor = $this->encryptIV;
|
||||||
|
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||||
|
$block = substr($plaintext, $i, 8);
|
||||||
|
$key = $this->_processBlock($this->_generate_xor(8, $xor), CRYPT_DES_ENCRYPT);
|
||||||
|
$ciphertext.= $block ^ $key;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->encryptIV = $xor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ciphertext;
|
return $ciphertext;
|
||||||
@ -358,24 +436,28 @@ class Crypt_DES {
|
|||||||
*/
|
*/
|
||||||
function decrypt($ciphertext)
|
function decrypt($ciphertext)
|
||||||
{
|
{
|
||||||
|
if ($this->mode != CRYPT_DES_MODE_CTR && $this->mode != 'ctr') {
|
||||||
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
||||||
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||||
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
|
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
|
||||||
|
|
||||||
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
|
||||||
$td = mcrypt_module_open(MCRYPT_DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
|
|
||||||
mcrypt_generic_init($td, $this->keys, $this->decryptIV);
|
|
||||||
|
|
||||||
$plaintext = mdecrypt_generic($td, $ciphertext);
|
|
||||||
|
|
||||||
mcrypt_generic_deinit($td);
|
|
||||||
mcrypt_module_close($td);
|
|
||||||
|
|
||||||
if ($this->continuousBuffer) {
|
|
||||||
$this->decryptIV = substr($ciphertext, -8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_unpad($plaintext);
|
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||||
|
if ($this->changed) {
|
||||||
|
if (!isset($this->demcrypt)) {
|
||||||
|
$this->demcrypt = mcrypt_module_open(MCRYPT_DES, '', $this->mode, '');
|
||||||
|
}
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV);
|
||||||
|
$this->changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
|
||||||
|
|
||||||
|
if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->keys, $this->decryptIV);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_array($this->keys)) {
|
if (!is_array($this->keys)) {
|
||||||
@ -399,9 +481,20 @@ class Crypt_DES {
|
|||||||
if ($this->continuousBuffer) {
|
if ($this->continuousBuffer) {
|
||||||
$this->decryptIV = $xor;
|
$this->decryptIV = $xor;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$xor = $this->decryptIV;
|
||||||
|
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||||
|
$block = substr($ciphertext, $i, 8);
|
||||||
|
$key = $this->_processBlock($this->_generate_xor(8, $xor), CRYPT_DES_ENCRYPT);
|
||||||
|
$plaintext.= $block ^ $key;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->decryptIV = $xor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_unpad($plaintext);
|
return $this->mode != CRYPT_DES_MODE_CTR ? $this->_unpad($plaintext) : $plaintext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -523,7 +616,8 @@ class Crypt_DES {
|
|||||||
/**
|
/**
|
||||||
* Unpads a string
|
* Unpads a string
|
||||||
*
|
*
|
||||||
* If padding is enabled and the reported padding length is invalid, padding will be, hence forth, disabled.
|
* If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
|
||||||
|
* and false will be returned.
|
||||||
*
|
*
|
||||||
* @see Crypt_DES::_pad()
|
* @see Crypt_DES::_pad()
|
||||||
* @access private
|
* @access private
|
||||||
@ -537,9 +631,7 @@ class Crypt_DES {
|
|||||||
$length = ord($text[strlen($text) - 1]);
|
$length = ord($text[strlen($text) - 1]);
|
||||||
|
|
||||||
if (!$length || $length > 8) {
|
if (!$length || $length > 8) {
|
||||||
user_error("The number of bytes reported as being padded ($length) is invalid (block size = 8)", E_USER_NOTICE);
|
return false;
|
||||||
$this->padding = false;
|
|
||||||
return $text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return substr($text, 0, -$length);
|
return substr($text, 0, -$length);
|
||||||
@ -614,6 +706,8 @@ class Crypt_DES {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$keys = $this->keys;
|
||||||
|
|
||||||
$temp = unpack('Na/Nb', $block);
|
$temp = unpack('Na/Nb', $block);
|
||||||
$block = array($temp['a'], $temp['b']);
|
$block = array($temp['a'], $temp['b']);
|
||||||
|
|
||||||
@ -668,14 +762,14 @@ class Crypt_DES {
|
|||||||
for ($i = 0; $i < 16; $i++) {
|
for ($i = 0; $i < 16; $i++) {
|
||||||
// start of "the Feistel (F) function" - see the following URL:
|
// start of "the Feistel (F) function" - see the following URL:
|
||||||
// http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
|
// http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
|
||||||
$temp = (($sbox[0][((($block[1] >> 27) & 0x1F) | (($block[1] & 1) << 5)) ^ $this->keys[$mode][$i][0]]) << 28)
|
$temp = (($sbox[0][((($block[1] >> 27) & 0x1F) | (($block[1] & 1) << 5)) ^ $keys[$mode][$i][0]]) << 28)
|
||||||
| (($sbox[1][(($block[1] & 0x1F800000) >> 23) ^ $this->keys[$mode][$i][1]]) << 24)
|
| (($sbox[1][(($block[1] & 0x1F800000) >> 23) ^ $keys[$mode][$i][1]]) << 24)
|
||||||
| (($sbox[2][(($block[1] & 0x01F80000) >> 19) ^ $this->keys[$mode][$i][2]]) << 20)
|
| (($sbox[2][(($block[1] & 0x01F80000) >> 19) ^ $keys[$mode][$i][2]]) << 20)
|
||||||
| (($sbox[3][(($block[1] & 0x001F8000) >> 15) ^ $this->keys[$mode][$i][3]]) << 16)
|
| (($sbox[3][(($block[1] & 0x001F8000) >> 15) ^ $keys[$mode][$i][3]]) << 16)
|
||||||
| (($sbox[4][(($block[1] & 0x0001F800) >> 11) ^ $this->keys[$mode][$i][4]]) << 12)
|
| (($sbox[4][(($block[1] & 0x0001F800) >> 11) ^ $keys[$mode][$i][4]]) << 12)
|
||||||
| (($sbox[5][(($block[1] & 0x00001F80) >> 7) ^ $this->keys[$mode][$i][5]]) << 8)
|
| (($sbox[5][(($block[1] & 0x00001F80) >> 7) ^ $keys[$mode][$i][5]]) << 8)
|
||||||
| (($sbox[6][(($block[1] & 0x000001F8) >> 3) ^ $this->keys[$mode][$i][6]]) << 4)
|
| (($sbox[6][(($block[1] & 0x000001F8) >> 3) ^ $keys[$mode][$i][6]]) << 4)
|
||||||
| ( $sbox[7][((($block[1] & 0x1F) << 1) | (($block[1] >> 31) & 1)) ^ $this->keys[$mode][$i][7]]);
|
| ( $sbox[7][((($block[1] & 0x1F) << 1) | (($block[1] >> 31) & 1)) ^ $keys[$mode][$i][7]]);
|
||||||
|
|
||||||
$msb = ($temp >> 31) & 1;
|
$msb = ($temp >> 31) & 1;
|
||||||
$temp &= 0x7FFFFFFF;
|
$temp &= 0x7FFFFFFF;
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @copyright MMIX Jim Wigginton
|
* @copyright MMIX Jim Wigginton
|
||||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
* @version $Id: RSA.php,v 1.3 2009/12/04 21:05:32 terrafrost Exp $
|
* @version $Id: RSA.php,v 1.14 2010/03/01 17:28:19 terrafrost Exp $
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -332,6 +332,14 @@ class Crypt_RSA {
|
|||||||
*/
|
*/
|
||||||
var $mgfHash;
|
var $mgfHash;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Length of MGF hash function output
|
||||||
|
*
|
||||||
|
* @var Integer
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $mgfHLen;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encryption mode
|
* Encryption mode
|
||||||
*
|
*
|
||||||
@ -393,6 +401,7 @@ class Crypt_RSA {
|
|||||||
$this->hLen = $this->hash->getLength();
|
$this->hLen = $this->hash->getLength();
|
||||||
$this->hashName = 'sha1';
|
$this->hashName = 'sha1';
|
||||||
$this->mgfHash = new Crypt_Hash('sha1');
|
$this->mgfHash = new Crypt_Hash('sha1');
|
||||||
|
$this->mgfHLen = $this->mgfHash->getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -409,7 +418,7 @@ class Crypt_RSA {
|
|||||||
* @param optional Integer $timeout
|
* @param optional Integer $timeout
|
||||||
* @param optional Math_BigInteger $p
|
* @param optional Math_BigInteger $p
|
||||||
*/
|
*/
|
||||||
function createKey($bits = 1024, $timeout = false, $primes = array())
|
function createKey($bits = 1024, $timeout = false, $partial = array())
|
||||||
{
|
{
|
||||||
if ( CRYPT_RSA_MODE == CRYPT_RSA_MODE_OPENSSL ) {
|
if ( CRYPT_RSA_MODE == CRYPT_RSA_MODE_OPENSSL ) {
|
||||||
$rsa = openssl_pkey_new(array('private_key_bits' => $bits));
|
$rsa = openssl_pkey_new(array('private_key_bits' => $bits));
|
||||||
@ -460,15 +469,19 @@ class Crypt_RSA {
|
|||||||
$finalMax = $max;
|
$finalMax = $max;
|
||||||
extract($this->_generateMinMax($temp));
|
extract($this->_generateMinMax($temp));
|
||||||
|
|
||||||
$exponents = $coefficients = array();
|
|
||||||
$generator = new Math_BigInteger();
|
$generator = new Math_BigInteger();
|
||||||
$generator->setRandomGenerator('crypt_random');
|
$generator->setRandomGenerator('crypt_random');
|
||||||
|
|
||||||
$n = $this->one->copy();
|
$n = $this->one->copy();
|
||||||
|
if (!empty($partial)) {
|
||||||
|
extract(unserialize($partial));
|
||||||
|
} else {
|
||||||
|
$exponents = $coefficients = $primes = array();
|
||||||
$lcm = array(
|
$lcm = array(
|
||||||
'top' => $this->one->copy(),
|
'top' => $this->one->copy(),
|
||||||
'bottom' => false
|
'bottom' => false
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$start = time();
|
$start = time();
|
||||||
$i0 = count($primes) + 1;
|
$i0 = count($primes) + 1;
|
||||||
@ -479,13 +492,19 @@ class Crypt_RSA {
|
|||||||
$timeout-= time() - $start;
|
$timeout-= time() - $start;
|
||||||
$start = time();
|
$start = time();
|
||||||
if ($timeout <= 0) {
|
if ($timeout <= 0) {
|
||||||
return array(
|
return serialize(array(
|
||||||
'privatekey' => '',
|
'privatekey' => '',
|
||||||
'publickey' => '',
|
'publickey' => '',
|
||||||
'partialkey' => $primes
|
'partialkey' => array(
|
||||||
);
|
'primes' => $primes,
|
||||||
|
'coefficients' => $coefficients,
|
||||||
|
'lcm' => $lcm,
|
||||||
|
'exponents' => $exponents
|
||||||
|
)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($i == $num_primes) {
|
if ($i == $num_primes) {
|
||||||
list($min, $temp) = $absoluteMin->divide($n);
|
list($min, $temp) = $absoluteMin->divide($n);
|
||||||
if (!$temp->equals($this->zero)) {
|
if (!$temp->equals($this->zero)) {
|
||||||
@ -500,7 +519,12 @@ class Crypt_RSA {
|
|||||||
return array(
|
return array(
|
||||||
'privatekey' => '',
|
'privatekey' => '',
|
||||||
'publickey' => '',
|
'publickey' => '',
|
||||||
'partialkey' => array_slice($primes, 0, $i - 1)
|
'partialkey' => empty($primes) ? '' : serialize(array(
|
||||||
|
'primes' => array_slice($primes, 0, $i - 1),
|
||||||
|
'coefficients' => $coefficients,
|
||||||
|
'lcm' => $lcm,
|
||||||
|
'exponents' => $exponents
|
||||||
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,7 +587,6 @@ class Crypt_RSA {
|
|||||||
function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients)
|
function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients)
|
||||||
{
|
{
|
||||||
$num_primes = count($primes);
|
$num_primes = count($primes);
|
||||||
|
|
||||||
$raw = array(
|
$raw = array(
|
||||||
'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
|
'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
|
||||||
'modulus' => $n->toBytes(true),
|
'modulus' => $n->toBytes(true),
|
||||||
@ -745,34 +768,80 @@ class Crypt_RSA {
|
|||||||
implementation are part of the standard, as well.
|
implementation are part of the standard, as well.
|
||||||
|
|
||||||
* OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */
|
* OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */
|
||||||
if (preg_match('#DEK-Info: DES-EDE3-CBC,(.+)#', $key, $matches)) {
|
if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) {
|
||||||
$iv = pack('H*', trim($matches[1]));
|
$iv = pack('H*', trim($matches[2]));
|
||||||
$symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key
|
$symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key
|
||||||
$symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8);
|
$symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8);
|
||||||
$ciphertext = base64_decode(preg_replace('#.+(\r|\n|\r\n)\1|[\r\n]|-.+-#s', '', $key));
|
$ciphertext = preg_replace('#.+(\r|\n|\r\n)\1|[\r\n]|-.+-#s', '', $key);
|
||||||
|
$ciphertext = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $ciphertext) ? base64_decode($ciphertext) : false;
|
||||||
if ($ciphertext === false) {
|
if ($ciphertext === false) {
|
||||||
return false;
|
$ciphertext = $key;
|
||||||
}
|
}
|
||||||
|
switch ($matches[1]) {
|
||||||
|
case 'DES-EDE3-CBC':
|
||||||
if (!class_exists('Crypt_TripleDES')) {
|
if (!class_exists('Crypt_TripleDES')) {
|
||||||
require_once('Crypt/TripleDES.php');
|
require_once('Crypt/TripleDES.php');
|
||||||
}
|
}
|
||||||
$des = new Crypt_TripleDES();
|
$crypto = new Crypt_TripleDES();
|
||||||
$des->setKey($symkey);
|
break;
|
||||||
$des->setIV($iv);
|
case 'DES-CBC':
|
||||||
$key = $des->decrypt($ciphertext);
|
if (!class_exists('Crypt_DES')) {
|
||||||
} else {
|
require_once('Crypt/DES.php');
|
||||||
$key = base64_decode(preg_replace('#-.+-|[\r\n]#', '', $key));
|
}
|
||||||
if ($key === false) {
|
$crypto = new Crypt_DES();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$crypto->setKey($symkey);
|
||||||
|
$crypto->setIV($iv);
|
||||||
|
$decoded = $crypto->decrypt($ciphertext);
|
||||||
|
} else {
|
||||||
|
$decoded = preg_replace('#-.+-|[\r\n]#', '', $key);
|
||||||
|
$decoded = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $decoded) ? base64_decode($decoded) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($decoded !== false) {
|
||||||
|
$key = $decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
$private = false;
|
|
||||||
$components = array();
|
$components = array();
|
||||||
|
|
||||||
$this->_string_shift($key); // skip over CRYPT_RSA_ASN1_SEQUENCE
|
if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
|
||||||
$this->_decodeLength($key); // skip over the length of the above sequence
|
return false;
|
||||||
$this->_string_shift($key); // skip over CRYPT_RSA_ASN1_INTEGER
|
}
|
||||||
|
if ($this->_decodeLength($key) != strlen($key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tag = ord($this->_string_shift($key));
|
||||||
|
if ($tag == CRYPT_RSA_ASN1_SEQUENCE) {
|
||||||
|
/* 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 */
|
||||||
|
$this->_string_shift($key, $this->_decodeLength($key));
|
||||||
|
$this->_string_shift($key); // skip over the BIT STRING tag
|
||||||
|
$this->_decodeLength($key); // skip over the BIT 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 teh 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)
|
||||||
|
$this->_string_shift($key);
|
||||||
|
if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($this->_decodeLength($key) != strlen($key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$tag = ord($this->_string_shift($key));
|
||||||
|
}
|
||||||
|
if ($tag != CRYPT_RSA_ASN1_INTEGER) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$length = $this->_decodeLength($key);
|
$length = $this->_decodeLength($key);
|
||||||
$temp = $this->_string_shift($key, $length);
|
$temp = $this->_string_shift($key, $length);
|
||||||
if (strlen($temp) != 1 || ord($temp) > 2) {
|
if (strlen($temp) != 1 || ord($temp) > 2) {
|
||||||
@ -783,7 +852,9 @@ class Crypt_RSA {
|
|||||||
|
|
||||||
return $components;
|
return $components;
|
||||||
}
|
}
|
||||||
$this->_string_shift($key); // skip over CRYPT_RSA_ASN1_INTEGER
|
if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_INTEGER) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$length = $this->_decodeLength($key);
|
$length = $this->_decodeLength($key);
|
||||||
$components['modulus'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
|
$components['modulus'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
|
||||||
$this->_string_shift($key);
|
$this->_string_shift($key);
|
||||||
@ -807,11 +878,16 @@ class Crypt_RSA {
|
|||||||
$this->_string_shift($key);
|
$this->_string_shift($key);
|
||||||
$length = $this->_decodeLength($key);
|
$length = $this->_decodeLength($key);
|
||||||
$components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($key, $length), -256));
|
$components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($key, $length), -256));
|
||||||
|
|
||||||
if (!empty($key)) {
|
if (!empty($key)) {
|
||||||
$key = substr($key, 1); // skip over CRYPT_RSA_ASN1_SEQUENCE
|
if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$this->_decodeLength($key);
|
$this->_decodeLength($key);
|
||||||
while (!empty($key)) {
|
while (!empty($key)) {
|
||||||
$key = substr($key, 1); // skip over CRYPT_RSA_ASN1_SEQUENCE
|
if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$this->_decodeLength($key);
|
$this->_decodeLength($key);
|
||||||
$key = substr($key, 1);
|
$key = substr($key, 1);
|
||||||
$length = $this->_decodeLength($key);
|
$length = $this->_decodeLength($key);
|
||||||
@ -832,19 +908,33 @@ class Crypt_RSA {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$components = array();
|
$cleanup = substr($key, 0, 11) == "\0\0\0\7ssh-rsa";
|
||||||
extract(unpack('Nlength', $this->_string_shift($key, 4)));
|
|
||||||
$components['modulus'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
|
|
||||||
extract(unpack('Nlength', $this->_string_shift($key, 4)));
|
|
||||||
$components['publicExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
|
|
||||||
|
|
||||||
return $components;
|
extract(unpack('Nlength', $this->_string_shift($key, 4)));
|
||||||
|
$publicExponent = new Math_BigInteger($this->_string_shift($key, $length), -256);
|
||||||
|
extract(unpack('Nlength', $this->_string_shift($key, 4)));
|
||||||
|
$modulus = new Math_BigInteger($this->_string_shift($key, $length), -256);
|
||||||
|
|
||||||
|
if ($cleanup && strlen($key)) {
|
||||||
|
extract(unpack('Nlength', $this->_string_shift($key, 4)));
|
||||||
|
return array(
|
||||||
|
'modulus' => new Math_BigInteger($this->_string_shift($key, $length), -256),
|
||||||
|
'publicExponent' => $modulus
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return array(
|
||||||
|
'modulus' => $modulus,
|
||||||
|
'publicExponent' => $publicExponent
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a public or private key
|
* Loads a public or private key
|
||||||
*
|
*
|
||||||
|
* Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed)
|
||||||
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param String $key
|
* @param String $key
|
||||||
* @param Integer $type optional
|
* @param Integer $type optional
|
||||||
@ -852,6 +942,10 @@ class Crypt_RSA {
|
|||||||
function loadKey($key, $type = CRYPT_RSA_PRIVATE_FORMAT_PKCS1)
|
function loadKey($key, $type = CRYPT_RSA_PRIVATE_FORMAT_PKCS1)
|
||||||
{
|
{
|
||||||
$components = $this->_parseKey($key, $type);
|
$components = $this->_parseKey($key, $type);
|
||||||
|
if ($components === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$this->modulus = $components['modulus'];
|
$this->modulus = $components['modulus'];
|
||||||
$this->k = strlen($this->modulus->toBytes());
|
$this->k = strlen($this->modulus->toBytes());
|
||||||
$this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent'];
|
$this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent'];
|
||||||
@ -866,6 +960,8 @@ class Crypt_RSA {
|
|||||||
$this->coefficients = array();
|
$this->coefficients = array();
|
||||||
$this->publicExponent = false;
|
$this->publicExponent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -906,7 +1002,7 @@ class Crypt_RSA {
|
|||||||
function setPublicKey($key, $type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
|
function setPublicKey($key, $type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
|
||||||
{
|
{
|
||||||
$components = $this->_parseKey($key, $type);
|
$components = $this->_parseKey($key, $type);
|
||||||
if (!$this->modulus->equals($components['modulus'])) {
|
if (empty($this->modulus) || !$this->modulus->equals($components['modulus'])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->publicExponent = $components['publicExponent'];
|
$this->publicExponent = $components['publicExponent'];
|
||||||
@ -926,6 +1022,10 @@ class Crypt_RSA {
|
|||||||
*/
|
*/
|
||||||
function getPublicKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
|
function getPublicKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
|
||||||
{
|
{
|
||||||
|
if (empty($this->modulus) || empty($this->publicExponent)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$oldFormat = $this->publicKeyFormat;
|
$oldFormat = $this->publicKeyFormat;
|
||||||
$this->publicKeyFormat = $type;
|
$this->publicKeyFormat = $type;
|
||||||
$temp = $this->_convertPublicKey($this->modulus, $this->publicExponent);
|
$temp = $this->_convertPublicKey($this->modulus, $this->publicExponent);
|
||||||
@ -945,7 +1045,7 @@ class Crypt_RSA {
|
|||||||
$bytes = $bits >> 3;
|
$bytes = $bits >> 3;
|
||||||
$min = str_repeat(chr(0), $bytes);
|
$min = str_repeat(chr(0), $bytes);
|
||||||
$max = str_repeat(chr(0xFF), $bytes);
|
$max = str_repeat(chr(0xFF), $bytes);
|
||||||
$msb = $num_bits & 7;
|
$msb = $bits & 7;
|
||||||
if ($msb) {
|
if ($msb) {
|
||||||
$min = chr(1 << ($msb - 1)) . $min;
|
$min = chr(1 << ($msb - 1)) . $min;
|
||||||
$max = chr((1 << $msb) - 1) . $max;
|
$max = chr((1 << $msb) - 1) . $max;
|
||||||
@ -975,7 +1075,6 @@ class Crypt_RSA {
|
|||||||
if ( $length & 0x80 ) { // definite length, long form
|
if ( $length & 0x80 ) { // definite length, long form
|
||||||
$length&= 0x7F;
|
$length&= 0x7F;
|
||||||
$temp = $this->_string_shift($string, $length);
|
$temp = $this->_string_shift($string, $length);
|
||||||
$start+= $length;
|
|
||||||
list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
|
list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
|
||||||
}
|
}
|
||||||
return $length;
|
return $length;
|
||||||
@ -1062,14 +1161,13 @@ class Crypt_RSA {
|
|||||||
case 'sha384':
|
case 'sha384':
|
||||||
case 'sha512':
|
case 'sha512':
|
||||||
$this->hash = new Crypt_Hash($hash);
|
$this->hash = new Crypt_Hash($hash);
|
||||||
$this->hLen = $this->hash->getLength();
|
|
||||||
$this->hashName = $hash;
|
$this->hashName = $hash;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$this->hash = new Crypt_Hash('sha1');
|
$this->hash = new Crypt_Hash('sha1');
|
||||||
$this->hLen = $this->hash->getLength();
|
|
||||||
$this->hashName = 'sha1';
|
$this->hashName = 'sha1';
|
||||||
}
|
}
|
||||||
|
$this->hLen = $this->hash->getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1096,6 +1194,7 @@ class Crypt_RSA {
|
|||||||
default:
|
default:
|
||||||
$this->mgfHash = new Crypt_Hash('sha1');
|
$this->mgfHash = new Crypt_Hash('sha1');
|
||||||
}
|
}
|
||||||
|
$this->mgfHLen = $this->mgfHash->getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1189,6 +1288,8 @@ class Crypt_RSA {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$num_primes = count($this->primes);
|
$num_primes = count($this->primes);
|
||||||
|
|
||||||
|
if (defined('CRYPT_RSA_DISABLE_BLINDING')) {
|
||||||
$m_i = array(
|
$m_i = array(
|
||||||
1 => $x->modPow($this->exponents[1], $this->primes[1]),
|
1 => $x->modPow($this->exponents[1], $this->primes[1]),
|
||||||
2 => $x->modPow($this->exponents[2], $this->primes[2])
|
2 => $x->modPow($this->exponents[2], $this->primes[2])
|
||||||
@ -1210,10 +1311,70 @@ class Crypt_RSA {
|
|||||||
|
|
||||||
$m = $m->add($r->multiply($h));
|
$m = $m->add($r->multiply($h));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$smallest = $this->primes[1];
|
||||||
|
for ($i = 2; $i <= $num_primes; $i++) {
|
||||||
|
if ($smallest->compare($this->primes[$i]) > 0) {
|
||||||
|
$smallest = $this->primes[$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$one = new Math_BigInteger(1);
|
||||||
|
$one->setRandomGenerator('crypt_random');
|
||||||
|
|
||||||
|
$r = $one->random($one, $smallest->subtract($one));
|
||||||
|
|
||||||
|
$m_i = array(
|
||||||
|
1 => $this->_blind($x, $r, 1),
|
||||||
|
2 => $this->_blind($x, $r, 2)
|
||||||
|
);
|
||||||
|
$h = $m_i[1]->subtract($m_i[2]);
|
||||||
|
$h = $h->multiply($this->coefficients[2]);
|
||||||
|
list(, $h) = $h->divide($this->primes[1]);
|
||||||
|
$m = $m_i[2]->add($h->multiply($this->primes[2]));
|
||||||
|
|
||||||
|
$r = $this->primes[1];
|
||||||
|
for ($i = 3; $i <= $num_primes; $i++) {
|
||||||
|
$m_i = $this->_blind($x, $r, $i);
|
||||||
|
|
||||||
|
$r = $r->multiply($this->primes[$i - 1]);
|
||||||
|
|
||||||
|
$h = $m_i->subtract($m);
|
||||||
|
$h = $h->multiply($this->coefficients[$i]);
|
||||||
|
list(, $h) = $h->divide($this->primes[$i]);
|
||||||
|
|
||||||
|
$m = $m->add($r->multiply($h));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $m;
|
return $m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs RSA Blinding
|
||||||
|
*
|
||||||
|
* Protects against timing attacks by employing RSA Blinding.
|
||||||
|
* Returns $x->modPow($this->exponents[$i], $this->primes[$i])
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param Math_BigInteger $x
|
||||||
|
* @param Math_BigInteger $r
|
||||||
|
* @param Integer $i
|
||||||
|
* @return Math_BigInteger
|
||||||
|
*/
|
||||||
|
function _blind($x, $r, $i)
|
||||||
|
{
|
||||||
|
$x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i]));
|
||||||
|
|
||||||
|
$x = $x->modPow($this->exponents[$i], $this->primes[$i]);
|
||||||
|
|
||||||
|
$r = $r->modInverse($this->primes[$i]);
|
||||||
|
$x = $x->multiply($r);
|
||||||
|
list(, $x) = $x->divide($this->primes[$i]);
|
||||||
|
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RSAEP
|
* RSAEP
|
||||||
*
|
*
|
||||||
@ -1289,7 +1450,7 @@ class Crypt_RSA {
|
|||||||
/**
|
/**
|
||||||
* MGF1
|
* MGF1
|
||||||
*
|
*
|
||||||
* See {@link http://tools.ietf.org/html/rfc3447#section-B.2.1 RFC3447#section-B.2.1}.
|
* See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}.
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @param String $mgfSeed
|
* @param String $mgfSeed
|
||||||
@ -1301,7 +1462,7 @@ class Crypt_RSA {
|
|||||||
// if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output.
|
// if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output.
|
||||||
|
|
||||||
$t = '';
|
$t = '';
|
||||||
$count = ceil($maskLen / $this->hLen);
|
$count = ceil($maskLen / $this->mgfHLen);
|
||||||
for ($i = 0; $i < $count; $i++) {
|
for ($i = 0; $i < $count; $i++) {
|
||||||
$c = pack('N', $i);
|
$c = pack('N', $i);
|
||||||
$t.= $this->mgfHash->hash($mgfSeed . $c);
|
$t.= $this->mgfHash->hash($mgfSeed . $c);
|
||||||
@ -1789,7 +1950,7 @@ class Crypt_RSA {
|
|||||||
|
|
||||||
// Compare
|
// Compare
|
||||||
|
|
||||||
return $em == $em2;
|
return $em === $em2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1834,7 +1995,12 @@ class Crypt_RSA {
|
|||||||
{
|
{
|
||||||
switch ($this->encryptionMode) {
|
switch ($this->encryptionMode) {
|
||||||
case CRYPT_RSA_ENCRYPTION_PKCS1:
|
case CRYPT_RSA_ENCRYPTION_PKCS1:
|
||||||
$plaintext = str_split($plaintext, $this->k - 11);
|
$length = $this->k - 11;
|
||||||
|
if ($length <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plaintext = str_split($plaintext, $length);
|
||||||
$ciphertext = '';
|
$ciphertext = '';
|
||||||
foreach ($plaintext as $m) {
|
foreach ($plaintext as $m) {
|
||||||
$ciphertext.= $this->_rsaes_pkcs1_v1_5_encrypt($m);
|
$ciphertext.= $this->_rsaes_pkcs1_v1_5_encrypt($m);
|
||||||
@ -1842,7 +2008,12 @@ class Crypt_RSA {
|
|||||||
return $ciphertext;
|
return $ciphertext;
|
||||||
//case CRYPT_RSA_ENCRYPTION_OAEP:
|
//case CRYPT_RSA_ENCRYPTION_OAEP:
|
||||||
default:
|
default:
|
||||||
$plaintext = str_split($plaintext, $this->k - 2 * $this->hLen - 2);
|
$length = $this->k - 2 * $this->hLen - 2;
|
||||||
|
if ($length <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plaintext = str_split($plaintext, $length);
|
||||||
$ciphertext = '';
|
$ciphertext = '';
|
||||||
foreach ($plaintext as $m) {
|
foreach ($plaintext as $m) {
|
||||||
$ciphertext.= $this->_rsaes_oaep_encrypt($m);
|
$ciphertext.= $this->_rsaes_oaep_encrypt($m);
|
||||||
@ -1861,32 +2032,32 @@ class Crypt_RSA {
|
|||||||
*/
|
*/
|
||||||
function decrypt($ciphertext)
|
function decrypt($ciphertext)
|
||||||
{
|
{
|
||||||
|
if ($this->k <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ciphertext = str_split($ciphertext, $this->k);
|
||||||
|
$plaintext = '';
|
||||||
|
|
||||||
switch ($this->encryptionMode) {
|
switch ($this->encryptionMode) {
|
||||||
case CRYPT_RSA_ENCRYPTION_PKCS1:
|
case CRYPT_RSA_ENCRYPTION_PKCS1:
|
||||||
$ciphertext = str_split($ciphertext, $this->k);
|
$decrypt = '_rsaes_pkcs1_v1_5_decrypt';
|
||||||
$plaintext = '';
|
break;
|
||||||
foreach ($ciphertext as $c) {
|
|
||||||
$temp = $this->_rsaes_pkcs1_v1_5_decrypt($c);
|
|
||||||
if ($temp === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$plaintext.= $temp;
|
|
||||||
}
|
|
||||||
return $plaintext;
|
|
||||||
//case CRYPT_RSA_ENCRYPTION_OAEP:
|
//case CRYPT_RSA_ENCRYPTION_OAEP:
|
||||||
default:
|
default:
|
||||||
$ciphertext = str_split($ciphertext, $this->k);
|
$decrypt = '_rsaes_oaep_decrypt';
|
||||||
$plaintext = '';
|
}
|
||||||
|
|
||||||
foreach ($ciphertext as $c) {
|
foreach ($ciphertext as $c) {
|
||||||
$temp = $this->_rsaes_oaep_decrypt($c);
|
$temp = $this->$decrypt($c);
|
||||||
if ($temp === false) {
|
if ($temp === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$plaintext.= $temp;
|
$plaintext.= $temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $plaintext;
|
return $plaintext;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a signature
|
* Create a signature
|
||||||
@ -1898,6 +2069,10 @@ class Crypt_RSA {
|
|||||||
*/
|
*/
|
||||||
function sign($message)
|
function sign($message)
|
||||||
{
|
{
|
||||||
|
if (empty($this->modulus) || empty($this->exponent)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch ($this->signatureMode) {
|
switch ($this->signatureMode) {
|
||||||
case CRYPT_RSA_SIGNATURE_PKCS1:
|
case CRYPT_RSA_SIGNATURE_PKCS1:
|
||||||
return $this->_rsassa_pkcs1_v1_5_sign($message);
|
return $this->_rsassa_pkcs1_v1_5_sign($message);
|
||||||
@ -1918,6 +2093,10 @@ class Crypt_RSA {
|
|||||||
*/
|
*/
|
||||||
function verify($message, $signature)
|
function verify($message, $signature)
|
||||||
{
|
{
|
||||||
|
if (empty($this->modulus) || empty($this->exponent)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch ($this->signatureMode) {
|
switch ($this->signatureMode) {
|
||||||
case CRYPT_RSA_SIGNATURE_PKCS1:
|
case CRYPT_RSA_SIGNATURE_PKCS1:
|
||||||
return $this->_rsassa_pkcs1_v1_5_verify($message, $signature);
|
return $this->_rsassa_pkcs1_v1_5_verify($message, $signature);
|
||||||
|
@ -35,36 +35,91 @@
|
|||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @copyright MMVII Jim Wigginton
|
* @copyright MMVII Jim Wigginton
|
||||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
* @version $Id: Random.php,v 1.4 2008/05/21 05:15:32 terrafrost Exp $
|
* @version $Id: Random.php,v 1.6 2010/02/28 05:28:38 terrafrost Exp $
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a random value. Feel free to replace this function with a cryptographically secure PRNG.
|
* Generate a random value.
|
||||||
|
*
|
||||||
|
* On 32-bit machines, the largest distance that can exist between $min and $max is 2**31.
|
||||||
|
* If $min and $max are farther apart than that then the last ($max - range) numbers.
|
||||||
|
*
|
||||||
|
* Depending on how this is being used, it may be worth while to write a replacement. For example,
|
||||||
|
* a PHP-based web app that stores its data in an SQL database can collect more entropy than this function
|
||||||
|
* can.
|
||||||
*
|
*
|
||||||
* @param optional Integer $min
|
* @param optional Integer $min
|
||||||
* @param optional Integer $max
|
* @param optional Integer $max
|
||||||
* @param optional String $randomness_path
|
|
||||||
* @return Integer
|
* @return Integer
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function crypt_random($min = 0, $max = 0x7FFFFFFF, $randomness_path = '/dev/urandom')
|
function crypt_random($min = 0, $max = 0x7FFFFFFF)
|
||||||
{
|
{
|
||||||
static $seeded = false;
|
if ($min == $max) {
|
||||||
|
return $min;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$seeded) {
|
// see http://en.wikipedia.org/wiki//dev/random
|
||||||
$seeded = true;
|
if (file_exists('/dev/urandom')) {
|
||||||
if (file_exists($randomness_path)) {
|
$fp = fopen('/dev/urandom', 'rb');
|
||||||
$fp = fopen($randomness_path, 'r');
|
extract(unpack('Nrandom', fread($fp, 4)));
|
||||||
$temp = unpack('Nint', fread($fp, 4));
|
|
||||||
mt_srand($temp['int']);
|
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
} else {
|
|
||||||
list($sec, $usec) = explode(' ', microtime());
|
// say $min = 0 and $max = 3. if we didn't do abs() then we could have stuff like this:
|
||||||
mt_srand((float) $sec + ((float) $usec * 100000));
|
// -4 % 3 + 0 = -1, even though -1 < $min
|
||||||
|
return abs($random) % ($max - $min) + $min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prior to PHP 4.2.0, mt_srand() had to be called before mt_rand() could be called.
|
||||||
|
Prior to PHP 5.2.6, mt_rand()'s automatic seeding was subpar, as elaborated here:
|
||||||
|
|
||||||
|
http://www.suspekt.org/2008/08/17/mt_srand-and-not-so-random-numbers/
|
||||||
|
|
||||||
|
The seeding routine is pretty much ripped from PHP's own internal GENERATE_SEED() macro:
|
||||||
|
|
||||||
|
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3_2/ext/standard/php_rand.h?view=markup */
|
||||||
|
if (version_compare(PHP_VERSION, '5.2.5', '<=')) {
|
||||||
|
static $seeded;
|
||||||
|
if (!isset($seeded)) {
|
||||||
|
$seeded = true;
|
||||||
|
mt_srand(fmod(time() * getmypid(), 0x7FFFFFFF) ^ fmod(1000000 * lcg_value(), 0x7FFFFFFF));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mt_rand($min, $max);
|
static $crypto;
|
||||||
|
|
||||||
|
// The CSPRNG's Yarrow and Fortuna periodically reseed. This function can be reseeded by hitting F5
|
||||||
|
// in the browser and reloading the page.
|
||||||
|
|
||||||
|
if (!isset($crypto)) {
|
||||||
|
$key = $iv = '';
|
||||||
|
for ($i = 0; $i < 8; $i++) {
|
||||||
|
$key.= pack('n', mt_rand(0, 0xFFFF));
|
||||||
|
$iv .= pack('n', mt_rand(0, 0xFFFF));
|
||||||
|
}
|
||||||
|
switch (true) {
|
||||||
|
case class_exists('Crypt_AES'):
|
||||||
|
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
|
||||||
|
break;
|
||||||
|
case class_exists('Crypt_TripleDES'):
|
||||||
|
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
|
||||||
|
break;
|
||||||
|
case class_exists('Crypt_DES'):
|
||||||
|
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
|
||||||
|
break;
|
||||||
|
case class_exists('Crypt_RC4'):
|
||||||
|
$crypto = new Crypt_RC4();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
extract(unpack('Nrandom', pack('H*', sha1(mt_rand(0, 0x7FFFFFFF)))));
|
||||||
|
return abs($random) % ($max - $min) + $min;
|
||||||
|
}
|
||||||
|
$crypto->setKey($key);
|
||||||
|
$crypto->setIV($iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
extract(unpack('Nrandom', $crypto->encrypt("\0\0\0\0")));
|
||||||
|
return abs($random) % ($max - $min) + $min;
|
||||||
}
|
}
|
||||||
?>
|
?>
|
@ -64,7 +64,7 @@
|
|||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @copyright MMVIII Jim Wigginton
|
* @copyright MMVIII Jim Wigginton
|
||||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
* @version $Id: Rijndael.php,v 1.8 2009/11/23 19:06:07 terrafrost Exp $
|
* @version $Id: Rijndael.php,v 1.12 2010/02/09 06:10:26 terrafrost Exp $
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -73,6 +73,14 @@
|
|||||||
* @see Crypt_Rijndael::encrypt()
|
* @see Crypt_Rijndael::encrypt()
|
||||||
* @see Crypt_Rijndael::decrypt()
|
* @see Crypt_Rijndael::decrypt()
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* Encrypt / decrypt using the Counter mode.
|
||||||
|
*
|
||||||
|
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
|
||||||
|
*
|
||||||
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
|
||||||
|
*/
|
||||||
|
define('CRYPT_RIJNDAEL_MODE_CTR', -1);
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Electronic Code Book mode.
|
* Encrypt / decrypt using the Electronic Code Book mode.
|
||||||
*
|
*
|
||||||
@ -363,16 +371,27 @@ class Crypt_Rijndael {
|
|||||||
switch ($mode) {
|
switch ($mode) {
|
||||||
case CRYPT_RIJNDAEL_MODE_ECB:
|
case CRYPT_RIJNDAEL_MODE_ECB:
|
||||||
case CRYPT_RIJNDAEL_MODE_CBC:
|
case CRYPT_RIJNDAEL_MODE_CBC:
|
||||||
|
case CRYPT_RIJNDAEL_MODE_CTR:
|
||||||
$this->mode = $mode;
|
$this->mode = $mode;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$this->mode = CRYPT_RIJNDAEL_MODE_CBC;
|
$this->mode = CRYPT_RIJNDAEL_MODE_CBC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$t3 = &$this->t3;
|
||||||
|
$t2 = &$this->t2;
|
||||||
|
$t1 = &$this->t1;
|
||||||
|
$t0 = &$this->t0;
|
||||||
|
|
||||||
|
$dt3 = &$this->dt3;
|
||||||
|
$dt2 = &$this->dt2;
|
||||||
|
$dt1 = &$this->dt1;
|
||||||
|
$dt0 = &$this->dt0;
|
||||||
|
|
||||||
// according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
|
// according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
|
||||||
// precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
|
// precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
|
||||||
// those are the names we'll use.
|
// those are the names we'll use.
|
||||||
$this->t3 = array(
|
$t3 = array(
|
||||||
0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
|
0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
|
||||||
0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
|
0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
|
||||||
0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
|
0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
|
||||||
@ -407,7 +426,7 @@ class Crypt_Rijndael {
|
|||||||
0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
|
0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->dt3 = array(
|
$dt3 = array(
|
||||||
0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
|
0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
|
||||||
0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
|
0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
|
||||||
0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
|
0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
|
||||||
@ -443,13 +462,13 @@ class Crypt_Rijndael {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for ($i = 0; $i < 256; $i++) {
|
for ($i = 0; $i < 256; $i++) {
|
||||||
$this->t2[$i << 8] = (($this->t3[$i] << 8) & 0xFFFFFF00) | (($this->t3[$i] >> 24) & 0x000000FF);
|
$t2[$i << 8] = (($t3[$i] << 8) & 0xFFFFFF00) | (($t3[$i] >> 24) & 0x000000FF);
|
||||||
$this->t1[$i << 16] = (($this->t3[$i] << 16) & 0xFFFF0000) | (($this->t3[$i] >> 16) & 0x0000FFFF);
|
$t1[$i << 16] = (($t3[$i] << 16) & 0xFFFF0000) | (($t3[$i] >> 16) & 0x0000FFFF);
|
||||||
$this->t0[$i << 24] = (($this->t3[$i] << 24) & 0xFF000000) | (($this->t3[$i] >> 8) & 0x00FFFFFF);
|
$t0[$i << 24] = (($t3[$i] << 24) & 0xFF000000) | (($t3[$i] >> 8) & 0x00FFFFFF);
|
||||||
|
|
||||||
$this->dt2[$i << 8] = (($this->dt3[$i] << 8) & 0xFFFFFF00) | (($this->dt3[$i] >> 24) & 0x000000FF);
|
$dt2[$i << 8] = (($this->dt3[$i] << 8) & 0xFFFFFF00) | (($dt3[$i] >> 24) & 0x000000FF);
|
||||||
$this->dt1[$i << 16] = (($this->dt3[$i] << 16) & 0xFFFF0000) | (($this->dt3[$i] >> 16) & 0x0000FFFF);
|
$dt1[$i << 16] = (($this->dt3[$i] << 16) & 0xFFFF0000) | (($dt3[$i] >> 16) & 0x0000FFFF);
|
||||||
$this->dt0[$i << 24] = (($this->dt3[$i] << 24) & 0xFF000000) | (($this->dt3[$i] >> 8) & 0x00FFFFFF);
|
$dt0[$i << 24] = (($this->dt3[$i] << 24) & 0xFF000000) | (($dt3[$i] >> 8) & 0x00FFFFFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,6 +551,45 @@ class Crypt_Rijndael {
|
|||||||
$this->changed = true;
|
$this->changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate CTR XOR encryption key
|
||||||
|
*
|
||||||
|
* Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
|
||||||
|
* plaintext / ciphertext in CTR mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_Rijndael::decrypt()
|
||||||
|
* @see Crypt_Rijndael::encrypt()
|
||||||
|
* @access public
|
||||||
|
* @param Integer $length
|
||||||
|
* @param String $iv
|
||||||
|
*/
|
||||||
|
function _generate_xor($length, &$iv)
|
||||||
|
{
|
||||||
|
$xor = '';
|
||||||
|
$block_size = $this->block_size;
|
||||||
|
$num_blocks = floor(($length + ($block_size - 1)) / $block_size);
|
||||||
|
for ($i = 0; $i < $num_blocks; $i++) {
|
||||||
|
$xor.= $iv;
|
||||||
|
for ($j = 4; $j <= $block_size; $j+=4) {
|
||||||
|
$temp = substr($iv, -$j, 4);
|
||||||
|
switch ($temp) {
|
||||||
|
case "\xFF\xFF\xFF\xFF":
|
||||||
|
$iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
|
||||||
|
break;
|
||||||
|
case "\x7F\xFF\xFF\xFF":
|
||||||
|
$iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
|
||||||
|
break 2;
|
||||||
|
default:
|
||||||
|
extract(unpack('Ncount', $temp));
|
||||||
|
$iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $xor;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts a message.
|
* Encrypts a message.
|
||||||
*
|
*
|
||||||
@ -553,19 +611,22 @@ class Crypt_Rijndael {
|
|||||||
function encrypt($plaintext)
|
function encrypt($plaintext)
|
||||||
{
|
{
|
||||||
$this->_setup();
|
$this->_setup();
|
||||||
|
if ($this->mode != CRYPT_RIJNDAEL_MODE_CTR) {
|
||||||
$plaintext = $this->_pad($plaintext);
|
$plaintext = $this->_pad($plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
|
$block_size = $this->block_size;
|
||||||
$ciphertext = '';
|
$ciphertext = '';
|
||||||
switch ($this->mode) {
|
switch ($this->mode) {
|
||||||
case CRYPT_RIJNDAEL_MODE_ECB:
|
case CRYPT_RIJNDAEL_MODE_ECB:
|
||||||
for ($i = 0; $i < strlen($plaintext); $i+=$this->block_size) {
|
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
|
||||||
$ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $this->block_size));
|
$ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CRYPT_RIJNDAEL_MODE_CBC:
|
case CRYPT_RIJNDAEL_MODE_CBC:
|
||||||
$xor = $this->encryptIV;
|
$xor = $this->encryptIV;
|
||||||
for ($i = 0; $i < strlen($plaintext); $i+=$this->block_size) {
|
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
|
||||||
$block = substr($plaintext, $i, $this->block_size);
|
$block = substr($plaintext, $i, $block_size);
|
||||||
$block = $this->_encryptBlock($block ^ $xor);
|
$block = $this->_encryptBlock($block ^ $xor);
|
||||||
$xor = $block;
|
$xor = $block;
|
||||||
$ciphertext.= $block;
|
$ciphertext.= $block;
|
||||||
@ -573,6 +634,17 @@ class Crypt_Rijndael {
|
|||||||
if ($this->continuousBuffer) {
|
if ($this->continuousBuffer) {
|
||||||
$this->encryptIV = $xor;
|
$this->encryptIV = $xor;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_RIJNDAEL_MODE_CTR:
|
||||||
|
$xor = $this->encryptIV;
|
||||||
|
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
|
||||||
|
$block = substr($plaintext, $i, $block_size);
|
||||||
|
$key = $this->_encryptBlock($this->_generate_xor($block_size, $xor));
|
||||||
|
$ciphertext.= $block ^ $key;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->encryptIV = $xor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ciphertext;
|
return $ciphertext;
|
||||||
@ -591,30 +663,45 @@ class Crypt_Rijndael {
|
|||||||
function decrypt($ciphertext)
|
function decrypt($ciphertext)
|
||||||
{
|
{
|
||||||
$this->_setup();
|
$this->_setup();
|
||||||
|
|
||||||
|
if ($this->mode != CRYPT_RIJNDAEL_MODE_CTR) {
|
||||||
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
|
||||||
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||||
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + $this->block_size - 1) % $this->block_size, chr(0));
|
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + $this->block_size - 1) % $this->block_size, chr(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
$block_size = $this->block_size;
|
||||||
$plaintext = '';
|
$plaintext = '';
|
||||||
switch ($this->mode) {
|
switch ($this->mode) {
|
||||||
case CRYPT_RIJNDAEL_MODE_ECB:
|
case CRYPT_RIJNDAEL_MODE_ECB:
|
||||||
for ($i = 0; $i < strlen($ciphertext); $i+=$this->block_size) {
|
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
|
||||||
$plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $this->block_size));
|
$plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CRYPT_RIJNDAEL_MODE_CBC:
|
case CRYPT_RIJNDAEL_MODE_CBC:
|
||||||
$xor = $this->decryptIV;
|
$xor = $this->decryptIV;
|
||||||
for ($i = 0; $i < strlen($ciphertext); $i+=$this->block_size) {
|
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
|
||||||
$block = substr($ciphertext, $i, $this->block_size);
|
$block = substr($ciphertext, $i, $block_size);
|
||||||
$plaintext.= $this->_decryptBlock($block) ^ $xor;
|
$plaintext.= $this->_decryptBlock($block) ^ $xor;
|
||||||
$xor = $block;
|
$xor = $block;
|
||||||
}
|
}
|
||||||
if ($this->continuousBuffer) {
|
if ($this->continuousBuffer) {
|
||||||
$this->decryptIV = $xor;
|
$this->decryptIV = $xor;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_RIJNDAEL_MODE_CTR:
|
||||||
|
$xor = $this->decryptIV;
|
||||||
|
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
|
||||||
|
$block = substr($ciphertext, $i, $block_size);
|
||||||
|
$key = $this->_encryptBlock($this->_generate_xor($block_size, $xor));
|
||||||
|
$plaintext.= $block ^ $key;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->decryptIV = $xor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_unpad($plaintext);
|
return $this->mode != CRYPT_RIJNDAEL_MODE_CTR ? $this->_unpad($plaintext) : $plaintext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -629,9 +716,19 @@ class Crypt_Rijndael {
|
|||||||
$state = array();
|
$state = array();
|
||||||
$words = unpack('N*word', $in);
|
$words = unpack('N*word', $in);
|
||||||
|
|
||||||
|
$w = $this->w;
|
||||||
|
$t0 = $this->t0;
|
||||||
|
$t1 = $this->t1;
|
||||||
|
$t2 = $this->t2;
|
||||||
|
$t3 = $this->t3;
|
||||||
|
$Nb = $this->Nb;
|
||||||
|
$Nr = $this->Nr;
|
||||||
|
$c = $this->c;
|
||||||
|
|
||||||
// addRoundKey
|
// addRoundKey
|
||||||
|
$i = 0;
|
||||||
foreach ($words as $word) {
|
foreach ($words as $word) {
|
||||||
$state[] = $word ^ $this->w[0][count($state)];
|
$state[] = $word ^ $w[0][$i++];
|
||||||
}
|
}
|
||||||
|
|
||||||
// fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
|
// fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
|
||||||
@ -643,49 +740,49 @@ class Crypt_Rijndael {
|
|||||||
|
|
||||||
// [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
|
// [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
|
||||||
$temp = array();
|
$temp = array();
|
||||||
for ($round = 1; $round < $this->Nr; $round++) {
|
for ($round = 1; $round < $Nr; $round++) {
|
||||||
$i = 0; // $this->c[0] == 0
|
$i = 0; // $c[0] == 0
|
||||||
$j = $this->c[1];
|
$j = $c[1];
|
||||||
$k = $this->c[2];
|
$k = $c[2];
|
||||||
$l = $this->c[3];
|
$l = $c[3];
|
||||||
|
|
||||||
while ($i < $this->Nb) {
|
while ($i < $this->Nb) {
|
||||||
$temp[$i] = $this->t0[$state[$i] & 0xFF000000] ^
|
$temp[$i] = $t0[$state[$i] & 0xFF000000] ^
|
||||||
$this->t1[$state[$j] & 0x00FF0000] ^
|
$t1[$state[$j] & 0x00FF0000] ^
|
||||||
$this->t2[$state[$k] & 0x0000FF00] ^
|
$t2[$state[$k] & 0x0000FF00] ^
|
||||||
$this->t3[$state[$l] & 0x000000FF] ^
|
$t3[$state[$l] & 0x000000FF] ^
|
||||||
$this->w[$round][$i];
|
$w[$round][$i];
|
||||||
$i++;
|
$i++;
|
||||||
$j = ($j + 1) % $this->Nb;
|
$j = ($j + 1) % $Nb;
|
||||||
$k = ($k + 1) % $this->Nb;
|
$k = ($k + 1) % $Nb;
|
||||||
$l = ($l + 1) % $this->Nb;
|
$l = ($l + 1) % $Nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ($i = 0; $i < $this->Nb; $i++) {
|
for ($i = 0; $i < $Nb; $i++) {
|
||||||
$state[$i] = $temp[$i];
|
$state[$i] = $temp[$i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// subWord
|
// subWord
|
||||||
for ($i = 0; $i < $this->Nb; $i++) {
|
for ($i = 0; $i < $Nb; $i++) {
|
||||||
$state[$i] = $this->_subWord($state[$i]);
|
$state[$i] = $this->_subWord($state[$i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// shiftRows + addRoundKey
|
// shiftRows + addRoundKey
|
||||||
$i = 0; // $this->c[0] == 0
|
$i = 0; // $c[0] == 0
|
||||||
$j = $this->c[1];
|
$j = $c[1];
|
||||||
$k = $this->c[2];
|
$k = $c[2];
|
||||||
$l = $this->c[3];
|
$l = $c[3];
|
||||||
while ($i < $this->Nb) {
|
while ($i < $this->Nb) {
|
||||||
$temp[$i] = ($state[$i] & 0xFF000000) ^
|
$temp[$i] = ($state[$i] & 0xFF000000) ^
|
||||||
($state[$j] & 0x00FF0000) ^
|
($state[$j] & 0x00FF0000) ^
|
||||||
($state[$k] & 0x0000FF00) ^
|
($state[$k] & 0x0000FF00) ^
|
||||||
($state[$l] & 0x000000FF) ^
|
($state[$l] & 0x000000FF) ^
|
||||||
$this->w[$this->Nr][$i];
|
$w[$Nr][$i];
|
||||||
$i++;
|
$i++;
|
||||||
$j = ($j + 1) % $this->Nb;
|
$j = ($j + 1) % $Nb;
|
||||||
$k = ($k + 1) % $this->Nb;
|
$k = ($k + 1) % $Nb;
|
||||||
$l = ($l + 1) % $this->Nb;
|
$l = ($l + 1) % $Nb;
|
||||||
}
|
}
|
||||||
$state = $temp;
|
$state = $temp;
|
||||||
|
|
||||||
@ -706,51 +803,62 @@ class Crypt_Rijndael {
|
|||||||
$state = array();
|
$state = array();
|
||||||
$words = unpack('N*word', $in);
|
$words = unpack('N*word', $in);
|
||||||
|
|
||||||
|
$num_states = count($state);
|
||||||
|
$dw = $this->dw;
|
||||||
|
$dt0 = $this->dt0;
|
||||||
|
$dt1 = $this->dt1;
|
||||||
|
$dt2 = $this->dt2;
|
||||||
|
$dt3 = $this->dt3;
|
||||||
|
$Nb = $this->Nb;
|
||||||
|
$Nr = $this->Nr;
|
||||||
|
$c = $this->c;
|
||||||
|
|
||||||
// addRoundKey
|
// addRoundKey
|
||||||
|
$i = 0;
|
||||||
foreach ($words as $word) {
|
foreach ($words as $word) {
|
||||||
$state[] = $word ^ $this->dw[0][count($state)];
|
$state[] = $word ^ $dw[$Nr][$i++];
|
||||||
}
|
}
|
||||||
|
|
||||||
$temp = array();
|
$temp = array();
|
||||||
for ($round = $this->Nr - 1; $round > 0; $round--) {
|
for ($round = $Nr - 1; $round > 0; $round--) {
|
||||||
$i = 0; // $this->c[0] == 0
|
$i = 0; // $c[0] == 0
|
||||||
$j = $this->Nb - $this->c[1];
|
$j = $Nb - $c[1];
|
||||||
$k = $this->Nb - $this->c[2];
|
$k = $Nb - $c[2];
|
||||||
$l = $this->Nb - $this->c[3];
|
$l = $Nb - $c[3];
|
||||||
|
|
||||||
while ($i < $this->Nb) {
|
while ($i < $Nb) {
|
||||||
$temp[$i] = $this->dt0[$state[$i] & 0xFF000000] ^
|
$temp[$i] = $dt0[$state[$i] & 0xFF000000] ^
|
||||||
$this->dt1[$state[$j] & 0x00FF0000] ^
|
$dt1[$state[$j] & 0x00FF0000] ^
|
||||||
$this->dt2[$state[$k] & 0x0000FF00] ^
|
$dt2[$state[$k] & 0x0000FF00] ^
|
||||||
$this->dt3[$state[$l] & 0x000000FF] ^
|
$dt3[$state[$l] & 0x000000FF] ^
|
||||||
$this->dw[$round][$i];
|
$dw[$round][$i];
|
||||||
$i++;
|
$i++;
|
||||||
$j = ($j + 1) % $this->Nb;
|
$j = ($j + 1) % $Nb;
|
||||||
$k = ($k + 1) % $this->Nb;
|
$k = ($k + 1) % $Nb;
|
||||||
$l = ($l + 1) % $this->Nb;
|
$l = ($l + 1) % $Nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ($i = 0; $i < $this->Nb; $i++) {
|
for ($i = 0; $i < $Nb; $i++) {
|
||||||
$state[$i] = $temp[$i];
|
$state[$i] = $temp[$i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// invShiftRows + invSubWord + addRoundKey
|
// invShiftRows + invSubWord + addRoundKey
|
||||||
$i = 0; // $this->c[0] == 0
|
$i = 0; // $c[0] == 0
|
||||||
$j = $this->Nb - $this->c[1];
|
$j = $Nb - $c[1];
|
||||||
$k = $this->Nb - $this->c[2];
|
$k = $Nb - $c[2];
|
||||||
$l = $this->Nb - $this->c[3];
|
$l = $Nb - $c[3];
|
||||||
|
|
||||||
while ($i < $this->Nb) {
|
while ($i < $Nb) {
|
||||||
$temp[$i] = $this->dw[0][$i] ^
|
$temp[$i] = $dw[0][$i] ^
|
||||||
$this->_invSubWord(($state[$i] & 0xFF000000) |
|
$this->_invSubWord(($state[$i] & 0xFF000000) |
|
||||||
($state[$j] & 0x00FF0000) |
|
($state[$j] & 0x00FF0000) |
|
||||||
($state[$k] & 0x0000FF00) |
|
($state[$k] & 0x0000FF00) |
|
||||||
($state[$l] & 0x000000FF));
|
($state[$l] & 0x000000FF));
|
||||||
$i++;
|
$i++;
|
||||||
$j = ($j + 1) % $this->Nb;
|
$j = ($j + 1) % $Nb;
|
||||||
$k = ($k + 1) % $this->Nb;
|
$k = ($k + 1) % $Nb;
|
||||||
$l = ($l + 1) % $this->Nb;
|
$l = ($l + 1) % $Nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
$state = $temp;
|
$state = $temp;
|
||||||
@ -1034,7 +1142,8 @@ class Crypt_Rijndael {
|
|||||||
/**
|
/**
|
||||||
* Unpads a string.
|
* Unpads a string.
|
||||||
*
|
*
|
||||||
* If padding is enabled and the reported padding length is invalid, padding will be, hence forth, disabled.
|
* If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
|
||||||
|
* and false will be returned.
|
||||||
*
|
*
|
||||||
* @see Crypt_Rijndael::_pad()
|
* @see Crypt_Rijndael::_pad()
|
||||||
* @access private
|
* @access private
|
||||||
@ -1048,9 +1157,7 @@ class Crypt_Rijndael {
|
|||||||
$length = ord($text[strlen($text) - 1]);
|
$length = ord($text[strlen($text) - 1]);
|
||||||
|
|
||||||
if (!$length || $length > $this->block_size) {
|
if (!$length || $length > $this->block_size) {
|
||||||
user_error("The number of bytes reported as being padded ($length) is invalid (block size = {$this->block_size})", E_USER_NOTICE);
|
return false;
|
||||||
$this->padding = false;
|
|
||||||
return $text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return substr($text, 0, -$length);
|
return substr($text, 0, -$length);
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
* @author Jim Wigginton <terrafrost@php.net>
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
* @copyright MMVII Jim Wigginton
|
* @copyright MMVII Jim Wigginton
|
||||||
* @license http://www.gnu.org/licenses/lgpl.txt
|
* @license http://www.gnu.org/licenses/lgpl.txt
|
||||||
* @version $Id: TripleDES.php,v 1.9 2009/11/23 19:06:07 terrafrost Exp $
|
* @version $Id: TripleDES.php,v 1.13 2010/02/26 03:40:25 terrafrost Exp $
|
||||||
* @link http://phpseclib.sourceforge.net
|
* @link http://phpseclib.sourceforge.net
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -142,15 +142,6 @@ class Crypt_TripleDES {
|
|||||||
*/
|
*/
|
||||||
var $decryptIV = "\0\0\0\0\0\0\0\0";
|
var $decryptIV = "\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
/**
|
|
||||||
* MCrypt parameters
|
|
||||||
*
|
|
||||||
* @see Crypt_TripleDES::setMCrypt()
|
|
||||||
* @var Array
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
var $mcrypt = array('', '');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Crypt_DES objects
|
* The Crypt_DES objects
|
||||||
*
|
*
|
||||||
@ -159,6 +150,40 @@ class Crypt_TripleDES {
|
|||||||
*/
|
*/
|
||||||
var $des;
|
var $des;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mcrypt resource for encryption
|
||||||
|
*
|
||||||
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::encrypt()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $enmcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mcrypt resource for decryption
|
||||||
|
*
|
||||||
|
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
||||||
|
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
||||||
|
*
|
||||||
|
* @see Crypt_AES::decrypt()
|
||||||
|
* @var String
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $demcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the (en|de)mcrypt resource need to be (re)initialized?
|
||||||
|
*
|
||||||
|
* @see setKey()
|
||||||
|
* @see setIV()
|
||||||
|
* @var Boolean
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $changed = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
@ -204,7 +229,11 @@ class Crypt_TripleDES {
|
|||||||
case CRYPT_DES_MODE_MCRYPT:
|
case CRYPT_DES_MODE_MCRYPT:
|
||||||
switch ($mode) {
|
switch ($mode) {
|
||||||
case CRYPT_DES_MODE_ECB:
|
case CRYPT_DES_MODE_ECB:
|
||||||
$this->mode = MCRYPT_MODE_ECB; break;
|
$this->mode = MCRYPT_MODE_ECB;
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$this->mode = 'ctr';
|
||||||
|
break;
|
||||||
case CRYPT_DES_MODE_CBC:
|
case CRYPT_DES_MODE_CBC:
|
||||||
default:
|
default:
|
||||||
$this->mode = MCRYPT_MODE_CBC;
|
$this->mode = MCRYPT_MODE_CBC;
|
||||||
@ -225,6 +254,7 @@ class Crypt_TripleDES {
|
|||||||
|
|
||||||
switch ($mode) {
|
switch ($mode) {
|
||||||
case CRYPT_DES_MODE_ECB:
|
case CRYPT_DES_MODE_ECB:
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
case CRYPT_DES_MODE_CBC:
|
case CRYPT_DES_MODE_CBC:
|
||||||
$this->mode = $mode;
|
$this->mode = $mode;
|
||||||
break;
|
break;
|
||||||
@ -254,7 +284,7 @@ class Crypt_TripleDES {
|
|||||||
$key = str_pad($key, 24, chr(0));
|
$key = str_pad($key, 24, chr(0));
|
||||||
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
|
// 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
|
// http://php.net/function.mcrypt-encrypt#47973
|
||||||
$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
|
//$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
|
||||||
}
|
}
|
||||||
$this->key = $key;
|
$this->key = $key;
|
||||||
switch (true) {
|
switch (true) {
|
||||||
@ -264,6 +294,7 @@ class Crypt_TripleDES {
|
|||||||
$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));
|
||||||
}
|
}
|
||||||
|
$this->changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -283,27 +314,46 @@ class Crypt_TripleDES {
|
|||||||
$this->des[1]->setIV($iv);
|
$this->des[1]->setIV($iv);
|
||||||
$this->des[2]->setIV($iv);
|
$this->des[2]->setIV($iv);
|
||||||
}
|
}
|
||||||
|
$this->changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets MCrypt parameters. (optional)
|
* Generate CTR XOR encryption key
|
||||||
*
|
*
|
||||||
* If MCrypt is being used, empty strings will be used, unless otherwise specified.
|
* Encrypt the output of this and XOR it against the ciphertext / plaintext to get the
|
||||||
|
* plaintext / ciphertext in CTR mode.
|
||||||
*
|
*
|
||||||
* @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
|
* @see Crypt_DES::decrypt()
|
||||||
|
* @see Crypt_DES::encrypt()
|
||||||
* @access public
|
* @access public
|
||||||
* @param optional Integer $algorithm_directory
|
* @param Integer $length
|
||||||
* @param optional Integer $mode_directory
|
* @param String $iv
|
||||||
*/
|
*/
|
||||||
function setMCrypt($algorithm_directory = '', $mode_directory = '')
|
function _generate_xor($length, &$iv)
|
||||||
{
|
{
|
||||||
$this->mcrypt = array($algorithm_directory, $mode_directory);
|
$xor = '';
|
||||||
if ( $this->mode == CRYPT_DES_MODE_3CBC ) {
|
$num_blocks = ($length + 7) >> 3;
|
||||||
$this->des[0]->setMCrypt($algorithm_directory, $mode_directory);
|
for ($i = 0; $i < $num_blocks; $i++) {
|
||||||
$this->des[1]->setMCrypt($algorithm_directory, $mode_directory);
|
$xor.= $iv;
|
||||||
$this->des[2]->setMCrypt($algorithm_directory, $mode_directory);
|
for ($j = 4; $j <= 8; $j+=4) {
|
||||||
|
$temp = substr($iv, -$j, 4);
|
||||||
|
switch ($temp) {
|
||||||
|
case "\xFF\xFF\xFF\xFF":
|
||||||
|
$iv = substr_replace($iv, "\x00\x00\x00\x00", -$j, 4);
|
||||||
|
break;
|
||||||
|
case "\x7F\xFF\xFF\xFF":
|
||||||
|
$iv = substr_replace($iv, "\x80\x00\x00\x00", -$j, 4);
|
||||||
|
break 2;
|
||||||
|
default:
|
||||||
|
extract(unpack('Ncount', $temp));
|
||||||
|
$iv = substr_replace($iv, pack('N', $count + 1), -$j, 4);
|
||||||
|
break 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $xor;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts a message.
|
* Encrypts a message.
|
||||||
@ -313,7 +363,9 @@ class Crypt_TripleDES {
|
|||||||
*/
|
*/
|
||||||
function encrypt($plaintext)
|
function encrypt($plaintext)
|
||||||
{
|
{
|
||||||
|
if ($this->mode != CRYPT_DES_MODE_CTR && $this->mode != 'ctr') {
|
||||||
$plaintext = $this->_pad($plaintext);
|
$plaintext = $this->_pad($plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
// if the key is smaller then 8, do what we'd normally do
|
// if the key is smaller then 8, do what we'd normally do
|
||||||
if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8) {
|
if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8) {
|
||||||
@ -323,16 +375,18 @@ class Crypt_TripleDES {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||||
$td = mcrypt_module_open(MCRYPT_3DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
|
if ($this->changed) {
|
||||||
mcrypt_generic_init($td, $this->key, $this->encryptIV);
|
if (!isset($this->enmcrypt)) {
|
||||||
|
$this->enmcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||||
|
}
|
||||||
|
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
||||||
|
$this->changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
$ciphertext = mcrypt_generic($td, $plaintext);
|
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
|
||||||
|
|
||||||
mcrypt_generic_deinit($td);
|
if (!$this->continuousBuffer) {
|
||||||
mcrypt_module_close($td);
|
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
||||||
|
|
||||||
if ($this->continuousBuffer) {
|
|
||||||
$this->encryptIV = substr($ciphertext, -8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ciphertext;
|
return $ciphertext;
|
||||||
@ -348,14 +402,16 @@ class Crypt_TripleDES {
|
|||||||
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
||||||
$plaintext = str_pad($plaintext, ceil(strlen($plaintext) / 8) * 8, chr(0));
|
$plaintext = str_pad($plaintext, ceil(strlen($plaintext) / 8) * 8, chr(0));
|
||||||
|
|
||||||
|
$des = $this->des;
|
||||||
|
|
||||||
$ciphertext = '';
|
$ciphertext = '';
|
||||||
switch ($this->mode) {
|
switch ($this->mode) {
|
||||||
case CRYPT_DES_MODE_ECB:
|
case CRYPT_DES_MODE_ECB:
|
||||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||||
$block = substr($plaintext, $i, 8);
|
$block = substr($plaintext, $i, 8);
|
||||||
$block = $this->des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
$block = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
$block = $this->des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
|
$block = $des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
$block = $this->des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
$block = $des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
$ciphertext.= $block;
|
$ciphertext.= $block;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -363,15 +419,29 @@ class Crypt_TripleDES {
|
|||||||
$xor = $this->encryptIV;
|
$xor = $this->encryptIV;
|
||||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||||
$block = substr($plaintext, $i, 8) ^ $xor;
|
$block = substr($plaintext, $i, 8) ^ $xor;
|
||||||
$block = $this->des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
$block = $des[0]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
$block = $this->des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
|
$block = $des[1]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
$block = $this->des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
$block = $des[2]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
$xor = $block;
|
$xor = $block;
|
||||||
$ciphertext.= $block;
|
$ciphertext.= $block;
|
||||||
}
|
}
|
||||||
if ($this->continuousBuffer) {
|
if ($this->continuousBuffer) {
|
||||||
$this->encryptIV = $xor;
|
$this->encryptIV = $xor;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$xor = $this->encryptIV;
|
||||||
|
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||||
|
$key = $this->_generate_xor(8, $xor);
|
||||||
|
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||||
|
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
|
||||||
|
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||||
|
$block = substr($plaintext, $i, 8);
|
||||||
|
$ciphertext.= $block ^ $key;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->encryptIV = $xor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ciphertext;
|
return $ciphertext;
|
||||||
@ -396,19 +466,21 @@ class Crypt_TripleDES {
|
|||||||
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
|
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
|
||||||
|
|
||||||
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||||
$td = mcrypt_module_open(MCRYPT_3DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
|
if ($this->changed) {
|
||||||
mcrypt_generic_init($td, $this->key, $this->decryptIV);
|
if (!isset($this->demcrypt)) {
|
||||||
|
$this->demcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||||
$plaintext = mdecrypt_generic($td, $ciphertext);
|
}
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
||||||
mcrypt_generic_deinit($td);
|
$this->changed = false;
|
||||||
mcrypt_module_close($td);
|
|
||||||
|
|
||||||
if ($this->continuousBuffer) {
|
|
||||||
$this->decryptIV = substr($ciphertext, -8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_unpad($plaintext);
|
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
|
||||||
|
|
||||||
|
if (!$this->continuousBuffer) {
|
||||||
|
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->mode != 'ctr' ? $this->_unpad($plaintext) : $plaintext;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen($this->key) <= 8) {
|
if (strlen($this->key) <= 8) {
|
||||||
@ -417,14 +489,16 @@ class Crypt_TripleDES {
|
|||||||
return $this->_unpad($this->des[0]->decrypt($plaintext));
|
return $this->_unpad($this->des[0]->decrypt($plaintext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$des = $this->des;
|
||||||
|
|
||||||
$plaintext = '';
|
$plaintext = '';
|
||||||
switch ($this->mode) {
|
switch ($this->mode) {
|
||||||
case CRYPT_DES_MODE_ECB:
|
case CRYPT_DES_MODE_ECB:
|
||||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||||
$block = substr($ciphertext, $i, 8);
|
$block = substr($ciphertext, $i, 8);
|
||||||
$block = $this->des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
|
$block = $des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
$block = $this->des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
$block = $des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
$block = $this->des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
|
$block = $des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
$plaintext.= $block;
|
$plaintext.= $block;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -432,18 +506,32 @@ class Crypt_TripleDES {
|
|||||||
$xor = $this->decryptIV;
|
$xor = $this->decryptIV;
|
||||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||||
$orig = $block = substr($ciphertext, $i, 8);
|
$orig = $block = substr($ciphertext, $i, 8);
|
||||||
$block = $this->des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
|
$block = $des[2]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
$block = $this->des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
$block = $des[1]->_processBlock($block, CRYPT_DES_ENCRYPT);
|
||||||
$block = $this->des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
|
$block = $des[0]->_processBlock($block, CRYPT_DES_DECRYPT);
|
||||||
$plaintext.= $block ^ $xor;
|
$plaintext.= $block ^ $xor;
|
||||||
$xor = $orig;
|
$xor = $orig;
|
||||||
}
|
}
|
||||||
if ($this->continuousBuffer) {
|
if ($this->continuousBuffer) {
|
||||||
$this->decryptIV = $xor;
|
$this->decryptIV = $xor;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case CRYPT_DES_MODE_CTR:
|
||||||
|
$xor = $this->decryptIV;
|
||||||
|
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||||
|
$key = $this->_generate_xor(8, $xor);
|
||||||
|
$key = $des[0]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||||
|
$key = $des[1]->_processBlock($key, CRYPT_DES_DECRYPT);
|
||||||
|
$key = $des[2]->_processBlock($key, CRYPT_DES_ENCRYPT);
|
||||||
|
$block = substr($ciphertext, $i, 8);
|
||||||
|
$plaintext.= $block ^ $key;
|
||||||
|
}
|
||||||
|
if ($this->continuousBuffer) {
|
||||||
|
$this->decryptIV = $xor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->_unpad($plaintext);
|
return $this->mode != CRYPT_DES_MODE_CTR ? $this->_unpad($plaintext) : $plaintext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -576,7 +664,8 @@ class Crypt_TripleDES {
|
|||||||
/**
|
/**
|
||||||
* Unpads a string
|
* Unpads a string
|
||||||
*
|
*
|
||||||
* If padding is enabled and the reported padding length is invalid, padding will be, hence forth, disabled.
|
* If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
|
||||||
|
* and false will be returned.
|
||||||
*
|
*
|
||||||
* @see Crypt_TripleDES::_pad()
|
* @see Crypt_TripleDES::_pad()
|
||||||
* @access private
|
* @access private
|
||||||
@ -590,9 +679,7 @@ class Crypt_TripleDES {
|
|||||||
$length = ord($text[strlen($text) - 1]);
|
$length = ord($text[strlen($text) - 1]);
|
||||||
|
|
||||||
if (!$length || $length > 8) {
|
if (!$length || $length > 8) {
|
||||||
user_error("The number of bytes reported as being padded ($length) is invalid (block size = 8)", E_USER_NOTICE);
|
return false;
|
||||||
$this->padding = false;
|
|
||||||
return $text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return substr($text, 0, -$length);
|
return substr($text, 0, -$length);
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user