Algoritma
Untuk menghasilkan string acak, karakter gabungan digambar secara acak dari himpunan simbol yang dapat diterima sampai string mencapai panjang yang diinginkan.
Penerapan
Berikut adalah beberapa kode yang cukup sederhana dan sangat fleksibel untuk menghasilkan pengidentifikasi acak. Baca informasi berikut untuk catatan aplikasi penting.
public class RandomString {
/**
* Generate a random string.
*/
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = symbols[random.nextInt(symbols.length)];
return new String(buf);
}
public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String lower = upper.toLowerCase(Locale.ROOT);
public static final String digits = "0123456789";
public static final String alphanum = upper + lower + digits;
private final Random random;
private final char[] symbols;
private final char[] buf;
public RandomString(int length, Random random, String symbols) {
if (length < 1) throw new IllegalArgumentException();
if (symbols.length() < 2) throw new IllegalArgumentException();
this.random = Objects.requireNonNull(random);
this.symbols = symbols.toCharArray();
this.buf = new char[length];
}
/**
* Create an alphanumeric string generator.
*/
public RandomString(int length, Random random) {
this(length, random, alphanum);
}
/**
* Create an alphanumeric strings from a secure generator.
*/
public RandomString(int length) {
this(length, new SecureRandom());
}
/**
* Create session identifiers.
*/
public RandomString() {
this(21);
}
}
Contoh penggunaan
Buat generator tidak aman untuk pengidentifikasi 8 karakter:
RandomString gen = new RandomString(8, ThreadLocalRandom.current());
Buat generator aman untuk pengidentifikasi sesi:
RandomString session = new RandomString();
Buat generator dengan kode yang mudah dibaca untuk dicetak. String lebih panjang dari string alfanumerik penuh untuk mengimbangi penggunaan simbol lebih sedikit:
String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);
Gunakan sebagai pengidentifikasi sesi
Membuat pengidentifikasi sesi yang cenderung unik tidak cukup baik, atau Anda bisa menggunakan penghitung sederhana. Penyerang membajak sesi ketika pengidentifikasi yang dapat diprediksi digunakan.
Ada ketegangan antara panjang dan keamanan. Pengidentifikasi yang lebih pendek lebih mudah ditebak, karena ada lebih sedikit kemungkinan. Tetapi pengidentifikasi yang lebih lama mengkonsumsi lebih banyak penyimpanan dan bandwidth. Serangkaian simbol yang lebih besar membantu, tetapi dapat menyebabkan masalah penyandian jika pengidentifikasi dimasukkan dalam URL atau dimasukkan kembali dengan tangan.
Sumber yang mendasari keacakan, atau entropi, untuk pengidentifikasi sesi harus berasal dari generator nomor acak yang dirancang untuk kriptografi. Namun, menginisialisasi generator ini terkadang mahal atau lambat secara komputasi, sehingga harus dilakukan upaya untuk menggunakannya kembali jika memungkinkan.
Gunakan sebagai pengidentifikasi objek
Tidak semua aplikasi membutuhkan keamanan. Penugasan acak dapat menjadi cara yang efisien bagi banyak entitas untuk menghasilkan pengidentifikasi di ruang bersama tanpa koordinasi atau partisi. Koordinasi bisa lambat, terutama di lingkungan yang berkerumun atau terdistribusi, dan pemisahan ruang menyebabkan masalah ketika entitas berakhir dengan saham yang terlalu kecil atau terlalu besar.
Pengidentifikasi yang dihasilkan tanpa mengambil tindakan untuk membuatnya tidak dapat diprediksi harus dilindungi dengan cara lain jika penyerang mungkin dapat melihat dan memanipulasinya, seperti yang terjadi pada sebagian besar aplikasi web. Harus ada sistem otorisasi terpisah yang melindungi objek yang pengenalnya dapat ditebak oleh penyerang tanpa izin akses.
Kehati-hatian juga harus diambil untuk menggunakan pengidentifikasi yang cukup lama untuk membuat tabrakan tidak mungkin mengingat jumlah total pengidentifikasi yang diantisipasi. Ini disebut sebagai "paradoks ulang tahun." Probabilitas tabrakan, p , kira-kira n 2 / (2q x ), di mana n adalah jumlah pengidentifikasi yang sebenarnya dihasilkan, q adalah jumlah simbol yang berbeda dalam alfabet, dan x adalah panjang pengidentifikasi. Ini harus menjadi jumlah yang sangat kecil, seperti 2-50 atau kurang.
Mengatasi hal ini menunjukkan bahwa peluang tabrakan di antara 500k 15-karakter pengidentifikasi adalah sekitar 2-52 , yang kemungkinan lebih kecil dari kesalahan yang tidak terdeteksi dari sinar kosmik, dll.
Perbandingan dengan UUID
Menurut spesifikasinya, UUID tidak dirancang untuk tidak dapat diprediksi, dan tidak boleh digunakan sebagai pengidentifikasi sesi.
UUID dalam format standar membutuhkan banyak ruang: 36 karakter hanya untuk 122 bit entropi. (Tidak semua bit UUID "acak" dipilih secara acak.) String alfanumerik yang dipilih secara acak mengemas lebih banyak entropi hanya dalam 21 karakter.
UUID tidak fleksibel; mereka memiliki struktur dan tata letak standar. Ini adalah kebajikan utama mereka serta kelemahan utama mereka. Ketika berkolaborasi dengan pihak luar, standardisasi yang ditawarkan oleh UUID mungkin membantu. Untuk penggunaan internal murni, mereka bisa tidak efisien.