我有一个完美的java代码
public static String encrypt(String message, String sercretKey)
{
String base64EncryptedString = "";
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digestOfPassword = md.digest(sercretKey.getBytes("utf-8"));
byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
byte[] iv = Arrays.copyOf(digestOfPassword, 16);
SecretKey key = new SecretKeySpec(keyBytes, "AES");
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, key, ivParameterSpec);
byte[] plainTextBytes = message.getBytes("utf-8");
byte[] buf = cipher.doFinal(plainTextBytes);
byte[] base64Bytes = Base64.getEncoder().encode(buf);
base64EncryptedString = new String(base64Bytes);
return base64EncryptedString;
}
我已经尝试使用下面的代码在PHP中重新创建上面的代码
function encryptTest($sSecretKey,$sValue)
{
$key = hash('sha256', $sSecretKey,false);
$key = utf8_encode($key);
$key = substr($key, 0, 24);
$iv = substr($key, 0, 16);
$data = $sValue;
$outEnc = openssl_encrypt($data, "AES-256-CBC", $key, OPENSSL_RAW_DATA, $iv);
return base64_encode($outEnc);
}
但显示不同的结果。我错过了什么
(相同类型的问题可在StackOverflow,但指出我的问题)
有以下问题:
- 在PHP代码中,当前返回的键是十六进制编码。相反,它必须作为字节串返回。为此,必须将
hash()
中的第三个参数从false
切换为true
。 - Java代码中使用192位密钥,即AES-192。因此,在PHP代码中必须应用
"AES-192-CBC"
(而不是"AES-256-CBC"
)。 - PHP代码中的
utf8_encode()
调用将被删除,因为这会破坏密钥。
通过这些更改,两个代码提供相同的密文。
安全性:
使用SHA256作为密钥派生是不安全的。相反,可以使用专用算法,如Argon2或PBKDF2。此外,使用密钥(或它的一部分)作为IV是不安全的,因为它会导致密钥/IV对的重用。相反,应该对每个加密应用随机生成的IV。