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-12-17 01:16:54 +01:00
use phpseclib\Crypt\AES ;
2016-07-31 05:18:06 +02:00
use phpseclib\Crypt\Common\BlockCipher ;
2014-12-17 01:16:54 +01:00
use phpseclib\Crypt\Rijndael ;
2014-08-14 17:47:26 +02:00
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-08-14 17:03:01 +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 ) {
2017-06-28 05:34:36 +02:00
self :: markTestSkipped ( 'Unable to initialize ' . $this -> engine . ' engine' );
2014-11-29 14:39:21 +01:00
}
2014-08-14 17:03:01 +02:00
}
/**
2015-03-29 18:07:17 +02:00
* Produces all combinations of test values .
*
* @ return array
*/
2014-08-14 17:03:01 +02:00
public function continuousBufferCombos ()
{
2017-11-27 09:30:14 +01:00
$modes = [
2017-06-28 05:34:36 +02:00
'ctr' ,
'ofb' ,
'cfb' ,
2017-10-04 12:32:29 +02:00
'cfb8'
2017-11-27 09:30:14 +01:00
];
$plaintexts = [
2014-08-14 17:03:01 +02:00
'' ,
'12345678901234567' , // https://github.com/phpseclib/phpseclib/issues/39
" \xDE \xAD \xBE \xAF " ,
':-):-):-):-):-):-)' , // https://github.com/phpseclib/phpseclib/pull/43
2017-11-27 09:30:14 +01:00
];
$ivs = [
2016-04-30 23:23:35 +02:00
str_repeat ( " \0 " , 16 ),
str_pad ( 'test123' , 16 , " \0 " ),
2017-11-27 09:30:14 +01:00
];
$keys = [
2016-04-30 23:23:35 +02:00
str_repeat ( " \0 " , 16 ),
str_pad ( ':-8' , 16 , " \0 " ), // https://github.com/phpseclib/phpseclib/pull/43
str_pad ( 'FOOBARZ' , 16 , " \0 " ),
2017-11-27 09:30:14 +01:00
];
2014-08-14 17:03:01 +02:00
2017-11-27 09:30:14 +01:00
$result = [];
2014-08-14 17:03:01 +02:00
2016-04-10 18:30:59 +02:00
foreach ( $modes as $mode ) {
foreach ( $plaintexts as $plaintext ) {
foreach ( $ivs as $iv ) {
foreach ( $keys as $key ) {
2017-11-27 09:30:14 +01:00
$result [] = [ $mode , $plaintext , $iv , $key ];
2016-04-10 18:30:59 +02:00
}
}
}
}
2014-08-14 17:03:01 +02:00
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
/**
2015-03-29 18:07:17 +02:00
* @ dataProvider continuousBufferCombos
*/
2014-08-14 17:03:01 +02:00
public function testEncryptDecryptWithContinuousBuffer ( $mode , $plaintext , $iv , $key )
2014-02-15 19:57:49 +01:00
{
2014-12-17 01:16:54 +01:00
$aes = new AES ( $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 );
2015-01-15 05:46:46 +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
/**
2015-03-29 18:07:17 +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
2017-06-28 05:34:36 +02:00
$aes = new Rijndael ( 'cbc' );
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.
2016-04-30 23:23:35 +02:00
$aes -> setIV ( str_repeat ( " \0 " , 16 ));
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
/**
2015-03-29 18:07:17 +02:00
* @ group github451
2016-04-30 23:23:35 +02:00
* @ expectedException \LengthException
2015-03-29 18:07:17 +02:00
*/
2014-08-14 17:03:01 +02:00
public function testKeyPaddingAES ()
{
// same as the above - just with a different ciphertext
2017-06-28 05:34:36 +02:00
$aes = new AES ( 'cbc' );
2014-11-29 14:39:21 +01:00
$aes -> setPreferredEngine ( $this -> engine );
2014-08-14 17:03:01 +02:00
$aes -> disablePadding ();
2016-04-30 23:23:35 +02:00
$aes -> setKey ( pack ( 'H*' , '2b7e151628aed2a6abf7158809cf4f3c762e7160' )); // 160-bit key. supported by Rijndael - not AES
$aes -> setIV ( str_repeat ( " \0 " , 16 ));
2015-01-15 05:46:46 +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
/**
2016-04-10 18:30:59 +02:00
* Produces all combinations of test values .
*
* @ return array
*/
2014-11-29 14:39:21 +01:00
public function continuousBufferBatteryCombos ()
{
2017-11-27 09:30:14 +01:00
$modes = [
2017-06-28 05:34:36 +02:00
'ctr' ,
'ofb' ,
'cfb' ,
2017-10-04 12:32:29 +02:00
'cfb8' ,
2017-11-27 09:30:14 +01:00
];
$combos = [
[ 16 ],
[ 17 ],
[ 1 , 16 ],
[ 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)
[ 15 , 4 ], // (15 to test openssl_encrypt call and buffer creation and 4 to test something that spans multpile bloc
[ 3 , 6 , 10 , 16 ], // this is why the strlen check in the buffer-only code was needed
[ 16 , 16 ], // two full size blocks
[ 3 , 6 , 7 , 16 ], // partial block + full size block
[ 16 , 3 , 6 , 7 ],
2014-11-29 14:39:21 +01:00
// a few others just for fun
2017-11-27 09:30:14 +01:00
[ 32 , 32 ],
[ 31 , 31 ],
[ 17 , 17 ],
[ 99 , 99 ]
];
2014-11-29 14:39:21 +01:00
2017-11-27 09:30:14 +01:00
$result = [];
2014-11-29 14:39:21 +01:00
2016-04-10 18:30:59 +02:00
foreach ( $modes as $mode ) {
foreach ( $combos as $combo ) {
2017-11-27 09:30:14 +01:00
foreach ([ 'encrypt' , 'decrypt' ] as $op ) {
$result [] = [ $op , $mode , $combo ];
2016-04-10 18:30:59 +02:00
}
}
}
2014-11-29 14:39:21 +01:00
return $result ;
}
/**
2016-04-10 18:30:59 +02:00
* @ dataProvider continuousBufferBatteryCombos
*/
2014-11-29 14:39:21 +01:00
public function testContinuousBufferBattery ( $op , $mode , $test )
{
$iv = str_repeat ( 'x' , 16 );
$key = str_repeat ( 'a' , 16 );
2015-04-02 12:32:31 +02:00
$aes = new AES ( $mode );
2014-11-29 14:39:21 +01:00
$aes -> setPreferredEngine ( $this -> engine );
$aes -> setKey ( $key );
$aes -> setIV ( $iv );
2015-01-15 05:46:46 +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 );
2015-04-02 12:32:31 +02:00
$aes = new AES ( $mode );
2014-11-29 14:39:21 +01:00
$aes -> setPreferredEngine ( $this -> engine );
$aes -> enableContinuousBuffer ();
$aes -> setKey ( $key );
$aes -> setIV ( $iv );
2015-01-15 03:19:03 +01:00
if ( ! $this -> _checkEngine ( $aes )) {
return ;
}
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 06:02:22 +01:00
$this -> assertSame ( bin2hex ( $c1 ), bin2hex ( $c2 ));
2014-11-29 14:39:21 +01:00
}
2014-12-31 22:00:54 +01:00
/**
2016-04-10 18:30:59 +02:00
* Pretty much the same as testContinuousBufferBattery with the caveat that continuous mode is not enabled .
*
* @ dataProvider continuousBufferBatteryCombos
*/
2014-12-31 22:00:54 +01:00
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 );
2015-04-02 12:32:31 +02:00
$aes = new AES ( $mode );
2014-12-31 22:00:54 +01:00
$aes -> setPreferredEngine ( $this -> engine );
$aes -> setKey ( $key );
$aes -> setIV ( $iv );
2015-01-15 05:46:46 +01:00
$this -> _checkEngine ( $aes );
2014-12-31 22:00:54 +01:00
$str = '' ;
$result = '' ;
foreach ( $test as $len ) {
$temp = str_repeat ( 'd' , $len );
$str .= $temp ;
}
$c1 = $aes -> $op ( $str );
2015-04-02 12:32:31 +02:00
$aes = new AES ( $mode );
2014-12-31 22:00:54 +01:00
$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 06:02:22 +01:00
$this -> assertNotSame ( bin2hex ( $c1 ), bin2hex ( $c2 ));
2014-12-31 22:00:54 +01:00
}
2015-01-02 06:56:01 +01:00
// from http://csrc.nist.gov/groups/STM/cavp/documents/aes/AESAVS.pdf#page=16
public function testGFSBox128 ()
{
2017-06-28 05:34:36 +02:00
$aes = new AES ( 'cbc' );
2015-01-02 06:56:01 +01:00
$aes -> setKey ( pack ( 'H*' , '00000000000000000000000000000000' ));
$aes -> setIV ( pack ( 'H*' , '00000000000000000000000000000000' ));
2015-01-08 04:36:02 +01:00
$aes -> disablePadding ();
2015-01-02 06:56:01 +01:00
$aes -> setPreferredEngine ( $this -> engine );
2015-01-15 05:46:46 +01:00
$this -> _checkEngine ( $aes );
2015-01-02 06:56:01 +01:00
2015-01-08 05:55:35 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , 'f34481ec3cc627bacd5dc3fb08f273e6' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '0336763e966d92595a567cc9ce537f5e' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '9798c4640bad75c7c3227db910174e72' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , 'a9a1631bf4996954ebc093957b234589' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '96ab5c2ff612d9dfaae8c31f30c42168' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , 'ff4f8391a6a40ca5b25d23bedd44a597' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '6a118a874519e64e9963798a503f1d35' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , 'dc43be40be0e53712f7e2bf5ca707209' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , 'cb9fceec81286ca3e989bd979b0cb284' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '92beedab1895a94faa69b632e5cc47ce' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , 'b26aeb1874e47ca8358ff22378f09144' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '459264f4798f6a78bacb89c15ed3d601' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '58c8e00b2631686d54eab84b91f0aca1' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '08a4e2efec8a8e3312ca7460b9040bbf' );
}
public function testGFSBox192 ()
{
2017-06-28 05:34:36 +02:00
$aes = new AES ( 'cbc' );
2015-01-02 06:56:01 +01:00
$aes -> setKey ( pack ( 'H*' , '000000000000000000000000000000000000000000000000' ));
$aes -> setIV ( pack ( 'H*' , '00000000000000000000000000000000' ));
2015-01-08 04:36:02 +01:00
$aes -> disablePadding ();
2015-01-02 06:56:01 +01:00
$aes -> setPreferredEngine ( $this -> engine );
2015-01-15 05:46:46 +01:00
$this -> _checkEngine ( $aes );
2015-01-02 06:56:01 +01:00
2015-01-08 05:55:35 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '1b077a6af4b7f98229de786d7516b639' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '275cfc0413d8ccb70513c3859b1d0f72' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '9c2d8842e5f48f57648205d39a239af1' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , 'c9b8135ff1b5adc413dfd053b21bd96d' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , 'bff52510095f518ecca60af4205444bb' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '4a3650c3371ce2eb35e389a171427440' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '51719783d3185a535bd75adc65071ce1' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '4f354592ff7c8847d2d0870ca9481b7c' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '26aa49dcfe7629a8901a69a9914e6dfd' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , 'd5e08bf9a182e857cf40b3a36ee248cc' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '941a4773058224e1ef66d10e0a6ee782' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '067cd9d3749207791841562507fa9626' );
}
public function testGFSBox256 ()
{
2017-06-28 05:34:36 +02:00
$aes = new AES ( 'cbc' );
2015-01-02 06:56:01 +01:00
$aes -> setKey ( pack ( 'H*' , '00000000000000000000000000000000' . '00000000000000000000000000000000' ));
$aes -> setIV ( pack ( 'H*' , '00000000000000000000000000000000' ));
2015-01-08 04:36:02 +01:00
$aes -> disablePadding ();
2015-01-02 06:56:01 +01:00
$aes -> setPreferredEngine ( $this -> engine );
2015-01-15 05:46:46 +01:00
$this -> _checkEngine ( $aes );
2015-01-02 06:56:01 +01:00
2015-01-08 05:55:35 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '014730f80ac625fe84f026c60bfd547d' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '5c9d844ed46f9885085e5d6a4f94c7d7' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '0b24af36193ce4665f2825d7b4749c98' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , 'a9ff75bd7cf6613d3731c77c3b6d0c04' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '761c1fe41a18acf20d241650611d90f1' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '623a52fcea5d443e48d9181ab32c7421' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '8a560769d605868ad80d819bdba03771' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '38f2c7ae10612415d27ca190d27da8b4' );
2015-01-15 05:46:46 +01:00
$result = bin2hex ( $aes -> encrypt ( pack ( 'H*' , '91fbef2d15a97816060bee1feaa49afe' )));
2015-01-02 06:56:01 +01:00
$this -> assertSame ( $result , '1bc704f1bce135ceb810341b216d7abe' );
}
2016-04-10 18:30:59 +02:00
public function testGetKeyLengthDefault ()
{
2017-06-28 05:34:36 +02:00
$aes = new AES ( 'cbc' );
2016-04-10 18:30:59 +02:00
$this -> assertSame ( $aes -> getKeyLength (), 128 );
}
public function testGetKeyLengthWith192BitKey ()
{
2017-06-28 05:34:36 +02:00
$aes = new AES ( 'cbc' );
2016-04-10 18:30:59 +02:00
$aes -> setKey ( str_repeat ( 'a' , 24 ));
$this -> assertSame ( $aes -> getKeyLength (), 192 );
}
2016-04-30 23:23:35 +02:00
/**
* @ expectedException \LengthException
*/
2016-04-10 18:30:59 +02:00
public function testSetKeyLengthWithLargerKey ()
{
2017-06-28 05:34:36 +02:00
$aes = new AES ( 'cbc' );
2016-04-10 18:30:59 +02:00
$aes -> setKeyLength ( 128 );
$aes -> setKey ( str_repeat ( 'a' , 24 ));
2016-04-30 23:23:35 +02:00
$aes -> setIV ( str_repeat ( " \0 " , 16 ));
2016-04-10 18:30:59 +02:00
$this -> assertSame ( $aes -> getKeyLength (), 128 );
$ciphertext = bin2hex ( $aes -> encrypt ( 'a' ));
$this -> assertSame ( $ciphertext , '82b7b068dfc60ed2a46893b69fecd6c2' );
$this -> assertSame ( $aes -> getKeyLength (), 128 );
}
2016-04-30 23:23:35 +02:00
/**
* @ expectedException \LengthException
*/
2016-04-10 18:30:59 +02:00
public function testSetKeyLengthWithSmallerKey ()
{
2017-06-28 05:34:36 +02:00
$aes = new AES ( 'cbc' );
2016-04-10 18:30:59 +02:00
$aes -> setKeyLength ( 256 );
$aes -> setKey ( str_repeat ( 'a' , 16 ));
2016-04-30 23:23:35 +02:00
$aes -> setIV ( str_repeat ( " \0 " , 16 ));
2016-04-10 18:30:59 +02:00
$this -> assertSame ( $aes -> getKeyLength (), 256 );
$ciphertext = bin2hex ( $aes -> encrypt ( 'a' ));
$this -> assertSame ( $ciphertext , 'fd4250c0d234aa7e1aa592820aa8406b' );
$this -> assertSame ( $aes -> getKeyLength (), 256 );
}
/**
* @ group github938
*/
public function testContinuousBuffer ()
{
2017-06-28 05:34:36 +02:00
$aes = new AES ( 'cbc' );
2016-04-10 18:30:59 +02:00
$aes -> disablePadding ();
$aes -> enableContinuousBuffer ();
$aes -> setIV ( pack ( 'H*' , '0457bdb4a6712986688349a29eb82535' ));
$aes -> setKey ( pack ( 'H*' , '00d596e2c8189b2592fac358e7396ad2' ));
$aes -> decrypt ( pack ( 'H*' , '9aa234ea7c750a8109a0f32d768b964e' ));
$plaintext = $aes -> decrypt ( pack ( 'H*' , '0457bdb4a6712986688349a29eb82535' ));
$expected = pack ( 'H*' , '6572617574689e1be8d2d8d43c594cf3' );
$this -> assertSame ( $plaintext , $expected );
}
2018-02-21 15:10:06 +01:00
public function testECBDecrypt ()
{
$aes = new AES ( 'ecb' );
$aes -> setPreferredEngine ( $this -> engine );
$aes -> setKey ( str_repeat ( 'x' , 16 ));
$this -> _checkEngine ( $aes );
$plaintext = str_repeat ( 'a' , 16 );
$actual = $aes -> decrypt ( $aes -> encrypt ( $plaintext ));
$this -> assertEquals ( $plaintext , $actual );
}
2014-08-14 18:09:54 +02:00
}