Saya ingin menggunakan /dev/random
atau /dev/urandom
di C. Bagaimana cara melakukannya? Saya tidak tahu bagaimana cara menanganinya di C, jika ada yang tahu tolong beri tahu saya caranya. Terima kasih.
Bagaimana cara menggunakan /dev/random atau urandom di C?
Jawaban (5)
Secara umum, sebaiknya hindari membuka file untuk mendapatkan data acak, karena banyaknya titik kegagalan yang ada dalam prosedur.
Pada distribusi Linux terbaru, panggilan sistem getrandom
dapat digunakan untuk mendapatkan nomor acak yang aman untuk kripto, dan tidak akan gagal jika GRND_RANDOM
tidak ditentukan sebagai tanda dan jumlah baca paling banyak 256 byte.
Mulai Oktober 2017, OpenBSD, Darwin, dan Linux (dengan -lbsd
) kini semuanya memiliki implementasi arc4random
yang aman terhadap kripto dan tidak dapat gagal. Itu menjadikannya pilihan yang sangat menarik:
char myRandomData[50];
arc4random_buf(myRandomData, sizeof myRandomData); // done!
Jika tidak, Anda dapat menggunakan perangkat acak seolah-olah itu adalah file. Anda membacanya dan Anda mendapatkan data acak. Saya menggunakan open
/read
di sini, tetapi fopen
/fread
juga bisa digunakan.
int randomData = open("/dev/urandom", O_RDONLY);
if (randomData < 0)
{
// something went wrong
}
else
{
char myRandomData[50];
ssize_t result = read(randomData, myRandomData, sizeof myRandomData);
if (result < 0)
{
// something went wrong
}
}
Anda dapat membaca lebih banyak byte acak sebelum menutup deskriptor file. /dev/urandom tidak pernah memblokir dan selalu mengisi byte sebanyak yang Anda minta, kecuali panggilan sistem terganggu oleh sinyal. Ini dianggap aman secara kriptografis dan harus menjadi perangkat acak Anda.
/dev/random lebih rewel. Pada sebagian besar platform, ia dapat mengembalikan byte lebih sedikit dari yang Anda minta dan dapat memblokir jika byte yang tersedia tidak mencukupi. Hal ini membuat cerita penanganan kesalahan menjadi lebih kompleks:
int randomData = open("/dev/random", O_RDONLY);
if (randomData < 0)
{
// something went wrong
}
else
{
char myRandomData[50];
size_t randomDataLen = 0;
while (randomDataLen < sizeof myRandomData)
{
ssize_t result = read(randomData, myRandomData + randomDataLen, (sizeof myRandomData) - randomDataLen);
if (result < 0)
{
// something went wrong
}
randomDataLen += result;
}
close(randomData);
}
/dev/urandom
. Jika sudah cukup diunggulkan sekali, ia akan menghasilkan nomor acak semu dalam jumlah tak terbatas yang sesuai untuk digunakan dalam kripto. Satu-satunya kekhawatiran adalah bahwa penyemaian awal mungkin tidak cukup. Masalah yang tidak terlalu acak hanya berlaku pada beberapa kasus khusus yang jarang terjadi, seperti di awal proses booting pada perangkat yang disematkan atau mengkloning mesin virtual.
- person CodesInChaos; 27.10.2013
/dev/urandom
baik-baik saja.
- person CodesInChaos; 27.10.2013
read
untuk memasukkannya. Menurut saya, secara umum, Anda harus selalu memeriksa kondisi kesalahan. Selain itu, jika aplikasi Anda sangat penting bagi keamanan, sebaiknya periksa apakah file tersebut adalah perangkat karakter.
- person zneak; 02.01.2015
randomData
selain menutupnya. Anda yakin seharusnya tidak terbaca read(randomData ...
? Menunjukkan pentingnya penamaan.
- person BoppreH; 01.08.2015
/dev/random
dan /dev/urandom
duduk di belakang CSPRNG yang sama. (Saran Anda untuk memilih /dev/urandom
daripada /dev/random
masih berlaku.)
- person Sebastian; 23.03.2017
Ada jawaban akurat lainnya di atas. Saya perlu menggunakan aliran FILE*
. Inilah yang saya lakukan...
int byte_count = 64;
char data[64];
FILE *fp;
fp = fopen("/dev/urandom", "r");
fread(&data, 1, byte_count, fp);
fclose(fp);
fread((char*)(&myInt),sizeof(myInt),1,fp)
- person Azeem Bande-Ali; 25.05.2013
byte_count
? Itu tidak terpakai.
- person CalculatorFeline; 10.08.2017
Buka saja file untuk dibaca lalu baca datanya. Di C++11 Anda mungkin ingin menggunakan std::random_device
yang menyediakan akses lintas platform ke perangkat tersebut.
std::random_device
tidak masuk dalam standar 2011. Hal ini muncul dalam draf N3797.
- person Keith Thompson; 02.01.2015
std::random_device
berhasil berhasil C++11 pada akhirnya.
- person legends2k; 26.06.2015
std::random_device
ada di C++ dan bukan di C, dan OP bertanya bagaimana cara menggunakan /dev/random
atau /dev/urandom
bukan bagaimana menggunakan std::random_device
meskipun itu adalah pilihan yang baik untuk menggunakan std::random_device
dan memiliki manfaat, hanya saja bukan itu yang diminta OP
- person Nfagie Yansaneh; 08.08.2017
Zneak 100% benar. Sangat umum juga untuk membaca buffer angka acak yang sedikit lebih besar dari yang Anda perlukan saat startup. Anda kemudian dapat mengisi array di memori, atau menulisnya ke file Anda sendiri untuk digunakan kembali nanti.
Implementasi tipikal di atas:
typedef struct prandom {
struct prandom *prev;
int64_t number;
struct prandom *next;
} prandom_t;
Ini menjadi lebih atau kurang seperti kaset yang hanya bergerak maju dan secara ajaib dapat diisi ulang oleh utas lain sesuai kebutuhan. Ada banyak dari layanan yang menyediakan dump file besar yang hanya berisi angka acak yang dihasilkan dengan generator yang jauh lebih kuat seperti:
- Peluruhan radioaktif
- Perilaku optik (foton mengenai cermin semi transparan)
- Kebisingan atmosfer (tidak sekuat di atas)
- Peternakan monyet mabuk yang mengetik di keyboard dan menggerakkan tikus (bercanda)
Jangan gunakan entropi 'paket' untuk benih kriptografi, jika hal tersebut tidak perlu dikatakan lagi. Kumpulan tersebut bagus untuk simulasi, tidak bagus sama sekali untuk menghasilkan kunci dan semacamnya.
Tidak peduli dengan kualitas, jika Anda memerlukan banyak angka untuk sesuatu seperti simulasi monte carlo, lebih baik menyediakannya dengan cara yang tidak menyebabkan read() diblokir.
Namun, ingat, keacakan suatu bilangan sama deterministiknya dengan kompleksitas yang ada dalam menghasilkannya. /dev/random
dan /dev/urandom
memang nyaman, tetapi tidak sekuat menggunakan HRNG (atau mengunduh dump besar dari HRNG). Perlu diperhatikan juga bahwa /dev/random
diisi ulang melalui entropi, sehingga dapat memblokir cukup lama sementara tergantung pada keadaan.
jawaban zneak mencakupnya secara sederhana, namun kenyataannya lebih rumit dari itu. Misalnya, Anda perlu mempertimbangkan apakah /dev/{u}random benar-benar merupakan perangkat nomor acak. Skenario seperti itu dapat terjadi jika mesin Anda telah disusupi dan perangkat diganti dengan symlink ke /dev/zero atau file yang jarang. Jika ini terjadi, aliran acak kini dapat diprediksi sepenuhnya.
Cara paling sederhana (setidaknya di Linux dan FreeBSD) adalah dengan melakukan panggilan ioctl pada perangkat yang hanya akan berhasil jika perangkat tersebut adalah generator acak:
int data;
int result = ioctl(fd, RNDGETENTCNT, &data);
// Upon success data now contains amount of entropy available in bits
Jika ini dilakukan sebelum pembacaan pertama perangkat acak, maka ada kemungkinan besar Anda mendapatkan perangkat acak tersebut. Jadi jawaban @zneak sebaiknya diperluas menjadi:
int randomData = open("/dev/random", O_RDONLY);
int entropy;
int result = ioctl(randomData, RNDGETENTCNT, &entropy);
if (!result) {
// Error - /dev/random isn't actually a random device
return;
}
if (entropy < sizeof(int) * 8) {
// Error - there's not enough bits of entropy in the random device to fill the buffer
return;
}
int myRandomInteger;
size_t randomDataLen = 0;
while (randomDataLen < sizeof myRandomInteger)
{
ssize_t result = read(randomData, ((char*)&myRandomInteger) + randomDataLen, (sizeof myRandomInteger) - randomDataLen);
if (result < 0)
{
// error, unable to read /dev/random
}
randomDataLen += result;
}
close(randomData);
Blog Insane Coding meliput hal ini, dan kendala lainnya belum lama ini; Saya sangat menyarankan membaca keseluruhan artikel. Saya harus memberikan penghargaan kepada mereka dari mana solusi ini diambil.
Diedit untuk ditambahkan (25-07-2014)...
Secara kebetulan, saya membacanya tadi malam sebagai bagian dari Upaya LibReSSL, Linux tampaknya mendapatkan Panggilan sistem GetRandom(). Pada saat penulisan, belum ada kabar kapan akan tersedia dalam rilis umum kernel. Namun ini akan menjadi antarmuka pilihan untuk mendapatkan data acak yang aman secara kriptografis karena menghilangkan semua jebakan yang disediakan oleh akses melalui file. Lihat juga kemungkinan penerapan LibReSSL.
getrandom()
diperkenalkan di kernel 3.17. Jadi stok Ubuntu 16.04 tidak memilikinya pada 17-01-2018. Jalankan uname -a
di terminal untuk memeriksa versi kernel Anda.
- person erapert; 17.01.2018