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 characters

OpenSSL dapat menghasilkan representasi tersebut secara langsung:

openssl rand -hex 32

Hasil tipikal memiliki bentuk seperti ini:

f5df8f0c8f4b2c3c2a3a9b967e327d193b42e87ef3e922c92a6d5b1b315c31ad

Nilai 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 32

Perintah 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 32

Pipeline tersebut melakukan dua pekerjaan terpisah:

/dev/urandom -> 32 unpredictable bytes -> hexadecimal encoding

Dokumentasi 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 32

Melakukan hashing pada byte acak menyelesaikan masalah yang berbeda

Perintah ini juga valid:

head -c 32 /dev/urandom | sha256sum

Namun aliran datanya berbeda:

/dev/urandom -> 32 random bytes -> SHA-256 -> 256-bit digest

Langkah 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 | sha256sum

Perintah 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 characters

Perintah yang sesuai adalah:

openssl rand -hex 16
openssl rand -hex 32
openssl rand -hex 64

Argumen 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:

uuidgen

UUID 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 | sha256sum

SHA-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 digest

Untuk membuat nilai 256-bit baru melalui shell, bentuk langsungnya adalah:

openssl rand -hex 32

Gunakan 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.