function get_prefix_len($key) { $mult = 3; $bsize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); $enc = encrypt_aes_ecb(str_repeat('A', $bsize * $mult), $key); $blocks = str_split($enc, $bsize); $index = $prefix_len = 0; for ($i = 1, $c = count($blocks); $i < $c; $i++) { if ($blocks[$i] == $blocks[$i - 1]) { $index = $i; } else { if ($index != 0) { break; } } } for ($i = $bsize * $mult - 1; $i >= 0; $i--, $prefix_len++) { $enc = encrypt_aes_ecb(str_repeat('A', $i), $key); $blocks = str_split($enc, $bsize); if ($blocks[$index] != $blocks[$index - 1]) { $prefix_len += $bsize * ($index - $mult + 1); break; } } return $prefix_len; }
// 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) { $j = 0; $end += $bsize; } }