2012-11-16 47 views
8

Nhóm của tôi cần phát triển một giải pháp để mã hóa dữ liệu nhị phân (được lưu trữ dưới dạng byte[]) trong ngữ cảnh của một ứng dụng Android được viết bằng Java. Dữ liệu được mã hóa sẽ được truyền và lưu trữ theo nhiều cách khác nhau, trong đó dữ liệu bị hỏng không thể loại trừ được. Cuối cùng, một ứng dụng Android khác (viết lại bằng Java) sẽ phải giải mã dữ liệu.Mã hóa dữ liệu trên Android, AES-GCM hoặc AES thuần túy?

Nó đã được quyết định rằng thuật toán mã hóa phải là AES, với khóa 256 bit. Tuy nhiên, tôi muốn đưa ra quyết định sáng suốt về việc triển khai AES và/hoặc "chế độ" mà chúng tôi nên sử dụng. Tôi đã đọc về một cái gì đó gọi là chế độ GCM, và chúng tôi đã làm một số thử nghiệm với nó (sử dụng BouncyCastle/SpongyCastle), nhưng nó không phải là hoàn toàn rõ ràng với tôi chính xác AES-GCM là gì và những gì nó "mua" chúng tôi so với đồng bằng AES - và liệu có bất kỳ sự cân bằng nào được tính đến hay không.

Dưới đây là danh sách các mối quan tâm/yêu cầu/câu hỏi chúng ta có:

  • Padding: dữ liệu chúng tôi cần để mã hóa sẽ không luôn luôn là một bội số của 128 bit, do đó AES thực hiện/chế độ nên thêm đệm, nhưng chỉ khi cần thiết. Tôi đã ấn tượng rằng việc triển khai AES đơn giản, chẳng hạn như được cung cấp bởi javax.crypto.Cipher, sẽ không làm điều đó, nhưng các thử nghiệm ban đầu chỉ ra rằng nó thực hiện. Vì vậy, tôi đoán các yêu cầu padding trong chính nó là không có lý do để nghỉ mát để một cái gì đó như GCM thay vì "đồng bằng" AES. Đúng không?

  • Xác thực: Chúng tôi cần một cách dễ dàng để phát hiện xem có xảy ra hỏng hóc dữ liệu hay không. Tuy nhiên, lý tưởng nhất chúng tôi cũng muốn phát hiện khi giải mã được thử bằng khóa không chính xác. Do đó, chúng tôi muốn có thể phân biệt giữa cả hai trường hợp này. Lý do tôi kết thúc xem xét GCM ở vị trí đầu tiên là do Stackoverflow question, nơi một trong những người trả lời có vẻ ngụ ý rằng việc phân biệt này có thể sử dụng AES-GCM, mặc dù anh ta không cung cấp giải thích chi tiết.

  • Giảm thiểu chi phí: Chúng tôi cần giới hạn chi phí lưu trữ và truyền dữ liệu được mã hóa. Vì vậy, chúng tôi muốn biết liệu, và ở mức độ nào, lựa chọn cho việc triển khai/chế độ AES cụ thể ảnh hưởng đến lượng chi phí.

  • Encryption/giải mã hiệu: Mặc dù nó không phải là một mối quan tâm chính mà chúng tôi đang tự hỏi đến mức độ nào lựa chọn một thực hiện AES/chế độ ảnh hưởng mã hóa và giải mã hoạt động cụ thể, cả về thời gian CPU và bộ nhớ.

Cảm ơn trước cho bất kỳ lời khuyên, làm rõ và/hoặc ví dụ mã nào.

EDIT: delnan helpfully chỉ ra không có những điều như "đồng bằng AES". Vì vậy, để làm rõ, những gì tôi có nghĩa là bằng cách sử dụng hỗ trợ AES được xây dựng trong Java.
Giống như vậy: Cipher localCipher = Cipher.getInstance("AES");

+5

AES "đơn giản" là gì? Trừ khi bạn chỉ xử lý 256 bit dữ liệu. Nếu bạn có nhiều dữ liệu hơn thế, bạn nhất thiết phải sử dụng chế độ * some *. Có lẽ thư viện của bạn chọn một chế độ theo mặc định (từ những gì tôi đã nghe, nhiều thư viện thực hiện một lựa chọn khá không an toàn ở đây). Vì vậy, bạn nên kiểm tra chế độ nào thực sự được sử dụng khi bạn sử dụng "đồng bằng" AES. – delnan

+0

Cảm ơn bạn đã bình luận @delnan, tôi đã chỉnh sửa để làm rõ ý tôi. – Matthias

Trả lời

10

Năm 2012 câu trả lời là dành cho GCM, trừ khi bạn gặp sự cố tương thích nghiêm trọng.

GCM là chế độ Mã hóa được xác thực. Nó cung cấp cho bạn tính bảo mật (mã hóa), tính toàn vẹn và xác thực (MAC) trong một lần.

Cho đến nay, các chế độ hoạt động bình thường là ECB (là mặc định cho Java), CBC, CTR, OFB và một số loại khác. Họ chỉ cung cấp mã hóa. Tính bảo mật của chính nó hiếm khi hữu ích mà không có tính toàn vẹn; người ta phải kết hợp các chế độ cổ điển như vậy với kiểm tra tính toàn vẹn theo một cách đặc biệt. Vì mật mã khó đạt được đúng, thường thì các kết hợp như vậy không an toàn, chậm hơn cần thiết hoặc thậm chí cả hai.

Mã hóa được xác thực chế độ đã được (khá gần đây) được tạo bởi các nhà mã hóa để giải quyết vấn đề đó. GCM là một trong những thành công nhất: nó đã được chọn bởi NIST, nó hiệu quả, nó là bằng sáng chế miễn phí, và nó có thể mang theo Dữ liệu được xác thực bổ sung (tức là, dữ liệu vẫn ở trong rõ ràng, nhưng bạn có thể xác minh tính xác thực). Để biết mô tả về các chế độ khác, hãy xem this excellent article of Matthew Green.

Đến với mối quan tâm của bạn:

  • Padding: theo mặc định, Java sử dụng PKCS # 7 đệm. Điều đó có hiệu quả, nhưng nó thường dễ bị tổn thương bởi padding oracle attacks được đánh bại tốt nhất với MAC. GCM đã nhúng một MAC (gọi là GMAC).

  • Xác thực: AES-GCM chỉ nhận một khóa AES làm đầu vào chứ không phải mật khẩu. Nó sẽ cho bạn biết nếu khóa AES là sai hoặc tải trọng đã bị giả mạo, nhưng các điều kiện như vậy được coi là một. Thay vào đó, bạn nên cân nhắc sử dụng một thuật toán Key Derivation Algorithm thích hợp như PBKDF2 hoặc bcrypt để lấy được khóa AES từ mật khẩu. Tôi không nghĩ rằng nó luôn luôn có thể cho biết nếu mật khẩu là không chính xác hoặc nếu trọng tải đã được sửa đổi, bởi vì các dữ liệu cần thiết để xác minh trước đây luôn luôn có thể bị hỏng. Bạn có thể mã hóa một chuỗi nhỏ được biết đến (với ECB AES), gửi nó cùng và sử dụng nó để xác minh xem mật khẩu có đúng không.

  • Giảm thiểu chi phí: Vào cuối ngày, tất cả các chế độ dẫn đến cùng một mức phí (khoảng 10-20 byte) nếu bạn muốn xác thực. Trừ khi bạn đang làm việc với tải trọng rất nhỏ, điểm này có thể bị bỏ qua.

  • Hiệu suất: GCM là khá tốt ở chỗ nó là một trực tuyến chế độ (không cần phải đệm toàn bộ tải trọng, vì vậy ít bộ nhớ), nó là parallelizable, và nó đòi hỏi một hoạt động AES và một nhân Galois cho mỗi khối bản rõ. Các chế độ cổ điển như ECB nhanh hơn (chỉ một thao tác AES trên mỗi khối), nhưng - một lần nữa - bạn cũng phải tính đến logic toàn vẹn, điều này có thể sẽ chậm hơn GMAC.

Đã nói rằng, người ta phải biết rằng bảo mật GCM dựa vào một thế hệ số ngẫu nhiên tốt để tạo IV.

+0

Tôi vừa thử nghiệm một số mã Android bằng AES/EAX trên Jelly Bean 4.2. Nó thất bại ở đó với NoSuchAlgorithmException. Điều đó làm tôi ngạc nhiên. Có danh sách các thuật toán được hỗ trợ chính thức không? – tiguchi

+0

@ Nobu-game Bạn đã thử mã trong [security.SO] (http: //security.stackexchange.com/questions/5457/which-type-of-mã hóa-thuật toán-android-hỗ trợ-và-mà-sẽ-được-tốt hơn) câu trả lời? – SquareRootOfTwentyThree

+0

Tôi đã kết thúc bằng gói SpongyCastle. Bằng cách đó tôi biết rằng mã hóa của tôi sẽ chạy trên bất kỳ thiết bị Android nào. Nó chỉ khiến tôi cảnh giác rằng bản phát hành Android chính thức mới nhất đã loại bỏ thứ gì đó được chứa trong những cái cũ (tôi có thể sử dụng AES/EAX trên Samsung Galaxy S với Android 2.3 mà không có vấn đề gì). – tiguchi

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