AES 256加密Java到PHP
我有一个基于数据加密AES256的源代码,但是此代码是Java,我想转换为PHP,我正在尝试此示例,但不正确。 PHP中的示例使用随机IV,但我要求它们为零。
private String encryptAES(String strToEncrypt) {
try {
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(SECRET_KEY.toCharArray(), SALT.getBytes(), 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes(StandardCharsets.UTF_8)));
} catch (Exception e) {
log.error("Error while encrypting: " + e.toString());
}
return null;
}
我尝试了
function encrypt($data){
$method = "AES-256-CBC";
$salt = 'vzQ8p=z';
$key = '!5&3usT';
$iv = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
$chars = array_map("chr", $iv);
$IVbytes = join($chars);
$hash = openssl_pbkdf2($key,$salt,'256','65536', 'sha1');
$encrypted = openssl_encrypt($data, $method, $hash, OPENSSL_RAW_DATA, $IVbytes);
return base64_encode($encrypted);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
最明显的缺陷是,尽管两者都使用PBKDF2,但您将HMAC-SHA2-256用作Java代码中的PRF(即伪随机函数,即Hash算法),而SHA1则用作PHP中的PRF。当然,这将产生两个不同的键(就像您通过SHA1和SHA2-256运行相同的字符串一样),因此您的文本将被加密到两个不同的密文,并且在每种情况下都需要相应的键来解密它。
您还需要检查您在两种情况下都使用相同的密码和填充方案。您在PHP中明确指定AES-256-CBC,但没有指定填充;您可以在Java中明确指定AES/CBC/PKCS5,但不是AES密钥大小。在实践中,我怀疑这是正确的(通过256位键时,Java可能会生成256位AES密钥,而PHP
openssl_encrypt
使用AES-256-CBC
可能会生成256位键。默认情况下使用PKCS5),但您不应该留下任何未指定的东西。其他想法:
secret_key
/$ key
是一个用户途径的值,否则没有理由每次都这样做。这是浪费CPU时间。The most obvious flaw is that while both use PBKDF2, you're using HMAC-SHA2-256 as the PRF (pseudo-random function, i.e. hash algorithm) in the Java code, and SHA1 as the PRF in the PHP. That will of course produce two different keys (just as if you ran the same string through SHA1 and SHA2-256), so your text will get encrypted to two different ciphertexts and need the corresponding key in each case to decrypt it.
You also need to check that you're using the same cipher and padding scheme in both cases. You explicitly specify AES-256-CBC in PHP, but not the padding; you explicitly specify AES/CBC/PKCS5 in Java, but not the AES key size. In practice I suspect that it's correct here (Java probably generates a 256-bit AES key when passed a 256-bit KeySpec, and PHP
openssl_encrypt
withAES-256-CBC
probably uses PKCS5 by default), but you shouldn't leave anything unspecified.Other thoughts:
SECRET_KEY
/$key
is a user-memorized value, there's no reason to do this every time; it's a waste of CPU time.