Các ứng dụng Java có thể và nên sử dụng lớp java.security.SecureRandom để tạo ra các giá trị ngẫu nhiên mạnh về mặt mật mã bằng cách sử dụng trình tạo số giả ngẫu nhiên mã hóa mạnh ( CSPRNG ). Việc triển khai JDK tiêu chuẩn của lớp java.util.Random không được coi là mạnh về mặt mật mã.
Các hệ điều hành giống như Unix có /dev/random
, một tệp đặc biệt phục vụ các số ngẫu nhiên giả truy cập vào tiếng ồn môi trường được thu thập từ trình điều khiển thiết bị và các nguồn khác. Tuy nhiên, nó chặn nếu có ít entropy có sẵn hơn yêu cầu ; /dev/urandom
thường không bao giờ chặn, ngay cả khi hạt giống trình tạo số giả ngẫu nhiên không được khởi tạo hoàn toàn với entropy kể từ khi khởi động. Vẫn còn một tệp đặc biệt thứ 3, /dev/arandom
chặn sau khi khởi động cho đến khi hạt giống được khởi tạo an toàn với đủ entropy, và sau đó không bao giờ chặn nữa.
Theo mặc định, JVM khởi tạo lớp SecureRandom bằng cách sử dụng /dev/random
, do đó mã Java của bạn có thể chặn bất ngờ . Tùy chọn -Djava.security.egd=file:/dev/./urandom
trong lời gọi dòng lệnh được sử dụng để bắt đầu quá trình Java báo cho JVM sử dụng /dev/urandom
thay thế.
Phần bổ sung /./
dường như làm cho JVM sử dụng thuật toán SHA1PRNG sử dụng SHA-1 làm nền tảng của PRNG (Pseudo Random Number Generator). Nó mạnh hơn thuật toán NativePRNG được sử dụng khi /dev/urandom
được chỉ định.
Cuối cùng, có một huyền thoại /dev/urandom
là một trình tạo số ngẫu nhiên giả, PRNG, trong khi đó /dev/random
là một trình tạo số ngẫu nhiên đúng . Điều này chỉ đơn giản là không đúng sự thật, cả hai /dev/random
và /dev/urandom
được cung cấp bởi cùng một CSPRNG (trình tạo số giả ngẫu nhiên bảo mật bằng mật mã). Chỉ hành vi khi nhóm tương ứng của họ hết entropy, theo một số ước tính, khác nhau: /dev/random
khối, trong khi /dev/urandom
không.
Thế còn entropy sắp hết? Nó không thành vấn đề.
Nó chỉ ra rằng, việc tìm kiếm ngẫu nhiên là một yêu cầu cơ bản cho rất nhiều khối xây dựng mật mã của chúng tôi. Và nếu bạn lấy đầu ra của hàm băm mật mã, nó phải không thể phân biệt được với một chuỗi ngẫu nhiên để mật mã sẽ chấp nhận nó. Đó là lý do của việc sử dụng thuật toán SHA1PRNG, vì nó sử dụng hàm băm và bộ đếm, cùng với một hạt giống.
Khi nào được cho là sẽ được áp dụng?
Luôn luôn, tôi muốn nói.
Nguồn:
https://gist.github.com/aussc/5a8accc57219b9548fe1
https://www.2uo.de/myths-about-urandom
EDIT 04/2020:
Một nhận xét đề cập đến một sự thay đổi về hành vi của lớp SecureRandom trong Java 8.
SHA1PRNG và NativePRNG đã được sửa để tôn trọng đúng các thuộc tính nguồn gốc của SecureRandom trong tệp java.security. (Cách giải quyết tối nghĩa bằng cách sử dụng tệp: /// dev / urandom và tệp: / dev /./ urandom không còn cần thiết.)
Điều này đã được chỉ ra bởi các thử nghiệm được tham chiếu trên phần Nguồn ở trên. Phần bổ sung /./
được yêu cầu để thay đổi thuật toán được SecureRanom sử dụng trong Java 8 từ NativePRNG sang SHA1PRNG.
Tuy nhiên, tôi có một số tin tức mà tôi muốn chia sẻ. Theo JEP-273 , kể từ Java 9, lớp SecureRandom thực hiện ba cơ chế Trình tạo bit ngẫu nhiên xác định (DRBG) được mô tả trong NIST 800-90Ar1 . Các cơ chế này thực hiện các thuật toán hiện đại mạnh như SHA-512 và AES-256.
JDK có hai loại triển khai SecureRandom :
- Một là phụ thuộc vào nền tảng và dựa trên các cuộc gọi gốc hoặc thiết bị HĐH như đọc
/dev/{u}random
trên Unix hoặc sử dụng CryptoAPI trên Windows. Các bản phát hành mới nhất của Linux và Windows đã hỗ trợ DRBG, nhưng các bản phát hành cũ hơn và các hệ thống nhúng có thể không .
- Loại khác là một triển khai Java thuần túy sử dụng triển khai RNG dựa trên SHA1 cũ hơn, không mạnh bằng các thuật toán được sử dụng bởi các cơ chế DRBG được phê duyệt.
Trong khi đó , Hướng dẫn dành cho nhà phát triển bảo mật Java 13 vẫn đọc
Trên Linux và macOS, nếu thiết bị thu thập entropy trong java.security được đặt thành file:/dev/urandom
hoặc file:/dev/random
, thì NativePRNG được ưu tiên hơn SHA1PRNG. Mặt khác, SHA1PRNG được ưu tiên.
Để làm rõ cách các cơ chế DRBG mới chơi cùng với các PRNG trước đó, tôi chạy một số thử nghiệm trên macOS (Darwin) với AdoptOpenJDK (bản dựng 13.0.2 + 8). Đây là kết quả:
tệp: / dev / ngẫu nhiên
Thứ tự ưu tiên cho nhà cung cấp:
SecureRandom.NativePRNG
SecureRandom.DRBG
SecureRandom.SHA1PRNG
tệp: / dev / urandom
Thứ tự ưu tiên cho nhà cung cấp:
SecureRandom.NativePRNG
SecureRandom.DRBG
SecureRandom.SHA1PRNG
tệp: / dev /./ urandom
Thứ tự ưu tiên cho nhà cung cấp:
SecureRandom.DRBG
SecureRandom.SHA1PRNG
SecureRandom.NativePRNG
Phần kết luận:
Tôi khuyên bạn nên sử dụng -Djava.security.egd=file:/dev/./urandom
để đảm bảo tận dụng triển khai SecureRandom mạnh nhất có sẵn bất kể nền tảng được sử dụng trong khi tránh việc mã bị chặn bất ngờ.