Aplikasi Java dapat dan harus menggunakan kelas java.security.SecureRandom untuk menghasilkan nilai acak yang kuat secara kriptografis dengan menggunakan pseudo-random number generator ( CSPRNG ) yang kuat secara kriptografis . Implementasi JDK standar dari kelas java.util.Random tidak dianggap kuat secara kriptografis.
Sistem operasi seperti Unix memiliki /dev/random
, file khusus yang melayani nomor acak semu mengakses kebisingan lingkungan yang dikumpulkan dari driver perangkat dan sumber lainnya. Namun, itu memblokir jika ada lebih sedikit entropi yang tersedia daripada yang diminta ; /dev/urandom
biasanya tidak pernah memblokir, bahkan jika seed generator nomor pseudorandom tidak sepenuhnya diinisialisasi dengan entropi sejak booting. Masih ada file khusus ke-3, /dev/arandom
yang memblokir setelah boot sampai benih telah diinisialisasi dengan aman dengan cukup entropi, dan kemudian tidak pernah memblokir lagi.
Secara default, JVM menggunakan kelas SecureRandom/dev/random
, sehingga kode Java Anda dapat memblokir secara tidak terduga . Opsi -Djava.security.egd=file:/dev/./urandom
dalam permintaan baris perintah yang digunakan untuk memulai proses Java memberitahu JVM untuk menggunakannya /dev/urandom
.
Kelebihan tersebut /./
tampaknya membuat JVM menggunakan algoritma SHA1PRNG yang menggunakan SHA-1 sebagai dasar dari PRNG (Pseudo Random Number Generator). Ini lebih kuat dari algoritma NativePRNG yang digunakan saat /dev/urandom
ditentukan.
Akhirnya, ada mitos yang /dev/urandom
merupakan generator nomor acak semu, sebuah PRNG, sementara itu /dev/random
adalah generator nomor acak "benar" . Ini tidak benar, keduanya /dev/random
dan /dev/urandom
diberi makan oleh CSPRNG yang sama (generator nomor pseudorandom yang aman secara kriptografis). Hanya perilaku ketika kumpulan masing-masing kehabisan entropi, menurut beberapa perkiraan, berbeda: /dev/random
blok, sementara /dev/urandom
tidak.
Bagaimana dengan entropi yang hampir habis? Itu tidak masalah.
Ternyata "tampak acak" adalah persyaratan dasar untuk banyak blok bangunan kriptografi kami. Dan jika Anda mengambil output dari hash kriptografi, itu harus dibedakan dari string acak sehingga cipher akan menerimanya. Itulah alasan menggunakan algoritma SHA1PRNG, karena menggunakan fungsi hash dan penghitung, bersama dengan seed.
Kapan seharusnya diterapkan?
Saya selalu mengatakan demikian.
Sumber:
https://gist.github.com/svrc/5a8accc57219b9548fe1
https://www.2uo.de/myths-about-urandom
EDIT 04/2020:
Sebuah komentar menyebutkan perubahan perilaku kelas SecureRandom di Java 8.
SHA1PRNG dan NativePRNG diperbaiki untuk menghormati dengan benar properti sumber seed SecureRandom di file java.security. (Solusi tidak jelas menggunakan file: /// dev / urandom dan file: / dev /./ urandom tidak lagi diperlukan.)
Ini sudah ditunjukkan oleh tes yang dirujuk pada bagian Sumber di atas. Ekstra /./
diperlukan untuk mengubah algoritma yang digunakan oleh SecureRanom di Java 8 dari NativePRNG ke SHA1PRNG.
Namun, saya punya beberapa berita yang ingin saya bagikan. Sesuai JEP-273 , sejak Java 9 kelas SecureRandom mengimplementasikan tiga mekanisme Deterministic Random Bit Generator (DRBG) yang dijelaskan dalam NIST 800-90Ar1 . Mekanisme ini menerapkan algoritma modern sekuat SHA-512 dan AES-256.
JDK memiliki dua jenis implementasi SecureRandom :
- Satu tergantung platform dan didasarkan pada panggilan asli atau perangkat OS seperti membaca
/dev/{u}random
di Unix atau menggunakan CryptoAPI di Windows. Rilis terbaru dari Linux dan Windows sudah mendukung DRBG, tetapi rilis yang lebih lama dan sistem embedded mungkin tidak .
- Jenis lainnya adalah implementasi Java murni yang menggunakan implementasi RNG berbasis SHA1 yang lebih tua, yang tidak sekuat algoritma yang digunakan oleh mekanisme DRBG yang disetujui.
Sementara itu , Panduan Pengembang Keamanan Java 13 masih membaca
Di Linux dan macOS, jika perangkat pengumpulan entropi di java.security diatur ke file:/dev/urandom
atau file:/dev/random
, maka NativePRNG lebih disukai daripada SHA1PRNG. Kalau tidak, SHA1PRNG lebih disukai.
Untuk memperjelas bagaimana mekanisme DRBG baru bermain bersama dengan PRNG sebelumnya, saya menjalankan beberapa tes pada macOS (Darwin) dengan AdoptOpenJDK (build 13.0.2 + 8). Inilah hasilnya:
file: / dev / random
Urutan preferensi untuk penyedia:
SecureRandom.NativePRNG
SecureRandom.DRBG
SecureRandom.SHA1PRNG
file: / dev / urandom
Urutan preferensi untuk penyedia:
SecureRandom.NativePRNG
SecureRandom.DRBG
SecureRandom.SHA1PRNG
file: / dev /./ urandom
Urutan preferensi untuk penyedia:
SecureRandom.DRBG
SecureRandom.SHA1PRNG
SecureRandom.NativePRNG
Kesimpulan:
Saya akan merekomendasikan menggunakan -Djava.security.egd=file:/dev/./urandom
untuk memastikan memanfaatkan implementasi SecureRandom terkuat yang tersedia terlepas dari platform yang digunakan sambil menghindari kode diblokir secara tak terduga.