问题描述
我最近遇到一种情况,这种情况下,我需要做一个256-AES跨平台的加密/ iOS和之间解密Android使用预定义的String
这样的密钥,如PreDefinedKey
。用零为AES/ECB 256位大小键自定义字符串填充/ PKCS7Padding
AES的实现是在iOS上完成的,使用this code,我需要做的就是更改Android上的代码,以便我可以执行“跨平台”加密/解密。
注:我知道的iOS上的AES代码有严重的安全/存储问题,但它目前不是我关心的:-)
我能够在做加密/解密无论是Android和iOS个人。但是,这里的两个AES实现似乎有一个微不足道的差别,这使得我无法进行“跨平台”的加密/解密。例如,我把Android加密的字符串放到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密钥达到与iOS实现不同的256位大小(它使用零填充密钥到256位)。
那么,我该如何改变这个方法,以便我可以使用我的预定义的字符串键填充零到256位?
如果您需要更多信息,请让我知道。谢谢!
很酷,我只是弹出并尝试你的方法,它工作!还有一个问题:我可能知道为什么(或如何)“固定大小”的东西不适用于最新的Android? – dumbfingers 2013-03-28 09:53:57
我的意思是'固定种子'。这里:http://android-developers.blogspot.jp/2013/02/using-cryptography-to-store-credentials.html – 2013-03-28 11:09:48
thx为链接:-) – dumbfingers 2013-03-28 11:23:10