2013-01-03 17:47:40 +01:00
< ? php
/**
2014-02-15 19:57:49 +01:00
* @ author Andreas Fischer < bantu @ phpbb . com >
2014-12-10 00:02:44 +01:00
* @ copyright 2013 Andreas Fischer
2014-02-15 19:57:49 +01:00
* @ license http :// www . opensource . org / licenses / mit - license . html MIT License
2013-01-03 17:47:40 +01:00
*/
2014-08-14 17:47:26 +02:00
require_once 'Crypt/AES.php' ;
abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
2013-01-03 17:47:40 +01:00
{
2014-11-29 14:39:21 +01:00
protected $engine ;
2014-10-16 00:59:48 +02:00
2014-12-13 20:47:37 +01:00
private function _checkEngine ( $aes )
2014-02-15 19:57:49 +01:00
{
2014-11-29 14:39:21 +01:00
if ( $aes -> getEngine () != $this -> engine ) {
$engine = 'internal' ;
switch ( $this -> engine ) {
2014-12-13 21:42:58 +01:00
case CRYPT_ENGINE_OPENSSL :
2014-11-29 14:39:21 +01:00
$engine = 'OpenSSL' ;
break ;
2014-12-13 21:42:58 +01:00
case CRYPT_ENGINE_MCRYPT :
2014-11-29 14:39:21 +01:00
$engine = 'mcrypt' ;
}
self :: markTestSkipped ( 'Unable to initialize ' . $engine . ' engine' );
}
2014-08-14 17:03:01 +02:00
}
/**
* Produces all combinations of test values .
*
* @ return array
*/
public function continuousBufferCombos ()
{
$modes = array (
'CRYPT_AES_MODE_CTR' ,
'CRYPT_AES_MODE_OFB' ,
'CRYPT_AES_MODE_CFB' ,
);
$plaintexts = array (
'' ,
'12345678901234567' , // https://github.com/phpseclib/phpseclib/issues/39
" \xDE \xAD \xBE \xAF " ,
':-):-):-):-):-):-)' , // https://github.com/phpseclib/phpseclib/pull/43
);
$ivs = array (
'' ,
'test123' ,
);
$keys = array (
'' ,
':-8' , // https://github.com/phpseclib/phpseclib/pull/43
'FOOBARZ' ,
);
$result = array ();
// @codingStandardsIgnoreStart
2014-08-14 17:59:37 +02:00
foreach ( $modes as $mode )
foreach ( $plaintexts as $plaintext )
foreach ( $ivs as $iv )
foreach ( $keys as $key )
2014-08-14 17:03:01 +02:00
$result [] = array ( $mode , $plaintext , $iv , $key );
// @codingStandardsIgnoreEnd
return $result ;
2014-02-15 19:57:49 +01:00
}
2013-01-03 17:47:40 +01:00
2014-08-14 17:03:01 +02:00
/**
* @ dataProvider continuousBufferCombos
*/
public function testEncryptDecryptWithContinuousBuffer ( $mode , $plaintext , $iv , $key )
2014-02-15 19:57:49 +01:00
{
2014-08-14 17:03:01 +02:00
$aes = new Crypt_AES ( constant ( $mode ));
2014-11-29 14:39:21 +01:00
$aes -> setPreferredEngine ( $this -> engine );
2014-08-14 17:03:01 +02:00
$aes -> enableContinuousBuffer ();
$aes -> setIV ( $iv );
$aes -> setKey ( $key );
2014-12-13 20:47:37 +01:00
$this -> _checkEngine ( $aes );
2014-11-29 14:39:21 +01:00
2014-08-14 17:03:01 +02:00
$actual = '' ;
for ( $i = 0 , $strlen = strlen ( $plaintext ); $i < $strlen ; ++ $i ) {
$actual .= $aes -> decrypt ( $aes -> encrypt ( $plaintext [ $i ]));
2014-02-15 19:57:49 +01:00
}
2014-08-14 17:03:01 +02:00
$this -> assertEquals ( $plaintext , $actual );
}
2014-08-14 17:06:25 +02:00
/**
* @ group github451
*/
2014-08-14 17:03:01 +02:00
public function testKeyPaddingRijndael ()
{
// this test case is from the following URL:
// https://web.archive.org/web/20070209120224/http://fp.gladman.plus.com/cryptography_technology/rijndael/aesdvec.zip
$aes = new Crypt_Rijndael ();
2014-11-29 14:39:21 +01:00
$aes -> setPreferredEngine ( $this -> engine );
2014-08-14 17:03:01 +02:00
$aes -> disablePadding ();
$aes -> setKey ( pack ( 'H*' , '2b7e151628aed2a6abf7158809cf4f3c762e7160' )); // 160-bit key. Valid in Rijndael.
2014-12-13 20:47:37 +01:00
//$this->_checkEngine($aes); // should only work in internal mode
2014-08-14 17:03:01 +02:00
$ciphertext = $aes -> encrypt ( pack ( 'H*' , '3243f6a8885a308d313198a2e0370734' ));
$this -> assertEquals ( $ciphertext , pack ( 'H*' , '231d844639b31b412211cfe93712b880' ));
}
2014-08-14 17:06:25 +02:00
/**
* @ group github451
*/
2014-08-14 17:03:01 +02:00
public function testKeyPaddingAES ()
{
// same as the above - just with a different ciphertext
$aes = new Crypt_AES ();
2014-11-29 14:39:21 +01:00
$aes -> setPreferredEngine ( $this -> engine );
2014-08-14 17:03:01 +02:00
$aes -> disablePadding ();
$aes -> setKey ( pack ( 'H*' , '2b7e151628aed2a6abf7158809cf4f3c762e7160' )); // 160-bit key. AES should null pad to 192-bits
2014-12-13 20:47:37 +01:00
$this -> _checkEngine ( $aes );
2014-08-14 17:03:01 +02:00
$ciphertext = $aes -> encrypt ( pack ( 'H*' , '3243f6a8885a308d313198a2e0370734' ));
$this -> assertEquals ( $ciphertext , pack ( 'H*' , 'c109292b173f841b88e0ee49f13db8c0' ));
2014-02-15 19:57:49 +01:00
}
2014-11-29 14:39:21 +01:00
/**
* Produces all combinations of test values .
*
* @ return array
*/
public function continuousBufferBatteryCombos ()
{
$modes = array (
'CRYPT_MODE_CTR' ,
'CRYPT_MODE_OFB' ,
'CRYPT_MODE_CFB' ,
);
$combos = array (
2014-12-20 18:14:08 +01:00
array ( 16 ),
array ( 17 ),
array ( 1 , 16 ),
array ( 3 , 6 , 7 ), // (3 to test the openssl_encrypt call and the buffer creation, 6 to test the exclusive use of the buffer and 7 to test the buffer's exhaustion and recreation)
2014-11-29 14:39:21 +01:00
array ( 15 , 4 ), // (15 to test openssl_encrypt call and buffer creation and 4 to test something that spans multpile bloc
array ( 3 , 6 , 10 , 16 ), // this is why the strlen check in the buffer-only code was needed
array ( 16 , 16 ), // two full size blocks
array ( 3 , 6 , 7 , 16 ), // partial block + full size block
array ( 16 , 3 , 6 , 7 ),
// a few others just for fun
array ( 32 , 32 ),
array ( 31 , 31 ),
array ( 17 , 17 ),
array ( 99 , 99 )
);
$result = array ();
// @codingStandardsIgnoreStart
foreach ( $modes as $mode )
foreach ( $combos as $combo )
foreach ( array ( 'encrypt' , 'decrypt' ) as $op )
$result [] = array ( $op , $mode , $combo );
// @codingStandardsIgnoreEnd
return $result ;
}
/**
* @ dataProvider continuousBufferBatteryCombos
*/
public function testContinuousBufferBattery ( $op , $mode , $test )
{
$iv = str_repeat ( 'x' , 16 );
$key = str_repeat ( 'a' , 16 );
$aes = new Crypt_AES ( constant ( $mode ));
$aes -> setPreferredEngine ( $this -> engine );
$aes -> setKey ( $key );
$aes -> setIV ( $iv );
2014-12-13 20:47:37 +01:00
$this -> _checkEngine ( $aes );
2014-11-29 14:39:21 +01:00
$str = '' ;
$result = '' ;
foreach ( $test as $len ) {
$temp = str_repeat ( 'd' , $len );
$str .= $temp ;
}
$c1 = $aes -> $op ( $str );
$aes = new Crypt_AES ( constant ( $mode ));
$aes -> setPreferredEngine ( $this -> engine );
$aes -> enableContinuousBuffer ();
$aes -> setKey ( $key );
$aes -> setIV ( $iv );
2014-12-13 20:47:37 +01:00
$this -> _checkEngine ( $aes );
2014-11-29 14:39:21 +01:00
foreach ( $test as $len ) {
$temp = str_repeat ( 'd' , $len );
$output = $aes -> $op ( $temp );
$result .= $output ;
}
$c2 = $result ;
2015-01-01 05:46:16 +01:00
$this -> assertSame ( bin2hex ( $c1 ), bin2hex ( $c2 ), " { $this -> engine } produced different results for ' $op ' in $mode with " . implode ( ',' , $test ));
2014-11-29 14:39:21 +01:00
}
2014-12-31 22:00:54 +01:00
/**
* @ dataProvider continuousBufferBatteryCombos
*/
// pretty much the same as testContinuousBufferBattery with the caveat that continuous mode is not enabled
public function testNonContinuousBufferBattery ( $op , $mode , $test )
{
2014-12-31 22:15:15 +01:00
if ( count ( $test ) == 1 ) {
return ;
}
2014-12-31 22:00:54 +01:00
$iv = str_repeat ( 'x' , 16 );
$key = str_repeat ( 'a' , 16 );
$aes = new Crypt_AES ( constant ( $mode ));
$aes -> setPreferredEngine ( $this -> engine );
$aes -> setKey ( $key );
$aes -> setIV ( $iv );
$this -> _checkEngine ( $aes );
$str = '' ;
$result = '' ;
foreach ( $test as $len ) {
$temp = str_repeat ( 'd' , $len );
$str .= $temp ;
}
$c1 = $aes -> $op ( $str );
$aes = new Crypt_AES ( constant ( $mode ));
$aes -> setPreferredEngine ( $this -> engine );
$aes -> setKey ( $key );
$aes -> setIV ( $iv );
$this -> _checkEngine ( $aes );
foreach ( $test as $len ) {
$temp = str_repeat ( 'd' , $len );
$output = $aes -> $op ( $temp );
$result .= $output ;
}
$c2 = $result ;
2015-01-01 05:32:55 +01:00
$this -> assertNotSame ( bin2hex ( $c1 ), bin2hex ( $c2 ), " { $this -> engine } produced identical results for ' $op ' in $mode with " . implode ( ',' , $test ));
2014-12-31 22:00:54 +01:00
}
2014-12-13 20:47:37 +01:00
}