---
title: "Generating Secure Random Numbers in R"
date: "`r Sys.Date()`"
vignette: >
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteIndexEntry{Generating Secure Random Numbers in R}
  \usepackage[utf8]{inputenc}  
output:
  html_document
---

```{r, echo = FALSE, message = FALSE}
knitr::opts_chunk$set(comment = "")
library(openssl)
```

The `rand_bytes` function binds to [RAND_bytes](https://docs.openssl.org/1.1.1/man3/RAND_bytes/) in OpenSSL to generate cryptographically strong pseudo-random bytes. See the OpenSSL documentation for what this means. 

```{r}
rnd <- rand_bytes(10)
print(rnd)
```

Bytes are 8 bit and hence can have `2^8 = 256` possible values.

```{r}
as.numeric(rnd)
```

Each random byte can be decomposed into 8 random bits (booleans)

```{r}
x <- rand_bytes(1)
as.logical(rawToBits(x))
```

## Secure Random Numbers

`rand_num` is a simple (2 lines) wrapper to `rand_bytes` to generate random numbers (doubles) between 0 and 1.

```{r}
rand_num(10)
```

To map random draws from [0,1] into a probability density, we can use a [Cumulative Distribution Function](https://en.wikipedia.org/wiki/Cumulative_distribution_function). For example we can combine `qnorm` and `rand_num` to simulate `rnorm`:

```{r}
# Secure rnorm
x <- qnorm(rand_num(1000), mean = 100, sd = 15)
hist(x)
```

Same for discrete distributions:

```{r}
# Secure rbinom
y <- qbinom(rand_num(1000), size = 20, prob = 0.1)
hist(y, breaks = -.5:(max(y)+1))
```