Đây là trang đầu tiên xuất hiện thông qua Google và các lỗ hổng bảo mật trong tất cả các triển khai khiến tôi chùn bước nên tôi đăng bài này để thêm thông tin liên quan đến mã hóa cho người khác vì đã 7 năm kể từ bài đăng gốc. Tôi có bằng Thạc sĩ về Kỹ thuật Máy tính và dành nhiều thời gian để học và học Mật mã, vì vậy tôi sẽ ném hai xu của mình để biến internet thành một nơi an toàn hơn.
Ngoài ra, xin lưu ý rằng rất nhiều triển khai có thể an toàn cho một tình huống nhất định, nhưng tại sao lại sử dụng chúng và có khả năng vô tình mắc lỗi? Sử dụng các công cụ mạnh nhất bạn có sẵn trừ khi bạn có lý do cụ thể không. Nhìn chung, tôi khuyên bạn nên sử dụng một thư viện và tránh xa các chi tiết khó chịu nếu bạn có thể.
CẬP NHẬT 4/5/18: Tôi viết lại một số phần để đơn giản hơn để hiểu và thay đổi thư viện được đề xuất từ Jasypt sang thư viện mới của Tink , tôi khuyên bạn nên xóa hoàn toàn Jasypt khỏi thiết lập hiện có.
Lời tựa
Tôi sẽ phác thảo những điều cơ bản về mật mã đối xứng an toàn dưới đây và chỉ ra những lỗi phổ biến tôi thấy trực tuyến khi mọi người tự mình thực hiện tiền điện tử với thư viện Java tiêu chuẩn. Nếu bạn muốn bỏ qua tất cả các chi tiết chạy đến thư viện mới của Google, hãy nhập vào dự án của bạn và sử dụng chế độ AES-GCM cho tất cả các mã hóa của bạn và bạn sẽ được an toàn.
Bây giờ nếu bạn muốn tìm hiểu các chi tiết nghiệt ngã về cách mã hóa trong java, hãy đọc tiếp :)
Mật mã khối
Điều đầu tiên trước tiên bạn cần chọn một khóa Mã hóa đối xứng. Mã hóa khối là một chức năng / chương trình máy tính được sử dụng để tạo Giả ngẫu nhiên. Giả ngẫu nhiên là tính ngẫu nhiên giả mà không có máy tính nào ngoài Máy tính lượng tử có thể cho biết sự khác biệt giữa nó và tính ngẫu nhiên thực. Mật mã khối giống như khối xây dựng thành mật mã, và khi được sử dụng với các chế độ hoặc sơ đồ khác nhau, chúng ta có thể tạo mã hóa.
Bây giờ liên quan đến Thuật toán mã hóa khối có sẵn ngày hôm nay, Hãy chắc chắn KHÔNG BAO GIỜ , tôi lặp lại KHÔNG BAO GIỜ sử dụng DES , thậm chí tôi sẽ nói KHÔNG BAO GIỜ sử dụng 3DES . Mã hóa khối duy nhất mà ngay cả bản phát hành NSA của Snowden cũng có thể xác minh là thực sự gần với Pseudo-Random nhất có thể là AES 256 . Ngoài ra còn có AES 128; sự khác biệt là AES 256 hoạt động trong các khối 256 bit, trong khi AES 128 hoạt động trong 128 khối. Nói chung, AES 128 được coi là an toàn mặc dù một số điểm yếu đã được phát hiện, nhưng 256 vẫn vững chắc như nó có.
Sự thật thú vị DES đã bị NSA phá vỡ khi nó được thành lập ban đầu và thực sự giữ bí mật trong một vài năm. Mặc dù một số người vẫn cho rằng 3DES là an toàn, nhưng có khá nhiều tài liệu nghiên cứu đã tìm thấy và phân tích điểm yếu trong 3DES .
Chế độ mã hóa
Mã hóa được tạo khi bạn lấy một mật mã khối và sử dụng một sơ đồ cụ thể để tính ngẫu nhiên được kết hợp với một khóa để tạo ra thứ gì đó có thể đảo ngược miễn là bạn biết khóa. Điều này được gọi là Chế độ mã hóa.
Dưới đây là một ví dụ về chế độ mã hóa và chế độ đơn giản nhất được gọi là ECB để bạn có thể hiểu trực quan những gì đang xảy ra:
Các chế độ mã hóa bạn sẽ thấy phổ biến nhất trên mạng là như sau:
TLB ECB, CBC, GCM
Có tồn tại các chế độ khác bên ngoài các chế độ được liệt kê và các nhà nghiên cứu luôn làm việc hướng tới các chế độ mới để cải thiện các vấn đề hiện có.
Bây giờ hãy chuyển sang triển khai và những gì an toàn. KHÔNG BAO GIỜ sử dụng ECB, điều này rất tệ trong việc ẩn dữ liệu lặp lại như được hiển thị bởi chim cánh cụt Linux nổi tiếng .
Khi triển khai trong Java, lưu ý rằng nếu bạn sử dụng mã sau đây, chế độ ECB được đặt theo mặc định:
Cipher cipher = Cipher.getInstance("AES");
... NGUY HIỂM NÀY LÀ MỘT VULNH VIỄN! và thật không may, điều này được nhìn thấy trên khắp StackOverflow và trực tuyến trong các hướng dẫn và ví dụ.
Nonces và IV
Để đối phó với vấn đề được tìm thấy với chế độ ECB, thông báo còn được gọi là IV đã được tạo. Ý tưởng là chúng tôi tạo ra một biến ngẫu nhiên mới và gắn nó vào mọi mã hóa để khi bạn mã hóa hai tin nhắn giống nhau, chúng sẽ xuất hiện khác nhau. Vẻ đẹp đằng sau điều này là IV hoặc nonce là kiến thức công cộng. Điều đó có nghĩa là kẻ tấn công có thể có quyền truy cập vào điều này nhưng miễn là họ không có chìa khóa của bạn, họ không thể làm gì với kiến thức đó.
Các vấn đề phổ biến tôi sẽ thấy là mọi người sẽ đặt IV làm giá trị tĩnh như trong cùng một giá trị cố định trong mã của họ. và đây là cạm bẫy đối với IV ngay khi bạn lặp lại một lần bạn thực sự thỏa hiệp toàn bộ bảo mật mã hóa của bạn.
Tạo IV ngẫu nhiên
SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
Lưu ý: SHA1 bị hỏng nhưng tôi không thể tìm thấy cách triển khai SHA256 vào trường hợp sử dụng này một cách chính xác, vì vậy nếu bất cứ ai muốn có một bản crack tại đây và cập nhật thì thật tuyệt vời! Ngoài ra các cuộc tấn công SHA1 vẫn còn độc đáo vì có thể mất vài năm trên một cụm lớn để phá vỡ. Kiểm tra chi tiết tại đây.
Thực hiện TLB
Không có phần đệm được yêu cầu cho chế độ CTR.
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
Triển khai CBC
Nếu bạn chọn triển khai Chế độ CBC, hãy thực hiện với PKCS7Padding như sau:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
Lỗ hổng CBC và CTR và Tại sao bạn nên sử dụng GCM
Mặc dù một số chế độ khác như CBC và CTR được bảo mật, chúng vẫn gặp phải vấn đề trong đó kẻ tấn công có thể lật dữ liệu được mã hóa, thay đổi giá trị của nó khi được giải mã. Vì vậy, giả sử bạn mã hóa một tin nhắn ngân hàng tưởng tượng "Bán 100", tin nhắn được mã hóa của bạn trông giống như "eu23ng", kẻ tấn công thay đổi một bit thành "eu53ng" và bất ngờ khi giải mã tin nhắn của bạn, nó đọc là "Bán 900".
Để tránh điều này, phần lớn internet sử dụng GCM và mỗi khi bạn thấy HTTPS thì có lẽ họ đang sử dụng GCM. GCM ký tin nhắn được mã hóa bằng hàm băm và kiểm tra để xác minh rằng tin nhắn không bị thay đổi khi sử dụng chữ ký này.
Tôi sẽ tránh thực hiện GCM vì sự phức tạp của nó. Bạn nên sử dụng thư viện mới của Googles Tink bởi vì ở đây một lần nữa nếu bạn vô tình lặp lại IV, bạn đang làm tổn hại khóa trong trường hợp với GCM, đó là lỗ hổng bảo mật tối thượng. Các nhà nghiên cứu mới đang làm việc theo hướng IV lặp lại các chế độ mã hóa trong đó ngay cả khi bạn lặp lại IV, khóa vẫn không gặp nguy hiểm nhưng điều này vẫn chưa trở thành xu hướng.
Bây giờ nếu bạn muốn thực hiện GCM, đây là một liên kết đến một triển khai GCM đẹp . Tuy nhiên, tôi không thể đảm bảo an ninh hoặc nếu nó được thực hiện đúng nhưng nó làm giảm cơ sở. Cũng lưu ý với GCM không có phần đệm.
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
Phím vs Mật khẩu
Một lưu ý rất quan trọng khác là khi nói về mật mã, Khóa và Mật khẩu không giống nhau. Khóa trong mật mã cần phải có một lượng entropy và tính ngẫu nhiên nhất định để được coi là an toàn. Đây là lý do tại sao bạn cần đảm bảo sử dụng các thư viện mật mã phù hợp để tạo khóa cho bạn.
Vì vậy, bạn thực sự có hai triển khai bạn có thể làm ở đây, đầu tiên là sử dụng mã được tìm thấy trên luồng StackOverflow này để tạo khóa ngẫu nhiên . Giải pháp này sử dụng trình tạo số ngẫu nhiên an toàn để tạo khóa từ đầu mà bạn có thể sử dụng.
Tùy chọn kém an toàn khác là sử dụng, nhập liệu của người dùng như mật khẩu. Vấn đề như chúng ta đã thảo luận là mật khẩu không có đủ entropy, vì vậy chúng ta sẽ phải sử dụng PBKDF2 , một thuật toán lấy mật khẩu và củng cố nó. Đây là một triển khai StackOverflow tôi thích . Tuy nhiên, thư viện Google Tink có tất cả những thứ này được tích hợp sẵn và bạn nên tận dụng nó.
Nhà phát triển Android
Một điểm quan trọng cần chỉ ra ở đây là biết rằng mã Android của bạn có thể thiết kế ngược và hầu hết các trường hợp hầu hết mã java cũng vậy. Điều đó có nghĩa là nếu bạn lưu trữ mật khẩu bằng văn bản đơn giản trong mã của bạn. Một hacker có thể dễ dàng lấy nó. Thông thường, đối với các loại mã hóa này, bạn muốn sử dụng Mật mã bất đối xứng, v.v. Điều này nằm ngoài phạm vi của bài này vì vậy tôi sẽ tránh đi sâu vào nó.
Một bài đọc thú vị từ năm 2013 : Chỉ ra rằng 88% việc triển khai Crypto trong Android đã được thực hiện không đúng cách.
Suy nghĩ cuối cùng
Một lần nữa tôi đề nghị tránh trực tiếp triển khai thư viện java cho tiền điện tử và sử dụng Google Tink , điều này sẽ giúp bạn đỡ đau đầu vì họ đã thực sự làm tốt việc thực hiện đúng tất cả các thuật toán. Và thậm chí sau đó hãy chắc chắn rằng bạn kiểm tra các vấn đề được đưa ra trên github Tink, cửa sổ bật lên lỗ hổng ở đây và đó.
Nếu bạn có bất kỳ câu hỏi hoặc phản hồi hãy bình luận! Bảo mật luôn thay đổi và bạn cần cố gắng hết sức để theo kịp nó :)