Ich möchte /dev/random
oder /dev/urandom
in C verwenden. Wie kann ich das tun? Ich weiß nicht, wie ich mit ihnen in C umgehen soll. Wenn jemand weiß, sagen Sie mir bitte, wie. Vielen Dank.
Ich möchte /dev/random
oder /dev/urandom
in C verwenden. Wie kann ich das tun? Ich weiß nicht, wie ich mit ihnen in C umgehen soll. Wenn jemand weiß, sagen Sie mir bitte, wie. Vielen Dank.
Antworten:
Im Allgemeinen ist es besser, das Öffnen von Dateien zu vermeiden, um zufällige Daten zu erhalten, da das Verfahren so viele Fehlerquellen aufweist.
Auf den letzten Linux - Distributionen, die getrandom
kann Systemaufruf verwendet wird Krypto sichere Zufallszahl zu bekommen, und es kann nicht umhin , wenn GRND_RANDOM
sie nicht als Flag und die Lesemenge beträgt maximal 256 Byte festgelegt.
Seit Oktober 2017 haben OpenBSD, Darwin und Linux (mit -lbsd
) eine Implementierung arc4random
, die kryptosicher ist und nicht fehlschlagen kann. Das macht es zu einer sehr attraktiven Option:
char myRandomData[50];
arc4random_buf(myRandomData, sizeof myRandomData); // done!
Andernfalls können Sie die zufälligen Geräte so verwenden, als wären sie Dateien. Sie lesen von ihnen und erhalten zufällige Daten. Ich benutze open
/ read
hier, aber fopen
/ fread
würde genauso gut funktionieren.
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
}
}
Sie können viel mehr zufällige Bytes lesen, bevor Sie den Dateideskriptor schließen. / dev / urandom blockiert niemals und füllt immer so viele Bytes aus, wie Sie angefordert haben, es sei denn, der Systemaufruf wird durch ein Signal unterbrochen. Es gilt als kryptografisch sicher und sollte Ihr zufälliges Gerät sein.
/ dev / random ist kniffliger. Auf den meisten Plattformen kann es weniger Bytes zurückgeben, als Sie angefordert haben, und es kann blockieren, wenn nicht genügend Bytes verfügbar sind. Dies macht die Fehlerbehandlungsgeschichte komplexer:
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
in Ordnung.
Es gibt andere genaue Antworten oben. Ich musste allerdings einen FILE*
Stream verwenden. Folgendes habe ich getan ...
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)
byte_count
? Es ist unbenutzt.
Öffnen Sie einfach die Datei zum Lesen und lesen Sie dann die Daten. In C ++ 11 möchten Sie möglicherweise verwenden, std::random_device
das plattformübergreifenden Zugriff auf solche Geräte bietet.
std::random_device
es nicht in den Standard von 2011 geschafft hat. Es erscheint im N3797-Entwurf .
std::random_device
std::random_device
es in C ++ und nicht in C ist und das OP gefragt hat, wie es verwendet werden soll /dev/random
oder /dev/urandom
nicht, std::random_device
obwohl es eine gute Wahl ist std::random_device
und Vorteile hat, ist es einfach nicht das, wonach das OP gefragt hat
Zneak ist 100% korrekt. Es ist auch sehr üblich, einen Puffer mit Zufallszahlen zu lesen, der etwas größer ist als der, den Sie beim Start benötigen. Sie können dann ein Array in den Speicher einfügen oder es zur späteren Wiederverwendung in Ihre eigene Datei schreiben.
Eine typische Implementierung der oben genannten:
typedef struct prandom {
struct prandom *prev;
int64_t number;
struct prandom *next;
} prandom_t;
Dies ähnelt mehr oder weniger einem Band, das sich nur vorwärts bewegt und bei Bedarf von einem anderen Thread auf magische Weise aufgefüllt werden kann. Es gibt eine Menge von Dienstleistungen , die große Datei Dumps von nichts als Zufallszahlen liefern , die mit vielen stärkeren Generatoren erzeugt werden , wie zum Beispiel:
Verwenden Sie keine "vorverpackte" Entropie für kryptografische Samen , falls dies nicht selbstverständlich ist. Diese Sätze eignen sich gut für Simulationen, überhaupt nicht zum Generieren von Schlüsseln und dergleichen.
Wenn Sie viele Zahlen für so etwas wie eine Monte-Carlo-Simulation benötigen, ist es viel besser, sie so verfügbar zu haben, dass read () nicht blockiert.
Denken Sie jedoch daran, dass die Zufälligkeit einer Zahl ebenso deterministisch ist wie die Komplexität, mit der sie generiert wird. /dev/random
und /dev/urandom
sind praktisch, aber nicht so stark wie die Verwendung eines HRNG (oder das Herunterladen eines großen Speicherauszugs von einem HRNG). Erwähnenswert ist auch, dass das /dev/random
Nachfüllen über Entropie erfolgt , sodass es je nach den Umständen für eine Weile blockieren kann.
Die Antwort von zneak deckt es einfach ab, aber die Realität ist komplizierter. Zum Beispiel müssen Sie überlegen, ob / dev / {u} random wirklich das Zufallszahlengerät ist. Ein solches Szenario kann auftreten, wenn Ihr Computer kompromittiert und die Geräte durch Symlinks zu / dev / zero oder eine Datei mit geringer Dichte ersetzt wurden. In diesem Fall ist der Zufallsstrom jetzt vollständig vorhersehbar.
Der einfachste Weg (zumindest unter Linux und FreeBSD) besteht darin, einen ioctl-Aufruf auf dem Gerät auszuführen, der nur erfolgreich ist, wenn das Gerät ein Zufallsgenerator ist:
int data;
int result = ioctl(fd, RNDGETENTCNT, &data);
// Upon success data now contains amount of entropy available in bits
Wenn dies vor dem ersten Lesen des zufälligen Geräts durchgeführt wird, gibt es eine faire Wette, dass Sie das zufällige Gerät haben. Die Antwort von @ zneak kann also besser wie folgt erweitert werden:
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);
Der Insane Coding-Blog hat dies und andere Fallstricke vor nicht allzu langer Zeit behandelt. Ich empfehle dringend, den gesamten Artikel zu lesen. Ich muss ihnen die Ehre erweisen, woher diese Lösung stammt.
Bearbeitet, um hinzuzufügen (25.07.2014) ... Zufälligerweise habe
ich gestern Abend gelesen, dass Linux im Rahmen der LibReSSL-Bemühungen anscheinend einen GetRandom () -Syscall erhält . Zum Zeitpunkt des Schreibens gibt es kein Wort darüber, wann es in einer allgemeinen Kernel-Version verfügbar sein wird. Dies wäre jedoch die bevorzugte Schnittstelle, um kryptografisch sichere Zufallsdaten zu erhalten, da alle Fallstricke beseitigt werden, die der Zugriff über Dateien bietet. Siehe auch die mögliche Implementierung von LibReSSL .