![](/img/trans.png)
[英]Problem with decrypt String which is Encrypted in iOS AES/CBC/PKCS7Padding 128 bit Algorithm in Android
[英]Custom String padding with zeroes to 256-bit size key for AES/ECB/PKCS7Padding
我最近遇到了一种情况,在这种情况下,我需要使用预定义的String
密钥(如PreDefinedKey
在iOS和Android之间进行256-AES跨平台加密/解密。
AES实现是使用此代码在iOS上完成的,而我要做的就是更改Android上的代码,以便可以进行“跨平台”加密/解密。
注意:我知道iOS上的AES代码存在严重的安全性/内存问题,但是目前我不关心它:-)
我能够分别在Android和iOS上进行加密/解密。 但是,这里的两个AES实现似乎有微不足道的区别,这使我无法进行“跨平台”加密/解密。 例如,我将Android加密的String放入iOS,它无法返回预期的结果(在这种情况下,它返回null)。
题:
在iOS和Android平台上,我都可以确定算法是AES/ECB/PKCS7Padding
,其中128-Rijndael
算法用于AES实现。
两个平台都应使用256位大小的密钥。 通过深入了解iOS AES代码,我发现它实际上使用zeroes
将密钥填充到256位。
这是iOS上与零填充相关的代码段:
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
这是该代码中的AES参数(它使用Rijndael-128算法,256位密钥大小,初始向量为NULL):
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
但是在Android上,我不知道如何做类似的事情,所以有人可以为我指出正确的方法吗?
在Android平台上,我使用以下代码进行AES实现:
private static final String AES_SECRET = "PreDefinedKey";
/**
* Method for AES encryption
* @param raw
* @param plain
* @return
* @throws Exception
*/
private static byte[] encrypt(byte[] raw, byte[] plain) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES/ECB/PKCS7Padding");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(plain);
return encrypted;
}
/**
* AES decryption
* @param encryptMsg
* @return
* @throws Exception
*/
public static String AESDecrypt(String encryptMsg)
throws Exception {
byte[] rawKey = getRawKey(AES_SECRET.getBytes());
//byte[] enc = toByte(encryptMsg);
byte[] enc = Base64.decode(encryptMsg, 0);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
/**
* Method for AES decryption
* @param raw
* @param encrypted
* @return
* @throws Exception
*/
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(raw, "AES/ECB/PKCS7Padding");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
//Init for 256bit AES key
kgen.init(256);
SecretKey secret = kgen.generateKey();
//Get secret raw key
byte[] raw = secret.getEncoded();
return seed;
}
在getRawKey()
方法中,它使用SHA1PRNG
生成随机填充,以将AES密钥设置为256位大小,这与iOS实现不同(它使用零将密钥填充到256位)。
因此,如何更改此方法,以便可以使用预定义的字符串键(该键用零填充到256位)?
如果您需要更多信息,请告诉我。 谢谢!
查找谁想出了这个零填充方案并解雇了他们。 然后让该应用进行审核。
对于您的问题,只需创建一个长度为32的字节数组,然后将密钥字节复制到开头,然后使用它来初始化SecretKeySpec
。 KeyGenerator
将生成一个随机密钥,并且整个“固定种子”构想有缺陷,并且不适用于最新的Android版本。 这是一些代码:
// zeros by default
byte[] rawKey = new byte[32];
// if you don't specify the encoding you might get weird results
byte[] keyBytes = AES_SECRET.getBytes("ASCII");
System.arraycopy(keyBytes, 0, rawKey, 0, keyBytes.length);
SecretKey key = new SecretKeySpec(rawKey, "AES");
Cipher cipher = ...
// rest of your decryption code
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.