{cryptorng} provides access to your operating system’s
cryptographically secure pseudorandom number generator
(CSPRNG).
System CSPRNGs provide high-quality, uniform random bytes which are secure against cryptographic analysis.
These bytes are suitable for use in other crypographic processes e.g.
{cryptorng} apart from other RNGs in R?library(cryptorng)
# uniform random bytes
rcrypto(16)
#> [1] 9d 29 5b 9a 4f 7c fd 4a 1e f1 c1 e1 54 34 30 1d
# uniform random bytes as a hexadecimal string
rcrypto(16, type = 'chr')
#> [1] "95b9bbed52bb1178797488ede2905a43"
# random logical values
rcrypto(16, type = 'lgl')
#> [1] FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE
#> [13] FALSE FALSE FALSE FALSE
# uniform random integers
rcrypto(16, type = 'int')
#> [1] -1462110675 -149265429 24479471 -1108190907 891595010 786375080
#> [7] 2062005447 56916768 1845302616 -852269330 -2093358023 43116425
#> [13] 1853964883 1208525937 -1385749686 670879908
# uniform random doubles in the range [0, 1)
rcrypto(16, type = 'dbl')
#> [1] 0.6866093 0.1157316 0.4953703 0.5625702 0.8608402 0.7837645 0.9046331
#> [8] 0.9356881 0.2529249 0.6325323 0.2894815 0.7857760 0.2388977 0.8496769
#> [15] 0.2457765 0.4280983
This package can be installed from CRAN
install.packages('cryptorng')
You can install the latest development version from GitHub with:
# install.packages('remotes')
remotes::install_github('coolbutuseless/cryptorng')
Pre-built source/binary versions can also be installed from R-universe
install.packages('cryptorng', repos = c('https://coolbutuseless.r-universe.dev', 'https://cloud.r-project.org'))
Major operating systems (e.g. macOS, Linux, Windows) now come with
CSPRNG functionality built-in.
These RNGs (Random Number Generators) are cryptographically secure -
meaning that
These are still only pseudo-random number generators though, as the production of numbers is deterministic given the seed. So a high entropy seed which is kept secret is considered standard practice.
For these OS-provided CSPRNGs, the entropy (and the seeding) is provided by the OS itself - using such things as hardware RNGs, timing jitter, network traffic, disk activity. The initial seed is never revealed to the user, and reseeding may take place to ensure that additional entropy is used when available.
The C function for generating random values varies depending on the OS:
| OS | CSPRNG | Notes |
|---|---|---|
| macOS, *BSD | arc4random_buf() |
macOS arc4rand.c |
| Linux |
SYS_getrandom() via syscall()
|
|
| Windows | BCryptGenRandom() |
All of these random number generators are internally seeded by the OS using entropy gathered from multiple sources and use random number algorithms which are considered cryptographically secure.
This package and code is MIT licensed. Please feel free to incorporate/adapt this code into your own project.
The following is a snapshot of the core function which calls the appropriate CSPRNG for your system.
Note: If your system is not supported, please open an
issue with
information on your systems CSPRNG and/or /dev/random information.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get random bytes from the system RNG (C Callable)
//
// @param buf pre-allocated buffer in which to put the random bytes
// @param n number of bytes. Note: when a system RNG runs out of entropy
// it may return fewer bytes than expected. This function throws an
// error in this situation
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void rcrypto(void *buf, size_t n) {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// macOS and BSD support arc4random_buf()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
// void arc4random_buf(void buf[.n], size_t n);
arc4random_buf(buf, n);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Windows: use BCryptGenRandom
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#elif defined(_WIN32)
// NTSTATUS BCryptGenRandom(
// [in, out] BCRYPT_ALG_HANDLE hAlgorithm,
// [in, out] PUCHAR pbBuffer,
// [in] ULONG cbBuffer,
// [in] ULONG dwFlags
// );
// dwFlags = BCRYPT_USE_SYSTEM_PREFERRED_RNG - Use the system-preferred random
// number generator algorithm. The hAlgorithm parameter must be NULL.
size_t status = (size_t)BCryptGenRandom( NULL, ( PUCHAR ) buf, n, BCRYPT_USE_SYSTEM_PREFERRED_RNG );
// Return value is 'NTSTATUS' value. STATUS_SUCCESS = 0.
if (status != 0) {
error("cryptorng_windows() error: Status = %zu.\n", status);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Linux use 'Sys_getrandom()'
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#elif defined(__linux__)
long status = (long)syscall( SYS_getrandom, buf, n, 0 );
if (status < 0 || status != n) {
error("cryptorng_linux() error: Status = %zu.\n", status);
}
#else
#error no secrure rcrypto() implemented for this platform
#endif
}