我已经实现了两个加密/解密数据的功能 在服务器(PHP)和客户端(Android应用程序)之间传输。 虽然两个键都相同,但我得到了完全不同的结果 从功能。有什么问题?
JAVA(Android Studio功能):
public static String encryptString(String string, String key){
try {
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(string.getBytes());
return Base64.encodeToString(encrypted, Base64.URL_SAFE);
} catch(Exception e){
return e.getMessage();
}
}
private static String decryptString(String string, String key){
try {
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(string.getBytes());
return Base64.decode(decrypted, Base64.DEFAULT ).toString();
} catch(Exception e){
return null;
}
}
PHP函数:
function fnEncrypt($sValue, $sSecretKey){
return rtrim(
base64_encode(
mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
$sSecretKey, $sValue,
MCRYPT_MODE_ECB,
mcrypt_create_iv(
mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_256,
MCRYPT_MODE_ECB
),
MCRYPT_RAND)
)
), "\0"
);
}
function fnDecrypt($sValue, $sSecretKey){
return rtrim(
mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
$sSecretKey,
base64_decode($sValue),
MCRYPT_MODE_ECB,
mcrypt_create_iv(
mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_256,
MCRYPT_MODE_ECB
),
MCRYPT_RAND
)
), "\0"
);
}
答案 0 :(得分:2)
在初始化字符串中未明确指定默认选项(填充,模式)时,很难说明这些选项是什么:Cipher.getInstance("AES")
。
AES的块大小为128.bits,因此您需要将其调整为mcrypt:MCRYPT_RIJNDAEL_128。 MCRYPT_RIJNDAEL_256不是AES。
一个可靠的假设是Java正在使用PKCS#5(实际上是PKCS#7 for AES)填充。但是mcrypt不支持PKCS#5(或PKCS#7)填充,只有空填充和空填充不能用于二进制数据。
最好的解决方案是明确指定Java填充和模式,php代码指定ECB(这是不安全的)。 Java字符串可能应该是:“AES / ECB / PKCS5Padding(128)”see Cipher docs。然后为mcrypt添加PKCS#7填充到要加密的数据并在解密后删除。见PKCS padding
为什么不使用:ECB mode,向下滚动到企鹅。