Kategori OWASP: MASVS-CRYPTO: Kriptografi
Ringkasan
Generator angka pseudorandom (PRNG) adalah algoritma yang menghasilkan urutan angka yang dapat diprediksi berdasarkan nilai awal yang disebut seed. Urutan angka yang dihasilkan PRNG memiliki perkiraan properti yang sama dengan urutan angka yang benar-benar acak, tetapi lebih cepat dan lebih murah secara komputasi untuk dibuat.
Dengan kata lain, PRNG memiliki jaminan yang lebih tinggi daripada RNG yang lemah (mis. java.math.Random
) dalam hal distribusi entropi yang merata, yang mengemulasikan urutan angka yang benar-benar acak. Pembuatan angka yang benar-benar acak memerlukan peralatan khusus dan sering kali berada di luar cakupan pengembangan normal. Artikel ini tidak mencakup pembuatan angka yang benar-benar acak, dan hanya berfokus pada PRNG karena merupakan metodologi standar yang digunakan.
Kerentanan PRNG yang lemah terjadi saat developer menggunakan PRNG biasa untuk tujuan kriptografi, bukan PRNG yang aman secara kriptografis (CSPRNG). CSPRNG memiliki persyaratan yang lebih ketat, dan jika seed tidak diketahui, hal tersebut hanya dapat memberikan keuntungan yang tidak signifikan kepada penyerang dalam membedakan urutan output dengan urutan acak yang sebenarnya.
Penyerang mungkin juga dapat menebak urutan angka yang dihasilkan saat seed yang dapat diprediksi, seperti yang di-hardcode oleh developer, digunakan untuk melakukan inisialisasi PRNG atau CSPRNG, karena penyerang dapat menebak seed dan dengan demikian dapat memprediksi output yang dihasilkan oleh PRNG.
Dampak
Jika PRNG yang tidak aman secara kriptografis digunakan dalam konteks keamanan seperti autentikasi, penyerang mungkin dapat menebak angka yang dibuat secara acak dan mendapatkan akses ke data atau fungsi dengan hak istimewa.
Mitigasi
Umum
- Gunakan
java.security.SecureRandom
jika ada implikasi keamanan. - Gunakan
java.util.Random
untuk kasus lainnya - Jangan pernah gunakan
Math.random
!
java.security.SecureRandom
Direkomendasikan untuk penggunaan keamanan. Jika versi kernel Linux adalah 5.17+ atau memblokir thread dapat diterima, tunggu hingga terakumulasi cukup entropi sebelum Anda menghasilkan angka acak (yaitu menggunakan /dev/random
). Untuk melakukannya, panggil getInstanceStrong()
:
Kotlin
val rand = SecureRandom.getInstanceStrong()
Java
SecureRandom rand = SecureRandom.getInstanceStrong();
Jika tidak, pada versi kernel Linux sebelum 5.17, ketika memblokir thread tidak dapat diterima saat menghasilkan angka acak, konstruktor SecureRandom
harus dipanggil secara langsung:
Kotlin
import java.security.SecureRandom
object generateRandom {
@JvmStatic
fun main(args: Array<String>) {
// Create instance of SecureRandom class
val rand = SecureRandom()
// Generate random integers in range 0 to 999
val rand_int = rand.nextInt(1000)
// Use rand_int for security & authentication
}
}
Java
import java.security.SecureRandom;
public class generateRandom {
public static void main(String args[])
{
// Create instance of SecureRandom class
SecureRandom rand = new SecureRandom();
// Generate random integers in range 0 to 999
int rand_int = rand.nextInt(1000);
// Use rand_int for security & authentication
}
}
SecureRandom
mendapatkan seed default dari /dev/urandom
, dan otomatis digunakan saat objek dibuat atau diperoleh, sehingga tidak perlu menyediakan PRNG secara eksplisit. Secara umum, setiap penggunaan SecureRandom yang deterministik tidak disarankan (terutama jika ini menyebabkan hardcode nilai seed, yang dapat dilihat oleh siapa saja yang mendekompilasi aplikasi). Developer yang ingin menghasilkan output pseudorandom yang dapat direproduksi harus menggunakan primitif yang lebih sesuai seperti HMAC, HKDF, SHAKE, dll.
java.util.Random
Hindari untuk tujuan keamanan/autentikasi, dapat digunakan untuk hal lain.
Kotlin
import java.util.Random
object generateRandom {
@JvmStatic
fun main(args: Array<String>) {
// Create instance of SecureRandom class
val rand = Random()
// Generate random integers in range 0 to 999
val rand_int = rand.nextInt(1000)
}
}
Java
import java.util.Random;
public class generateRandom {
public static void main(String args[])
{
// Create instance of Random class
Random rand = new Random();
// Generate random integers in range 0 to 999
int rand_int = rand.nextInt(1000);
}
}