Random number generator (device): Difference between revisions
Line 951: | Line 951: | ||
</lang> |
</lang> |
||
=={{header|Mathematica}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
<lang Mathematica>rand32[] := RandomInteger[{-2^31, 2^31 - 1}]</lang> |
<lang Mathematica>rand32[] := RandomInteger[{-2^31, 2^31 - 1}]</lang> |
||
Example: create array of 10 rand32 numbers |
Example: create array of 10 rand32 numbers |
||
<lang Mathematica>Table[rand32[], {i, 1, 10}]</lang> |
<lang Mathematica>Table[rand32[], {i, 1, 10}]</lang> |
||
{{out}} |
{{out}} |
||
<pre>{355587317, -869860319, -91421859, 1605907693, 101463390, 891823090, |
<pre>{355587317, -869860319, -91421859, 1605907693, 101463390, 891823090, |
Revision as of 09:44, 14 August 2021
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
If your system has a means to generate random numbers involving not only a software algorithm (like the /dev/urandom devices in Unix), then:
show how to obtain a random 32-bit number from that mechanism.
- Related task
AArch64 Assembly
Linux provides getrandom
syscall for most architectures, which draws random bytes from /dev/urandom
by default.
The syscall number on AArch64 is 278.
<lang ARM_Assembly>.equ STDOUT, 1 .equ SVC_WRITE, 64 .equ SVC_GETRANDOM, 278 .equ SVC_EXIT, 93
.text .global _start
_start: stp x29, x30, [sp, -32]! // allocate buffer space at [sp] mov x29, sp mov x0, sp mov x1, #4 bl _getrandom // getrandom(&tmp, 4); ldr w0, [sp] bl print_uint64 // print_uint64(tmp); ldp x29, x30, [sp], 32 mov x0, #0 b _exit // exit(0);
// void print_uint64(uint64_t x) - print an unsigned integer in base 10. print_uint64: // x0 = remaining number to convert // x1 = pointer to most significant digit // x2 = 10 // x3 = x0 / 10 // x4 = x0 % 10 // compute x0 divmod 10, store a digit, repeat if x0 > 0 ldr x1, =strbuf_end mov x2, #10 1: udiv x3, x0, x2 msub x4, x3, x2, x0 add x4, x4, #48 mov x0, x3 strb w4, [x1, #-1]! cbnz x0, 1b // compute the number of digits to print, then call write() ldr x3, =strbuf_end_newline sub x2, x3, x1 mov x0, #STDOUT b _write
.data strbuf: .space 31 strbuf_end: .ascii "\n" strbuf_end_newline: .align 4
.text //////////////// system call wrappers // ssize_t _write(int fd, void *buf, size_t count) _write: mov x8, #SVC_WRITE svc #0 ret
// ssize_t getrandom(void *buf, size_t buflen, unsigned int flags=0) _getrandom: mov x2, #0 mov x8, #SVC_GETRANDOM svc #0 ret
// void _exit(int retval) _exit: mov x8, #SVC_EXIT svc #0</lang>
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>
ARM Assembly
<lang ARM Assembly>
/* ARM assembly Raspberry PI */ /* program urandom.s */
/* Constantes */ .equ STDOUT, 1 @ Linux output console .equ EXIT, 1 @ Linux syscall .equ READ, 3 .equ WRITE, 4 .equ OPEN, 5 .equ CLOSE, 6
.equ O_RDONLY, 0 @ open for reading only
.equ BUFFERSIZE, 4 @ random number 32 bits
/* Initialized data */ .data szFileName: .asciz "/dev/urandom" @ see linux doc szCarriageReturn: .asciz "\n" /* datas error display */ szMessErreur: .asciz "Error detected.\n" szMessErr: .ascii "Error code hexa : " sHexa: .space 9,' '
.ascii " decimal : "
sDeci: .space 15,' '
.asciz "\n"
/* datas message display */ szMessResult: .ascii "Random number :" sValue: .space 12,' '
.asciz "\n"
/* UnInitialized data */ .bss sBuffer: .skip BUFFERSIZE @ buffer result
/* code section */ .text .global main main:
ldr r0,iAdrszFileName @ File name mov r1,#O_RDONLY @ flags mov r2,#0 @ mode mov r7,#OPEN @ open file svc #0 cmp r0,#0 @ error ? ble error mov r8,r0 @ save FD mov r4,#0 @ loop counter
1:
mov r0,r8 @ File Descriptor ldr r1,iAdrsBuffer @ buffer address mov r2,#BUFFERSIZE @ buffer size mov r7,#READ @ call system read file svc 0 cmp r0,#0 @ read error ? ble error ldr r1,iAdrsBuffer @ buffer address ldr r0,[r1] @ display buffer value ldr r1,iAdrsValue bl conversion10 ldr r0,iAdrszMessResult bl affichageMess add r4,#1 @ increment counter cmp r4,#10 @ maxi ? blt 1b @ no -> loop
end:
mov r0,r8 mov r7, #CLOSE @ call system close file svc #0 cmp r0,#0 blt error mov r0,#0 @ return code b 100f
error:
ldr r1,iAdrszMessErreur @ error message bl displayError mov r0,#1 @ return error code
100: @ standard end of the program
mov r7, #EXIT @ request to exit program svc 0 @ perform system call
iAdrsBuffer: .int sBuffer iAdrsValue: .int sValue iAdrszMessResult: .int szMessResult iAdrszFileName: .int szFileName iAdrszMessErreur: .int szMessErreur iAdrszCarriageReturn: .int szCarriageReturn
/******************************************************************/ /* display text with size calculation */ /******************************************************************/ /* r0 contains the address of the message */ affichageMess:
push {r0,r1,r2,r7,lr} @ save registers mov r2,#0 @ counter length */
1: @ loop length calculation
ldrb r1,[r0,r2] @ read octet start position + index cmp r1,#0 @ if 0 its over addne r2,r2,#1 @ else add 1 in the length bne 1b @ and loop @ so here r2 contains the length of the message mov r1,r0 @ address message in r1 mov r0,#STDOUT @ code to write to the standard output Linux mov r7, #WRITE @ code call system "write" svc #0 @ call system pop {r0,r1,r2,r7,lr} @ restaur registers bx lr @ return
/***************************************************/ /* display error message */ /***************************************************/ /* r0 contains error code r1 : message address */ displayError:
push {r0-r2,lr} @ save registers mov r2,r0 @ save error code mov r0,r1 bl affichageMess mov r0,r2 @ error code ldr r1,iAdrsHexa bl conversion16 @ conversion hexa mov r0,r2 @ error code ldr r1,iAdrsDeci @ result address bl conversion10S @ conversion decimale ldr r0,iAdrszMessErr @ display error message bl affichageMess
100:
pop {r0-r2,lr} @ restaur registers bx lr @ return
iAdrszMessErr: .int szMessErr iAdrsHexa: .int sHexa iAdrsDeci: .int sDeci /******************************************************************/ /* Converting a register to hexadecimal */ /******************************************************************/ /* r0 contains value and r1 address area */ conversion16:
push {r1-r4,lr} @ save registers mov r2,#28 @ start bit position mov r4,#0xF0000000 @ mask mov r3,r0 @ save entry value
1: @ start loop
and r0,r3,r4 @ value register and mask lsr r0,r2 @ move right cmp r0,#10 @ compare value addlt r0,#48 @ <10 ->digit addge r0,#55 @ >10 ->letter A-F strb r0,[r1],#1 @ store digit on area and + 1 in area address lsr r4,#4 @ shift mask 4 positions subs r2,#4 @ counter bits - 4 <= zero ? bge 1b @ no -> loop
100:
pop {r1-r4,lr} @ restaur registers bx lr
/***************************************************/ /* Converting a register to a signed decimal */ /***************************************************/ /* r0 contains value and r1 area address */ conversion10S:
push {r0-r4,lr} @ save registers mov r2,r1 @ debut zone stockage mov r3,#'+' @ par defaut le signe est + cmp r0,#0 @ negative number ? movlt r3,#'-' @ yes mvnlt r0,r0 @ number inversion addlt r0,#1 mov r4,#10 @ length area
1: @ start loop
bl divisionpar10U add r1,#48 @ digit strb r1,[r2,r4] @ store digit on area sub r4,r4,#1 @ previous position cmp r0,#0 @ stop if quotient = 0 bne 1b
strb r3,[r2,r4] @ store signe subs r4,r4,#1 @ previous position blt 100f @ if r4 < 0 -> end
mov r1,#' ' @ space
2:
strb r1,[r2,r4] @store byte space subs r4,r4,#1 @ previous position bge 2b @ loop if r4 > 0
100:
pop {r0-r4,lr} @ restaur registers bx lr
/***************************************************/ /* division par 10 unsigned */ /***************************************************/ /* r0 dividende */ /* r0 quotient */ /* r1 remainder */ divisionpar10U:
push {r2,r3,r4, lr} mov r4,r0 @ save value //mov r3,#0xCCCD @ r3 <- magic_number lower raspberry 3 //movt r3,#0xCCCC @ r3 <- magic_number higter raspberry 3 ldr r3,iMagicNumber @ r3 <- magic_number raspberry 1 2 umull r1, r2, r3, r0 @ r1<- Lower32Bits(r1*r0) r2<- Upper32Bits(r1*r0) mov r0, r2, LSR #3 @ r2 <- r2 >> shift 3 add r2,r0,r0, lsl #2 @ r2 <- r0 * 5 sub r1,r4,r2, lsl #1 @ r1 <- r4 - (r2 * 2) = r4 - (r0 * 10) pop {r2,r3,r4,lr} bx lr @ leave function
iMagicNumber: .int 0xCCCCCCCD
</lang>
Batch File
The dynamic environmental variable %random%
contains a number between 0 and 32767.
<lang dos>
@echo %random%
</lang>
BBC BASIC
Requires Windows XP or later. <lang bbcbasic> SYS "SystemFunction036", ^random%, 4
PRINT ~random%</lang>
C
It works on systems having /dev/urandom, like GNU/Linux.
<lang c>#include <stdio.h>
- include <stdlib.h>
- define RANDOM_PATH "/dev/urandom"
int main(void) {
unsigned char buf[4]; unsigned long v; FILE *fin;
if ((fin = fopen(RANDOM_PATH, "r")) == NULL) { fprintf(stderr, "%s: unable to open file\n", RANDOM_PATH); return EXIT_FAILURE; } if (fread(buf, 1, sizeof buf, fin) != sizeof buf) { fprintf(stderr, "%s: not enough bytes (expected %u)\n", RANDOM_PATH, (unsigned) sizeof buf); return EXIT_FAILURE; } fclose(fin); v = buf[0] | buf[1] << 8UL | buf[2] << 16UL | buf[3] << 24UL; printf("%lu\n", v); 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>
debian/linux made from scratch
<lang c>
- include <stdio.h>
- include <stdlib.h>
/*
(C) 2020 J.G.A. Debaere, all rights reserved 2020/10/29
Put into Public Domain for individuals only Tested with NIST, Diehard, Diehard 3.31 gcc -lm ./jpsrand_f.c -o ./jpsrand_f.o
dieharder -a -f /tmp/tmp.bin
I consider it TRNG,
using Time, Hardddisk and Memory as the hardware component
No warranty of any kind, "AS IS"
Last time I tested ( 2021/07/07 ) with dieharder:
rgb_bitdist | 8| 100000| 100|0.99716738| WEAK rgb_lagged_sum | 3| 1000000| 100|0.99661184| WEAK
Out of 114 tests, rest PASSED
Obviously, it changes per run :)
- /
unsigned int jps_rand() {
/* (C) 2020 J.G.A. Debaere, all rights reserved */ #include <dirent.h>
#include <sys/time.h>
struct timeval current_time ; DIR *folder ; struct dirent *en ; folder = opendir ( "." ) ;
while ( ( folder ) && ( en = readdir ( folder ) ) != NULL )
asm ( "nop" ) ; closedir ( folder ) ; gettimeofday( ¤t_time, NULL ) ; unsigned int t = ( current_time.tv_sec * current_time.tv_usec / 17.17 ) ; return t ;
}
int main() {
FILE * f1;
f1 = fopen("/tmp/tmp.bin", "wb");
unsigned int t = ( unsigned int ) jps_rand() ; for ( unsigned int k = 0; k < 40000000 ; k++ ) { t = jps_rand () ;
fwrite ( &t, sizeof( unsigned int ), 1, f1 ) ; } fflush(f1); fclose(f1); return 0;
}
</lang> JPD 2021/07/07
Output:
Random
C++
std::random_device
is a uniformly-distributed integer random number generator that produces non-deterministic random numbers.
Note that std::random_device
may be implemented in terms of a pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation.
See the C++ section on Random number generator (included) for the list of pseudo-random number engines available.
<lang cpp>#include <iostream>
- include <random>
int main() {
std::random_device rd; std::uniform_int_distribution<long> dist; // long is guaranteed to be 32 bits std::cout << "Random Number: " << dist(rd) << std::endl;
}</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>
Park-Miller random number generator <lang csharp> const long m = 2147483647L; const long a = 48271L; const long q = 44488L; const long r = 3399L; static long r_seed = 12345678L;
public static byte gen() {
long hi = r_seed / q; long lo = r_seed - q * hi; long t = a * lo - r * hi; if (t > 0) r_seed = t; else r_seed = t + m; return (byte)r_seed;
}
public static void ParkMiller(byte[] arr) {
byte[] arr = new byte[10900000]; for (int i = 0; i < arr.Length; i++) { arr[i] = gen(); }
}</lang>
ChucK
<lang c> Math.random2(-(Math.random()),Math.random(); </lang>
Common Lisp
<lang lisp>(defun random-int32 ()
(with-open-file (s "/dev/random" :element-type '(unsigned-byte 32)) (read-byte s)))</lang>
D
Example of MersenneTwisterEngine for generating uniformly-distributed 32-bit numbers with a period of 2 to the power of 19937. <lang d> import std.stdio; import std.random;
void main() {
Mt19937 gen; gen.seed(unpredictableSeed); auto n = gen.front; writeln(n);
} </lang>
- Output:
run 1: 3500391376 run 2: 9537841895 run 3: 1588499117 run 4: ...
Delphi
Windows
[[1]]
<lang Delphi> program Random_number_generator;
{$APPTYPE CONSOLE}
uses
System.SysUtils, Winapi.WinCrypt;
var
hCryptProv: NativeUInt; i: Byte; UserName: PChar;
function Random: UInt64; var
pbData: array[0..7] of byte; i: integer;
begin
if not CryptGenRandom(hCryptProv, 8, @pbData[0]) then exit(0); Result := 0; for i := 0 to 7 do Result := Result + (pbData[i] shl (8 * i));
end;
procedure Randomize; begin
CryptAcquireContext(hCryptProv, UserName, nil, PROV_RSA_FULL, 0);
end;
begin
Randomize; for i := 0 to 9 do Writeln(Random); Readln;
end.</lang>
- Output:
6246170830 2020144138 5469928375 5580575688 3947181392 4671237100 4269461866 4842880207 4217687233 1714028876
Linux
See #Pascal.
EchoLisp
No random device provided by the host (browser). But we can use the system timer to get a physical input. <lang lisp> (random-seed "simon") (random (expt 2 32)) → 2275215386 (random-seed "simon") (random (expt 2 32)) → 2275215386 ;; the same
(random-seed (current-time-milliseconds ))
(random (expt 2 32)) → 4061857345
(random-seed (current-time-milliseconds ))
(random (expt 2 32)) → 1322611152
</lang>
Factor
Factor has good support for switching between different random number generators. with-system-random
is a combinator that encapsulates the task of using a system RNG (/dev/random in the case of GNU/Linux).
<lang factor>USE: random
[ random-32 ] with-system-random .</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>
Fortran
Using system /dev/urandom in GNU/Linux.
<lang fortran> !----------------------------------------------------------------------- ! Test Linux urandom in Fortran !----------------------------------------------------------------------- program urandom_test
use iso_c_binding, only : c_long implicit none
character(len=*), parameter :: RANDOM_PATH = "/dev/urandom" integer :: funit, ios integer(c_long) :: buf
open(newunit=funit, file=RANDOM_PATH, access="stream", form="UNFORMATTED", & iostat=ios, status="old", action="read") if ( ios /= 0 ) stop "Error opening file: "//RANDOM_PATH
read(funit) buf
close(funit)
write(*,'(A,I64)') "Integer: ", buf write(*,'(A,B64)') "Binary: ", buf write(*,'(A,Z64)') "Hexadecimal: ", buf
end program urandom_test </lang>
Here's an example of the use of the latter:
FreeBASIC
FreeBASIC can in theory use any C library to produce pseudo-random numbers including those which are partly device based.
However, in practice, there is little need for this as specifying a second parameter of 5 to FB's Randomize statement produces cryptographically strong pseudo-random numbers using either the Win32 Crypto API or the /dev/urandom device under Linux. <lang freebasic>' FB 1.05.0 Win64
Randomize , 5
'generate 10 cryptographic random integers in the range 1 To 100 For i As Integer = 1 To 10
Print Int(Rnd * 100) + 1
Next
Sleep</lang>
GlovePIE
<lang glovepie>var.rand=random(10)</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 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>
Groovy
Based, necessarily, on Java solution: <lang groovy>def rng = new java.security.SecureRandom()</lang>
Test: <lang groovy>(0..4).each { println rng.nextInt() }</lang>
- Output:
380425053 -1003791794 -1972330603 1152610574 714616658
Haskell
<lang haskell>#!/usr/bin/env runhaskell
import System.Entropy import Data.Binary.Get import qualified Data.ByteString.Lazy as B
main = do
bytes <- getEntropy 4 print (runGet getWord32be $ B.fromChunks [bytes])</lang>
Icon and Unicon
The following is Unicon-specific but trivially converted into Icon.
<lang unicon>procedure main(A)
n := integer(A[1])|5 every !n do write(rand(4))
end
procedure rand(n)
f := open("/dev/urandom") | stop("Cannot get to urandom!") x := 0 every !n do x := x*256 + ord(reads(f,1)) close(f) return x
end</lang>
Sample runs:
->urand 910795827 1135996175 3545606085 944909079 2464790129 ->
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>
jq
jq does not provide direct access to /dev/urandom, so in the following we assume the availability of `od`, `tr`, and `fold`, and illustrate how to produce an indefinitely long stream of pseudo-random numbers that are approximately uniformly distributed in the range [0,1].
Assuming the jq program shown below is in a file named uniform.jq, the command-line invocation would be:
od -t x -An /dev/urandom | tr -d " " | fold -w 8 | jq -R -f uniform.jq
<lang jq># allow both upper and lower-case characters def hex2integer:
explode | reverse | map(if . > 96 then . - 87 elif . > 64 then . - 55 else . - 48 end) | reduce .[] as $c # state: [power, ans] ([1,0]; (.[0] * 16) as $b | [$b, .[1] + (.[0] * $c)]) | .[1];
select(length>0) | hex2integer / pow(16;length)</lang>
Notice that the program automatically adjusts the precision based on the length of the hexadecimal numbers presented. Since jq uses IEEE 754 64-bit arithmetic, specifying a larger value to `fold`, such as 10, will produce more precise results.
Julia
<lang Julia> const rdev = "/dev/random" rstream = try
open(rdev, "r")
catch
false
end
if isa(rstream, IOStream)
b = readbytes(rstream, 4) close(rstream) i = reinterpret(Int32, b)[1] println("A hardware random number is: ", i)
else
println("The hardware random number stream, ", rdev, ", was unavailable.")
end </lang>
- Output:
A hardware random number is: 986109744
Kotlin
<lang scala>// version 1.1.2
import java.security.SecureRandom
fun main(args: Array<String>) {
val rng = SecureRandom() val rn1 = rng.nextInt() val rn2 = rng.nextInt() val newSeed = rn1.toLong() * rn2 rng.setSeed(newSeed) // reseed using the previous 2 random numbers println(rng.nextInt()) // get random 32-bit number and print it
}</lang>
Lasso
<lang lasso>file(`/dev/urandom`)->readSomeBytes(4)->export32bits</lang>
- Output:
723217350
M2000 Interpreter
<lang M2000 Interpreter> Module checkit {
Declare random1 lib "advapi32.SystemFunction036" {long lpbuffer, long length} Buffer Clear Alfa as long*2 Print Eval(Alfa,0) Print Eval(Alfa,1) call void random1(alfa(0), 8) Print Eval(Alfa,0) Print Eval(Alfa,1)
} checkit </lang>
<lang M2000 Interpreter>
Function Random2 {
Declare CryptAcquireContext Lib "advapi32.CryptAcquireContextW" {long ByRefhProv, pszContainer$,pszProvider$, long dwProvType, long dwFlags} Declare CryptReleaseContext Lib "advapi32.CryptReleaseContext" {Long hProv, Long dwFlags} Declare CryptGenRandom Lib "advapi32.CryptGenRandom" {Long hProv, Long dwLen, Long ByRef} Const PROV_RSA_FULL As Long = 1 Const VERIFY_CONTEXT As Long = 0xF0000000& Buffer Clear RandomNum as Long Buffer Clear hProv as long Call Void CryptAcquireContext( hProv(0), "", "", PROV_RSA_FULL, VERIFY_CONTEXT) Call Void CryptGenRandom( Eval(hProv,0), 4, RandomNum(0)) Call Void CryptReleaseContext(Eval(hProv,0), 0&) =Eval(RandomNum,0)
} Print Random2() </lang>
Mathematica /Wolfram Language
<lang Mathematica>rand32[] := RandomInteger[{-2^31, 2^31 - 1}]</lang> Example: create array of 10 rand32 numbers <lang Mathematica>Table[rand32[], {i, 1, 10}]</lang>
- Output:
{355587317, -869860319, -91421859, 1605907693, 101463390, 891823090, -531713717, -1038608428, 1717313407, 674189312}
NetRexx
and probably other UNIX systems that provide /dev/random or /dev/urandom random data source devices.
<lang NetRexx>/* NetRexx */ options replace format comments java crossref savelog symbols binary
import java.math.BigInteger
randomDevNameFile = File randomDevNameList = ['/dev/random', '/dev/urandom'] -- list of random data source devices randomDevIStream = InputStream do
loop dn = 0 to randomDevNameList.length - 1 randomDevNameFile = File(randomDevNameList[dn]) if randomDevNameFile.exists() then leave dn -- We're done! Use this device randomDevNameFile = null -- ensure we don't use a non-existant device end dn if randomDevNameFile == null then signal FileNotFoundException('Cannot locate a random data source device on this system')
-- read 8 bytes from the random data source device, convert it into a BigInteger then display the result randomBytes = byte[8] randomDevIStream = BufferedInputStream(FileInputStream(randomDevNameFile)) randomDevIStream.read(randomBytes, 0, randomBytes.length) randomDevIStream.close() randomNum = BigInteger(randomBytes) say Rexx(randomNum.longValue()).right(24) '0x'Rexx(Long.toHexString(randomNum.longValue())).right(16, 0)
catch ex = IOException
ex.printStackTrace()
end return
/* To run the program in a loop 10 times from a bash shell prompt use: for ((i=0; i<10; ++i)); do java <program_name>; done # Shell loop to run the command 10 times
- /
</lang>
- Output:
$ for ((i=0; i<10; ++i)); do java RRandomGen; done # Shell loop to run the command 10 times -3724652236619320966 0xcc4f60865c70f17a -8287324416757903696 0x8cfd8259e0b94eb0 -2951181559250748016 0xd70b4c02052cfd90 8171526404483923658 0x716717f863fd3eca -4285529734202916706 0xc486bd699676009e 4783094698411310978 0x4260f74949dc3f82 6972277496665184225 0x60c28171482d97e1 -2382194670272317046 0xdef0be919c96f98a 7952058769071853043 0x6e5b6351938ecdf3 -1857830580859698636 0xe637a8ee0f000234 $
Nim
<lang nim>var f = open("/dev/urandom") var r: int32 discard f.readBuffer(addr r, 4) close(f) echo r</lang>
OCaml
OCaml's default integers are 31 bits on 32 bits architectures:
<lang ocaml>let input_rand_int ic =
let i1 = int_of_char (input_char ic) and i2 = int_of_char (input_char ic) and i3 = int_of_char (input_char ic) and i4 = int_of_char (input_char ic) in i1 lor (i2 lsl 8) lor (i3 lsl 16) lor (i4 lsl 24)
let () =
let ic = open_in "/dev/urandom" in let ri31 = input_rand_int ic in close_in ic; Printf.printf "%d\n" ri31;
- </lang>
but if we really want 32 bits integers there is a module for this:
<lang ocaml>let input_rand_int32 ic =
let i1 = Int32.of_int (int_of_char (input_char ic)) and i2 = Int32.of_int (int_of_char (input_char ic)) and i3 = Int32.of_int (int_of_char (input_char ic)) and i4 = Int32.of_int (int_of_char (input_char ic)) in let i2 = Int32.shift_left i2 8 and i3 = Int32.shift_left i3 16 and i4 = Int32.shift_left i4 24 in Int32.logor i1 (Int32.logor i2 (Int32.logor i3 i4))
let () =
let ic = open_in "/dev/urandom" in let ri32 = input_rand_int32 ic in close_in ic; Printf.printf "%ld\n" ri32;
- </lang>
PARI/GP
It works on systems having /dev/urandom and Linux.
<lang parigp>rnd(n=10)=extern("cat /dev/urandom|tr -dc '[:digit:]'|fold -w"n"|head -1")</lang>
The code above creates a new function rnd() which returns cryptographically strong integers with max. 10 random digits from /dev/urandom. rnd(n) returns integer with max. n random digits. No leading zeros.
- Output:
rnd() = 3055652197 rnd(20) = 75735303746547944580 ...
Pascal
This works with FreePascal on "unixoids": <lang pascal>program RandomNumberDevice; var
byteFile: file of byte; randomByte: byte;
begin
assign(byteFile, '/dev/urandom'); reset (byteFile); read (byteFile, randomByte); close (byteFile); writeln('The random byte is: ', randomByte);
end. </lang>
- Output:
>: ./RandomNumberDevice The random byte is: 9 >: ./RandomNumberDevice The random byte is: 237
Perl
Typically one would use a module as they will work on UNIX, Win32, and other O/S's. Crypt::Random::Seed, for instance, will use Win32 sources, EGD/PRNGD, /dev/u?random, or if none of those exist for some reason, a userspace entropy method. <lang Perl>use Crypt::Random::Seed; my $source = Crypt::Random::Seed->new( NonBlocking => 1 ); # Allow non-blocking sources like /dev/urandom print "$_\n" for $source->random_values(10); # A method returning an array of 32-bit values</lang> or (similar but many more dependencies): <lang Perl>use Crypt::Random::Source qw/get_weak/; # Alternately get_strong print unpack('L*',get_weak(4)), "\n" for 1..10;</lang>
Or we can read values from /dev/urandom ourselves: <lang Perl>sub read_random {
my $device = '/dev/urandom'; open my $in, "<:raw", $device # :raw because it's not unicode string or die "Can't open $device: $!";
sysread $in, my $rand, 4 * shift; unpack('L*', $rand);
}
print "$_\n" for read_random(10);</lang> Whether /dev/urandom is good enough for cryptographic work is debated, though on most UNIX systems it is at least as good as the Win32 Crypto API.
Phix
My machine does not support the rdrand instruction.
Tested as best I can by commenting out the jnc instructions and replacing rdrand with rdtsc.
I have uploaded replacement pttree.e and pilasm.e (use at your own risk) for
anyone wanting to test prior to 0.8.0 being shipped.
If your chip does not support rdrand, you get {1,0}, else {0,-2147483648..2147483647}.
For completeness, I have shown how to convert the signed result to an unsigned one.
integer res -- 1=failure, 0=success atom rint = 0 -- random 32-bit int #ilASM{ mov eax,1 cpuid bt ecx,30 mov edi,1 -- exit code: failure jnc :exit -- rdrand sets CF=0 if no random number -- was available. Intel documentation -- recommends 10 retries in a tight loop mov ecx,11 ::loop1 sub ecx, 1 jz :exit -- exit code is set already rdrand eax -- (the above generates exception #C000001D if not supported) -- rdtsc jnc :loop1 lea edi,[rint] call :%pStoreMint xor edi,edi ::exit mov [res],edi xor ebx,ebx -- important! } ?{res,rint} if res=0 then -- (success) -- -- To convert a signed 32-bit int to an unsigned one: -- -- method 1 -- atom urint1 = rint -- if urint1<0 then urint1+=#100000000 end if atom urint1 = rint+iff(rint<0?#100000000:0) -- method 2 atom pMem = allocate(4) poke4(pMem,rint) atom urint2 = peek4u(pMem) free(pMem) -- method 3 atom urint3 = bytes_to_int(int_to_bytes(rint,4),signed:=false) ?{urint1,urint2,urint3} end if
A linux-only solution:
integer fn = open("/dev/urandom","rb") if fn=-1 then puts(1,"cannot open /dev/urandom\n") else sequence s = {} for i=1 to 4 do s &= getc(fn) end for close(fn) ?bytes_to_int(s,signed:=false) end if
PicoLisp
<lang PicoLisp>: (in "/dev/urandom" (rd 4)) -> 2917110327</lang>
PowerShell
<lang PowerShell> function Get-RandomInteger {
Param ( [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [ValidateScript({$_ -ge 4})] [int[]] $InputObject = 64 )
Begin { $rng = New-Object -TypeName System.Security.Cryptography.RNGCryptoServiceProvider } Process { foreach($count in $InputObject) { $bytes = New-Object -TypeName Byte[] -Argument $count $rng.GetBytes($bytes) [System.BitConverter]::ToInt32($bytes,0) } } End { Remove-Variable -Name rng -Scope Local }
} </lang> <lang PowerShell> 4,8,16,32,64,128 | Get-RandomInteger | Format-Wide {$_} -Column 6 -Force </lang>
- Output:
1402572656 432337086 413089699 1404567509 -82797202 -261009960
As hexadecimal: <lang PowerShell> 4,8,16,32,64,128 | Get-RandomInteger | Format-Wide {"0x{0:X}" -f $_} -Column 6 -Force </lang>
- Output:
0x24305255 0x916002DD 0x9587046 0x5F236274 0xC0BAF6F0 0xC0B93118
ProDOS
Uses math module: <lang ProDOS>printline -random- </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>
Racket
<lang Racket>
- lang racket
- Assuming a device to provide random bits
(call-with-input-file* "/dev/random"
(λ(i) (integer-bytes->integer (read-bytes 4 i) #f)))
</lang>
Raku
(formerly Perl 6)
A lazy list of random numbers:
<lang perl6>use experimental :pack; my $UR = open("/dev/urandom", :bin) orelse .die; my @random-spigot = $UR.read(1024).unpack("L*") ... *;
.say for @random-spigot[^10];</lang>
- Output:
1431009271 1702240522 670020272 588612037 1864913839 2155430433 1690056587 385405103 2366495746 692037942
REXX
version 1
The 32-bit random number is unsigned and constructed from two smaller 16-bit numbers, and it's expressed in decimal.
Note: the REXX random BIF has a maximum range of 100,000. <lang rexx>/*REXX program generates and displays a random 32-bit number using the RANDOM BIF.*/ numeric digits 10 /*ensure REXX has enough decimal digits*/ _=2**16 /*a handy─dandy constant to have around*/ r#= random(0, _-1) * _ + random(0, _-1) /*generate an unsigned 32-bit random #.*/ say r# /*stick a fork in it, we're all done. */</lang>
- Output:
4294967296
version 2
This program generates a random 4 byte character string in the range '00000000'x to 'ffffffff'x <lang rexx>left=0 rite=0 lo=hex(left)hex(rite) Say 'low ' c2x(lo) left=random(0,2**16-1) rite=random(0,2**16-1) rand=hex(left)hex(rite) Say 'random' c2x(rand) left=2**16-1 rite=2**16-1 hi=hex(left)hex(rite) Say 'high ' c2x(hi) Exit hex: Return d2c(arg(1),2)</lang>
- Output:
low 00000000 random 3E4C3CDE high FFFFFFFF
Ring
<lang ring> nr = 10 for i = 1 to nr
see random(i) + nl
next </lang>
Ruby
Ruby 1.8.7 introduces the 'securerandom' library. For MRI users, this library tries to get random numbers by loading OpenSSL, or opening /dev/urandom, or calling CryptGenRandom.
<lang Ruby>require 'securerandom' SecureRandom.random_number(1 << 32)
- or specifying SecureRandom as the desired RNG:
p (1..10).to_a.sample(3, random: SecureRandom) # =>[1, 4, 5] </lang>
Rust
rand
used to be part of Rust standard library but it was extracted as a 'crate' (https://crates.io/crates/rand). OsRng
uses the appropriate device for many platforms including Unix, Windows, BSD, and iOS (listed here). Other methods like RDRAND
can be found in other crates (https://crates.io/crates/rdrand).
<lang rust>extern crate rand;
use rand::{OsRng, Rng};
fn main() {
// because `OsRng` opens files, it may fail let mut rng = match OsRng::new() { Ok(v) => v, Err(e) => panic!("Failed to obtain OS RNG: {}", e) };
let rand_num: u32 = rng.gen(); println!("{}", rand_num);
}</lang>
Scala
<lang Scala>import java.security.SecureRandom
object RandomExample extends App {
new SecureRandom { val newSeed: Long = this.nextInt().toLong * this.nextInt() this.setSeed(newSeed) // reseed using the previous 2 random numbers println(this.nextInt()) // get random 32-bit number and print it }
}</lang>
Sidef
<lang ruby>func urandom() {
const device = %f'/dev/urandom';
device.open('<:raw', \var fh, \var err) -> || die "Can't open `#{device}': #{err}";
fh.sysread(\var noise, 4); 'L'.unpack(noise);
}
say urandom(); # sample: 3517432564</lang>
Standard ML
<lang sml>fun sysRand32 () =
let val strm = BinIO.openIn "/dev/urandom" in PackWord32Big.subVec (BinIO.inputN (strm, 4), 0) before BinIO.closeIn strm end
val () = print (LargeWord.fmt StringCvt.DEC (sysRand32 ()) ^ "\n")</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>
UNIX Shell
<lang UNIX Shell>od -An -N 4 -t u4 /dev/urandom</lang>
Wee Basic
Due to how the code works, any key has to be entered to generate the random number. <lang Wee Basic>let keycode=0 let number=1 print 1 "Press any key to generate a random number from 1 to 10. while keycode=0 let number=number+1 let keycode=key() rem The maximum number is the number in the "if number=" line with 1 taken away. For example, if this number was 11, the maximum number would be 10. * if number=11 let number=1 endif wend print 1 number end</lang>
Wren
<lang ecmascript>import "io" for File
File.open("/dev/urandom") { |file|
var b = file.readBytes(4).bytes.toList var n = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 System.print(n)
}</lang>
- Output:
Sample run:
2614048905
X86 Assembly
Processors supporting the new RDRAND feature can generate a random 32-bit integer in two instructions: <lang x86>L: rdrand eax jnc L</lang> RDRAND reads the CPU's cryptographically-secure hardware random number generator. The loop is needed because RDRAND can occasionally fail to retrieve a value — it sets the carry flag to indicate whether it succeeded.
XPL0
The random number generator is seeded with the 32-bit system timer each time a program starts. From then on, a linear congruential algorithm is used (that passes the Diehard test suite). Since the Ran intrinsic routine returns a signed positive integer (modulo the argument), the value is limited to 31 bits.
<lang XPL0>code Ran=1; int R; R:= Ran($7FFF_FFFF)</lang>
zkl
Linux: <lang zkl>const RANDOM_PATH="/dev/urandom";
fin,buf:=File(RANDOM_PATH,"r"), fin.read(4); fin.close(); // GC would also close the file println(buf.toBigEndian(0,4)); // 4 bytes @ offset 0</lang>
- Output:
2152746403
- Programming Tasks
- Solutions by Programming Task
- Input Output
- AArch64 Assembly
- Ada
- ARM Assembly
- Batch File
- BBC BASIC
- C
- BSD libc
- OpenSSL
- C++
- C sharp
- ChucK
- Common Lisp
- D
- Delphi
- Windows
- System.SysUtils
- Winapi.WinCrypt
- Linux
- EchoLisp
- Factor
- Forth
- Fortran
- FreeBASIC
- GlovePIE
- Go
- Groovy
- Haskell
- Entropy
- Icon
- Unicon
- J
- Java
- Jq
- Julia
- Kotlin
- Lasso
- M2000 Interpreter
- Mathematica
- Wolfram Language
- NetRexx
- Nim
- OCaml
- PARI/GP
- Pascal
- Perl
- Phix
- PicoLisp
- PowerShell
- ProDOS
- PureBasic
- Python
- Racket
- Raku
- REXX
- Ring
- Ruby
- Rust
- Scala
- Sidef
- Standard ML
- Tcl
- UNIX Shell
- Wee Basic
- Wren
- X86 Assembly
- XPL0
- Zkl
- GUISS/Omit
- PARI/GP/Omit
- Randomness