需要替换现有的加密和解密功能,该功能将McRypt Blowfish CBC模式与Openssl等效替换。
它需要能够处理较旧的值,以使方法保持兼容。
具有解密的工作,并且加密是"几乎可以的",但不完全。
这是我拥有的代码:
$value = "myTextValue";
$key = 'c40f5b7ad3b7c787d400e923e461064b141fa878ce61cb0d1782593a5a2d842832c80fc2';
$enc = @encrypt_openssl($value, $key);
//$enc = @encrypt_mcrypt($value, $key);
$original_openssl = @decrypt_openssl($enc, $key);
$original_mcrypt = @decrypt_mcrypt($enc, $key);
echo $original_mcrypt."n";
echo $original_openssl."n";
function encrypt_openssl($string, $key) {
$iv_size = openssl_cipher_iv_length("BF-CBC");
$iv = openssl_random_pseudo_bytes($iv_size);
$enc = openssl_encrypt($string, "BF-CBC", pack('H*',$key), OPENSSL_RAW_DATA, $iv);
return base64_encode($iv.$enc);
}
function encrypt_mcrypt($string, $key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$enc = mcrypt_encrypt(MCRYPT_BLOWFISH, pack('H*', $key), $string, MCRYPT_MODE_CBC, $iv);
return base64_encode($iv.$enc);
}
function decrypt_openssl($enc, $key) {
$iv_size = openssl_cipher_iv_length("BF-CBC");
$dec = base64_decode($enc);
$iv = substr($dec, 0, $iv_size);
$string = openssl_decrypt(substr($dec, $iv_size), "BF-CBC", pack('H*',$key), OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING | OPENSSL_DONT_ZERO_PAD_KEY, $iv);
return rtrim($string, "x00");
}
function decrypt_mcrypt($enc, $key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
$dec = base64_decode($enc);
$iv = substr($dec, 0, $iv_size);
$string = mcrypt_decrypt(MCRYPT_BLOWFISH, pack('H*', $key), substr($dec, $iv_size), MCRYPT_MODE_CBC, $iv);
return rtrim($string, "x00");
}
使用OpenSSL加密时,会添加一些额外的二进制数据。
不是加密大师,只得到一半的大师,这是我在其他Stackoverflow帖子和全能的Google
的帮助下得到的。编辑
遵循topaco建议,我来了以下有效的代码:
function encrypt_openssl($string, $key) {
$string_padded = $string;
if (strlen($string_padded) % 8) {
$string_padded = str_pad($string_padded,
strlen($string_padded) + 8 - strlen($string_padded) % 8, " ");
}
$iv_size = openssl_cipher_iv_length("BF-CBC");
$iv = openssl_random_pseudo_bytes($iv_size);
$enc = openssl_encrypt($string_padded, "BF-CBC", pack('H*',$key), OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv);
return base64_encode($iv.$enc);
}
openssl_encrypt/decrypt
使用pkcs7-padding,默认情况下, mcrypt_encrypt/decrypt
使用零字节盖。
解密后观察到的额外数据是PKCS7-padding的填充物:当前代码使用openssl_encrypt
-CALL(OPENSSL_ZERO_PADDING
-FLAG未设置(使用PKCS7填充。由于openssl_decrypt
-call(OPENSSL_ZERO_PADDING
-Flag集(不使用填充物,因此填充后仍存在填充物。请注意,OPENSSL_ZERO_PADDING
-Flag禁用填充物,它确实不是平均零字节盖。
尽管与零字节填充(因为后者是不可靠的(相比,PKCS7填充通常是更好的选择,但在这种情况下,使用旧数据的填充,即零字节填充,即零字节,即更有意义关于旧数据的兼容性。否则,会有带有不同填充的数据,通常不能从数据中得出这些数据,例如填充的最终块41 42 43 44 45 46 02 02
可能是由PKCS7-padding或零字节填充创建的:
before padding after padding
41 42 43 44 45 46 __ __ -> 41 42 43 44 45 46 02 02 PKCS7-Padding
41 42 43 44 45 46 02 02 -> 41 42 43 44 45 46 02 02 Zero-Byte-Padding (variant of mcrypt_encrypt)
这将使毫无脚垫更加复杂。使用零字节盖避免了此问题。
由于openssl_encrypt/decrypt
不支持零字节填充,因此必须明确实现它。使用mcrypt_encrypt
的零字节 - 底漆变化是有意义的:如果块化已被块化(8个字节供洪水(排除,则不会添加零字节的其他额外块。否则,用零字节完成填充,直到明文的长度对应于块的整数倍数。
必须在openssl_encrypt
-call之前进行零字节填充。此外,必须禁用openssl_encrypt
-CALL中的填充物(设置OPENSSL_ZERO_PADDING
-Flag,类似于openssl_decrypt
-CALL(。