2012-08-14 46 views
13

Điều đầu tiên trước tiên. Một số thời gian trước, tôi cần một mã hóa AES đơn giản trong Android để mã hóa mật khẩu và gửi nó như một tham số cho dịch vụ web .net nơi mật khẩu được giải mã.Mã hóa AES trong iOS và Android và giải mã trong C# .NET

Sau đây là mã hóa Android của tôi:

private static String Encrypt(String text, String key) 
     throws Exception { 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     byte[] keyBytes= new byte[16]; 
     byte[] b= key.getBytes("UTF-8"); 
     int len= b.length; 
     if (len > keyBytes.length) len = keyBytes.length; 
     System.arraycopy(b, 0, keyBytes, 0, len); 
     SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); 
     IvParameterSpec ivSpec = new IvParameterSpec(keyBytes); 
     cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivSpec); 

     byte[] results = cipher.doFinal(text.getBytes("UTF-8")); 
     String result = Base64.encodeBytes(results); 
     return result; 
     } 

Và sau đó tôi đã giải mã nó trong C# với:

 public static string Decrypt(string textToDecrypt, string key) 
    { 
     System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); 

     RijndaelManaged rijndaelCipher = new RijndaelManaged(); 
     rijndaelCipher.Mode = CipherMode.CBC; 
     rijndaelCipher.Padding = PaddingMode.PKCS7; 

     rijndaelCipher.KeySize = 0x80; 
     rijndaelCipher.BlockSize = 0x80; 

     string decodedUrl = HttpUtility.UrlDecode(textToDecrypt); 
     byte[] encryptedData = Convert.FromBase64String(decodedUrl); 
     byte[] pwdBytes = Encoding.UTF8.GetBytes(key); 
     byte[] keyBytes = new byte[0x10]; 
     int len = pwdBytes.Length; 
     if (len > keyBytes.Length) 
     { 
      len = keyBytes.Length; 
     } 
     Array.Copy(pwdBytes, keyBytes, len); 
     rijndaelCipher.Key = keyBytes; 
     rijndaelCipher.IV = keyBytes; 
     byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length); 
     return encoding.GetString(plainText); 
    } 

này làm việc như một nét duyên dáng, nhưng những vấn đề đến khi tôi đã cố gắng để làm tương tự trong iOS. Tôi ứng dụng phát triển khá mới cho iphone/ipad, vì vậy ofcause Tôi googled nó, và hầu hết các mẫu mã được cung cấp là như sau:

- (NSData *)AESEncryptionWithKey:(NSString *)key { 
char keyPtr[kCCKeySizeAES128]; // room for terminator (unused) 
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

// fetch key data 
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

NSUInteger dataLength = [self length]; 

size_t bufferSize = dataLength + kCCBlockSizeAES128; 
void *buffer = malloc(bufferSize); 

size_t numBytesEncrypted = 0; 

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
             keyPtr, kCCKeySizeAES128, 
             NULL /* initialization vector (optional) */, 
             [self bytes], [self length], /* input */ 
             buffer, bufferSize, /* output */ 
             &numBytesEncrypted); 
if (cryptStatus == kCCSuccess) { 
    //the returned NSData takes ownership of the buffer and will free it on deallocation 
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; 
} 

free(buffer); //free the buffer; 
return nil; 

}

Có lẽ tôi là một chút quá lạc quan, khi tôi đã hy vọng cho một chuyển đổi suôn sẻ ở đây, bởi vì khi Android là ném cho tôi một cái gì đó như:

"EgQVKvCLS4VKLoR0xEGexA=="

thì iOS mang lại cho tôi:

"yP42c9gajUra7n0zSEuVJQ==" 

Hy vọng đó chỉ là điều tôi quên hoặc một số cài đặt sai?

[CẬP NHẬT] Kết quả hiện được hiển thị sau khi mã hóa base64.

+1

Phiên bản Android là chuỗi base64 được mã hóa URL bằng "YHH + gTxyIxvAx1cPFLcP0IEW2HcVHQVi9X11656CFsk =" '' (60 71 fe 81 3c 72 23 1b c0 c7 57 0f 14 b7 0f d0 81 16 d8 77 15 1d 05 62 f5 7d 75 eb 9e 82 16 c9) '. – Joe

+0

Woops, xin lỗi tôi quên đề cập đến điều đó. Tôi cũng đang mã hóa kết quả từ phiên bản iOS, chỉ trong một phương pháp khác, nhưng kết quả khác nhau trước khi mã hóa. – Morten

+0

Cập nhật câu hỏi để hiển thị kết quả sau khi mã hóa base64. Cùng một mật khẩu và cùng một khóa được sử dụng. – Morten

Trả lời

5

Lưu ý đầu tiên là bạn có vấn đề bảo mật quan trọng trong mã này. Bạn đang lấy một mật khẩu chuỗi và chỉ cần thả nó vào một khóa. Nếu chuỗi đó có thể đánh máy được, thì bạn đã hạn chế đáng kể keyspace của mình (biến AES-128 thành nhiều hơn như AES-40 hoặc AES-50, thậm chí còn tệ hơn). Bạn cần phải muối và kéo dài khóa bằng cách sử dụng PBKDF2. Xem Properly encrypting with AES with CommonCrypto để có cuộc thảo luận đầy đủ hơn.

Bạn cũng có vấn đề bảo mật quan trọng vì bạn đang sử dụng khóa làm IV của bạn (xem chi tiết bên dưới; đây thực sự là nguyên nhân gây ra triệu chứng của bạn). Đây không phải là cách chính xác để chọn một IV và làm cho bản mã của bạn có thể đoán trước được. Mã hóa rõ ràng được mã hóa bằng cùng một khóa sẽ cho kết quả tương tự. Điều này cũng tương tự như không có IV. IV cần phải là ngẫu nhiên. Xem liên kết ở trên để biết thêm thảo luận.

Bây giờ đến triệu chứng thực tế của bạn. Vấn đề là bạn đang sử dụng khóa như IV trong Java và C#, nhưng bạn đang sử dụng 0 (NULL) làm IV trên iOS (IV không phải là tùy chọn, bạn chỉ cần đi qua 0). Bạn cần sử dụng cùng một IV trong mọi trường hợp.

+0

Tôi biết có một số vấn đề bảo mật, nhưng nó chỉ là một giải pháp tạm thời. Đây chỉ là vấn đề sửa chữa nhanh, vì vậy chúng tôi không chuyển văn bản có thể đọc được, cho đến khi giải pháp cuối cùng của chúng tôi được thực hiện. Tôi thực sự không thể kiểm tra bất cứ điều gì ngay bây giờ, bởi vì nó là một vấn đề tại nơi làm việc, nhưng nếu tôi hiểu nó một cách chính xác, nó sẽ được sửa nếu tôi thay đổi như sau: Trong C# -decryption: rijndaelCipher.IV = X; Trong mã hóa Java: IvParameterSpec ivSpec = new IvParameterSpec (X); ... và thay đổi tham số NULL thành X, trong đó X ofcause có cùng giá trị? Nhân tiện, cảm ơn bạn rất nhiều vì câu trả lời của bạn ... – Morten

+0

Hiện tại "X" trong mã trên của bạn là bản sao khóa ở mọi nơi trừ iOS. Bạn có thể biến nó thành khóa trên iOS hoặc làm cho nó bằng 0 của C# và Java. Tôi sẽ không làm cho nó một số giá trị tĩnh (khác 0). –

+0

Được rồi, cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn. Tôi sẽ thử nó vào ngày mai, và đánh dấu câu trả lời của bạn là "chấp nhận" là tốt ... – Morten

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