Android的AES解密和数据的iOS:javax.crypto.BadPaddingException:垫块损坏 [英] Android AES decryption and data from iOS:javax.crypto.BadPaddingException: pad block corrupted
问题描述
我试图解密Android上的备份这是从的iOS
发,异常 javax.crypto.BadPaddingException:垫块损坏
是在表现方法doFinal。
公共字符串解密(字节[]的密文,SecretKey的关键,字节[] initialVector)抛出异常{
密密码= Cipher.getInstance(AES / CBC / PKCS7Padding);
IvParameterSpec ivParameterSpec =新IvParameterSpec(initialVector);
cipher.init(Cipher.DECRYPT_MODE,钥匙,ivParameterSpec);
密文= cipher.doFinal(密文); 返回新的String(密文,UTF-8);
}
键和initialVector从iOS版用base64字符串发送。相关code:
公共静态的byte []德codeWebSafe(String s)将抛出Base64De $ C $ {crException
字节[]字节= s.getBytes();
返回德codeWebSafe(字节,0,bytes.length);
}字节[] IV = Base64.de codeWebSafe(enciv);
字节[] =盐Base64.de codeWebSafe(encsalt);
字节[]数据= Base64.de codeWebSafe(encdata);
SecretKey的关键= Security.getExistingKey(口令,盐);
原字符串= aes.decrypt(数据,键,IV);
和有关Security.getExistingKey:
公共静态SecretKey的getExistingKey(字符串密码,字节[]盐)抛出异常{
SecretKey的关键= NULL;
KeySpec keySpec =新PBEKeySpec(password.toCharArray(),盐,10000,256);
SecretKeyFactory的KeyFactory = SecretKeyFactory.getInstance(PBKDF2WithHmacSHA1); 字节[] = keyBytes新的字节[32];
keyBytes = keyFactory.generateSecret(keySpec)根据.getEn codeD();
关键=新SecretKeySpec(keyBytes,AES); 返回键;
}
THX任何解决方案。
P.S.This是我们如何在iOS中设置的加密:
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
self.encryptionKey.bytes,kCCKeySizeAES128,
self.encryptionIV.bytes,[RAWDATA字节] DATALENGTH,
/ *输入* /缓冲区,缓冲区大小,/ *输出* /&安培; numBytesEncrypted);
键和IV推导方法:
(NSData的*)keyForPassword:(* NSString的)密码盐:(NSData的*)盐{
NSMutableData *
derivedKey = [NSMutableData dataWithLength:kCCKeySizeAES128];INT结果= CCKeyDerivationPBKDF(kCCPBKDF2,//算法
password.UTF8String,
password.length,
salt.bytes,//盐
salt.length,// saltLen
kCCPRFHmacAlgSHA1,// PRF
kPBKDFRounds,//发
derivedKey.mutableBytes,// derivedKey
derivedKey.length); // derivedKeyLen
}
我可以看到在路上几个不同你生成密钥:
- 在iOS上,16字节的键/生成128位;在Android的是256位。
- 在iOS上,密码为UTF-8 EN codeD而Android无论是采用低8位或每个字符的全16位(我不知道具体算法的细节)。
- 在iOS上,你传递无效长度的密码(字符数,而不是字节的UTF-8编码数)。
您更好地投入一些时间更好的相匹配的密钥生成和密钥解密前相比。
I tried to decrypt a backup on Android which is sent from iOS
, and the exception javax.crypto.BadPaddingException: pad block corrupted
is showed at method doFinal.
public String decrypt(byte[] cipherText, SecretKey key, byte [] initialVector) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
cipherText = cipher.doFinal(cipherText);
return new String(cipherText, "UTF-8");
}
The key and initialVector are sent from iOS in base64 string. Related code:
public static byte[] decodeWebSafe(String s) throws Base64DecoderException {
byte[] bytes = s.getBytes();
return decodeWebSafe(bytes, 0, bytes.length);
}
byte[] iv = Base64.decodeWebSafe(enciv);
byte[] salt = Base64.decodeWebSafe(encsalt);
byte[] data = Base64.decodeWebSafe(encdata);
SecretKey key = Security.getExistingKey(password, salt);
String original = aes.decrypt(data, key, iv);
And about the Security.getExistingKey:
public static SecretKey getExistingKey(String password, byte[] salt) throws Exception{
SecretKey key= null;
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 10000, 256);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes=new byte[32];
keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
key= new SecretKeySpec(keyBytes, "AES");
return key;
}
Thx for any solutions.
P.S.This is how we set the encryption in iOS:
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
self.encryptionKey.bytes, kCCKeySizeAES128,
self.encryptionIV.bytes, [rawData bytes], dataLength,
/* input */buffer, bufferSize, /* output */&numBytesEncrypted);
the key and IV derivation method:
(NSData *)keyForPassword:(NSString *)password salt:(NSData *)salt {
NSMutableData *
derivedKey = [NSMutableData dataWithLength:kCCKeySizeAES128];
int result = CCKeyDerivationPBKDF(kCCPBKDF2, // algorithm
password.UTF8String,
password.length,
salt.bytes, // salt
salt.length, // saltLen
kCCPRFHmacAlgSHA1, // PRF
kPBKDFRounds, // rounds
derivedKey.mutableBytes, // derivedKey
derivedKey.length); // derivedKeyLen
}
I can see several differences in the way you generate the key:
- In iOS, a key of 16 bytes / 128 bit is generated; in Android it's 256 bits.
- In iOS, the password is UTF-8 encoded while Android either takes the lower 8 bits or the full 16 bits of each characters (I don't know the details of the specific algorithm).
- In iOS, you pass an invalid length for the password (the number of characters instead the number of bytes in UTF-8 encoding).
You better invest some time in better matching the key generation and comparing the keys before decryption.
这篇关于Android的AES解密和数据的iOS:javax.crypto.BadPaddingException:垫块损坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!