A fast userspace CSPRNG

frand

GoDoc Go Report Card

go get lukechampine.com/frand

frand is a fast-key-erasure CSPRNG in userspace. Its output is sourced from the keystream of a ChaCha cipher, much like the CSPRNG in the Linux and BSD kernels. The initial cipher key is derived from the kernel CSPRNG, after which no new entropy is ever mixed in.

The primary advantage of frand over crypto/rand is speed: when generating large amounts of random data, frand is 20x faster than crypto/rand, and over 100x faster when generating data in parallel. frand is also far more convenient to use than crypto/rand, as its methods cannot return errors, and helper methods such as Intn and Perm are provided. In short, it is as fast and convenient as math/rand, but far more secure.

Design

frand closely follows the FKE-CSPRNG design linked above. The generator maintains a buffer consisting of a ChaCha key followed by random data. When a caller requests data, the generator fills the request from its buffer, and immediately overwrites that portion of the buffer with zeros. If the buffer is exhausted, the generator "refills" the buffer by xoring it with the ChaCha key's keystream; thus, the key is only used once, and immediately overwrites itself. This provides forward secrecy: even if an attacker learns the secret key, they cannot learn what data was previously output from the generator.

One optimization is implemented. If the caller requests a large amount of data (larger than the generator's buffer), the generator does not repeatedly fill and drain its buffer. Instead, it requests 32 bytes from itself, and uses this as a ChaCha key to directly generate the amount of data requested. The key is then overwritten with zeros.

The default generator uses ChaCha12. ChaCha8 is significantly weaker without being much faster; ChaCha20 is significantly slower without being much stronger.

At init time, a "master" generator is created using an initial key sourced from crypto/rand. New generators source their initial keys from this master generator. Following djb's recommendation, the generator never mixes in new entropy.

Calls to global functions like Read and Intn are serviced by a sync.Pool of generators derived from the master generator. This allows frand to scale near-linearly across CPU cores, which is what makes it so much faster than crypto/rand and math/rand in parallel benchmarks.

Security

Some may object to substituting a userspace CSPRNG for the kernel's CSPRNG. Certain userspace CSPRNGs (e.g. OpenSSL) have contained bugs, causing serious vulnerabilities. frand has some advantages over these CSPRNGs: it never mixes in new entropy, it doesn't maintain an "entropy estimate," and its implementation is extremely simple. Still, if you only need to generate a handful of secret keys, you should probably stick with crypto/rand.

Even if you aren't comfortable using frand for critical secrets, you should still use it everywhere you would normally use an insecure PRNG like math/rand. Go programmers frequently use math/rand because it is faster and more convenient than crypto/rand, and only use crypto/rand when "true" randomness is required. This is an unfortunate state of affairs, because misuse of math/rand can lead to bugs or vulnerabilities. For example, using math/rand to generate "random" test cases will produce identical coverage from run-to-run if the generator is left unseeded. More seriously, using math/rand to salt a hash table may make your program vulnerable to denial of service attacks. Substituting frand for math/rand would avoid both of these outcomes.

Benchmarks

Benchmark frand crypto/rand math/rand (insecure) fastrand
Read (32b) 964 MB/s 59 MB/s 634.21 MB/s 215 MB/s
Read (32b, concurrent) 3566 MB/s 70 MB/s 198.97 MB/s 615 MB/s
Read (512kb) 5094 MB/s 239 MB/s 965.85 MB/s 452 MB/s
Read (512kb, concurrent) 19665 MB/s 191 MB/s 958.01 MB/s 1599 MB/s
Intn (n =~ 4e18) 45 ns/op 725 ns/op 20 ns/op 210 ns/op
BigIntn (n = 2^630) 223 ns/op 1013 ns/op 295 ns/op 468 ns/op
Perm (n = 32) 954 ns/op 17197 ns/op 789 ns/op 5021 ns/op

Benchmark details:

"Concurrent" means the Read function was called in parallel from 64 goroutines.

Intn was benchmarked with n = 2^62 + 1, which maximizes the number of expected retries required to remove bias. The number of expected retries is 1.333.

Owner
Luke Champine
"If the world were perfect, it wouldn't be." - Yogi Berra
Luke Champine
Similar Resources

A simple, fast, and fun package for building command line apps in Go

cli cli is a simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable comm

Dec 31, 2022

Fast, secure, efficient backup program

Fast, secure, efficient backup program

Introduction restic is a backup program that is fast, efficient and secure. It supports the three major operating systems (Linux, macOS, Windows) and

Dec 31, 2022

A fast and powerful alternative to grep

sift A fast and powerful open source alternative to grep. Features sift has a slightly different focus than most other grep alternatives. Code search,

Jan 3, 2023

Experiment - Sync files to S3, fast. Go package and CLI.

gosync I want to be the fastest way to concurrently sync files and directories to/from S3. Gosync will concurrently transfer your files to and from S3

Nov 3, 2022

Alternative archiving tool with fast performance for huge numbers of small files

fast-archiver fast-archiver is a command-line tool for archiving directories, and restoring those archives written in [Go](http://golang.org). fast-ar

Nov 22, 2022

Walrus - Fast, Secure and Reliable System Backup, Set up in Minutes.

Walrus - Fast, Secure and Reliable System Backup, Set up in Minutes.

Walrus is a fast, secure and reliable backup system suitable for modern infrastructure. With walrus, you can backup services like MySQL, PostgreSQL, Redis, etcd or a complete directory with a short interval and low overhead. It supports AWS S3, digitalocean spaces and any S3-compatible object storage service.

Jan 5, 2023

Go implementation of SipHash-2-4, a fast short-input PRF created by Jean-Philippe Aumasson and Daniel J. Bernstein.

SipHash (Go) Go implementation of SipHash-2-4, a fast short-input PRF created by Jean-Philippe Aumasson and Daniel J. Bernstein (http://131002.net/sip

Dec 25, 2022

Fast ring-buffer deque (double-ended queue)

deque Fast ring-buffer deque (double-ended queue) implementation. For a pictorial description, see the Deque diagram Installation $ go get github.com/

Dec 26, 2022

Go native library for fast point tracking and K-Nearest queries

Geo Index Geo Index library Overview Splits the earth surface in a grid. At each cell we can store data, such as list of points, count of points, etc.

Dec 3, 2022

Fast in-memory key:value store/cache with TTL

MCache library go-mcache - this is a fast key:value storage. Its major advantage is that, being essentially a thread-safe . map[string]interface{} wit

Nov 11, 2022

Data structure and relevant algorithms for extremely fast prefix/fuzzy string searching.

Trie Data structure and relevant algorithms for extremely fast prefix/fuzzy string searching. Usage Create a Trie with: t := trie.New() Add Keys with:

Dec 27, 2022

Fast and easy-to-use skip list for Go.

Skip List in Golang Skip list is an ordered map. See wikipedia page skip list to learn algorithm details about this data structure. Highlights in this

Dec 4, 2022

Fast key-value DB in Go.

Fast key-value DB in Go.

BadgerDB BadgerDB is an embeddable, persistent and fast key-value (KV) database written in pure Go. It is the underlying database for Dgraph, a fast,

Dec 29, 2022

Fast thread-safe inmemory cache for big number of entries in Go. Minimizes GC overhead

fastcache - fast thread-safe inmemory cache for big number of entries in Go Features Fast. Performance scales on multi-core CPUs. See benchmark result

Dec 30, 2022

moss - a simple, fast, ordered, persistable, key-val storage library for golang

moss moss provides a simple, fast, persistable, ordered key-val collection implementation as a 100% golang library. moss stands for "memory-oriented s

Dec 18, 2022

A simple, fast, embeddable, persistent key/value store written in pure Go. It supports fully serializable transactions and many data structures such as list, set, sorted set.

NutsDB English | 简体中文 NutsDB is a simple, fast, embeddable and persistent key/value store written in pure Go. It supports fully serializable transacti

Jan 1, 2023

Fast and simple key/value store written using Go's standard library

Fast and simple key/value store written using Go's standard library

Table of Contents Description Usage Cookbook Disadvantages Motivation Benchmarks Test 1 Test 4 Description Package pudge is a fast and simple key/valu

Nov 17, 2022

Fast specialized time-series database for IoT, real-time internet connected devices and AI analytics.

Fast specialized time-series database for IoT, real-time internet connected devices and AI analytics.

unitdb Unitdb is blazing fast specialized time-series database for microservices, IoT, and realtime internet connected devices. As Unitdb satisfy the

Jan 1, 2023

VictoriaMetrics: fast, cost-effective monitoring solution and time series database

VictoriaMetrics: fast, cost-effective monitoring solution and time series database

VictoriaMetrics VictoriaMetrics is a fast, cost-effective and scalable monitoring solution and time series database. It is available in binary release

Jan 8, 2023
Comments
  • Optimize copy+erase with asm

    Optimize copy+erase with asm

    Currently we call copy to output the RNG buffer, then erase to overwrite the buffer with zeros. This is wasteful, as it requires iterating over the buffer contents twice. Instead, we should erase as we copy.

    I tried implementing this in pure Go, but the results were much slower. This is because copy and erase compile down to optimized asm functions (runtime.memmove and runtime.memclrNoHeapPointers), while the new loop does not. So a specialized asm routine is necessary.

    Profiling indicates that this could improve speed by around 10%. So, potentially worth it (especially if it means we can beat (math/rand).Intn). On that note, it's possible that dropping down to asm adds too much overhead for very small buffers (e.g. the 8-byte buffers used by Intn), since custom asm can't be inlined. Perhaps we could add a smallRead function that avoids this cost, and call it in Intn, Perm, etc.

  • Implement

    Implement "nearly-divisionless" Uint64n

    Uint64n uses the same approach as Go's math/rand: truncate the range [0, math.MaxUint64] to the nearest multiple of n, then resample until we get a value within the truncated range and take the modulus. This is fairly fast, and easy to understand, but there's a faster approach that requires no divisions in the common case (whereas the current approach requires at least two). Indeed, math/rand adopted this approach for its Shuffle API (other APIs can't be changed due to the compatibility promise).

    For Hacktoberfest, I'm inviting anyone to implement Lemire's algorithm for the Uint64n function. I expect that the speedup will be relatively small, but frand is all about speed, so we might as well push it to the limit.

Fast (linear time) implementation of the Gaussian Blur algorithm in Go.
Fast (linear time) implementation of the Gaussian Blur algorithm in Go.

Song2 Fast (linear time) implementation of the Gaussian Blur algorithm in Go.

Oct 25, 2022
fast integer log base 10

Package log10 calculates log base 10 of an integer, fast. It is inspired by Daniel Lemire's blog post on this topic. TODO: Add implementations for oth

Mar 3, 2022
How fast could I write tic tac toe in Go, while not knowing Go, but with the aid of GitHub Copilot?

tictactoe-go-with-copilot How fast could I write tic tac toe in Go, while not knowing Go, but with the aid of GitHub Copilot? This took me about 30 mi

Dec 9, 2021
netcat using netstack userspace library

netkat netcat version using raw sockets to avoid iptables and/or other OS filtering mechanisms. Install make build Usage It requires root privileges:

Dec 9, 2022
An userspace SORACOM Arc client powered by wireguard-go

soratun An easy-to-use, userspace SORACOM Arc client powered by wireguard-go. For deploying and scaling Linux servers/Raspberry Pi devices working wit

Jun 2, 2022
Mimic - a eBPF virtual machine and emulator which runs in userspace

Mimic is a eBPF virtual machine and emulator which runs in userspace. Mimic attempts to 'mimic' the eBPF machinery we find in the Linux kernel, as well as other possible implementation/environments.

Dec 6, 2022
llb - It's a very simple but quick backend for proxy servers. Can be useful for fast redirection to predefined domain with zero memory allocation and fast response.

llb What the f--k it is? It's a very simple but quick backend for proxy servers. You can setup redirect to your main domain or just show HTTP/1.1 404

Sep 27, 2022
Chisel is a fast TCP/UDP tunnel, transported over HTTP, secured via SSH.
Chisel is a fast TCP/UDP tunnel, transported over HTTP, secured via SSH.

Chisel is a fast TCP/UDP tunnel, transported over HTTP, secured via SSH. Single executable including both client and server. Written in Go (golang). Chisel is mainly useful for passing through firewalls, though it can also be used to provide a secure endpoint into your network.

Jan 1, 2023
Safe, simple and fast JSON Web Tokens for Go

jwt JSON Web Token for Go RFC 7519, also see jwt.io for more. The latest version is v3. Rationale There are many JWT libraries, but many of them are h

Jan 4, 2023
Fast, secure and efficient secure cookie encoder/decoder

Encode and Decode secure cookies This package provides functions to encode and decode secure cookie values. A secure cookie has its value ciphered and

Dec 9, 2022