Jika Anda ingin angka acak kriptografis kuat di Jawa, Anda gunakan SecureRandom
. Sayangnya, SecureRandom
bisa sangat lambat. Jika digunakan /dev/random
di Linux, ia dapat memblokir menunggu untuk membangun cukup entropi. Bagaimana Anda menghindari hukuman kinerja?
Adakah yang menggunakan Uncommon Maths sebagai solusi untuk masalah ini?
Adakah yang bisa mengkonfirmasi bahwa masalah kinerja ini telah diselesaikan di JDK 6?
Jawaban:
Jika Anda ingin data acak yang benar, maka sayangnya Anda harus menunggu untuk itu. Ini termasuk benih untuk
SecureRandom
PRNG. Matematika yang tidak umum tidak dapat mengumpulkan data acak yang sebenarnya lebih cepat dari ituSecureRandom
, meskipun dapat terhubung ke internet untuk mengunduh data unggulan dari situs web tertentu. Dugaan saya adalah bahwa ini tidak mungkin lebih cepat daripada/dev/random
yang tersedia.Jika Anda menginginkan PRNG, lakukan sesuatu seperti ini:
String apa yang didukung tergantung pada
SecureRandom
penyedia SPI, tetapi Anda dapat menghitungnya menggunakanSecurity.getProviders()
danProvider.getService()
.Sun menyukai SHA1PRNG, jadi itu tersedia secara luas. Ini tidak terlalu cepat seperti PRNG berjalan, tetapi PRNG hanya akan menjadi angka-angka, tidak menghalangi untuk pengukuran fisik entropi.
Pengecualiannya adalah bahwa jika Anda tidak menelepon
setSeed()
sebelum mendapatkan data, maka PRNG akan melakukan seeded sendiri setelah pertama kali Anda meneleponnext()
ataunextBytes()
. Biasanya akan melakukan ini menggunakan sejumlah kecil data acak benar dari sistem. Panggilan ini dapat memblokir, tetapi akan membuat sumber Anda nomor acak jauh lebih aman daripada varian "hash waktu saat ini bersama dengan PID, tambahkan 27, dan berharap yang terbaik". Namun, jika semua yang Anda butuhkan adalah angka acak untuk sebuah game, atau jika Anda ingin streaming diulangi di masa depan menggunakan seed yang sama untuk tujuan pengujian, seed yang tidak aman masih berguna.sumber
Anda harus dapat memilih / dev / urandom Linux yang lebih cepat tapi sedikit kurang aman menggunakan:
Namun, ini tidak berfungsi dengan Java 5 dan yang lebih baru ( Java Bug 6202721 ). Solusi yang disarankan adalah menggunakan:
(perhatikan tambahan
/./
)sumber
/dev/urandom
, Sun memperlakukan ini sebagai string ajaib dan menggunakan/dev/random
pula, jadi Anda harus memalsukannya. Kapanfile:
URL bukanfile:
URL? Setiap kali Sun memutuskan itu bukan :-(file:/dev/urandom
set in-Djava.security.egd
atau disecurerandom.source
file java.security,/dev/random/
masih dibaca kapan sajaSecureRandom.getSeed()
(atausetSeed()
dipanggil). Penanganannya denganfile:/dev/./urandom
hasil dalam tidak membaca/dev/random
sama sekali (dikonfirmasi dengan strace)/dev/urandom
tidak kalah aman daripada/dev/random
ketika diimplementasikan dengan CSPRNG modern: en.wikipedia.org/wiki//dev/random#FreeBSD/dev/urandom/
adalah apa yang terjadi jika Anda menggunakannya untuk menghasilkan rahasia pada perangkat keras baru di luar kotak, yang mungkin dalam keadaan yang cukup dapat diprediksi./dev/urandom/
tidak akan memblokir untuk entropi meskipun itu adalah satu kasus di mana Anda harus. Situasinya bahkan lebih buruk jika rahasianya persisten, seperti jika hal pertama yang dilakukan perangkat Anda saat boot pertama adalah menghasilkan pasangan kunci publik-swasta. Di luar dari situasi yang menakutkan itu, suatu kebaikan/dev/urandom
lebih baik daripada menggunakanSecureRandom
algoritma umum pula.Di Linux, implementasi default untuk
SecureRandom
adalahNativePRNG
(kode sumber di sini ), yang cenderung sangat lambat. Di Windows, defaultnya adalahSHA1PRNG
, yang seperti yang ditunjukkan orang lain dapat Anda gunakan di Linux jika Anda menentukannya secara eksplisit.NativePRNG
berbeda dariSHA1PRNG
dan AESCounterRNG Matematika yang Tidak Biasa dalam hal ia terus menerima entropi dari sistem operasi (dengan membaca dari/dev/urandom
). PRNG lain tidak memperoleh entropi tambahan setelah penyemaian.AESCounterRNG sekitar 10x lebih cepat daripada
SHA1PRNG
, yang IIRC itu sendiri dua atau tiga kali lebih cepat daripadaNativePRNG
.Jika Anda memerlukan PRNG yang lebih cepat yang memperoleh entropi setelah inisialisasi, lihat apakah Anda dapat menemukan implementasi Java dari Fortuna . PRNG inti dari implementasi Fortuna identik dengan yang digunakan oleh AESCounterRNG, tetapi ada juga sistem pengelompokan entropi yang canggih dan penanaman ulang otomatis.
sumber
Banyak distro Linux (kebanyakan berbasis Debian) mengkonfigurasi OpenJDK untuk digunakan
/dev/random
untuk entropi./dev/random
menurut definisi lambat (dan bahkan dapat memblokir).Dari sini Anda memiliki dua opsi tentang cara membuka blokir itu:
Opsi 1, Tingkatkan entropi
Untuk mendapatkan lebih banyak entropi
/dev/random
, cobalah daemon yang telah dirajut . Ini adalah daemon yang secara terus-menerus mengumpulkan entropi HAVEGE, dan berfungsi juga dalam lingkungan tervirtualisasi karena tidak memerlukan perangkat keras khusus, hanya CPU itu sendiri dan sebuah jam.Di Ubuntu / Debian:
Di RHEL / CentOS:
Opsi 2. Mengurangi persyaratan keacakan
Jika karena alasan tertentu solusi di atas tidak membantu atau Anda tidak peduli dengan keacakan yang kuat secara kriptografis, Anda dapat beralih ke sana
/dev/urandom
, yang dijamin tidak akan diblokir.Untuk melakukannya secara global, edit file
jre/lib/security/java.security
di instalasi Java default Anda untuk menggunakan/dev/urandom
(karena bug lain perlu ditentukan sebagai/dev/./urandom
).Seperti ini:
Maka Anda tidak perlu menentukannya di baris perintah.
Catatan: Jika Anda melakukan kriptografi, Anda perlu entropi yang baik. Contoh kasus - masalah PRNG android mengurangi keamanan dompet Bitcoin.
sumber
/dev/random
menurut definisi lambat (dan bahkan dapat memblokir)" salah; sepenuhnya tergantung pada konfigurasi sistem. Mesin yang lebih baru mungkin memiliki misalnya RNG cepat dalam CPU yang dapat digunakan, dan mesin BSD umumnya memiliki implementasi yang sama untuk/dev/random
dan/devl/urandom
. Namun, Anda mungkin tidak harus bergantung pada/dev/random
kecepatan, tentu saja. Pada VM, Anda mungkin ingin menginstal toolset klien pada VM klien sehingga dapat menggunakan RNG dari OS host.Saya memiliki masalah yang sama dengan panggilan untuk
SecureRandom
memblokir sekitar 25 detik pada server Debian tanpa kepala. Saya menginstalhaveged
daemon untuk memastikan/dev/random
disimpan di atas, pada server tanpa kepala Anda perlu sesuatu seperti ini untuk menghasilkan entropi yang diperlukan. Panggilan saya untukSecureRandom
sekarang mungkin membutuhkan milidetik.sumber
Jika Anda ingin keacakan yang benar-benar "kuat secara kriptografis", maka Anda memerlukan sumber entropi yang kuat.
/dev/random
lambat karena harus menunggu acara sistem untuk mengumpulkan entropi (disk membaca, paket jaringan, gerakan mouse, penekanan tombol, dll.).Solusi yang lebih cepat adalah generator nomor acak perangkat keras. Anda mungkin sudah memiliki satu bawaan untuk motherboard Anda; lihat dokumentasi hw_random untuk mengetahui cara mencari tahu jika Anda memilikinya, dan cara menggunakannya. Paket rng-tools termasuk daemon yang akan memasukkan perangkat keras yang dihasilkan ke dalam entropi
/dev/random
.Jika HRNG tidak tersedia di sistem Anda, dan Anda bersedia mengorbankan kekuatan entropi untuk kinerja, Anda akan ingin menyemai PRNG yang baik dengan data dari
/dev/random
, dan biarkan PRNG melakukan sebagian besar pekerjaan. Ada beberapa PRNG yang disetujui NIST yang terdaftar di SP800-90 yang mudah untuk diimplementasikan.sumber
Menggunakan Java 8, saya menemukan bahwa pada panggilan Linux
SecureRandom.getInstanceStrong()
akan memberi sayaNativePRNGBlocking
algoritma. Ini sering memblokir selama beberapa detik untuk menghasilkan beberapa byte garam.Saya beralih ke meminta secara eksplisit sebagai
NativePRNGNonBlocking
gantinya, dan seperti yang diharapkan dari namanya, itu tidak lagi diblokir. Saya tidak tahu apa implikasi keamanan dari ini. Mungkin versi non-pemblokiran tidak dapat menjamin jumlah entropi yang digunakan.Pembaruan : Oke, saya menemukan penjelasan yang sangat bagus .
Singkatnya, untuk menghindari pemblokiran, gunakan
new SecureRandom()
. Ini menggunakan/dev/urandom
, yang tidak memblokir dan pada dasarnya seaman/dev/random
. Dari pos: "Satu-satunya saat Anda ingin memanggil / dev / random adalah ketika mesin pertama kali boot, dan entropi belum terakumulasi".SecureRandom.getInstanceStrong()
memberi Anda RNG terkuat mutlak, tetapi itu hanya aman untuk digunakan dalam situasi di mana sekelompok pemblokiran tidak akan mempengaruhi Anda.sumber
getInstanceStrong()
kunci jangka panjang, seperti untuk sertifikat TLS. Dan bahkan kemudian saya lebih suka menggunakannew SecureRandom()
atau generator pasangan kunci yang sesuai FIPS atau generator nomor acak. Jadi ya, ini memberikan jawaban, jika/dev/urandom
tidak memblokir: pada akhirnya tetap bergantung pada entropi sistem; tapi itu saran yang sangat bagus secara umum . Jika/dev/urandom
blok, Anda mungkin harus memperbaiki sumber masalah daripada aplikasi Java Anda.Ada alat (setidaknya di Ubuntu) yang akan memberi makan keacakan buatan ke dalam sistem Anda. Perintahnya sederhana:
dan Anda mungkin perlu sudo di depan. Jika Anda tidak memiliki paket rng-tools, Anda harus menginstalnya. Saya mencoba ini, dan itu pasti membantu saya!
Sumber: matt vs dunia
sumber
sudo rngd -r /dev/urandom
dengansudo apt install rng-tools
dalam xenialSaya menghadapi masalah yang sama . Setelah beberapa Googling dengan istilah pencarian yang tepat, saya menemukan artikel bagus ini di DigitalOcean .
telah menjadi solusi potensial tanpa mengorbankan keamanan.
Saya hanya mengutip bagian yang relevan dari artikel di sini.
Cara memasang telah
Ikuti langkah-langkah di artikel ini. https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged
Saya telah mempostingnya di sini
sumber
Masalah yang Anda rujuk
/dev/random
bukan denganSecureRandom
algoritma, tetapi dengan sumber keacakan yang digunakannya. Keduanya orthogonal. Anda harus mencari tahu yang mana dari keduanya yang memperlambat Anda.Halaman Matematika yang tidak biasa yang Anda tautkan secara eksplisit menyebutkan bahwa mereka tidak membahas sumber keacakan.
Anda dapat mencoba berbagai penyedia JCE, seperti BouncyCastle, untuk melihat apakah implementasinya
SecureRandom
lebih cepat.Pencarian singkat juga mengungkapkan tambalan Linux yang menggantikan implementasi default dengan Fortuna. Saya tidak tahu banyak tentang ini, tetapi Anda dipersilakan untuk menyelidikinya.
Saya juga harus menyebutkan bahwa meskipun sangat berbahaya untuk menggunakan
SecureRandom
algoritma yang diimplementasikan dengan buruk dan / atau sumber keacakan, Anda dapat melempar Penyedia JCE Anda sendiri dengan implementasi kustomSecureRandomSpi
. Anda harus melalui proses dengan Sun untuk mendapatkan penyedia Anda ditandatangani, tetapi sebenarnya cukup mudah; mereka hanya perlu Anda mengirimi mereka faks formulir yang menyatakan bahwa Anda mengetahui pembatasan ekspor AS pada pustaka kripto.sumber
Gunakan acak aman sebagai sumber inisialisasi untuk algoritma berulang; Anda dapat menggunakan twister Mersenne untuk pekerjaan massal, bukan yang di UncommonMath, yang telah ada selama beberapa waktu dan terbukti lebih baik daripada prng lainnya.
http://en.wikipedia.org/wiki/Mersenne_twister
Pastikan untuk menyegarkan sekarang dan kemudian acak aman yang digunakan untuk inisialisasi, misalnya Anda dapat memiliki satu acak dihasilkan aman per klien, menggunakan satu generator acak semu mersenne twister per klien, memperoleh tingkat pengacakan yang cukup tinggi
sumber
Random
, tetapi tidak untukSecureRandom
.Menurut dokumentasi , berbagai algoritme yang digunakan oleh SecureRandom adalah, sesuai urutan preferensi:
Karena Anda bertanya tentang Linux, saya mengabaikan implementasi Windows, dan juga SunPKCS11 yang hanya benar-benar tersedia di Solaris, kecuali Anda menginstalnya sendiri - dan Anda tidak akan menanyakan hal ini.
Menurut dokumentasi yang sama, apa yang digunakan algoritma ini
SHA1PRNG
Penyemaian awal saat ini dilakukan melalui kombinasi atribut sistem dan perangkat pengumpulan entropi java.security.
NativePRNG
nextBytes()
menggunakan/dev/urandom
generateSeed()
kegunaan/dev/random
NativePRNGB mengunci
nextBytes()
dangenerateSeed()
menggunakan/dev/random
NativePRNGNonBlocking
nextBytes()
dangenerateSeed()
gunakan/dev/urandom
Itu berarti jika Anda menggunakan
SecureRandom random = new SecureRandom()
, itu turun daftar itu sampai menemukan yang berfungsi, yang biasanya NativePRNG. Dan itu berarti bahwa itu berasal dari/dev/random
(atau menggunakannya jika Anda secara eksplisit menghasilkan benih), lalu gunakan/dev/urandom
untuk mendapatkan byte, int, dobel, boolean berikutnya, apa-yang-Anda-miliki.Sejak
/dev/random
memblokir (itu memblokir sampai memiliki cukup entropi di kumpulan entropi), yang dapat menghambat kinerja.Salah satu solusi untuk itu adalah menggunakan sesuatu seperti ditempa untuk menghasilkan entropi yang cukup, solusi lain menggunakan
/dev/urandom
sebagai gantinya. Meskipun Anda bisa mengaturnya untuk seluruh jvm, solusi yang lebih baik adalah melakukannya untuk instance khusus iniSecureRandom
, dengan menggunakanSecureRandom random = SecureRandom.getInstance("NativePRNGNonBlocking")
. Perhatikan bahwa metode itu dapat melempar NoSuchAlgorithmException jika NativePRNGNonBlocking, jadi bersiaplah untuk mundur ke default.Perhatikan juga bahwa pada sistem * nix lain,
/dev/urandom
mungkin berperilaku berbeda .Apakah
/dev/urandom
cukup acak?Kebijaksanaan konvensional mengatakan bahwa hanya
/dev/random
cukup acak. Namun, beberapa suara berbeda. Dalam "Cara yang Tepat untuk Menggunakan SecureRandom" dan "Mitos tentang / dev / urandom" , dikatakan bahwa/dev/urandom/
itu sama baiknya.Para pengguna di tumpukan Keamanan Informasi setuju dengan itu . Pada dasarnya, jika Anda harus bertanya,
/dev/urandom
boleh saja untuk tujuan Anda.sumber
Saya sendiri belum menemukan masalah ini, tetapi saya akan menelurkan utas di awal program yang segera mencoba untuk menghasilkan benih, kemudian mati. Metode yang Anda panggil untuk tebusan akan bergabung ke utas itu jika masih hidup sehingga panggilan pertama hanya memblokir jika itu terjadi sangat awal dalam pelaksanaan program.
sumber
Pengalaman saya hanya dengan inisialisasi lambat dari PRNG, bukan dengan generasi data acak setelah itu. Coba strategi inisialisasi yang lebih bersemangat. Karena mahal untuk dibuat, perlakukan seperti singleton dan gunakan kembali contoh yang sama. Jika ada terlalu banyak pertikaian utas untuk satu contoh, kumpulkan atau buat mereka utas-lokal.
Jangan kompromi pada pembuatan angka acak. Kelemahan di sana membahayakan keamanan Anda.
Saya tidak melihat banyak generator berbasis peluruhan atom COTS, tetapi ada beberapa rencana di luar sana untuk mereka, jika Anda benar-benar membutuhkan banyak data acak. Salah satu situs yang selalu memiliki hal-hal menarik untuk dilihat, termasuk HotBits, adalah John Walker's Fourmilab.
sumber
SecureRandom
telah berubah beberapa kali dalam 10 tahun terakhir dalam pertemuan entropinya.SecureRandom
masih menjadi masalah, tetapi entropi rendah dalam suatu sistem akan selalu menjadi masalah. Menggunakan singleton akan membuat kode yang sangat berpasangan, yang merupakan desain anti-pola. Karena itu harus digunakan dengan sangat hati-hati; Anda sebaiknya membalik semua referensi dalam kode jika Anda akan memperbaiki masalah.Sepertinya Anda harus lebih jelas tentang persyaratan RNG Anda. Persyaratan RNG kriptografi terkuat (seperti yang saya mengerti) adalah bahwa bahkan jika Anda tahu algoritma yang digunakan untuk menghasilkan mereka, dan Anda tahu semua nomor acak yang dihasilkan sebelumnya, Anda tidak bisa mendapatkan informasi yang berguna tentang salah satu nomor acak yang dihasilkan dalam masa depan, tanpa menghabiskan jumlah daya komputasi yang tidak praktis.
Jika Anda tidak membutuhkan jaminan penuh keacakan ini, maka mungkin ada tradeoff kinerja yang sesuai. Saya cenderung setuju dengan tanggapan Dan Dyer tentang AESCounterRNG dari Uncommons-Maths, atau Fortuna (salah satu penulisnya adalah Bruce Schneier, seorang ahli kriptografi). Saya tidak pernah menggunakan keduanya tetapi ide-ide itu tampak memiliki reputasi baik pada pandangan pertama.
Saya pikir bahwa jika Anda dapat menghasilkan benih acak awal secara berkala (misalnya sekali per hari atau jam atau apa pun), Anda dapat menggunakan cipher aliran cepat untuk menghasilkan angka acak dari potongan aliran yang berurutan (jika cipher aliran menggunakan XOR maka hanya lewat aliran nol atau ambil bit XOR secara langsung). EStream ECRYPTproyek memiliki banyak informasi yang baik termasuk tolok ukur kinerja. Ini tidak akan mempertahankan entropi di antara titik-titik waktu yang Anda isi ulang, jadi jika seseorang tahu salah satu angka acak dan algoritma yang Anda gunakan, secara teknis dimungkinkan, dengan banyak daya komputasi, untuk memecahkan stream cipher dan tebak kondisi internal untuk dapat memprediksi angka acak di masa depan. Tetapi Anda harus memutuskan apakah risiko dan konsekuensinya cukup untuk membenarkan biaya mempertahankan entropi.
Sunting: inilah beberapa catatan mata kuliah kriptografis di RNG yang saya temukan di internet yang terlihat sangat relevan dengan topik ini.
sumber
Jika perangkat keras Anda mendukungnya coba gunakan Java RdRand Utility yang saya pembuatnya.
Ini didasarkan pada
RDRAND
instruksi Intel dan sekitar 10 kali lebih cepat daripadaSecureRandom
dan tidak ada masalah bandwidth untuk implementasi volume besar.Perhatikan bahwa implementasi ini hanya bekerja pada CPU yang memberikan instruksi (yaitu ketika
rdrand
flag prosesor diatur). Anda harus secara instantiate secara eksplisit melaluiRdRandRandom()
konstruktor; belum ada yang spesifik yangProvider
diterapkan.sumber
RDRAND
itu sumber yang bagus, tapi agak tidak bisa dipercaya. Pasti perlu menjadi salah satu masukan dari banyak orang menjadi seorang kolektor (jangan tersinggung oleh David Johnston).Sesuatu yang lain untuk dilihat adalah properti securerandom.source dalam file lib / security / java.security
Mungkin ada manfaat kinerja untuk menggunakan / dev / urandom daripada / dev / random. Ingat bahwa jika kualitas nomor acak itu penting, jangan buat kompromi yang merusak keamanan.
sumber