質問の説明
String
最近、このような事前定義されたキーを使用して、iOS と Android の間で 256-AES クロス プラットフォームの暗号化/復号化を行う必要がある状況に遭遇しましたPreDefinedKey
。
AES の実装は、このコードを使用して iOS で行われます。「クロスプラットフォーム」の暗号化/復号化を実行できるように、Android でコードを変更するだけです。
注: iOS の AES コードには重大なセキュリティ/メモリの問題があることは承知していますが、現時点では問題ではありません :-)
Android と iOS のいずれかで個別に暗号化/復号化を行うことができました。ただし、ここでの 2 つの AES 実装には些細な違いがあるようで、「クロスプラットフォーム」の暗号化/復号化を実行できませんでした。たとえば、Android で暗号化された文字列を iOS に配置すると、期待される結果が返されません (この場合は null が返されます)。
質問:
iOS と Android の両方のプラットフォームで、アルゴリズムは AES 実装のアルゴリズムであると確信していAES/ECB/PKCS7Padding
ます128-Rijndael
。
両方のプラットフォームで 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 ビットにパディングするためにゼロを使用します)。
では、このメソッドを変更して、事前に定義された文字列キーを使用できるようにするにはどうすればよいでしょうか。
さらに情報が必要な場合はお知らせください。どうも!