mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-29 04:23:34 +00:00
3DES: Fixed ContinuousBuffer() in CTR/CFB/OFB
FIXED: multiple calls to enable/enableContinuousBuffer() work's now in CTR/CFB/OFB FIXED: "Illegal string offset" and strlen(array()) Warning/Notice Performance improvement in CFB Mode with enableContinuousBuffer() using MODE_MCRYPT
This commit is contained in:
parent
c7c150bcd9
commit
f7dc23a18e
@ -212,19 +212,19 @@ class Crypt_TripleDES {
|
||||
* Encryption buffer for CTR, OFB and CFB modes
|
||||
*
|
||||
* @see Crypt_TripleDES::encrypt()
|
||||
* @var String
|
||||
* @var Array
|
||||
* @access private
|
||||
*/
|
||||
var $enbuffer = '';
|
||||
var $enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
|
||||
|
||||
/**
|
||||
* Decryption buffer for CTR, OFB and CFB modes
|
||||
*
|
||||
* @see Crypt_TripleDES::decrypt()
|
||||
* @var String
|
||||
* @var Array
|
||||
* @access private
|
||||
*/
|
||||
var $debuffer = '';
|
||||
var $debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true);
|
||||
|
||||
/**
|
||||
* mcrypt resource for CFB mode
|
||||
@ -287,6 +287,7 @@ class Crypt_TripleDES {
|
||||
break;
|
||||
case CRYPT_DES_MODE_CFB:
|
||||
$this->mode = 'ncfb';
|
||||
$this->ecb = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_ECB, '');
|
||||
break;
|
||||
case CRYPT_DES_MODE_OFB:
|
||||
$this->mode = MCRYPT_MODE_NOFB;
|
||||
@ -296,6 +297,8 @@ class Crypt_TripleDES {
|
||||
$this->paddable = true;
|
||||
$this->mode = MCRYPT_MODE_CBC;
|
||||
}
|
||||
$this->enmcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||
$this->demcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -444,29 +447,24 @@ class Crypt_TripleDES {
|
||||
* @see Crypt_TripleDES::decrypt()
|
||||
* @see Crypt_TripleDES::encrypt()
|
||||
* @access private
|
||||
* @param Integer $length
|
||||
* @param String $iv
|
||||
*/
|
||||
function _generate_xor($length, &$iv)
|
||||
function _generate_xor(&$iv)
|
||||
{
|
||||
$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;
|
||||
}
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -494,48 +492,64 @@ class Crypt_TripleDES {
|
||||
|
||||
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||
if ($this->enchanged) {
|
||||
if (!isset($this->enmcrypt)) {
|
||||
$this->enmcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||
}
|
||||
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
||||
if ($this->mode != 'ncfb') {
|
||||
$this->enchanged = false;
|
||||
if ($this->mode == 'ncfb') {
|
||||
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0");
|
||||
}
|
||||
$this->enchanged = false;
|
||||
}
|
||||
|
||||
if ($this->mode != 'ncfb') {
|
||||
if ($this->mode != 'ncfb' || !$this->continuousBuffer) {
|
||||
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
|
||||
} else {
|
||||
if ($this->enchanged) {
|
||||
$this->ecb = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_ECB, '');
|
||||
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0");
|
||||
$this->enchanged = false;
|
||||
}
|
||||
|
||||
if (strlen($this->enbuffer)) {
|
||||
$ciphertext = $plaintext ^ substr($this->encryptIV, strlen($this->enbuffer));
|
||||
$this->enbuffer.= $ciphertext;
|
||||
if (strlen($this->enbuffer) == 8) {
|
||||
$this->encryptIV = $this->enbuffer;
|
||||
$this->enbuffer = '';
|
||||
mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
||||
$iv = &$this->encryptIV;
|
||||
$pos = &$this->enbuffer['pos'];
|
||||
$len = strlen($plaintext);
|
||||
$ciphertext = '';
|
||||
$i = 0;
|
||||
if ($pos) {
|
||||
$orig_pos = $pos;
|
||||
$max = 8 - $pos;
|
||||
if ($len >= $max) {
|
||||
$i = $max;
|
||||
$len-= $max;
|
||||
$pos = 0;
|
||||
} else {
|
||||
$i = $len;
|
||||
$pos+= $len;
|
||||
$len = 0;
|
||||
}
|
||||
$plaintext = substr($plaintext, strlen($ciphertext));
|
||||
} else {
|
||||
$ciphertext = '';
|
||||
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
|
||||
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
|
||||
$this->enbuffer['enmcrypt_init'] = true;
|
||||
}
|
||||
|
||||
$last_pos = strlen($plaintext) & 0xFFFFFFF8;
|
||||
$ciphertext.= $last_pos ? mcrypt_generic($this->enmcrypt, substr($plaintext, 0, $last_pos)) : '';
|
||||
|
||||
if (strlen($plaintext) & 0x7) {
|
||||
if (strlen($ciphertext)) {
|
||||
$this->encryptIV = substr($ciphertext, -8);
|
||||
if ($len >= 8) {
|
||||
if ($this->enbuffer['enmcrypt_init'] === false || $len > 950) {
|
||||
if ($this->enbuffer['enmcrypt_init'] === true) {
|
||||
mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
|
||||
$this->enbuffer['enmcrypt_init'] = false;
|
||||
}
|
||||
$ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % 8));
|
||||
$iv = substr($ciphertext, -8);
|
||||
$i = strlen($ciphertext);
|
||||
$len%= 8;
|
||||
} else {
|
||||
while ($len >= 8) {
|
||||
$iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, 8);
|
||||
$ciphertext.= $iv;
|
||||
$len-= 8;
|
||||
$i+= 8;
|
||||
}
|
||||
}
|
||||
$this->encryptIV = mcrypt_generic($this->ecb, $this->encryptIV);
|
||||
$this->enbuffer = substr($plaintext, $last_pos) ^ $this->encryptIV;
|
||||
$ciphertext.= $this->enbuffer;
|
||||
}
|
||||
if ($len) {
|
||||
$iv = mcrypt_generic($this->ecb, $iv);
|
||||
$block = $iv ^ substr($plaintext, $i);
|
||||
$iv = substr_replace($iv, $block, 0, $len);
|
||||
$ciphertext.= $block;
|
||||
$pos = $len;
|
||||
}
|
||||
return $ciphertext;
|
||||
}
|
||||
|
||||
if (!$this->continuousBuffer) {
|
||||
@ -591,7 +605,7 @@ class Crypt_TripleDES {
|
||||
if (strlen($buffer['encrypted'])) {
|
||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||
$block = substr($plaintext, $i, 8);
|
||||
$key = $this->_generate_xor(8, $xor);
|
||||
$key = $this->_generate_xor($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);
|
||||
@ -602,7 +616,7 @@ class Crypt_TripleDES {
|
||||
} else {
|
||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||
$block = substr($plaintext, $i, 8);
|
||||
$key = $this->_generate_xor(8, $xor);
|
||||
$key = $this->_generate_xor($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);
|
||||
@ -612,7 +626,7 @@ class Crypt_TripleDES {
|
||||
if ($this->continuousBuffer) {
|
||||
$this->encryptIV = $xor;
|
||||
if ($start = strlen($plaintext) & 7) {
|
||||
$buffer['encrypted'] = substr($key, $start) . $buffer;
|
||||
$buffer['encrypted'] = substr($key, $start) . $buffer['encrypted'];
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -651,13 +665,13 @@ class Crypt_TripleDES {
|
||||
break;
|
||||
case CRYPT_DES_MODE_OFB:
|
||||
$xor = $this->encryptIV;
|
||||
if (strlen($buffer)) {
|
||||
if (strlen($buffer['xor'])) {
|
||||
for ($i = 0; $i < strlen($plaintext); $i+=8) {
|
||||
$xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
|
||||
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$buffer.= $xor;
|
||||
$key = $this->_string_shift($buffer, 8);
|
||||
$buffer['xor'].= $xor;
|
||||
$key = $this->_string_shift($buffer['xor'], 8);
|
||||
$ciphertext.= substr($plaintext, $i, 8) ^ $key;
|
||||
}
|
||||
} else {
|
||||
@ -672,7 +686,7 @@ class Crypt_TripleDES {
|
||||
if ($this->continuousBuffer) {
|
||||
$this->encryptIV = $xor;
|
||||
if ($start = strlen($plaintext) & 7) {
|
||||
$buffer = substr($key, $start) . $buffer;
|
||||
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -702,50 +716,72 @@ class Crypt_TripleDES {
|
||||
|
||||
if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) {
|
||||
if ($this->dechanged) {
|
||||
if (!isset($this->demcrypt)) {
|
||||
$this->demcrypt = mcrypt_module_open(MCRYPT_3DES, '', $this->mode, '');
|
||||
}
|
||||
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
||||
if ($this->mode != 'ncfb') {
|
||||
$this->dechanged = false;
|
||||
if ($this->mode == 'ncfb') {
|
||||
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0");
|
||||
}
|
||||
$this->dechanged = false;
|
||||
}
|
||||
|
||||
if ($this->mode != 'ncfb') {
|
||||
if ($this->mode != 'ncfb' || !$this->continuousBuffer) {
|
||||
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
|
||||
} else {
|
||||
if ($this->dechanged) {
|
||||
$this->ecb = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_ECB, '');
|
||||
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0");
|
||||
$this->dechanged = false;
|
||||
}
|
||||
|
||||
if (strlen($this->debuffer)) {
|
||||
$plaintext = $ciphertext ^ substr($this->decryptIV, strlen($this->debuffer));
|
||||
|
||||
$this->debuffer.= substr($ciphertext, 0, strlen($plaintext));
|
||||
if (strlen($this->debuffer) == 8) {
|
||||
$this->decryptIV = $this->debuffer;
|
||||
$this->debuffer = '';
|
||||
mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
||||
$iv = &$this->decryptIV;
|
||||
$pos = &$this->debuffer['pos'];
|
||||
$len = strlen($ciphertext);
|
||||
$plaintext = '';
|
||||
$i = 0;
|
||||
if ($pos) {
|
||||
$orig_pos = $pos;
|
||||
$max = 8 - $pos;
|
||||
if ($len >= $max) {
|
||||
$i = $max;
|
||||
$len-= $max;
|
||||
$pos = 0;
|
||||
} else {
|
||||
$i = $len;
|
||||
$pos+= $len;
|
||||
$len = 0;
|
||||
}
|
||||
$ciphertext = substr($ciphertext, strlen($plaintext));
|
||||
} else {
|
||||
$plaintext = '';
|
||||
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
|
||||
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
|
||||
// $this->debuffer['demcrypt_init'] = true;
|
||||
}
|
||||
|
||||
$last_pos = strlen($ciphertext) & 0xFFFFFFF8;
|
||||
$plaintext.= $last_pos ? mdecrypt_generic($this->demcrypt, substr($ciphertext, 0, $last_pos)) : '';
|
||||
|
||||
if (strlen($ciphertext) & 0x7) {
|
||||
if (strlen($plaintext)) {
|
||||
$this->decryptIV = substr($ciphertext, $last_pos - 8, 8);
|
||||
if ($len >= 8) {
|
||||
// In decrypt() possible. Will work with better performance as the commented code below
|
||||
$cb = substr($ciphertext, $i, $len - $len % 8);
|
||||
$plaintext.= mcrypt_generic($this->ecb, $iv.$cb) ^ $cb;
|
||||
$iv = substr($cb, -8);
|
||||
$len%= 8;
|
||||
/*
|
||||
if ($this->debuffer['demcrypt_init'] === false || $len > 950) {
|
||||
if ($this->debuffer['demcrypt_init'] === true) {
|
||||
mcrypt_generic_init($this->demcrypt, $this->key, $iv);
|
||||
$this->debuffer['demcrypt_init'] = false;
|
||||
}
|
||||
$cb = substr($ciphertext, $i, $len - $len % 8);
|
||||
$plaintext.= mdecrypt_generic($this->demcrypt, $cb);
|
||||
$iv = substr($cb, -8);
|
||||
$len%= 8;
|
||||
} else {
|
||||
while ($len >= 8) {
|
||||
$iv = mcrypt_generic($this->ecb,$iv);
|
||||
$cb = substr($ciphertext, $i, 8);
|
||||
$plaintext.= $iv ^ $cb;
|
||||
$iv = $cb;
|
||||
$i+= 8;
|
||||
$len-= 8;
|
||||
}
|
||||
}
|
||||
$this->decryptIV = mcrypt_generic($this->ecb, $this->decryptIV);
|
||||
$this->debuffer = substr($ciphertext, $last_pos);
|
||||
$plaintext.= $this->debuffer ^ $this->decryptIV;
|
||||
*/
|
||||
}
|
||||
if ($len) {
|
||||
$iv = mcrypt_generic($this->ecb, $iv);
|
||||
$cb = substr($ciphertext, -$len);
|
||||
$plaintext.= $iv ^ $cb;
|
||||
$iv = substr_replace($iv, $cb, 0, $len);
|
||||
$pos = $len;
|
||||
}
|
||||
|
||||
return $plaintext;
|
||||
}
|
||||
|
||||
@ -764,7 +800,7 @@ class Crypt_TripleDES {
|
||||
|
||||
$des = $this->des;
|
||||
|
||||
$buffer = &$this->enbuffer;
|
||||
$buffer = &$this->debuffer;
|
||||
$continuousBuffer = $this->continuousBuffer;
|
||||
$plaintext = '';
|
||||
switch ($this->mode) {
|
||||
@ -796,7 +832,7 @@ class Crypt_TripleDES {
|
||||
if (strlen($buffer['ciphertext'])) {
|
||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||
$block = substr($ciphertext, $i, 8);
|
||||
$key = $this->_generate_xor(8, $xor);
|
||||
$key = $this->_generate_xor($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);
|
||||
@ -807,7 +843,7 @@ class Crypt_TripleDES {
|
||||
} else {
|
||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||
$block = substr($ciphertext, $i, 8);
|
||||
$key = $this->_generate_xor(8, $xor);
|
||||
$key = $this->_generate_xor($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);
|
||||
@ -861,13 +897,13 @@ class Crypt_TripleDES {
|
||||
break;
|
||||
case CRYPT_DES_MODE_OFB:
|
||||
$xor = $this->decryptIV;
|
||||
if (strlen($buffer)) {
|
||||
if (strlen($buffer['xor'])) {
|
||||
for ($i = 0; $i < strlen($ciphertext); $i+=8) {
|
||||
$xor = $des[0]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$xor = $des[1]->_processBlock($xor, CRYPT_DES_DECRYPT);
|
||||
$xor = $des[2]->_processBlock($xor, CRYPT_DES_ENCRYPT);
|
||||
$buffer.= $xor;
|
||||
$key = $this->_string_shift($buffer, 8);
|
||||
$buffer['xor'].= $xor;
|
||||
$key = $this->_string_shift($buffer['xor'], 8);
|
||||
$plaintext.= substr($ciphertext, $i, 8) ^ $key;
|
||||
}
|
||||
} else {
|
||||
@ -882,7 +918,7 @@ class Crypt_TripleDES {
|
||||
if ($this->continuousBuffer) {
|
||||
$this->decryptIV = $xor;
|
||||
if ($start = strlen($ciphertext) & 7) {
|
||||
$buffer = substr($key, $start) . $buffer;
|
||||
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -950,6 +986,10 @@ class Crypt_TripleDES {
|
||||
$this->continuousBuffer = false;
|
||||
$this->encryptIV = $this->iv;
|
||||
$this->decryptIV = $this->iv;
|
||||
$this->enchanged = true;
|
||||
$this->dechanged = true;
|
||||
$this->enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
|
||||
$this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'demcrypt_init' => true);
|
||||
|
||||
if ($this->mode == CRYPT_DES_MODE_3CBC) {
|
||||
$this->des[0]->disableContinuousBuffer();
|
||||
|
Loading…
Reference in New Issue
Block a user