{ $data .= base64_decode('Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK'); return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, 'ecb'); } // Attempts to determine block cipher mode based on duplicate blocks (or lack of) - (requires repitition). function detect_aes_mode($data) { $blocks = str_split($data, mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB)); return count(array_unique($blocks)) < count($blocks) ? 'ecb' : 'cbc'; } $key = random_aes_key(16); // Determines block-size of padded ciphertext by invoking the pad function and monitoring the result. for ($s = 'A', $j = strlen(encrypt_aes_ecb($s, $key)); ($k = strlen(encrypt_aes_ecb($s, $key))) == $j; $s .= 'A') { } $bsize = $k - $j; $mode = detect_aes_mode(encrypt_aes_ecb(str_repeat('A', $bsize * 2), $key)); $chars = range(chr(0), chr(255)); echo "Block size: {$bsize}\nCipher mode: {$mode}\n\n"; for ($i = 0, $j = 1, $end = $bsize, $dec = ''; $i < $end; $i++, $j++) { $str = str_repeat('A', $bsize - $j); $block = substr(encrypt_aes_ecb($str, $key), 0, $end); $str2 = $str . $dec; foreach ($chars as $char) { $dict[$char] = substr(encrypt_aes_ecb($str2 . $char, $key), 0, $end); } if (in_array($block, $dict)) { $char = array_search($block, $dict); $dec .= $char; echo $char; } if (strlen($dec) % $bsize == 0) {
if ($ksize > mcrypt_get_key_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB)) { echo 'Warning: ', __FUNCTION__, '() is intended for AES-128 key generation; key is too long.', PHP_EOL; } for ($key = '', $size = count($chars) - 1; strlen($key) < $ksize; $key .= $chars[rand(0, $size)]) { } return $key; } // Encrypts data using an unknown/random key and mode (AES-128) - also encapsulated in random data. function encryption_oracle($data, $iv = '') { $modes = array('ecb', 'cbc'); $key = random_aes_key(32); $data = random_aes_key(rand(5, 10)) . $data . random_aes_key(rand(5, 10)); return $modes[rand(0, 1)] == 'ecb' ? mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, 'ecb') : encrypt_aes_cbc($key, $data, random_aes_key(16)); } // Attempts to determine block cipher mode based on duplicate blocks (or lack of) - (requires repitition). function detect_aes_mode($data) { $blocks = str_split($data, mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB)); return count(array_unique($blocks)) < count($blocks) ? 'ecb' : 'cbc'; } function pad_pkcs7($string) { $bsize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); $padding = $bsize - strlen($string) % $bsize; $string .= str_repeat(chr($padding), $padding); return $string; } $enc = base64_encode(encryption_oracle('The YELLOW SUBMARINE is a great friend, the YELLOW SUBMARINE itself is great. All hail, the YELLOW SUBMARINE.')); $mode = strtoupper(detect_aes_mode($enc)); echo "Ciphertext: {$enc}", PHP_EOL, "Mode: {$mode}", PHP_EOL;