function encrypt_aes_cbc($key, $data, $iv = '') { // mcrypt pads with null bytes, but Matasano implies desire for implementation of PKCS#7. $ksize = mcrypt_get_key_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); $bsize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); $data = pad_pkcs7($data); if (strlen($iv) != $bsize) { echo 'Warning: IV must match block-size in length. Defaulting to null bytes.', PHP_EOL; $iv = str_repeat("", $bsize); } if (strlen($key) > $ksize) { die("Error: Maximum key-size for AES-128-CBC is {$ksize}." . PHP_EOL); } $blocks = str_split($data, $bsize); $blocks[0] = mcrypt_ecb(MCRYPT_RIJNDAEL_128, $key, $blocks[0] ^ $iv, MCRYPT_ENCRYPT); for ($i = 1, $j = count($blocks), $enc = $blocks[0]; $i < $j; $i++) { $blocks[$i] ^= $blocks[$i - 1]; $blocks[$i] = mcrypt_ecb(MCRYPT_RIJNDAEL_128, $key, $blocks[$i], MCRYPT_ENCRYPT); $enc .= $blocks[$i]; } return $enc; }
<?php function strip_pkcs7($padded_str) { $len = strlen($padded_str); $pad = ord($padded_str[$len - 1]); if (substr($padded_str, $len - $pad) != str_repeat(chr($pad), $pad)) { throw new Exception(__FUNCTION__ . '(): Bad padding.'); } return substr($padded_str, 0, $len - $pad); } 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; } $padded = pad_pkcs7('BANKAI!'); try { echo strip_pkcs7($padded); } catch (Exception $e) { echo $e->getMessage(), PHP_EOL; }