2013-03-13 74 views
6

Tôi đang cố gắng triển khai mã hóa AES128 trên Android. Tôi đã có một giải pháp làm việc trên iPhone với Objective C nhưng gặp sự cố khi chuyển nó sang Android. Tôi đã tìm kiếm stackoverflow cho một giải pháp, nhưng tôi dường như đang làm điều gì đó sai trái. Tôi khá mới với Java vì vậy tôi nghĩ rằng tôi đang thiếu một cái gì đó để làm với dữ liệu, chuyển đổi chuỗi.Mã hóa AES 128 của Android

Đây là mã hóa iPhone của tôi:

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]; 

Đây là Java của tôi:

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")); 

Sử dụng cùng quan trọng và rõ trong iPhone và Java cho kết quả khác nhau. Kết quả iPhone của tôi hoạt động theo cách tôi cần nó vì vậy tôi đang cố gắng để có được java để cho tôi kết quả iPhone. Tôi đang thiếu một cái gì đó trong Java chắc chắn, chỉ cần không chắc chắn nó là gì.

chỉnh sửa

dựa trên gợi ý dưới đây tôi sửa đổi Java của tôi để này

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")); 

nhưng tôi vẫn nhận được kết quả khác nhau giữa Android và iPhone

+3

mã hóa của bạn là khác nhau đối với các văn bản gốc. Android đang sử dụng UTF8, iPhone đang sử dụng ASCII. – vcsjones

+1

Là một lưu ý phụ, tôi sẽ không khuyến khích sử dụng ECB cho chế độ mã hóa của bạn (trừ khi bạn đang cố gắng duy trì tính tương thích với một hệ thống đã sử dụng nó). Nó làm cho nó khá dễ dàng để phân biệt các mẫu trong dữ liệu được mã hóa. – vcsjones

+0

Cảm ơn vcsjones, tôi đã cập nhật mã của mình thành plainText.getBytes ("ASCII") nhưng kết quả vẫn khác nhau – Pabs

Trả lời

4

ngoài mã hóa khó khăn với bản rõ của bạn (như vcsjones chỉ ra trong các ý kiến), hãy chắc chắn rằng mã hóa là giống nhau cho chuỗi khóa (lưu ý rằng bằng cách sử dụng một chuỗi thô, giống như mật khẩu, trực tiếp dưới dạng khóa mật mã là gấu tin xấu, sử dụng một hàm dẫn xuất quan trọng như PBKDF2 trên mật khẩu để lấy được khóa).

Ngoài ra, chuỗi mã hóa cho Java cho ASCII là US-ASCII, không chỉ ASCII, do đó hãy đảm bảo sử dụng chuỗi đó trong các cuộc gọi getBytes của bạn.

EDIT: đã tìm thấy sự cố của bạn: chuỗi iOS đang được mã hóa với thêm charcter null (0x00) ở cuối, trong khi java thì không. Vì vậy, mã hóa "hello world \ 0" trong java sẽ cung cấp cho bạn kết quả tương tự như "hello world" trong iOS

+0

Cảm ơn những lời khuyên, tôi hoàn toàn bị mất "US-ASCII". tiếc là vấn đề vẫn như cũ.Tôi hiểu các vấn đề với EBC, nhưng trong trường hợp cụ thể này tôi cần phải sử dụng nó. Tôi cũng đã cập nhật mã để sử dụng "US-ASCII" cả bản rõ và khóa nhưng vẫn là kết quả tương tự. – Pabs

+0

@Pabs xem chỉnh sửa của tôi - tôi đã tìm ra sự cố của bạn –

+0

Ngọt ngào! Cảm ơn Peter, đã làm việc hoàn hảo! – Pabs

0

Hầu hết các ví dụ trên internet đều là triển khai yếu kém của AES. Để thực hiện được mạnh mẽ, IV ngẫu nhiên nên được sử dụng tất cả các thời gian và chìa khóa nên được băm.

Đối với an toàn hơn (ngẫu nhiên IV + phím băm) đa nền tảng (Android, iOS, C#) thực hiện AES xem câu trả lời của tôi ở đây - https://stackoverflow.com/a/24561148/2480840

Các vấn đề liên quan