我需要在服务器端进行中到强加密,所以我想我会在 PHP 中使用 mcrypt。如果我使用原始字符串开头下面的函数,解密后会变成二进制垃圾。(这不是附加额外垃圾的常见问题,而是我的字符串被更改。)根据文档, mcrypt_encrypt() 应该填充足够的字符以匹配所选算法的块大小,但我怀疑它不起作用。
但是,如果我手动将它填充到 Rijndael 的 128 位(16 字节)块大小,它也不起作用。我可以让它工作的唯一方法是预先添加一些足够长的字符串以(可能)覆盖垃圾块,并在该字符串和我的数据之间添加一个已知的前缀,如“DATA#”。解密后,该块已部分损坏,但我的前缀和之后的所有数据都已正确解密。
$GLOBALS['encryptionmarker'] = 'DATA#';
function encrypt($plain, $key) {
/*
// workaround because beginning of decrypted string is being mangled
// so we simply prefix with some text plus marker
$prefix = str_pad('', 128, '#', STR_PAD_RIGHT).$GLOBALS['encryptionmarker'];
$plain = $prefix.$plain;
*/
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $plain, MCRYPT_MODE_CFB,
mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB),
MCRYPT_DEV_URANDOM));
return $encrypted;
}
function decrypt($encrypted, $key) {
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CFB,
mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB),
MCRYPT_DEV_URANDOM));
/*
// workaround: remove garbage
$pos = strpos($decrypted, $GLOBALS['encryptionmarker']);
$decrypted = trim(substr($decrypted, $pos + strlen($GLOBALS['encryptionmarker'])));
*/
return $decrypted;
}
我的功能有什么问题?为什么我必须像这样为我的数据添加前缀(我认为这是一种肮脏的解决方法,所以我想修复它)?
存储加密数据不是问题;加密后立即解密而不将其存储到数据库会导致相同的错误。