Membuat String Alfanumerik secara Acak di PHP




Mari kita mulai postingan kali ini dengan mengatakan bahwa hampir tidak ada peristiwa yang benar-benar acak. Bahkan hasil lemparan koin klasik bisa secara teori diprediksi jika kita tahu efek dari setiap faktor yang terlibat, seperti gesekan udara, gravitasi, dan gaya awal.

Hal yang sama berlaku untuk generasi angka acak (Random Numbers) dan string alfanumerik. Yang terbaik yang bisa kita harapkan adalah untuk membuat angka dan string yang tampaknya tidak mengikuti pola dan tidak dapat diprediksi oleh seorang attacker.

Dalam tutorial ini, kita akan membahas teknik yang berbeda untuk membuat angka acak dan string alfanumerik di PHP. 

Beberapa di antaranya akan aman secara kriptografi, sementara yang lain hanya dimaksudkan untuk penggunaan biasa, seperti memasukkan pseudocode nama file secara acak atau membuat URL dan menyarankan username.

Membuat Angka Acak di PHP

Ada tiga fungsi yang berbeda untuk membuat angka acak di PHP. Semua dari mereka akan menerima nilai minimum dan maksimum yang mungkin untuk angka acak dan menghasilkan angka acak untuk kalian. Ini adalah rand($min, $max), mt_rand($min, $max), dan random_int($min, $max).

Dengan rand(), nilai minimum dan maksimum dari integer kalian bisa membuat nilai palsu antara 0 dan nilai yang dikembalikan dengan getrandmax(). Sebelum PHP 7.1.0, fungsi ini sekitar empat kali lebih lambat daripada mt_rand(). Namun, setelah hadirnya PHP 7.1.0 dan versi yang lebih tinggi, telah dibuat alias mt_rand(). Tidak seperti mt_rand(), kalian bisa mengatur nilai $max menjadi lebih rendah dari $min tanpa menyebabkan kesalahan.

Dengan mt_rand(), nilai minimum dan maksimum dari integer, kalian bisa membuat nilai palsu antara 0 dan nilai yang dikembalikan dengan mt_getrandmax()

Ini bergantung pada implementasi dari Mersenne Twister untuk membuat angka acak. Hati-hati, meskipun methode ini ada sebelum PHP 7.1.0, fungsi ini menerapkan versi algoritma yang salah untuk menghasilkan angka. Namun, telah diperbaiki dalam versi yang lebih baru.

Fungsi menjadi lebih baik di PHP 7.2.0 dengan menghapus bug dari sebuah modul. Ini berarti bahwa untuk beberapa seed tertentu, urutan angka acak kalian sekarang akan sedikit lebih baik dibandingkan dengan versi yang lama. 

Namun, beberapa kode khusus mungkin benar-benar bergantung pada bias ini. Jika demikian, kalian bisa menggunakan algoritma seed yang lebih tua dengan memanggil fungsi mt_srand() untuk menempatkan generator angka acak dan melewatkan MT_RAND_PHP sebagai nilai parameter kedua.

Fungsi mt_rand() memiliki periode 219937−1, yang pada dasarnya berarti bahwa dalam skenario terbaik kalian mendapatkan sebanyak 219937−1 angka acak sebelum urutan mulai terulang. 

Kalian harus mencatat bahwa pengulangan urutan tidak sama dengan pengulangan angka tertentu. Dengan kata lain, kalian mungkin mendapatkan angka acak yang sama dua kali, tetapi itu tidak berarti bahwa urutan itu sendiri sudah mulai terulang. Urutan berikut adalah contoh:


  187 3276 1267 15 1267 34598 3467 125 17
  

Dalam urutan di atas, kita memiliki 1267 dua kali dalam output, tetapi itu tidak berarti bahwa seluruh urutan mulai mengulang setelah itu. Tidak mungkin untuk mendapatkan angka yang sama diulang begitu cepat dalam urutan acak, tetapi itu mungkin!

Kriptografi yang Diamankan menggunakan Angka Acak (Cryptographically Secure Random Integers)

Jika kalian ingin angka pseudo-random kriptografi aman, fungsi random_int() di PHP adalah taruhan terbaik kalian. Ini akan menghasilkan angka acak antara nilai $min dan $max yang disediakan, yang default ke PHP_INT_MIN dan PHP_INT_MAX. Sayangnya, fungsi ini hanya tersedia mulai dari PHP 7.0. Untuk versi sebelumnya, kalian menggunakan polyfill ini di GitHub.

Random Float

Selain menghasilkan integer acak, kalian mungkin juga ingin menghasilkan float. Ini dapat dilakukan dengan mudah dengan hanya membagi angka acak dengan nilai yang dikembalikan oleh mt_getrandmax(). Contoh berikut akan mengilustrasikan cara membuat float acak antara 0 dan 1 atau antara batas minimum dan maksimum lainnya.

  
<?php
 
// Output: 0.69458310943776
echo mt_rand(0, mt_getrandmax())/mt_getrandmax();
 
function mt_random_float($min, $max) {
    $float_part = mt_rand(0, mt_getrandmax())/mt_getrandmax();
    $integer_part = mt_rand($min, $max - 1);
    return $integer_part + $float_part;
}
 
// Output: 10.199064863938
echo mt_random_float(10, 11);
 
// Output: 35.540808309121
echo mt_random_float(15, 50);
 
?>

Ketika membuat float acak antara batas yang diberikan, kita memastikan bahwa integer acak tidak melewati di atas $max - 1. Dengan cara ini, kita dapat yakin bahwa menambahkan bagian float tidak akan mengambil jumlah di atas batas maksimum.

Menempatkan Generator Angka Acak

Satu konsep yang perlu sedikit penjelasan adalah seed. Sederhananya, ini hanya angka yang dapat digunakan untuk menginisialisasi fungsi rand() dan mt_rand() sebelum menghasilkan angka acak. Fungsi seed rand() disebut srand($seed), dan fungsi seed mt_rand() disebut mt_srand($seed, $mode).

Penting untuk diingat bahwa memberikan inisialisasi awal seed setiap saat sebelum memanggil rand() dan mt_rand() tidak selalu menghasilkan angka acak yang lebih baik. Bahkan, menggunakan seed yang sama setiap kali akan memberikan kalian angka acak yang sama juga!

  
<?php
 
mt_srand(10);
// Output: 1656398468
echo mt_rand();
 
mt_srand(10);
// Output: 1656398468
echo mt_rand();
 
mt_srand(10);
// Output: 1656398468
echo mt_rand();
 
?>

Menempatkan angka acak itu berguna ketika kalian ingin membuat angka yang bisa direproduksi secara berurutan. Potongan kode berikut menghasilkan urutan angka acak yang sama ketika dijalankan dua kali.

  
<?php
 
mt_srand(10);
 
$count = 0;
 
while($count < 10) {
    echo mt_rand(0, 100)." ";
    $count++;
}
 
// Output on First Run:
// 68 58 68 13 3 48 30 37 96 82
 
// Output on Second Run:
// 68 58 68 13 3 48 30 37 96 82

Membuat urutan acak yang dapat direproduksi dengan cara ini dapat membantu debug program yang sedang diuji menggunakan data acak ketika kalian tau tempatnya, kalian dapat mereproduksi input yang sama untuk mencari tahu apa yang salah.

Membuat String Alfanumerik secara Acak di PHP

Ada banyak cara untuk membuat string acak alfanumerik, dan apa yang kalian gunakan akan bergantung pada kebutuhan kalian itu sendiri.

Membuat Shuffled String

Jika kalian ingin membuat string alfanumerik secara acak dari satu set karakter tetap, kalian menggunakan fungsi str_shuffle($string) Fungsi ini akan memberikan kalian shuffled string acak. Di mulai dari PHP 7.1, algoritma yang menentukan urutan acak dari karakter dalam output string telah diubah ke Mersenne Twister.

Ingat bahwa string acak yang dihasilkan dengan cara ini tidak aman secara kriptografi. Namun, string akan tetap tidak dapat diprediksi untuk penggunaan umum seperti membuat nama file acak atau URL. Berikut beberapa contohnya:

  
<?php
 
$permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyz';
// Output: 54esmdr0qf
echo substr(str_shuffle($permitted_chars), 0, 10);
 
$permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
// Output: video-g6swmAP8X5VG4jCi.mp4
echo 'video-'.substr(str_shuffle($permitted_chars), 0, 16).'.mp4';
 
?>


Output kalian kemungkinan besar akan berbeda dalam kedua kasus. Dalam kasus pertama, kita hanya mengocok string karakter yang diizinkan dan kemudian mengambil 10 karakter pertama. Dalam kasus kedua, kita menambahkan "video" di awal pembuatan string dan ".mp4" di bagian akhir.

Metode ini membuat string alfanumerik acak yang sangat mudah, tetapi memiliki beberapa masalah. Sebagai contoh, kalian tidak akan pernah mendapatkan karakter yang sama dalam string acak kalian sebanyak dua kali. Juga, panjangnya output string acak hanya bisa selama input string.

Membuat String Acak

Jika masalah yang saya cantumkan di atas adalah deal breaker, kalian mungkin ingin melihat beberapa penerapan lain. Kode berikut akan menyelesaikan kedua masalah ini.

  
<?php
 
$permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
 
function generate_string($input, $strength = 16) {
    $input_length = strlen($input);
    $random_string = '';
    for($i = 0; $i < $strength; $i++) {
        $random_character = $input[mt_rand(0, $input_length - 1)];
        $random_string .= $random_character;
    }
 
    return $random_string;
}
 
// Output: iNCHNGzByPjhApvn7XBD
echo generate_string($permitted_chars, 20);
 
// Output: 70Fmr9mOlGID7OhtTbyj
echo generate_string($permitted_chars, 20);
 
// Output: Jp8iVNhZXhUdSlPi1sMNF7hOfmEWYl2UIMO9YqA4faJmS52iXdtlA3YyCfSlAbLYzjr0mzCWWQ7M8AgqDn2aumHoamsUtjZNhBfU
echo generate_string($permitted_chars, 100);
 
?>

Kalian bisa memodifikasinya dengan menambahkan sufiks dan prefiks tertentu ke string acak yang dibuat. Orang yang menggunakan PHP 7 dapat meningkatkan generasi string dengan menggunakan fungsi kriptografi random_int() daripada mt_rand().

Membuat String Acak Heksadesimal

Jika kalian ingin membuat string acak heksadesimal di PHP, kalian juga bisa menggunakan fungsi md5($string, $raw_output) atau sha1($string, $raw_output) Keduanya akan menghasilkan hash input string yang diberikan.

Kalian akan terus mendapatkan hash unik asalkan inputnya unik. Ini bisa dicapai dengan menggunakan output dari fungsi seperti time() sebagai input. Secara default, md5() akan mengembalikan string heksadesimal 32-karakter, dan sha1() akan mengembalikan string heksadesimal 40-karakter. Ini dapat dipotong hingga panjang tertentu menggunakan fungsi substr().

Berikut adalah contoh output yang dikembalikan oleh fungsi-fungsi ini:


  
<?php
 
// Output: 36e5e490f14b031e
echo substr(md5(time()), 0, 16);
 
// Output: aa88ef597c77a5b3
echo substr(sha1(time()), 0, 16);
 
// Output: 447c13ce896b820f353bec47248675b3
echo md5(time());
 
// Output: 6c2cef9fe21832a232da7386e4775654b77c7797
echo sha1(time());
 
?>

Seperti yang kalian lihat, membuat string heksadesimal acak dan unik hingga 40 karakter sangat mudah di PHP.

Membentuk Keamanan Kriptografi dari String Acak

Ketiga fungsi untuk membuat string alfanumerik acak yang telah kita bahas sejauh ini tidak aman secara kriptografi. Untungnya, PHP juga memiliki fungsi yang disebut random_bytes($length) untuk membuat byte pseudo-random yang aman secara kriptografi. Parameter $length menentukan berapa lama output string seharusnya.

Setelah kalian memiliki output dalam bentuk byte acak, kalian bisa menggunakan fungsi bin2hex() untuk mengubahnya menjadi nilai heksadesimal. Ini akan menggandakan panjang string.

  
<?php
 
// Output: b7b33efa07915b60ad55
echo bin2hex(random_bytes(10));
 
// Output: a2e6cb1f25616324c8a11a2cceb0b47c590949ea
echo bin2hex(random_bytes(20));
 
// Output: 25af3b86e11884ef5e8ef70a0ad06cba81b89ed6af3781a0
echo bin2hex(random_bytes(24));
 
?>

Fungsi lain yang bisa kalian gunakan untuk membuat byte acak kriptografi yang aman adalah openssl_random_pseudo_bytes($length, &$crypto_strong). Nilai parameter kedua dapat digunakan untuk menentukan apakah output string akan dibuat menggunakan algoritma kriptografi yang aman atau tidak.

Kesimpulan

Dalam tutorial kali ini, kita melihat generasi bilangan acak dan string alfanumerik di PHP. Membuat bilangan acak dapat berguna dalam berbagai situasi, seperti dalam permainan di mana kalian harus memanggil pemain musuh atau secara acak memberi pengguna beberapa petunjuk tentang huruf sehingga mereka dapat mengisi seluruh kata.

Sama seperti angka acak, generasi string acak alfanumerik juga bisa sangat membantu dalam banyak keadaan. Dengan bantuan str_shuffle(), kalian bisa memilih set karakter mana yang muncul dalam string acak kalian. Dengan sha1() dan md5(), kalian bisa dengan mudah membuat urutan acak heksadesimal, dan dengan random_bytes() kalian bisa membuat string kriptografi yang aman. Ini memperbolehkan kalian untuk membentuk nama file yang berarti dan sebuah username yang sulit ditebak.

Saya harap kalian menikmati tutorial ini. Jika kalian memiliki pertanyaan, jangan sungkan untuk bertanya di komentar. See You Next Time :)