2013-03-13 138 views
6

我正試圖在Android上實現AES128加密。我有一個解決方案,使用Objective C工作在iPhone上,但無法將其移植到Android。我已經搜索了一個解決方案的stackoverflow,但我似乎做錯了什麼。我對Java相當陌生,所以我想我錯過了一些與數據,字符串轉換有關的事情。Android AES 128加密

這裏是我的iPhone加密:

char keyPtr[kCCKeySizeAES128+1]; 
[keyString getCString:keyPtr 
      maxLength:sizeof(keyPtr) 
      encoding:NSASCIIStringEncoding]; 

// CString for the plain text 
char plainBytes[[plainString length]+1]; 
[plainString getCString:plainBytes 
       maxLength:sizeof(plainBytes) 
       encoding:NSASCIIStringEncoding]; 

size_t bytesEncrypted = 0; 

// Allocate the space for encrypted data 
NSUInteger dataLength = [plainString length]; 
size_t bufferSize = dataLength + kCCBlockSizeAES128; 
void* buffer = malloc(bufferSize); 

// Encrypt 
CCCryptorStatus ret = CCCrypt(kCCEncrypt, 
           kCCAlgorithmAES128, 
           kCCOptionPKCS7Padding | kCCOptionECBMode, 
           keyPtr, 
           kCCKeySizeAES128, 
           NULL, 
           plainBytes, sizeof(plainBytes), 
           buffer, bufferSize, 
           &bytesEncrypted); 
if (ret != kCCSuccess) { 
    free(buffer); 
} 

encryptedData = [NSData dataWithBytes:buffer length:bytesEncrypted]; 

這裏是我的Java:

SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); 
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); 
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
    byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8")); 

使用相同的密鑰和明文的iPhone和Java給出不同的結果。我的iPhone結果以我需要的方式工作,所以我試圖讓java給我iPhone結果。我在Java中遺漏了一些東西,只是不確定它是什麼。

編輯

基於下面的建議我修改我的Java這個

byte[] keyBytes = plainTextKey.getBytes("US-ASCII"); 
    SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES"); 
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); 
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
    byte[] encrypted = cipher.doFinal(plainText.getBytes("US-ASCII")); 

但我仍然除了編碼獲得Android和iPhone

+3

你的編碼是明文不同。 Android使用UTF8,iPhone使用ASCII。 – vcsjones 2013-03-13 16:08:21

+1

作爲一個方面說明,我會勸阻你的密碼模式使用ECB(除非你試圖保持與已經使用它的系統的兼容性)。它使得識別加密數據中的模式變得相當容易。 – vcsjones 2013-03-13 16:10:49

+0

感謝vcsjones,我已將代碼更新爲plainText.getBytes(「ASCII」),但結果仍然不同 – Pabs 2013-03-13 16:37:58

回答

4

之間不同的結果您的明文存在困難(如註釋中指出的vcsjones),請確保密鑰字符串的編碼相同(請注意,使用原始字符串,像密碼,直接作爲加密密鑰是壞消息,使用密碼派生函數,如密碼中的PBKDF2來獲得密鑰)。

此外,用於ASCII的Java編碼字符串是US-ASCII,而不僅僅是ASCII,因此請確保在getBytes調用中使用該編碼字符串。

編輯:發現你的問題:iOS字符串在最後加上一個額外的空字符(0x00),而java不是。因此,在java中加密「hello world \ 0」會給你輸出與「你好世界」在iOS中一樣的輸出

+0

感謝您的提示,我完全錯過了「US-ASCII」。不幸的是問題仍然是一樣的。我瞭解EBC的問題,但在這種特殊情況下,我需要使用它。我也更新了代碼,使用「US-ASCII」既明文和密鑰,但仍然是相同的結果。 – Pabs 2013-03-13 17:40:37

+0

@Pabs看到我的編輯 - 我想通了你的問題 – 2013-03-13 18:35:58

+0

甜蜜!感謝彼得,這完美無缺! – Pabs 2013-03-13 19:51:19

0

因特網上的大多數例子都是AES的弱執行。爲了實現強壯,應隨時使用隨機IV,密鑰應該散列。

更安全(隨機IV +哈希鍵)跨平臺(Android,iOS設備的C#)實現AES的在這裏看到我的回答 - https://stackoverflow.com/a/24561148/2480840