Pembuat token acak

Menghasilkan rahasia dari CSPRNG peramban — heksadesimal, base64url, atau alfabet khusus, plus frasa-sandi diceware EFF — dengan entropi dalam bit.

Membuat…
Entropi192,0 bit

Waktu rata-rata untuk menemukannya, pada tiga laju tebakan. Sebaran di antaranya lebih besar daripada perbedaan apa pun yang dibuat rahasianya sendiri.

  • Terhadap login yang membatasi laju — 10 tebakan/dtk10^49 tahun
  • Terhadap hash lambat yang bocor (bcrypt, argon2) — 10⁴/dtk10^46 tahun
  • Terhadap hash cepat yang bocor (SHA-256, MD5) — 10¹²/dtk10^38 tahun

Mengambil dari 64 karakter, jadi masing-masing membawa 6,00 bit.

Apa yang dilakukan alat ini

Ia menghasilkan rahasia: nilai yang satu-satunya pertahanannya adalah tak ada yang bisa menebaknya. Pilih alfabet dan panjang untuk kunci API atau sandi basis data, atau beralih ke frasa-sandi yang diambil dari daftar kata yang diterbitkan untuk sesuatu yang harus diketik seseorang. Setiap hasil dibuat di peramban Anda dan ditampilkan dengan satu angka yang menjelaskan kekuatannya dengan jujur.

Ini adalah pekerjaan berbeda dari pembangkit UUID di situs ini. UUID harus unik, sehingga dua catatan tak pernah bertumbukan; rahasia harus tak-tertebak, yang merupakan syarat yang lebih kuat dan kegagalan yang berbeda. Pengenal yang dapat diprediksi tak berbahaya. Rahasia yang dapat diprediksi adalah pintu terbuka.

Dari mana keacakan datang

Semuanya di sini mengambil dari crypto.getRandomValues, pembangkit acak peramban yang aman secara kriptografis, yang dibenihi dari kolam entropi sistem operasi — sumber yang sama yang dipakai openssl rand dan /dev/urandom.

Alternatifnya, Math.random, bukan fungsi keamanan dan tak pernah mengklaim demikian. Ia adalah pembangkit pseudo-acak yang cepat dengan keadaan internal kecil, dan di setiap mesin saat ini keadaan itu bisa dipulihkan dari rangkaian pendek keluaran, setelahnya setiap nilai masa lalu dan masa depan diketahui. Token yang dibangun darinya tampak persis seacak token yang nyata; perbedaannya hanya muncul ketika seseorang repot-repot memeriksanya.

Pertanyaan yang masuk akal adalah apakah halaman web adalah tempat yang tepat untuk menghasilkan rahasia produksi sama sekali. Pembangkitannya sendiri kukuh: ia adalah CSPRNG platform, halamannya statis, dan tak ada yang dikirim. Bagian yang layak dipikirkan adalah yang di sekitarnya — rahasia yang melewati papan-klip bisa dibaca aplikasi lain, dan yang ditempel ke terminal biasanya mendarat di riwayat shell. Itu adalah pertimbangan yang sama dengan metode lain mana pun.

Bias yang bersembunyi dalam implementasi yang jelas

Mengubah bita acak menjadi karakter tampak seperti satu baris: ambil bita, ambil ia modulo ukuran alfabet, indeks ke dalam alfabet. Ia secara halus salah untuk setiap alfabet yang ukurannya tak membagi 256 secara rata, dan keluarannya tak memberi tanda apa pun.

Dengan 62 karakter alfanumerik, 256 tak membagi secara rata: 62 masuk ke 256 empat kali dengan 8 tersisa. Kedelapan nilai bita sisa itu — 248 sampai 255 — melipat kembali ke 8 karakter pertama alfabet, jadi masing-masing dari itu mendapat lima peluang dari 256 sementara sisanya mendapat empat. Kedelapan karakter pertama sekitar 25% lebih mungkin daripada yang lain.

Perbaikannya adalah pengambilan-penolakan: buang pengambilan yang mendarat di ekor sisa dan ambil lagi, ketimbang melipatnya kembali. Ia menelan sekitar satu pengambilan ekstra dalam tiga puluh dua untuk alfabet 62-karakter dan tak sama sekali untuk heksadesimal atau base64url, yang ukurannya adalah pangkat dua dan karenanya tak punya ekor. Alat ini menolak; efeknya tak terlihat dalam token tunggal mana pun, dan itulah persis alasan ia layak dinyatakan.

Entropi, satu-satunya ukuran yang jujur

Entropi dalam bit mengatakan seberapa besar ruang rahasia yang sama-sama mungkin: n bit berarti 2^n kemungkinan. Ia aditif dan mudah dibandingkan, dan ia tak mengatakan apa pun tentang seberapa cepat siapa pun bisa mencari ruang itu — yang merupakan fitur, karena bagian itu bergantung pada hal yang tak bisa diketahui pembangkit.

Aritmetikanya sengaja sederhana. Setiap karakter menyumbang log2(ukuran alfabet) bit, dan setiap kata menyumbang log2(ukuran daftar kata), jadi:

  • Karakter heksadesimal adalah 4 bit, jadi token heksadesimal 32-karakter persis 128 bit — kunci AES-128 yang ditulis penuh.
  • Karakter base64url adalah 6 bit, jadi 22 karakter melewati 128 bit dan 43 melewati 256.
  • Karakter alfanumerik sekitar 5,95 bit; mengecualikan yang mirip-rupa menjatuhkan alfabet ke 58 dan karakter ke 5,86, yang menelan kira-kira satu karakter panjang setiap enam puluh.
  • Kata dari daftar panjang EFF adalah 12,925 bit, karena daftar punya 7.776 entri, yaitu 6^5 — lima lemparan dadu.
  • Kata dari daftar pendek EFF adalah 10,34 bit, dari 1.296 entri, yaitu 6^4.

Target umum adalah 128 bit, yang adalah tempat brute force berhenti menjadi strategi ketimbang sekadar mahal. Itu adalah 32 karakter heksadesimal, 22 karakter base64url, atau 10 kata dari daftar panjang EFF.

Mengapa tak ada satu "waktu untuk memecahkan"

Rahasia tak punya waktu pemecahan. Pasangan rahasia dan apa pun yang menjaganya punya satu, dan penjaga itu jauh lebih penting daripada rahasianya. Nilai yang sama yang akan memakan lebih lama daripada umur alam semesta untuk ditemukan melalui formulir login jatuh dalam satu sore jika ia disimpan sebagai SHA-256 tanpa-salt dan basis data bocor.

Jadi tiga laju ditampilkan ketimbang satu angka, dan masing-masing dinamai:

  • Sepuluh tebakan sedetik, terhadap login yang membatasi laju. Ini adalah plafon realistis untuk seorang penyerang yang harus melewati layanan Anda.
  • Sepuluh ribu tebakan sedetik, terhadap hash sandi bocor yang dibangun agar lambat — bcrypt pada biaya modern, atau argon2. Kelambatan adalah seluruh inti fungsi itu.
  • Satu triliun tebakan sedetik, terhadap hash bocor yang tak pernah dimaksudkan untuk sandi. SHA-256 dan MD5 dirancang agar cepat, dan rig GPU memang sangat cepat.

Laju dibulatkan ke pangkat sepuluh secara sengaja. Apa pun yang lebih presisi akan mengesankan pengukuran atas satu penyerang tertentu, ketika informasi yang berguna adalah sebelas orde besaran antara baris pertama dan terakhir. Jika rahasia nyaman di ketiganya, pertanyaan terselesaikan tanpa perlu angka pastinya.

Setiap angka adalah rata-rata, yang berarti setengah ruang ketimbang seluruhnya — rata-rata pencarian menemukan jawabannya di tengah jalan. Dan melampaui sejuta tahun jawaban diberikan sebagai orde besaran, karena "empat ratus triliun tahun" bukan durasi yang bisa dibandingkan siapa pun. Alam semesta berusia sekitar 10^10 tahun, yang menjadi jangkar berguna untuk baris yang menjangkau sejauh itu.

Frasa-sandi, dan dari mana kekuatannya sebenarnya datang

Frasa-sandi kuat karena persis satu alasan: beberapa kata dipilih secara acak dari daftar besar. Ia tak kuat karena ia panjang, dan ia tak kuat karena ia tampak seperti bahasa. Enam kata acak dari daftar 7.776-kata sekitar 77 bit; enam kata yang seseorang pikirkan bernilai jauh lebih sedikit, karena orang tak memilih secara seragam dan seorang penyerang tahu hal yang sama tentang frasa umum seperti yang Anda tahu.

Kedua daftar di sini datang dari EFF dan merupakan daftar diceware yang diterbitkan, diunduh tanpa perubahan. Mereka bukan daftar yang dirakit di sini, dan itu penting: daftar kata yang seseorang ciptakan punya ukuran tak diketahui, tumpang-tindih tak diketahui dengan daftar lain, dan tak ada cara memeriksa klaim entropi yang dibuat tentangnya.

  • Daftar panjang punya 7.776 kata, satu untuk setiap lemparan lima dadu, dan memberi 12,925 bit per kata.
  • Daftar pendek punya 1.296 kata, satu untuk setiap lemparan empat dadu, dan memberi 10,34 bit per kata. Kata-katanya lebih pendek — tak ada yang lebih dari lima huruf — yang membuatnya lebih mudah diketik dengan biaya butuh lebih banyak kata untuk kekuatan yang sama.

Kata yang berulang dalam frasa-sandi bukan cacat dan tak dihasilkan ulang di sini. Setiap pengambilan mandiri, jadi pasangan kata tertentu mana pun persis sama mungkinnya dengan yang lain; menolak pengulangan akan menyusutkan ruang frasa-sandi yang mungkin dan membuatnya sedikit lebih lemah, bukan lebih kuat.

Kedua daftar EFF mengandung segelintir entri bertanda-hubung — t-shirt, yo-yo, drop-down, felt-tip. Jika pemisahnya juga tanda hubung, frasa-sandi yang mengandung salah satunya tak bisa dipecah kembali menjadi kata-katanya tanpa ambigu. Ia adalah masalah tampilan ketimbang keamanan, dan memilih spasi atau titik sebagai pemisah menghindarinya sepenuhnya.

Opsi yang menelan entropi, dan yang tidak

Mengecualikan karakter mirip-rupa menukar kekuatan demi keterbacaan, dan pertukarannya terlihat. Membuang 0, O, I, dan l menurunkan alfabet alfanumerik dari 62 karakter menjadi 58 — yang, persis, alfabet base58 yang dipakai Bitcoin, dan karena alasan yang sama. Setiap karakter jatuh dari 5,95 ke 5,86 bit, jadi token butuh sekitar satu karakter ekstra setiap enam puluh untuk tetap sama kuatnya. Itu biasanya sepadan untuk apa pun yang akan seseorang baca dari layar dan ketik di tempat lain.

Opsi ditawarkan hanya di tempat ia berarti sesuatu. Heksadesimal dan base64url adalah pengodean, bukan kumpulan karakter: alfabetnya ditetapkan oleh spesifikasi, dan heksadesimal tanpa 0 bukan heksadesimal lagi — tak ada yang bisa mendekodenya.

Mengapitalkan tiap kata dari frasa-sandi tak menambah apa pun sama sekali, dan angka kekuatan di sini secara sengaja tak bergerak ketika Anda menyalakannya. Ia adalah transformasi yang sama diterapkan setiap kali, jadi ia tak menciptakan satu kemungkinan baru pun: seorang penyerang yang tahu frasanya dikapitalkan persis di tempat mereka mulai. Opsi ada karena bidang sandi masih menuntut huruf kapital, bukan karena ia membantu.

Memilih panjang

Untuk apa pun yang ditangani mesin — kunci API, token sesi, rahasia webhook, sandi basis data — tak ada alasan untuk berhemat. 32 karakter heksadesimal atau 22 karakter base64url memberi 128 bit, dan melangkah lebih jauh hanya menelan bita dalam berkas konfigurasi.

Untuk apa pun yang diketik seseorang, kendalanya berbeda dan frasa-sandi biasanya bentuk yang lebih baik. Enam kata dari daftar panjang lebih kuat daripada sandi acak dua-belas-karakter dan jauh lebih mudah diketik dengan benar pada percobaan pertama, yang lebih penting daripada kedengarannya: rahasia yang orang salah ketik adalah rahasia yang orang tuliskan.

Untuk kode numerik, pembacaan jujurnya adalah bahwa empat digit adalah 13 bit dan bisa dihabiskan dalam detik oleh apa pun yang tak membatasi laju. PIN aman semata-mata karena kebijakan penguncian di sekitarnya, tak pernah karena kekuatannya sendiri.

Pertanyaan yang sering diajukan

Berapa panjang kunci API seharusnya?
Bidik 128 bit entropi atau lebih, yang adalah tempat brute force berhenti menjadi strategi. Itu adalah 32 karakter heksadesimal, 22 karakter base64url, atau 43 karakter base64url jika Anda menginginkan 256 bit. Untuk nilai yang hanya perangkat lunak yang menanganinya, opsi yang lebih panjang tak menelan apa pun.
Apakah ini lebih aman daripada menghasilkan rahasia dengan Math.random?
Ya, dan perbedaannya bukan soal tingkat. Math.random adalah pembangkit pseudo-acak dengan keadaan kecil yang mesin saat ini memungkinkannya dipulihkan dari rangkaian pendek keluaran, setelahnya setiap nilai yang akan pernah dihasilkannya diketahui. Alat ini memakai crypto.getRandomValues, CSPRNG platform, yang adalah sumber yang sama yang diambil openssl rand.
Mengapa Anda tak menampilkan satu "waktu untuk memecahkan"?
Karena tak ada angka semacam itu. Rahasia yang sama tak terjangkau di balik login yang membatasi laju dan jatuh cepat di balik hash cepat yang bocor — terpaut sebelas orde besaran. Angka tunggal harus memilih satu asumsi lalu menyembunyikannya, dan pembaca mengingat angkanya ketimbang asumsinya. Tiga laju bernama menaruh asumsi di tempat Anda bisa melihatnya.
Apakah frasa-sandi lebih lemah daripada string acak?
Tidak — kekuatannya bergantung hanya pada berapa banyak kata yang diambil dan dari daftar sebesar apa, dan keduanya ditampilkan. Enam kata dari daftar panjang EFF sekitar 77 bit, lebih dari sandi acak sepuluh-karakter. Yang melemahkan frasa-sandi adalah memilih sendiri kata-katanya, yang ini tidak.
Apakah saya sebaiknya mengecualikan karakter mirip-rupa?
Jika seorang manusia akan membaca rahasia dari layar dan mengetiknya di tempat lain, ya: biayanya kecil dan token yang salah baca adalah tiket dukungan. Jika hanya perangkat lunak yang menanganinya, tak ada alasan untuk. Membuang 0, O, I, dan l menurunkan alfabet dari 62 karakter menjadi 58, yang persis alfabet base58, dan menelan sekitar satu karakter panjang setiap enam puluh.
Apakah mengapitalkan frasa-sandi membuatnya lebih kuat?
Tidak. Ia adalah perubahan yang sama diterapkan setiap kali, jadi ia tak menambah satu kemungkinan baru pun ke ruang frasa-sandi. Angka entropi di sini tetap ketika Anda menyalakannya, yang merupakan perilaku yang akurat. Opsi ada karena beberapa bidang sandi bersikeras pada huruf kapital.
Apakah ada yang saya hasilkan dikirim ke server?
Tidak. Pembangkitan berjalan sepenuhnya di peramban Anda memakai pembangkit acak platform, tak ada yang diunggah atau dicatat, dan ia bekerja tanpa koneksi jaringan. Token tak disimpan di mana pun — memuat ulang halaman menghasilkan yang baru dan yang lama hilang.

Alat terkait