问题描述
我最近遇到了一种情况,在这种情况下,我需要使用这样的预定义String
密钥在 iOS 和 Android 之间进行 256-AES 跨平台加密/解密PreDefinedKey
。
AES 实现是在 iOS 上使用此代码完成的,我需要做的就是更改 Android 上的代码,以便我可以进行“跨平台”加密/解密。
注意:我知道 iOS 上的 AES 代码存在严重的安全/内存问题,但目前我不关心 :-)
我能够分别在 Android 和 iOS 上进行加密/解密。然而,这里的两个 AES 实现似乎有一个微不足道的差异,这阻止了我进行“跨平台”加密/解密。例如,我将 Android 加密的 String 放到 iOS 中,它无法返回预期的结果(在这种情况下,它返回 null)。
问题:
AES/ECB/PKCS7Padding
在 iOS 和 Android 平台上,我确信算法是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 位?
如果您需要更多信息,请告诉我。谢谢!