在 Android 中的 iOS AES/CBC/PKCS7Padding 128 位算法中加密的解密字符串的问题
Posted
技术标签:
【中文标题】在 Android 中的 iOS AES/CBC/PKCS7Padding 128 位算法中加密的解密字符串的问题【英文标题】:Problem with decrypt String which is Encrypted in iOS AES/CBC/PKCS7Padding 128 bit Algorithm in Android 【发布时间】:2020-08-24 07:34:10 【问题描述】:请指导我。我在解密由 ios“AES/CBC/PKCS7Padding”加密的字符串时遇到问题。它抛出异常。我想在android中解密字符串,在ios中加密。
在 Android 中,我遵循以下结构:
For Example:
String text = "rzp_test_DezQO1BVMXhkZY";
String key = "5b0904cfada01b8182bcc029b928244d"; // secret key - 128 bit key
String iv_key ="c999cbd1f130db1d";
我想加密和解密上面提到的“文本”字符串。如果我只从 Android 进行加密和解密。然后它工作正常。但是如果我试图解密在 ios 中加密的密钥,那么它会引发错误。
// Create key and cipher
Cipher dcipher, d1cipher;
IvParameterSpec ivSpec = new IvParameterSpec(iv_key.getBytes());
Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
dcipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
ecipher.init(ENCRYPT_MODE, aesKey, ivSpec);
dcipher.init(DECRYPT_MODE, aesKey, ivSpec);
加密算法:
public String encrypt(String str) throws Exception
// Encode the string into bytes using utf-8
byte[] utf8 = str.getBytes("UTF8");
// Encrypt
byte[] enc = ecipher.doFinal(utf8);
// Encode bytes to base64 to get a string
return Base64.encodeToString(enc, Base64.DEFAULT);
解密算法:
public String decrypt(String str) throws Exception
// Decode base64 to get bytes
String decrypted = "";
try
byte[] dec = Base64.decode(str, Base64.DEFAULT);
byte[] utf8 = dcipher.doFinal(dec);
// Decode using utf-8
decrypted = new String(utf8, "UTF8").trim();
catch (Exception e)
e.printStackTrace();
return decrypted;
它在 Android 中的加密和解密都可以正常工作。用这个检查:
String encrypted = encrypt(text);
System.out.println("Encrypted String: " + encrypted);
String decrypted = decrypt(encrypted);
System.out.println("Decrypted String: " + decrypted);
问题在于从 ios 解密以下加密字符串,这会引发错误:
String decrypted1 = decrypt("c7076c78fc5d9d92c1d86c1500dcc0366ddf1b6e32df00ceadc911239935460d");
System.out.println("Decrypted String1: " + decrypted1);
错误是:
W/System.err: javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
W/System.err: at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
W/System.err: at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:570)
W/System.err: at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:351)
W/System.err: at javax.crypto.Cipher.doFinal(Cipher.java:1741)
W/System.err: at com.example.aesencryption.Activities.MainActivity1.decrypt(MainActivity1.java:178)
有人可以指导我吗??
在IOS中:
使用以下函数。
func aesEncrypt() -> String
let iv: [UInt8] = Array(AES_IV.utf8)
let key: [UInt8] = Array(AES_SECRET.utf8)
do
let encrypted = try AES (key: key, blockMode: CBC(iv: iv)).encrypt([UInt8](self.data(using: .utf8)!))
return Data(encrypted).base64EncodedString()
catch
print("error on encrypting data ")
return ""
func aesDecrypt() -> String
let iv: [UInt8] = Array(AES_IV.utf8)
let key: [UInt8] = Array(AES_SECRET.utf8)
do
guard let data = Data(base64Encoded: self) else return ""
let decrypted = try AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7).decrypt([UInt8](data))
return String(bytes: decrypted, encoding: .utf8) ?? self
catch
print("error on encrypting data ")
return ""
【问题讨论】:
iOS 是否使用相同的PKCS7Padding
进行加密?
iOS 密文是十六进制编码的。但是,Android 代码中的 decrypt
需要 Base64 编码的字符串(因为 encrypt
Base64 对密文进行编码)。所以你有两种可能性:要么将 iOS 密文转换为 Base64,例如Base64.encodeToString(hexStringToByteArray("c707...460d"), Base64.DEFAULT);
和 hexStringToByteArray
来自 here 或者您相应地修改 Android 代码(以便也应用十六进制编码)。
另外,使用了 AES-256(而不是 AES-128)。
@RodrigoQueiroz 我添加了 iOS 算法。请看一看。
@topaco,我添加了 iOS 算法。请看一看。
【参考方案1】:
我通过以下方法得到了真正的字符串。
public static String decryptKey(String key_id)
// Decode base64 to get bytes
String decrypted = "";
try
Cipher dcipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
dcipher.init(DECRYPT_MODE, aesKey, ivSpec);
byte[] utf8 = dcipher.doFinal(hexToBytes(key_id));
// Decode using utf-8
decrypted = new String(utf8, "UTF8").trim();
catch (Exception e)
e.printStackTrace();
return decrypted;
public static byte[] hexToBytes(String str)
if (str == null)
return null;
else if (str.length() < 2)
return null;
else
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i = 0; i < len; i++)
buffer[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16);
return buffer;
【讨论】:
以上是关于在 Android 中的 iOS AES/CBC/PKCS7Padding 128 位算法中加密的解密字符串的问题的主要内容,如果未能解决你的问题,请参考以下文章
AES/CBC/PKCS5 填充 |替代 PHP OpenSSL 中的 mcrypt_get_block_size()
如何使用Javascript中的AES CBC零填充进行加密并使用Java进行解密
AES (aes-cbc-128, aes-cbc-192, aes-cbc-256) 使用 openssl C 加密/解密