Perintah seperti openssl rand -hex 32 sering disebut sebagai cara membuat “hash acak.” Hasilnya memang terlihat seperti digest SHA-256: 64 karakter heksadesimal. Namun, tidak ada operasi hash di sana. OpenSSL menghasilkan 32 byte acak lalu meng-encode-nya sebagai heksadesimal.
Perbedaannya penting. Fungsi hash mengubah input menjadi digest berukuran tetap. Cryptographically secure random number generator menghasilkan byte yang tidak dapat diprediksi. Jika kebutuhannya adalah token, session secret, kredensial API, nonce, atau nilai acak baru lainnya, bagian yang penting adalah byte acaknya. Melakukan hashing setelahnya biasanya tidak menambah ketidakpastian yang berguna.
32 byte acak menjadi 64 karakter heksadesimal
Encoding heksadesimal merepresentasikan setiap byte dengan dua karakter. Karena itu:
32 random bytes × 2 hex characters per byte = 64 hex charactersOpenSSL dapat menghasilkan representasi tersebut secara langsung:
openssl rand -hex 32Hasil tipikal memiliki bentuk seperti ini:
f5df8f0c8f4b2c3c2a3a9b967e327d193b42e87ef3e922c92a6d5b1b315c31adNilai tersebut adalah data acak yang ditampilkan sebagai hex, bukan digest dari nilai lain. Dengan asumsi generator bekerja dengan benar, 32 byte acak berisi 256 bit output acak sebelum encoding. Hex hanya mengubah representasi, bukan jumlah keacakannya.
Base64 adalah representasi lain:
openssl rand -base64 32Perintah itu membawa 32 byte yang sama-sama dihasilkan secara acak, tetapi memakai encoding teks yang lebih ringkas daripada hex.
Linux sudah menyediakan sumber acak kriptografis
Linux memelihara cryptographically secure pseudorandom number generator (CSPRNG) di kernel. Software di user space dapat mengambil output darinya melalui interface seperti getrandom() dan /dev/urandom.
Untuk penggunaan di shell, membaca 32 byte dari /dev/urandom lalu mengubahnya ke hex cukup langsung:
head -c 32 /dev/urandom | xxd -p -c 32Pipeline tersebut melakukan dua pekerjaan terpisah:
/dev/urandom -> 32 unpredictable bytes -> hexadecimal encodingDokumentasi Linux modern merekomendasikan sumber urandom untuk penggunaan kriptografis normal. Aplikasi yang membutuhkan randomness pada fase boot yang sangat awal sebaiknya menggunakan getrandom(), karena perilaku default-nya menunggu sampai random pool kernel selesai diinisialisasi.
OpenSSL menyediakan interface command-line yang praktis. Random generator-nya melakukan seeding dari sumber tepercaya milik operating system, sehingga ketika OpenSSL tersedia, bentuk berikut biasanya paling sederhana:
openssl rand -hex 32Melakukan hashing pada byte acak menyelesaikan masalah yang berbeda
Perintah ini juga valid:
head -c 32 /dev/urandom | sha256sumNamun aliran datanya berbeda:
/dev/urandom -> 32 random bytes -> SHA-256 -> 256-bit digestLangkah SHA-256 memetakan input acak menjadi nilai 256-bit lainnya. Ini dapat berguna jika sebuah protokol memang mensyaratkan digest, tetapi tidak mengubah randomness yang lemah menjadi kuat dan tidak diperlukan hanya untuk mendapatkan string acak 64 karakter.
Perbedaan yang sama berlaku pada:
openssl rand -base64 32 | sha256sumPerintah tersebut terlebih dahulu menghasilkan byte acak, meng-encode-nya menjadi teks Base64, lalu melakukan hashing pada teks itu. Jika kebutuhannya hanya token acak 256-bit dalam bentuk hex, openssl rand -hex 32 menyatakan maksudnya dengan lebih langsung tanpa transformasi tambahan.
Tentukan panjang dalam byte sebelum encoding
Kesalahan yang cukup umum adalah menentukan ukuran token dari panjang string yang terlihat, bukan dari jumlah byte acaknya.
Untuk hex:
16 bytes = 128 bits = 32 hex characters
32 bytes = 256 bits = 64 hex characters
64 bytes = 512 bits = 128 hex charactersPerintah yang sesuai adalah:
openssl rand -hex 16
openssl rand -hex 32
openssl rand -hex 64Argumen pada openssl rand adalah jumlah byte yang akan dihasilkan, bukan jumlah karakter output.
Untuk sebagian besar application secret, entropy yang dibutuhkan sebaiknya mengikuti security design atau protokol, bukan sekadar keinginan menghasilkan string yang panjang. Karakter yang lebih banyak tidak otomatis berguna jika protokol mengharapkan ukuran tertentu.
UUID adalah identifier, bukan pengganti byte secret arbitrer
uuidgen praktis ketika kebutuhan sebenarnya adalah UUID:
uuidgenUUID memiliki struktur dan representasi yang sudah ditentukan. Pilih UUID karena aplikasi membutuhkan semantik UUID, bukan hanya karena output-nya terlihat acak.
Demikian juga, timestamp yang di-hash dengan SHA-256 bukan pengganti CSPRNG yang baik:
date +%s | sha256sumSHA-256 dapat menyamarkan bentuk teks timestamp, tetapi tidak dapat menciptakan entropy yang tidak ada pada input. Penyerang yang dapat mempersempit timestamp ke interval kecil dapat melakukan hashing terhadap kandidat nilai yang sama.
Gunakan primitive sesuai kebutuhan
Perbedaan yang perlu dijaga adalah generation, encoding, dan hashing:
random generation: produce unpredictable bytes
encoding: represent bytes as hex or Base64
hashing: map input data to a fixed-size digestUntuk membuat nilai 256-bit baru melalui shell, bentuk langsungnya adalah:
openssl rand -hex 32Gunakan sha256sum ketika operasi memang membutuhkan SHA-256. Gunakan CSPRNG ketika yang dibutuhkan adalah nilai yang tidak dapat diprediksi. Memisahkan kedua operasi tersebut membuat perintah shell lebih mudah ditinjau dan mencegah digest yang terlihat acak dianggap sebagai bukti bahwa input-nya juga tidak dapat diprediksi.