問題描述
我最近遇到一種情況,這種情況下,我需要做一個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