Skip to contents

Generate deterministic streams of random data based off a secret key and random nonce.


chacha20(size, key, nonce)

salsa20(size, key, nonce)

xsalsa20(size, key, nonce)



length of cipher stream in bytes


secret key used by the cipher


non-secret unique data to randomize the cipher


You usually don't need to call these methods directly. For local encryption use data_encrypt. For secure communication use simple_encrypt or auth_encrypt.

Random streams form the basis for most cryptographic methods. Based a shared secret (the key) we generate a predictable random data stream of equal length as the message we need to encrypt. Then we xor the message data with this random stream, which effectively inverts each byte in the message with probabiliy 0.5. The message can be decrypted by re-generating exactly the same random data stream and xor'ing it back. See the examples.

Each stream generator requires a key and a nonce. Both are required to re-generate the same stream for decryption. The key forms the shared secret and should only known to the trusted parties. The nonce is not secret and should be stored or sent along with the ciphertext. The purpose of the nonce is to make a random stream unique to protect gainst re-use attacks. This way you can re-use a your key to encrypt multiple messages, as long as you never re-use the same nonce.


# Very basic encryption
myfile <- file.path(R.home(), "COPYING")
message <- readBin(myfile, raw(),$size)
passwd <- charToRaw("My secret passphrase")

# Encrypt:
key <- hash(passwd)
nonce8 <- random(8)
stream <- chacha20(length(message), key, nonce8)
ciphertext <- base::xor(stream, message)

# Decrypt:
stream <- chacha20(length(ciphertext), key, nonce8)
out <- base::xor(ciphertext, stream)
stopifnot(identical(out, message))

# Other stream ciphers
stream <- salsa20(10000, key, nonce8)
stream <- xsalsa20(10000, key, random(24))