Random number generator (device): Difference between revisions
({{omit from|PARI/GP}}) |
|||
Line 232: | Line 232: | ||
636131349</lang> |
636131349</lang> |
||
{{omit from|PARI/GP|No good way to access system devices}} |
|||
[[Category:Randomness]] |
[[Category:Randomness]] |
Revision as of 07:58, 7 May 2011
You are encouraged to solve this task according to the task description, using any language you may know.
If your system has a means to generate random numbers involving not only a software algorithm (like the /dev/random devices in Unix), show how to obtain a random 32-bit number from that mechanism.
Ada
random.adb: <lang Ada>with Ada.Streams.Stream_IO; with Ada.Text_IO; procedure Random is
Number : Integer; Random_File : Ada.Streams.Stream_IO.File_Type;
begin
Ada.Streams.Stream_IO.Open (File => Random_File, Mode => Ada.Streams.Stream_IO.In_File, Name => "/dev/random"); Integer'Read (Ada.Streams.Stream_IO.Stream (Random_File), Number); Ada.Streams.Stream_IO.Close (Random_File); Ada.Text_IO.Put_Line ("Number:" & Integer'Image (Number));
end Random;</lang>
C
It works on systems having /dev/urandom, like GNU/Linux.
<lang c>#include <inttypes.h>
- include <stdio.h>
- include <stdint.h>
int main(int argc, char **argv) {
uint32_t v; FILE *r = fopen("/dev/urandom", "r"); if (r == NULL) {
perror("/dev/urandom"); return 1;
}
size_t br = fread(&v, sizeof v, 1, r); if (br < 1) {
fputs("/dev/urandom: Not enough bytes\n", stderr); return 1;
}
printf("%" PRIu32 "\n", v); fclose(r); return 0;
}</lang>
arc4random() appeared in OpenBSD 2.1 and has spread to many BSD systems. This function runs an ARC4 random number generator that takes entropy from a kernel device. (This kernel device is sysctl kern.arandom in OpenBSD, or /dev/urandom in some other systems.)
<lang c>#include <inttypes.h> /* PRIu32 */
- include <stdlib.h> /* arc4random */
- include <stdio.h> /* printf */
int main() { printf("%" PRIu32 "\n", arc4random()); return 0; }</lang>
OpenSSL can generate random numbers. The default generator uses SHA1. For Unix systems, OpenSSL will gather entropy by reading a kernel device like /dev/urandom, or by using EGD, the Entropy Gathering Daemon. For other systems, OpenSSL might use a different source of entropy.
<lang c>#include <inttypes.h>
- include <stdio.h>
- include <openssl/err.h>
- include <openssl/rand.h>
int main() { uint32_t v;
if (RAND_bytes((unsigned char *)&v, sizeof v) == 0) { ERR_print_errors_fp(stderr); return 1; } printf("%" PRIu32 "\n", v); return 0; }</lang>
Windows
<lang c>#include <stdio.h> /* printf */
- include <windows.h>
- include <wincrypt.h> /* CryptAcquireContext, CryptGenRandom */
int main() { HCRYPTPROV p; ULONG i;
if (CryptAcquireContext(&p, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) { fputs("CryptAcquireContext failed.\n", stderr); return 1; } if (CryptGenRandom(p, sizeof i, (BYTE *)&i) == FALSE) { fputs("CryptGenRandom failed.\n", stderr); return 1; } printf("%lu\n", i); CryptReleaseContext(p, 0); return 0; }</lang>
C#
<lang csharp>using System; using System.Security.Cryptography;
private static int GetRandomInt() {
int result = 0; var rng = new RNGCryptoServiceProvider(); var buffer = new byte[4];
rng.GetBytes(buffer); result = BitConverter.ToInt32(buffer, 0);
return result;
}</lang>
Forth
<lang forth>variable rnd
- randoms ( n -- )
s" /dev/random" r/o open-file throw swap 0 do dup rnd 1 cells rot read-file throw drop rnd @ . loop close-file throw ;</lang>
Go
In the Go library is crypto/rand, a source specified to use dev/urandom on Unix-like systems and the CryptGenRandom API on Windows. Also implemented here is a source using dev/random, if you really want it. On my system it would print a few numbers then hang until I moved the mouse or pressed some keys on the keyboard. <lang go>package main
import (
"crypto/rand" "encoding/binary" "fmt" "io" "os"
)
func main() {
testRandom("crypto/rand", rand.Reader) testRandom("dev/random", newDevRandom())
}
func newDevRandom() (f *os.File) {
var err os.Error if f, err = os.Open("/dev/random"); err != nil { panic(err) } return
}
func testRandom(label string, src io.Reader) {
fmt.Printf("%s:\n", label) var r int32 for i := 0; i < 10; i++ { if err := binary.Read(src, binary.LittleEndian, &r); err != nil { panic(err) } fmt.Print(r, " ") } fmt.Println()
}</lang>
J
Untested: <lang j>256#.a.i.1!:11'/dev/urandom';0 4</lang>
Fallback: <lang j>256#.a.i.4{.host'dd if=/dev/urandom bs=4 count=1'</lang>
Note: this assumes that J is running on linux.
Java
<lang java>import java.security.SecureRandom;
public class RandomExample { public static void main(String[] args) { SecureRandom rng = new SecureRandom();
/* Prints a random signed 32-bit integer. */ System.out.println(rng.nextInt()); } }</lang>
PicoLisp
<lang PicoLisp>: (in "/dev/urandom" (rd 4)) -> 2917110327</lang>
PureBasic
PureBasic has the source for the random data is the "/dev/urandom" device on Linux or Mac OSX and the "Microsoft Cryptography API" on Windows. <lang PureBasic>If OpenCryptRandom()
MyRandom = CryptRandom(#MAXLONG) CloseCryptRandom()
EndIf</lang>
Python
<lang Python>import random rand = random.SystemRandom() rand.randint(1,10)</lang>
Ruby
<lang Ruby> require 'securerandom' SecureRandom.random_number(1 << 31) </lang>
Tcl
<lang tcl>package require Tcl 8.5
- Allow override of device name
proc systemRandomInteger Template:Device "/dev/random" {
set f [open $device "rb"] binary scan [read $f 4] "I" x close $f return $x
}</lang> Usage: <lang tcl>% puts [systemRandomInteger] 636131349</lang>