1
0
mirror of https://github.com/danog/tgseclib.git synced 2024-12-05 21:48:52 +01:00

Added support for AES IGE

This commit is contained in:
Daniil Gentili 2017-02-10 04:37:59 +01:00
parent ab1da5ac1f
commit 12dc23d9ab
2 changed files with 157 additions and 6 deletions

View File

@ -90,6 +90,10 @@ abstract class SymmetricKey
* Encrypt / decrypt using streaming mode.
*/
const MODE_STREAM = 5;
/**
* Encrypt / decrypt using the Infinite Garble Extension mode.
*/
const MODE_IGE = 6;
/**#@-*/
/**#@+
@ -452,6 +456,8 @@ abstract class SymmetricKey
*
* - self::MODE_OFB
*
* - self::MODE_IGE
*
* @param int $mode
* @access public
* @throws \InvalidArgumentException if an invalid / unsupported mode is provided
@ -468,6 +474,7 @@ abstract class SymmetricKey
case self::MODE_CFB:
case self::MODE_OFB:
case self::MODE_STREAM:
case self::MODE_IGE:
$this->paddable = false;
break;
default:
@ -498,10 +505,12 @@ abstract class SymmetricKey
throw new \InvalidArgumentException('This algorithm does not use an IV.');
}
if (strlen($iv) != $this->block_size) {
throw new \LengthException('Received initialization vector of size ' . strlen($iv) . ', but size ' . $this->block_size . ' is required');
if (strlen($iv) != $this->block_size*($this->mode === self::MODE_IGE ? 2 : 1)) {
throw new \LengthException('Received initialization vector of size ' . strlen($iv) . ', but size ' . $this->block_size*($this->mode === self::MODE_IGE ? 2 : 1). ' is required');
}
$this->iv = $iv;
$this->changed = true;
}
@ -840,6 +849,21 @@ abstract class SymmetricKey
return $result;
case self::MODE_CTR:
return $this->openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
case self::MODE_IGE:
$ciphertext = '';
$iv_part_1 = substr($this->encryptIV, 0, $this->block_size);
$iv_part_2 = substr($this->encryptIV, $this->block_size);
for ($i = 0; $i < strlen($plaintext); $i += $this->block_size) {
$indata = substr($plaintext, $i, $this->block_size);
$outdata = openssl_encrypt($indata ^ $iv_part_1, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING) ^ $iv_part_2;
$iv_part_1 = $outdata;
$iv_part_2 = $indata;
$ciphertext .= $outdata;
}
if ($this->continuousBuffer) {
$this->encryptIV = $iv_part_1.$iv_part_2;
}
return $ciphertext;
case self::MODE_CFB:
// cfb loosely routines inspired by openssl's:
// {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
@ -958,7 +982,22 @@ abstract class SymmetricKey
return $ciphertext;
}
if ($this->mode === self::MODE_IGE) {
$ciphertext = '';
$iv_part_1 = substr($this->encryptIV, 0, $this->block_size);
$iv_part_2 = substr($this->encryptIV, $this->block_size);
for ($i = 0; $i < strlen($plaintext); $i += $this->block_size) {
$indata = substr($plaintext, $i, $this->block_size);
$outdata = @mcrypt_generic($this->enmcrypt, $indata ^ $iv_part_1) ^ $iv_part_2;
$iv_part_1 = $outdata;
$iv_part_2 = $indata;
$ciphertext .= $outdata;
}
if ($this->continuousBuffer) {
$this->encryptIV = $iv_part_1.$iv_part_2;
}
return $ciphertext;
}
$ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext);
if (!$this->continuousBuffer) {
@ -986,6 +1025,20 @@ abstract class SymmetricKey
$ciphertext.= $this->encryptBlock(substr($plaintext, $i, $block_size));
}
break;
case self::MODE_IGE:
$iv_part_1 = substr($this->encryptIV, 0, $this->block_size);
$iv_part_2 = substr($this->encryptIV, $this->block_size);
for ($i = 0; $i < strlen($plaintext); $i += $this->block_size) {
$indata = substr($plaintext, $i, $this->block_size);
$outdata = $this->encryptBlock($indata ^ $iv_part_1) ^ $iv_part_2;
$iv_part_1 = $outdata;
$iv_part_2 = $indata;
$ciphertext .= $outdata;
}
if ($this->continuousBuffer) {
$this->encryptIV = $iv_part_1.$iv_part_2;
}
break;
case self::MODE_CBC:
$xor = $this->encryptIV;
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
@ -1139,9 +1192,26 @@ abstract class SymmetricKey
$this->decryptIV = substr($ciphertext, -$offset, $this->block_size);
}
break;
case self::MODE_IGE:
$plaintext = '';
$iv_part_1 = substr($this->decryptIV, 0, $this->block_size);
$iv_part_2 = substr($this->decryptIV, $this->block_size);
for ($i = 0; $i < strlen($ciphertext); $i += $this->block_size) {
$indata = substr($ciphertext, $i, $this->block_size);
$outdata = openssl_decrypt($indata ^ $iv_part_2, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING) ^ $iv_part_1;
$iv_part_1 = $indata;
$iv_part_2 = $outdata;
$plaintext .= $outdata;
}
if ($this->continuousBuffer) {
$this->decryptIV = $iv_part_1.$iv_part_2;
}
break;
case self::MODE_CTR:
$plaintext = $this->openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
break;
case self::MODE_CFB:
// cfb loosely routines inspired by openssl's:
// {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
@ -1242,6 +1312,22 @@ abstract class SymmetricKey
return $plaintext;
}
if ($this->mode === self::MODE_IGE) {
$plaintext = '';
$iv_part_1 = substr($this->decryptIV, 0, $this->block_size);
$iv_part_2 = substr($this->decryptIV, $this->block_size);
for ($i = 0; $i < strlen($ciphertext); $i += $this->block_size) {
$indata = substr($ciphertext, $i, $this->block_size);
$outdata = @mcrypt_generic($this->demcrypt, $indata ^ $iv_part_2) ^ $iv_part_1;
$iv_part_1 = $indata;
$iv_part_2 = $outdata;
$plaintext .= $outdata;
}
if ($this->continuousBuffer) {
$this->decryptIV = $iv_part_1.$iv_part_2;
}
return $plaintext;
}
$plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext);
@ -1282,6 +1368,20 @@ abstract class SymmetricKey
$this->decryptIV = $xor;
}
break;
case self::MODE_IGE:
$iv_part_1 = substr($this->decryptIV, 0, $this->block_size);
$iv_part_2 = substr($this->decryptIV, $this->block_size);
for ($i = 0; $i < strlen($ciphertext); $i += $this->block_size) {
$indata = substr($ciphertext, $i, $this->block_size);
$outdata = $this->decryptBlock($indata ^ $iv_part_2) ^ $iv_part_1;
$iv_part_1 = $indata;
$iv_part_2 = $outdata;
$plaintext .= $outdata;
}
if ($this->continuousBuffer) {
$this->decryptIV = $iv_part_1.$iv_part_2;
}
break;
case self::MODE_CTR:
$xor = $this->decryptIV;
if (strlen($buffer['ciphertext'])) {
@ -1553,6 +1653,7 @@ abstract class SymmetricKey
{
switch ($this->mode) {
case self::MODE_ECB:
case self::MODE_IGE:
return 'ecb';
case self::MODE_CBC:
return 'cbc';
@ -1906,6 +2007,7 @@ abstract class SymmetricKey
if (!isset($this->enmcrypt)) {
static $mcrypt_modes = [
self::MODE_CTR => 'ctr',
self::MODE_IGE => MCRYPT_MODE_ECB,
self::MODE_ECB => MCRYPT_MODE_ECB,
self::MODE_CBC => MCRYPT_MODE_CBC,
self::MODE_CFB => 'ncfb',
@ -1919,7 +2021,7 @@ abstract class SymmetricKey
// we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
// to workaround mcrypt's broken ncfb implementation in buffered mode
// see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
if ($this->mode == self::MODE_CFB) {
if ($this->mode === self::MODE_CFB) {
$this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
}
} // else should mcrypt_generic_deinit be called?
@ -2520,6 +2622,52 @@ abstract class SymmetricKey
$decrypt = $init_decrypt . '
$_plaintext = "";
'.$decrypt_block.'
return $_plaintext;
';
break;
case self::MODE_IGE:
$encrypt = $init_encrypt . '
$_ciphertext = "";
$_plaintext_len = strlen($_text);
$_iv_part_1 = substr($this->encryptIV, 0, '.$block_size.');
$_iv_part_2 = substr($this->encryptIV, '.$block_size.');
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
$in = ($indata = substr($_text, $_i, '.$block_size.')) ^ $_iv_part_1;
'.$encrypt_block.'
$outdata = $in ^ $_iv_part_2;
$_iv_part_1 = $outdata;
$_iv_part_2 = $indata;
$_ciphertext .= $outdata;
}
if ($this->continuousBuffer) {
$this->encryptIV = $_iv_part_1.$_iv_part_2;
}
return $_ciphertext;
';
$decrypt = $init_decrypt . '
$_plaintext = "";
$_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
$_ciphertext_len = strlen($_text);
$_iv_part_1 = substr($this->decryptIV, 0, '.$block_size.');
$_iv_part_2 = substr($this->decryptIV, '.$block_size.');
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
$in = ($indata = substr($_text, $_i, '.$block_size.')) ^ $_iv_part_2;
'.$decrypt_block.'
$outdata = $in ^ $_iv_part_1;
$_iv_part_1 = $indata;
$_iv_part_2 = $outdata;
$_plaintext .= $outdata;
}
if ($this->continuousBuffer) {
$this->decryptIV = $_iv_part_1.$_iv_part_2;
}
return $_plaintext;
';
break;

View File

@ -39,6 +39,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
BlockCipher::MODE_CTR,
BlockCipher::MODE_OFB,
BlockCipher::MODE_CFB,
BlockCipher::MODE_IGE,
);
$plaintexts = array(
'',
@ -61,6 +62,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
foreach ($modes as $mode) {
foreach ($plaintexts as $plaintext) {
foreach ($ivs as $iv) {
if ($mode === BlockCipher::MODE_IGE) $iv .= strrev($iv);
foreach ($keys as $key) {
$result[] = array($mode, $plaintext, $iv, $key);
}
@ -139,6 +141,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
BlockCipher::MODE_CTR,
BlockCipher::MODE_OFB,
BlockCipher::MODE_CFB,
BlockCipher::MODE_IGE,
);
$combos = array(
@ -176,7 +179,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
*/
public function testContinuousBufferBattery($op, $mode, $test)
{
$iv = str_repeat('x', 16);
$iv = str_repeat('x', 16*($mode === BlockCipher::MODE_IGE ? 2 : 1));
$key = str_repeat('a', 16);
$aes = new AES($mode);
@ -227,7 +230,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
return;
}
$iv = str_repeat('x', 16);
$iv = str_repeat('x', 16*($mode === BlockCipher::MODE_IGE ? 2 : 1));
$key = str_repeat('a', 16);
$aes = new AES($mode);