sodium/0000755000176200001440000000000013067274754011571 5ustar liggesuserssodium/inst/0000755000176200001440000000000013062010604012517 5ustar liggesuserssodium/inst/doc/0000755000176200001440000000000013062010614013265 5ustar liggesuserssodium/inst/doc/intro.html0000644000176200001440000257467113063263647015355 0ustar liggesusers Sodium: A Modern and Easy-to-Use Crypto Library

The sodium R package provides bindings to libsodium: a modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more.

The goal of Sodium is to provide the core operations needed to build higher-level cryptographic tools. It is not intended for implementing standardized protocols such as TLS, SSH or GPG. Sodium only supports a limited set of state-of-the-art elliptic curve methods, resulting in a simple but very powerful tool-kit for building secure applications.

Authenticated Encryption Encryption only Authentication only
Symmetric (secret key): data_encrypt / data_decrypt data_tag
Asymmetric (public+private key): auth_encrypt / auth_decrypt simple_encrypt / simple_decrypt sig_sign / sig_verify

Using Sodium

All Sodium functions operate on binary data, called ‘raw’ vectors in R. Use charToRaw and rawToChar to convert between strings and raw vectors. Alternatively hex2bin and bin2hex can convert between binary data to strings in hex notation:

test <- hash(charToRaw("test 123"))
str <- bin2hex(test)
print(str)
[1] "e8b785b02e702c0b7edc9683130db36c91e0241ba0c489ff1e20cbb4fa3920f9"
hex2bin(str)
 [1] e8 b7 85 b0 2e 70 2c 0b 7e dc 96 83 13 0d b3 6c 91 e0 24 1b a0 c4 89
[24] ff 1e 20 cb b4 fa 39 20 f9

Random data generator

The random() function generates n bytes of unpredictable data, suitable for creating secret keys.

secret <- random(8)
print(secret)
[1] 90 70 7a fd 1d 39 bc 75

Implementation is platform specific, see the docs for details.

Hash functions

Sodium has several hash functions including hash(), shorthash(), sha256(), sha512 and scrypt(). The generic hash() is usually recommended. It uses blake2b with a configurable size between 16 bytes (128bit) and 64 bytes (512bit).

# Generate keys from passphrase
passphrase <- charToRaw("This is super secret")
hash(passphrase)
 [1] 98 5c 9b b6 f6 92 d5 26 10 80 99 25 3e a5 a6 66 67 13 fd 88 10 b6 12
[24] 74 86 c8 e9 5c 44 07 45 f5
hash(passphrase, size = 16)
 [1] eb 6c df 04 18 40 16 28 c1 b0 2e 76 f3 e6 bd 89
hash(passphrase, size = 64)
 [1] d0 89 68 30 26 1d 1b 85 76 dc ad 20 c9 58 0a fb b1 d0 62 ba 10 d6 80
[24] f6 cb c6 ae 2d 42 57 ee a0 65 fd b0 e8 90 02 ae b3 e0 4f 88 df ba ea
[47] 26 bb 47 3f 29 5a a4 06 cd b8 05 78 83 31 66 dc 7b 24

The shorthash() function is a special 8 byte (64 bit) hash based on SipHash-2-4. The output of this function is only 64 bits (8 bytes). It is useful for in e.g. Hash tables, but it should not be considered collision-resistant.

Secret key encryption

Symmetric encryption uses the same secret key for both encryption and decryption. It is mainly useful for encrypting local data, or as a building block for more complex methods.

Most encryption methods require a nonce: a piece of non-secret unique data that is used to randomize the cipher. This allows for safely using the same key for encrypting multiple messages. The nonce should be stored or shared along with the ciphertext.

key <- hash(charToRaw("This is a secret passphrase"))
msg <- serialize(iris, NULL)

# Encrypt with a random nonce
nonce <- random(24)
cipher <- data_encrypt(msg, key, nonce)

# Decrypt with same key and nonce
orig <- data_decrypt(cipher, key, nonce)
identical(iris, unserialize(orig))
[1] TRUE

Because the secret has to be known by all parties, symmetric encryption by itself is often impractical for communication with third parties. For this we need asymmetric (public key) methods.

Secret key authentication

Secret key authentication is called tagging in Sodium. A tag is basically a hash of the data together with a secret key.

key <- hash(charToRaw("This is a secret passphrase"))
msg <- serialize(iris, NULL)
mytag <- data_tag(msg, key)

To verify the integrity of the data at a later point in time, simply re-calculate the tag with the same key:

stopifnot(identical(mytag, data_tag(msg, key)))

The secret key protects against forgery of the data+tag by an intermediate party, as would be possible with a regular checksum.

Public key encryption

Where symmetric methods use the same secret key for encryption and decryption, asymmetric methods use a key-pair consisting of a public key and private key. The private key is secret and only known by its owner. The public key on the other hand can be shared with anyone. Public keys are often published on the user’s website or posted in public directories or keyservers.

key <- keygen()
pub <- pubkey(key)

In public key encryption, data encrypted with a public key can only be decrypted using the corresponding private key. This allows anyone to send somebody a secure message by encrypting it with the receivers public key. The encrypted message will only be readable by the owner of the corresponding private key.

# Encrypt message with pubkey
msg <- serialize(iris, NULL)
ciphertext <- simple_encrypt(msg, pub)

# Decrypt message with private key
out <- simple_decrypt(ciphertext, key)
stopifnot(identical(out, msg))

Public key authentication (signatures)

Public key authentication works the other way around. First, the owner of the private key creates a ‘signature’ (an authenticated checksum) for a message in a way that allows anyone who knows his/her public key to verify the integrity of the message and identity of the sender.

Currently sodium requires a different type of key-pair for signatures (ed25519) than for encryption (curve25519).

# Generate signature keypair
key <- sig_keygen()
pubkey <- sig_pubkey(key)

# Create signature with private key
msg <- serialize(iris, NULL)
sig <- sig_sign(msg, key)
print(sig)
 [1] 75 b0 62 9b 52 e0 2a 00 21 f2 f1 d8 61 09 a7 88 25 82 5c 4a a6 c7 c5
[24] 4e 8f 0c c6 ff 6d 57 26 71 94 b7 6a 15 c9 a3 b6 c9 d6 80 6a 04 93 7a
[47] 7e 81 b6 95 b7 01 20 20 77 f0 77 ea d4 7f 52 f2 67 05
# Verify a signature from public key
sig_verify(msg, sig, pubkey)
[1] TRUE

Signatures are useful when the message itself is not confidential but integrity is important. A common use is for software repositories where to include an index file with checksums for all packages, signed by the repository maintainer. This allows client package managers to verify that the binaries were not manipulated by intermediate parties during the distribution process.

Public key authenticated encryption

Authenticated encryption implements best practices for secure messaging. It requires that both sender and receiver have a keypair and know each other’s public key. Each message gets authenticated with the key of the sender and encrypted with the key of the receiver.

# Bob's keypair:
bob_key <- keygen()
bob_pubkey <- pubkey(bob_key)

# Alice's keypair:
alice_key <- keygen()
alice_pubkey <- pubkey(alice_key)

# Bob sends encrypted message for Alice:
msg <- charToRaw("TTIP is evil")
ciphertext <- auth_encrypt(msg, bob_key, alice_pubkey)

# Alice verifies and decrypts with her key
out <- auth_decrypt(ciphertext, alice_key, bob_pubkey)
stopifnot(identical(out, msg))

# Alice sends encrypted message for Bob
msg <- charToRaw("Let's protest")
ciphertext <- auth_encrypt(msg, alice_key, bob_pubkey)

# Bob verifies and decrypts with his key
out <- auth_decrypt(ciphertext, bob_key, alice_pubkey)
stopifnot(identical(out, msg))

Note that even though public keys are not confidential, you should not exchange them over the same insecure channel you are trying to protect. If the connection is being tampered with, the attacker could simply replace the key with another one to hijack the interaction.

sodium/inst/doc/crypto101.html0000644000176200001440000257631113063263647015755 0ustar liggesusers How does cryptography work?

This page attempts to give a very basic conceptual introduction to cryptographic methods. Before we start the usual disclaimer:

I am not a cryptographer. This document is only for educational purposes. Crypto is hard, you should never trust your home-grown implementation. Unless you’re a cryptographer you will probably overlook some crucial details. Developers should only use the high-level functions that have been implemented by an actual cryptographer.

Now that we got this is out of the way, let’s start hacking :)

The XOR operator

The bitwise XOR operator outputs true only when both inputs differ (one is true, the other is false). It is sometimes called an invertor because the output of a bit in x gets inverted if and only if the corresponding bit in y is true:

# XOR two (8bit) bytes 'x' and 'y'
x <- as.raw(0x7a)
y <- as.raw(0xe4)
z <- base::xor(x, y)
dput(z)
as.raw(0x9e)
# Show the bits in each byte
cbind(x = rawToBits(x), y = rawToBits(y), z = rawToBits(z))
      x  y  z
[1,] 00 00 00
[2,] 01 00 01
[3,] 00 01 01
[4,] 01 00 01
[5,] 01 00 01
[6,] 01 01 00
[7,] 01 01 00
[8,] 00 01 01

In cryptography we xor a message x with secret random data y. Because each bit in y is randomly true with probability 0.5, the xor output is completely random and uncorrelated to x. This is called perfect secrecy. Only if we know y we can decipher the message x.

# Encrypt message using random one-time-pad
msg <- charToRaw("TTIP is evil")
one_time_pad <- random(length(msg))
ciphertext <- base::xor(msg, one_time_pad)

# It's really encrypted
rawToChar(ciphertext)
[1] "\xe9\x8c8\u009fd\xfd\x93\xf1\xed/%"
# Decrypt with same pad
rawToChar(base::xor(ciphertext, one_time_pad))
[1] "TTIP is evil"

This method is perfectly secure and forms the basis for most cryptograhpic methods. However the challenge is generating and communicating unique pseudo-random y data every time we want to encrypt something. One-time-pads as in the example are not very practical for large messages. Also we should never re-use a one-time-pad y for encrypting multiple messages, as this compromises the secrecy.

Stream ciphers

The solution to this problem are stream ciphers. A stream cipher generates a unique stream of pseudo-random data based on a secret key and a unique nonce. For a given set of parameters the stream cipher always generates the same stream of data. Sodium implements a few popular stream ciphers:

password <- "My secret passphrase"
key <- hash(charToRaw(password))
nonce <- random(8)
chacha20(size = 20, key, nonce)
 [1] bb 96 2f 70 96 7d bd 2d ee 20 b5 e6 61 50 59 7b e7 be d1 9f

Each stream requires a key and a nonce. The key forms the shared secret and should only be known to trusted parties. The nonce is not secret and is 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.

salsa20(size = 20, key, nonce)
 [1] 56 47 ff d1 96 14 3a f2 f2 70 30 fe ba 8a 05 1e 74 2a 4d be

Over the years cryptographers have come up with many more variants. Many stream ciphers are based on a block cipher such as AES: a keyed permutation of fixed length amount of data. The block ciphers get chained in a particular mode of operation which repeatedly applies the cipher’s single-block operation to securely transform amounts of data larger than a block.

We are not going to discuss implementation details, but you could probably come up with something yourself. For example you could use a hash function such sha256 as the block cipher and append counter which is incremented for each block (this is called CTR mode).

# Illustrative example.
sha256_ctr <- function(size, key, nonce){
  n <- ceiling(size/32)
  output <- raw()
  for(i in 1:n){
    counter <- packBits(intToBits(i))
    block <- sha256(c(key, nonce, counter))
    output <- c(output, block)
  }
  return(output[1:size])
}

This allows us to generate an arbitrary length stream from a single secret key:

password <- "My secret passphrase"
key <- hash(charToRaw(password))
nonce <- random(8)
sha256_ctr(50, key, nonce)
 [1] e3 29 96 fb b5 bd 15 d7 55 df d7 b3 1e 12 d1 5c 0b 74 86 4a 5d 85 b3
[24] bf aa 62 bb 6e 0b d3 bf ab 05 a2 31 9f a6 3a fd 83 1d 26 9f 7f 35 8d
[47] eb ec eb c3

In practice, you should never write your own ciphers. A lot of research goes into studying the properties of block ciphers under various modes of operation. In the remainder we just use the standard Sodium ciphers: chacha20, salsa20 or xsalsa20.

Symmetric encryption

Symmetric encryption means that the same secret key is used for both encryption and decryption. All that is needed to implement symmetric encryption is xor and a stream cipher. For example to encrypt an arbitrary length message using password:

# Encrypt 'message' using 'password'
myfile <- file.path(R.home(), "COPYING")
message <- readBin(myfile, raw(), file.info(myfile)$size)
passwd <- charToRaw("My secret passphrase")

A hash function converts the password to a key of suitable size for the stream cipher, which we use to generate a psuedo random stream of equal length to the message:

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

Now the ciphertext is an encrypted version of the message. Only those that know the key and the nonce can re-generate the same keystream in order to xor the ciphertext back into the original message.

# Decrypt with the same key
key <- hash(charToRaw("My secret passphrase"))
stream <- chacha20(length(ciphertext), key, nonce8)
out <- base::xor(ciphertext, stream)

# Print part of the message
cat(substring(rawToChar(out), 1, 120))
            GNU GENERAL PUBLIC LICENSE
               Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.

The Sodium functions data_encrypt and data_decrypt provide a more elaborate implementation of the above. This is what you should use in practice for secret key encryption.

Symmetric encryption can be used for e.g. encrypting local data. However because the same secret is used for both encryption and decryption, it is impractical for communication with other parties. For exchanging secure messages we need public key encryption.

Public-key encryption and Diffie-Hellman

Rather than using a single secret-key, assymetric (public key) encryption requires a keypair, consisting of a public key for encryption and a private-key for decryption. Data that is encrypted using a given public key can only be decrypted using the corresponding private key.

The public key is not confidential and can be shared on e.g. a website or keyserver. This allows anyone to send somebody a secure message by encrypting it with the receivers public key. The encrypted message will only be readable by the owner of the corresponding private key.

# Create keypair
key <- keygen()
pub <- pubkey(key)

# Encrypt message for receiver using his/her public key
msg <- serialize(iris, NULL)
ciphertext <- simple_encrypt(msg, pub)

# Receiver decrypts with his/her private key
out <- simple_decrypt(ciphertext, key)
identical(msg, out)
[1] TRUE

How does this work? Public key encryption makes use of Diffie-Hellman (D-H): a method which allows two parties that have no prior knowledge of each other to jointly establish a shared secret key over an insecure channel. In the most simple case, both parties generate a temporary keypair and exchange their public key over the insecure channel. Then both parties use the D-H function to calculcate the (same) shared secret key by combining their own private key with the other person’s public key:

# Bob generates keypair
bob_key <- keygen()
bob_pubkey <- pubkey(bob_key)

# Alice generates keypair
alice_key <- keygen()
alice_pubkey <- pubkey(alice_key)

# After Bob and Alice exchange pubkey they can both derive the secret
alice_secret <- diffie_hellman(alice_key, bob_pubkey)
bob_secret <- diffie_hellman(bob_key, alice_pubkey)
identical(alice_secret, bob_secret)
[1] TRUE

Once the shared secret has been established, both parties can discard their temporary public/private key and use the shared secret to start encrypting communications with symmetric encryption as discussed earlier. Because the shared secret cannot be calculated using only the public keys, the process is safe from eavesdroppers.

The classical Diffie-Hellman method is based on the discrete logarithm problem with large prime numbers. Sodium uses curve25519, a state-of-the-art D-H function by Daniel Bernsteinan designed for use with the elliptic curve Diffie–Hellman (ECDH) key agreement scheme.

sodium/inst/doc/intro.R0000644000176200001440000000530413063263647014566 0ustar liggesusers## ---- echo = FALSE, message = FALSE-------------------------------------- knitr::opts_chunk$set(comment = "") library(sodium) ## ------------------------------------------------------------------------ test <- hash(charToRaw("test 123")) str <- bin2hex(test) print(str) hex2bin(str) ## ------------------------------------------------------------------------ secret <- random(8) print(secret) ## ------------------------------------------------------------------------ # Generate keys from passphrase passphrase <- charToRaw("This is super secret") hash(passphrase) hash(passphrase, size = 16) hash(passphrase, size = 64) ## ------------------------------------------------------------------------ key <- hash(charToRaw("This is a secret passphrase")) msg <- serialize(iris, NULL) # Encrypt with a random nonce nonce <- random(24) cipher <- data_encrypt(msg, key, nonce) # Decrypt with same key and nonce orig <- data_decrypt(cipher, key, nonce) identical(iris, unserialize(orig)) ## ------------------------------------------------------------------------ key <- hash(charToRaw("This is a secret passphrase")) msg <- serialize(iris, NULL) mytag <- data_tag(msg, key) ## ------------------------------------------------------------------------ stopifnot(identical(mytag, data_tag(msg, key))) ## ------------------------------------------------------------------------ key <- keygen() pub <- pubkey(key) ## ------------------------------------------------------------------------ # Encrypt message with pubkey msg <- serialize(iris, NULL) ciphertext <- simple_encrypt(msg, pub) # Decrypt message with private key out <- simple_decrypt(ciphertext, key) stopifnot(identical(out, msg)) ## ------------------------------------------------------------------------ # Generate signature keypair key <- sig_keygen() pubkey <- sig_pubkey(key) # Create signature with private key msg <- serialize(iris, NULL) sig <- sig_sign(msg, key) print(sig) # Verify a signature from public key sig_verify(msg, sig, pubkey) ## ------------------------------------------------------------------------ # Bob's keypair: bob_key <- keygen() bob_pubkey <- pubkey(bob_key) # Alice's keypair: alice_key <- keygen() alice_pubkey <- pubkey(alice_key) # Bob sends encrypted message for Alice: msg <- charToRaw("TTIP is evil") ciphertext <- auth_encrypt(msg, bob_key, alice_pubkey) # Alice verifies and decrypts with her key out <- auth_decrypt(ciphertext, alice_key, bob_pubkey) stopifnot(identical(out, msg)) # Alice sends encrypted message for Bob msg <- charToRaw("Let's protest") ciphertext <- auth_encrypt(msg, alice_key, bob_pubkey) # Bob verifies and decrypts with his key out <- auth_decrypt(ciphertext, bob_key, alice_pubkey) stopifnot(identical(out, msg)) sodium/inst/doc/crypto101.rmd0000644000176200001440000002252613063263647015563 0ustar liggesusers--- title: "How does cryptography work?" output: html_document date: "`r Sys.Date()`" vignette: > %\VignetteIndexEntry{How does cryptography work} %\VignetteEngine{knitr::rmarkdown} \usepackage[utf8]{inputenc} --- ```{r, echo = FALSE, message = FALSE} knitr::opts_chunk$set(comment = "") library(sodium) # hack for printable bits random <- function(n = 1){ if(n != nchar("TTIP is evil")) return(sodium::random(n)) repeat { x <- sodium::random(n) y <- base::xor(charToRaw("TTIP is evil"), x) if(all(c(x,y) != 0)) return(x) } } ``` This page attempts to give a very basic conceptual introduction to cryptographic methods. Before we start the usual disclaimer: ___I am not a cryptographer. This document is only for educational purposes. Crypto is hard, you should never trust your home-grown implementation. Unless you're a cryptographer you will probably overlook some crucial details. Developers should only use the high-level functions that have been implemented by an actual cryptographer.___ Now that we got this is out of the way, let's start hacking :) ### The XOR operator The bitwise [XOR operator](https://en.wikipedia.org/wiki/Exclusive_or#Truth_table) outputs `true` only when both inputs differ (one is `true`, the other is `false`). It is sometimes called an *invertor* because the output of a bit in `x` gets inverted if and only if the corresponding bit in `y` is true: ```{r} # XOR two (8bit) bytes 'x' and 'y' x <- as.raw(0x7a) y <- as.raw(0xe4) z <- base::xor(x, y) dput(z) # Show the bits in each byte cbind(x = rawToBits(x), y = rawToBits(y), z = rawToBits(z)) ``` In cryptography we `xor` a message `x` with secret random data `y`. Because each bit in `y` is randomly `true` with probability 0.5, the `xor` output is completely random and uncorrelated to `x`. This is called *perfect secrecy*. Only if we know `y` we can decipher the message `x`. ```{r} # Encrypt message using random one-time-pad msg <- charToRaw("TTIP is evil") one_time_pad <- random(length(msg)) ciphertext <- base::xor(msg, one_time_pad) # It's really encrypted rawToChar(ciphertext) # Decrypt with same pad rawToChar(base::xor(ciphertext, one_time_pad)) ``` This method is perfectly secure and forms the basis for most cryptograhpic methods. However the challenge is generating and communicating unique pseudo-random `y` data every time we want to encrypt something. One-time-pads as in the example are not very practical for large messages. Also we should never re-use a one-time-pad `y` for encrypting multiple messages, as this compromises the secrecy. ### Stream ciphers The solution to this problem are stream ciphers. A *stream cipher* generates a unique stream of pseudo-random data based on a secret `key` and a unique `nonce`. For a given set of parameters the stream cipher always generates the same stream of data. Sodium implements a few popular stream ciphers: ```{r} password <- "My secret passphrase" key <- hash(charToRaw(password)) nonce <- random(8) chacha20(size = 20, key, nonce) ``` Each stream requires a `key` and a `nonce`. The key forms the shared secret and should only be known to trusted parties. The `nonce` is not secret and is 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. ```{r} salsa20(size = 20, key, nonce) ``` Over the years cryptographers have come up with many more variants. Many stream ciphers are based on a block cipher such as [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard): a keyed permutation of fixed length amount of data. The block ciphers get chained in a particular [mode of operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation) which repeatedly applies the cipher's single-block operation to securely transform amounts of data larger than a block. We are not going to discuss implementation details, but you could probably come up with something yourself. For example you could use a hash function such `sha256` as the block cipher and append counter which is incremented for each block (this is called CTR mode). ```{r} # Illustrative example. sha256_ctr <- function(size, key, nonce){ n <- ceiling(size/32) output <- raw() for(i in 1:n){ counter <- packBits(intToBits(i)) block <- sha256(c(key, nonce, counter)) output <- c(output, block) } return(output[1:size]) } ``` This allows us to generate an arbitrary length stream from a single secret key: ```{r} password <- "My secret passphrase" key <- hash(charToRaw(password)) nonce <- random(8) sha256_ctr(50, key, nonce) ``` In practice, you should never write your own ciphers. A lot of [research](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.58.1811&rep=rep1&type=pdf) goes into studying the properties of block ciphers under various modes of operation. In the remainder we just use the standard Sodium ciphers: [`chacha20`](https://download.libsodium.org/libsodium/content/advanced/chacha20.html), [`salsa20`](https://download.libsodium.org/libsodium/content/advanced/salsa20.html) or [`xsalsa20`](https://download.libsodium.org/libsodium/content/advanced/xsalsa20.html). ### Symmetric encryption Symmetric encryption means that the same secret key is used for both encryption and decryption. All that is needed to implement symmetric encryption is `xor` and a stream cipher. For example to encrypt an arbitrary length `message` using `password`: ```{r} # Encrypt 'message' using 'password' myfile <- file.path(R.home(), "COPYING") message <- readBin(myfile, raw(), file.info(myfile)$size) passwd <- charToRaw("My secret passphrase") ``` A hash function converts the password to a key of suitable size for the stream cipher, which we use to generate a psuedo random stream of equal length to the message: ```{r} # Basic secret key encryption key <- hash(passwd) nonce8 <- random(8) stream <- chacha20(length(message), key, nonce8) ciphertext <- base::xor(stream, message) ``` Now the `ciphertext` is an encrypted version of the message. Only those that know the `key` and the `nonce` can re-generate the same keystream in order to `xor` the ciphertext back into the original message. ```{r} # Decrypt with the same key key <- hash(charToRaw("My secret passphrase")) stream <- chacha20(length(ciphertext), key, nonce8) out <- base::xor(ciphertext, stream) # Print part of the message cat(substring(rawToChar(out), 1, 120)) ``` The Sodium functions `data_encrypt` and `data_decrypt` provide a more elaborate implementation of the above. This is what you should use in practice for secret key encryption. Symmetric encryption can be used for e.g. encrypting local data. However because the same secret is used for both encryption and decryption, it is impractical for communication with other parties. For exchanging secure messages we need public key encryption. ### Public-key encryption and Diffie-Hellman Rather than using a single secret-key, assymetric (public key) encryption requires a *keypair*, consisting of a *public key* for encryption and a *private-key* for decryption. Data that is encrypted using a given public key can only be decrypted using the corresponding private key. The public key is not confidential and can be shared on e.g. a website or keyserver. This allows anyone to send somebody a secure message by encrypting it with the receivers public key. The encrypted message will only be readable by the owner of the corresponding private key. ```{r} # Create keypair key <- keygen() pub <- pubkey(key) # Encrypt message for receiver using his/her public key msg <- serialize(iris, NULL) ciphertext <- simple_encrypt(msg, pub) # Receiver decrypts with his/her private key out <- simple_decrypt(ciphertext, key) identical(msg, out) ``` How does this work? Public key encryption makes use of [Diffie-Hellman](http://mathworld.wolfram.com/Diffie-HellmanProtocol.html) (D-H): a method which allows two parties that have no prior knowledge of each other to jointly establish a shared secret key over an insecure channel. In the most simple case, both parties generate a temporary keypair and exchange their public key over the insecure channel. Then both parties use the D-H function to calculcate the (same) shared secret key by combining their own private key with the other person's public key: ```{r} # Bob generates keypair bob_key <- keygen() bob_pubkey <- pubkey(bob_key) # Alice generates keypair alice_key <- keygen() alice_pubkey <- pubkey(alice_key) # After Bob and Alice exchange pubkey they can both derive the secret alice_secret <- diffie_hellman(alice_key, bob_pubkey) bob_secret <- diffie_hellman(bob_key, alice_pubkey) identical(alice_secret, bob_secret) ``` Once the shared secret has been established, both parties can discard their temporary public/private key and use the shared secret to start encrypting communications with symmetric encryption as discussed earlier. Because the shared secret cannot be calculated using only the public keys, the process is safe from eavesdroppers. The classical [Diffie-Hellman method](http://mathworld.wolfram.com/Diffie-HellmanProtocol.html) is based on the discrete logarithm problem with large prime numbers. Sodium uses [curve25519](http://cr.yp.to/ecdh/curve25519-20060209.pdf), a state-of-the-art D-H function by Daniel Bernsteinan designed for use with the elliptic curve Diffie–Hellman (ECDH) key agreement scheme. sodium/inst/doc/crypto101.R0000644000176200001440000000656513063263647015207 0ustar liggesusers## ---- echo = FALSE, message = FALSE-------------------------------------- knitr::opts_chunk$set(comment = "") library(sodium) # hack for printable bits random <- function(n = 1){ if(n != nchar("TTIP is evil")) return(sodium::random(n)) repeat { x <- sodium::random(n) y <- base::xor(charToRaw("TTIP is evil"), x) if(all(c(x,y) != 0)) return(x) } } ## ------------------------------------------------------------------------ # XOR two (8bit) bytes 'x' and 'y' x <- as.raw(0x7a) y <- as.raw(0xe4) z <- base::xor(x, y) dput(z) # Show the bits in each byte cbind(x = rawToBits(x), y = rawToBits(y), z = rawToBits(z)) ## ------------------------------------------------------------------------ # Encrypt message using random one-time-pad msg <- charToRaw("TTIP is evil") one_time_pad <- random(length(msg)) ciphertext <- base::xor(msg, one_time_pad) # It's really encrypted rawToChar(ciphertext) # Decrypt with same pad rawToChar(base::xor(ciphertext, one_time_pad)) ## ------------------------------------------------------------------------ password <- "My secret passphrase" key <- hash(charToRaw(password)) nonce <- random(8) chacha20(size = 20, key, nonce) ## ------------------------------------------------------------------------ salsa20(size = 20, key, nonce) ## ------------------------------------------------------------------------ # Illustrative example. sha256_ctr <- function(size, key, nonce){ n <- ceiling(size/32) output <- raw() for(i in 1:n){ counter <- packBits(intToBits(i)) block <- sha256(c(key, nonce, counter)) output <- c(output, block) } return(output[1:size]) } ## ------------------------------------------------------------------------ password <- "My secret passphrase" key <- hash(charToRaw(password)) nonce <- random(8) sha256_ctr(50, key, nonce) ## ------------------------------------------------------------------------ # Encrypt 'message' using 'password' myfile <- file.path(R.home(), "COPYING") message <- readBin(myfile, raw(), file.info(myfile)$size) passwd <- charToRaw("My secret passphrase") ## ------------------------------------------------------------------------ # Basic secret key encryption key <- hash(passwd) nonce8 <- random(8) stream <- chacha20(length(message), key, nonce8) ciphertext <- base::xor(stream, message) ## ------------------------------------------------------------------------ # Decrypt with the same key key <- hash(charToRaw("My secret passphrase")) stream <- chacha20(length(ciphertext), key, nonce8) out <- base::xor(ciphertext, stream) # Print part of the message cat(substring(rawToChar(out), 1, 120)) ## ------------------------------------------------------------------------ # Create keypair key <- keygen() pub <- pubkey(key) # Encrypt message for receiver using his/her public key msg <- serialize(iris, NULL) ciphertext <- simple_encrypt(msg, pub) # Receiver decrypts with his/her private key out <- simple_decrypt(ciphertext, key) identical(msg, out) ## ------------------------------------------------------------------------ # Bob generates keypair bob_key <- keygen() bob_pubkey <- pubkey(bob_key) # Alice generates keypair alice_key <- keygen() alice_pubkey <- pubkey(alice_key) # After Bob and Alice exchange pubkey they can both derive the secret alice_secret <- diffie_hellman(alice_key, bob_pubkey) bob_secret <- diffie_hellman(bob_key, alice_pubkey) identical(alice_secret, bob_secret) sodium/inst/doc/intro.rmd0000644000176200001440000001750613063263647015156 0ustar liggesusers--- title: "Sodium: A Modern and Easy-to-Use Crypto Library" output: html_document: toc: false date: "`r Sys.Date()`" vignette: > %\VignetteIndexEntry{Introduction to Sodium for R} %\VignetteEngine{knitr::rmarkdown} \usepackage[utf8]{inputenc} --- ```{r, echo = FALSE, message = FALSE} knitr::opts_chunk$set(comment = "") library(sodium) ``` The sodium R package provides bindings to [libsodium](https://download.libsodium.org/doc/): a modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more. The goal of Sodium is to provide the core operations needed to build higher-level cryptographic tools. It is not intended for implementing standardized protocols such as TLS, SSH or GPG. Sodium only supports a limited set of state-of-the-art elliptic curve methods, resulting in a simple but very powerful tool-kit for building secure applications. | | Authenticated Encryption | Encryption only | Authentication only | |-----------------------------:|:--------------------------------:|:-----------------------------------:|:--------------------------:| | __Symmetric__ *(secret key)*: | [`data_encrypt` / `data_decrypt`](#secret-key-encryption) | | [`data_tag`](#secret-key-authentication) | | __Asymmetric__ *(public+private key)*: | [`auth_encrypt` / `auth_decrypt`](#public-key-authenticated-encryption) | [`simple_encrypt` / `simple_decrypt`](#public-key-encryption) | [`sig_sign` / `sig_verify`](#public-key-authentication-signatures) | | | | | | ### Using Sodium All Sodium functions operate on binary data, called 'raw' vectors in R. Use `charToRaw` and `rawToChar` to convert between strings and raw vectors. Alternatively `hex2bin` and `bin2hex` can convert between binary data to strings in hex notation: ```{r} test <- hash(charToRaw("test 123")) str <- bin2hex(test) print(str) hex2bin(str) ``` ### Random data generator The `random()` function generates n bytes of unpredictable data, suitable for creating secret keys. ```{r} secret <- random(8) print(secret) ``` Implementation is platform specific, see the [docs](https://download.libsodium.org/doc/generating_random_data/index.html) for details. ### Hash functions Sodium has several hash functions including `hash()`, `shorthash()`, `sha256()`, `sha512` and `scrypt()`. The generic `hash()` is usually recommended. It uses [blake2b](https://download.libsodium.org/doc/hashing/generic_hashing.html) with a configurable size between 16 bytes (128bit) and 64 bytes (512bit). ```{r} # Generate keys from passphrase passphrase <- charToRaw("This is super secret") hash(passphrase) hash(passphrase, size = 16) hash(passphrase, size = 64) ``` The `shorthash()` function is a special 8 byte (64 bit) hash based on [SipHash-2-4](https://download.libsodium.org/doc/hashing/short-input_hashing.html). The output of this function is only 64 bits (8 bytes). It is useful for in e.g. Hash tables, but it should not be considered collision-resistant. ### Secret key encryption Symmetric encryption uses the same secret key for both encryption and decryption. It is mainly useful for encrypting local data, or as a building block for more complex methods. Most encryption methods require a `nonce`: a piece of non-secret unique data that is used to randomize the cipher. This allows for safely using the same `key` for encrypting multiple messages. The nonce should be stored or shared along with the ciphertext. ```{r} key <- hash(charToRaw("This is a secret passphrase")) msg <- serialize(iris, NULL) # Encrypt with a random nonce nonce <- random(24) cipher <- data_encrypt(msg, key, nonce) # Decrypt with same key and nonce orig <- data_decrypt(cipher, key, nonce) identical(iris, unserialize(orig)) ``` Because the secret has to be known by all parties, symmetric encryption by itself is often impractical for communication with third parties. For this we need asymmetric (public key) methods. ### Secret key authentication Secret key authentication is called tagging in Sodium. A tag is basically a hash of the data together with a secret key. ```{r} key <- hash(charToRaw("This is a secret passphrase")) msg <- serialize(iris, NULL) mytag <- data_tag(msg, key) ``` To verify the integrity of the data at a later point in time, simply re-calculate the tag with the same key: ```{r} stopifnot(identical(mytag, data_tag(msg, key))) ``` The secret key protects against forgery of the data+tag by an intermediate party, as would be possible with a regular checksum. ### Public key encryption Where symmetric methods use the same secret key for encryption and decryption, asymmetric methods use a key-pair consisting of a public key and private key. The private key is secret and only known by its owner. The public key on the other hand can be shared with anyone. Public keys are often published on the user's website or posted in public directories or keyservers. ```{r} key <- keygen() pub <- pubkey(key) ``` In public key encryption, data encrypted with a public key can only be decrypted using the corresponding private key. This allows anyone to send somebody a secure message by encrypting it with the receivers public key. The encrypted message will only be readable by the owner of the corresponding private key. ```{r} # Encrypt message with pubkey msg <- serialize(iris, NULL) ciphertext <- simple_encrypt(msg, pub) # Decrypt message with private key out <- simple_decrypt(ciphertext, key) stopifnot(identical(out, msg)) ``` ### Public key authentication (signatures) Public key authentication works the other way around. First, the owner of the private key creates a 'signature' (an authenticated checksum) for a message in a way that allows anyone who knows his/her public key to verify the integrity of the message and identity of the sender. Currently sodium requires a different type of key-pair for signatures (ed25519) than for encryption (curve25519). ```{r} # Generate signature keypair key <- sig_keygen() pubkey <- sig_pubkey(key) # Create signature with private key msg <- serialize(iris, NULL) sig <- sig_sign(msg, key) print(sig) # Verify a signature from public key sig_verify(msg, sig, pubkey) ``` Signatures are useful when the message itself is not confidential but integrity is important. A common use is for software repositories where to include an index file with checksums for all packages, signed by the repository maintainer. This allows client package managers to verify that the binaries were not manipulated by intermediate parties during the distribution process. ### Public key authenticated encryption Authenticated encryption implements best practices for secure messaging. It requires that both sender and receiver have a keypair and know each other's public key. Each message gets authenticated with the key of the sender and encrypted with the key of the receiver. ```{r} # Bob's keypair: bob_key <- keygen() bob_pubkey <- pubkey(bob_key) # Alice's keypair: alice_key <- keygen() alice_pubkey <- pubkey(alice_key) # Bob sends encrypted message for Alice: msg <- charToRaw("TTIP is evil") ciphertext <- auth_encrypt(msg, bob_key, alice_pubkey) # Alice verifies and decrypts with her key out <- auth_decrypt(ciphertext, alice_key, bob_pubkey) stopifnot(identical(out, msg)) # Alice sends encrypted message for Bob msg <- charToRaw("Let's protest") ciphertext <- auth_encrypt(msg, alice_key, bob_pubkey) # Bob verifies and decrypts with his key out <- auth_decrypt(ciphertext, bob_key, alice_pubkey) stopifnot(identical(out, msg)) ``` Note that even though public keys are not confidential, you should not exchange them over the same insecure channel you are trying to protect. If the connection is being tampered with, the attacker could simply replace the key with another one to hijack the interaction. sodium/src/0000755000176200001440000000000013067251130012337 5ustar liggesuserssodium/src/secret.c0000644000176200001440000000374413067251130014000 0ustar liggesusers#include #include #include SEXP R_crypto_secret_encrypt(SEXP message, SEXP key, SEXP nonce){ if(LENGTH(key) != crypto_secretbox_KEYBYTES) Rf_error("Invalid key: must be exactly %d bytes", crypto_secretbox_KEYBYTES); if(LENGTH(nonce) != crypto_secretbox_NONCEBYTES) Rf_error("Invalid nonce: must be exactly %d bytes", crypto_secretbox_NONCEBYTES); int mlen = LENGTH(message); int clen = mlen + crypto_secretbox_MACBYTES; SEXP res = allocVector(RAWSXP, clen); if(crypto_secretbox_easy(RAW(res), RAW(message), mlen, RAW(nonce), RAW(key))) Rf_error("Failed to encrypt"); return res; } SEXP R_crypto_secret_decrypt(SEXP cipher, SEXP key, SEXP nonce){ if(LENGTH(key) != crypto_secretbox_KEYBYTES) Rf_error("Invalid key. Key must be exactly %d bytes", crypto_secretbox_KEYBYTES); if(LENGTH(nonce) != crypto_secretbox_NONCEBYTES) Rf_error("Invalid key. Key must be exactly %d bytes", crypto_secretbox_NONCEBYTES); int clen = LENGTH(cipher); int mlen = clen - crypto_secretbox_MACBYTES; SEXP res = allocVector(RAWSXP, mlen); if(crypto_secretbox_open_easy(RAW(res), RAW(cipher), clen, RAW(nonce), RAW(key))) Rf_error("Failed to decrypt"); return res; } SEXP R_crypto_secret_auth(SEXP message, SEXP key){ if(LENGTH(key) != crypto_auth_KEYBYTES) Rf_error("Invalid key. Key must be exactly %d bytes", crypto_auth_KEYBYTES); SEXP res = allocVector(RAWSXP, crypto_auth_BYTES); if(crypto_auth(RAW(res), RAW(message), LENGTH(message), RAW(key))) Rf_error("Authentication failed."); return res; } SEXP R_crypto_secret_verify(SEXP message, SEXP key, SEXP tag){ if(LENGTH(key) != crypto_auth_KEYBYTES) Rf_error("Invalid key. Key must be exactly %d bytes", crypto_auth_KEYBYTES); if(LENGTH(tag) != crypto_auth_BYTES) Rf_error("Invalid tag. Key must be exactly %d bytes", crypto_auth_BYTES); int res = crypto_auth_verify(RAW(tag), RAW(message), LENGTH(message), RAW(key)); return ScalarLogical(res == 0); } sodium/src/diffie.c0000644000176200001440000000102513067251130013727 0ustar liggesusers#include #include SEXP R_diffie_hellman(SEXP key, SEXP pubkey){ if(LENGTH(key) != crypto_scalarmult_SCALARBYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_scalarmult_SCALARBYTES); if(LENGTH(pubkey) != crypto_scalarmult_BYTES) Rf_error("Invalid pubkey, must be exactly %d bytes", crypto_scalarmult_BYTES); SEXP res = allocVector(RAWSXP, crypto_scalarmult_BYTES); if(crypto_scalarmult(RAW(res), RAW(key), RAW(pubkey))) Rf_error("Failed crypto_scalarmult"); return res; } sodium/src/seal.c0000644000176200001440000000164213067251130013432 0ustar liggesusers#include #include SEXP R_seal_box(SEXP msg, SEXP pubkey){ if(LENGTH(pubkey) != crypto_box_PUBLICKEYBYTES) Rf_error("Invalid pubkey, must be exactly %d bytes", crypto_box_PUBLICKEYBYTES); int mlen = LENGTH(msg); int clen = mlen + crypto_box_SEALBYTES; SEXP res = allocVector(RAWSXP, clen); if(crypto_box_seal(RAW(res), RAW(msg), mlen, RAW(pubkey))) Rf_error("Failed to encrypt"); return res; } SEXP R_seal_open(SEXP cipher, SEXP key){ if(LENGTH(key) != crypto_box_SECRETKEYBYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_box_SECRETKEYBYTES); int clen = LENGTH(cipher); int mlen = clen - crypto_box_SEALBYTES; SEXP res = allocVector(RAWSXP, mlen); unsigned char pk[crypto_box_PUBLICKEYBYTES]; crypto_scalarmult_base(pk, RAW(key)); if(crypto_box_seal_open(RAW(res), RAW(cipher), clen, pk, RAW(key))) Rf_error("Failed to decrypt"); return res; } sodium/src/hashing.c0000644000176200001440000000562713067251130014136 0ustar liggesusers#include #include /* SHA256 */ SEXP R_sha256(SEXP buf){ SEXP res = allocVector(RAWSXP, crypto_hash_sha256_BYTES); if(crypto_hash_sha256(RAW(res), RAW(buf), LENGTH(buf))) Rf_error("Failed to hash"); return res; } SEXP R_auth_sha256(SEXP buf, SEXP key){ if(LENGTH(key) != crypto_auth_hmacsha256_BYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_auth_hmacsha256_BYTES); SEXP res = allocVector(RAWSXP, crypto_hash_sha256_BYTES); if(crypto_auth_hmacsha256(RAW(res), RAW(buf), LENGTH(buf), RAW(key))) Rf_error("Failed to hash"); return res; } /* SHA512 */ SEXP R_sha512(SEXP buf){ SEXP res = allocVector(RAWSXP, crypto_hash_sha512_BYTES); if(crypto_hash_sha512(RAW(res), RAW(buf), LENGTH(buf))) Rf_error("Failed to hash"); return res; } SEXP R_auth_sha512(SEXP buf, SEXP key){ if(LENGTH(key) != crypto_auth_hmacsha512_BYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_auth_hmacsha512_BYTES); SEXP res = allocVector(RAWSXP, crypto_hash_sha512_BYTES); if(crypto_auth_hmacsha512(RAW(res), RAW(buf), LENGTH(buf), RAW(key))) Rf_error("Failed to hash"); return res; } /* BLAKE2b */ SEXP R_crypto_generichash(SEXP buf, SEXP size, SEXP key){ int outlen = asInteger(size); if(outlen < crypto_generichash_BYTES_MIN || outlen > crypto_generichash_BYTES_MAX) Rf_error("Invalid output length, must be in between %d and %d", crypto_generichash_BYTES_MIN, crypto_generichash_BYTES_MAX); unsigned char *keyval = NULL; int keysize = 0; if(key != R_NilValue){ keysize = LENGTH(key); keyval = RAW(key); if(keysize < crypto_generichash_KEYBYTES_MIN || keysize > crypto_generichash_KEYBYTES_MAX) Rf_error("Invalid key size, must be between %d and %d bytes", crypto_generichash_KEYBYTES_MIN, crypto_generichash_KEYBYTES_MAX); } SEXP res = allocVector(RAWSXP, outlen); if(crypto_generichash(RAW(res), outlen, RAW(buf), LENGTH(buf), keyval, keysize)) Rf_error("Failed to hash"); return res; } /* Shorthash */ SEXP R_crypto_shorthash(SEXP buf, SEXP key){ if(LENGTH(key) != crypto_shorthash_KEYBYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_shorthash_KEYBYTES); SEXP res = allocVector(RAWSXP, crypto_shorthash_BYTES); if(crypto_shorthash(RAW(res), RAW(buf), LENGTH(buf), RAW(key))) Rf_error("Failed to hash"); return res; } /* Password hashing */ SEXP R_pwhash(SEXP buf, SEXP salt, SEXP size){ int outlen = asInteger(size); if(LENGTH(salt) != crypto_pwhash_scryptsalsa208sha256_SALTBYTES) Rf_error("Invalid salt, must be exactly %d bytes", crypto_pwhash_scryptsalsa208sha256_SALTBYTES); SEXP res = allocVector(RAWSXP, outlen); if(crypto_pwhash_scryptsalsa208sha256(RAW(res), outlen, (char*) RAW(buf), LENGTH(buf), RAW(salt), crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE)) Rf_error("pwhash failed"); return res; } sodium/src/password.c0000644000176200001440000000154013067251130014345 0ustar liggesusers#include #include SEXP R_password_hash(SEXP password){ char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES]; if(crypto_pwhash_scryptsalsa208sha256_str(out, CHAR(STRING_ELT(password, 0)), LENGTH(STRING_ELT(password, 0)), crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE)) Rf_error("pwhash failed"); return mkString(out); } SEXP R_password_verify(SEXP hash, SEXP password){ if(LENGTH(STRING_ELT(hash, 0)) != crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1) Rf_error("Invalid hash, must be exactly %d characters", crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1); int res = crypto_pwhash_scryptsalsa208sha256_str_verify(CHAR(STRING_ELT(hash, 0)), CHAR(STRING_ELT(password, 0)), LENGTH(STRING_ELT(password, 0))); return ScalarLogical(res == 0); } sodium/src/stream.c0000644000176200001440000000305113067251130013775 0ustar liggesusers#include #include SEXP R_stream_chacha20(SEXP n, SEXP key, SEXP nonce){ if(LENGTH(key) != crypto_stream_chacha20_KEYBYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_stream_chacha20_KEYBYTES); if(LENGTH(nonce) != crypto_stream_chacha20_NONCEBYTES) Rf_error("Invalid nonce, must be exactly %d bytes", crypto_stream_chacha20_NONCEBYTES); unsigned long long clen = (unsigned long long) asReal(n); SEXP res = allocVector(RAWSXP, clen); crypto_stream_chacha20(RAW(res), clen, RAW(nonce), RAW(key)); return res; } SEXP R_stream_salsa20(SEXP n, SEXP key, SEXP nonce){ if(LENGTH(key) != crypto_stream_salsa20_KEYBYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_stream_salsa20_KEYBYTES); if(LENGTH(nonce) != crypto_stream_salsa20_NONCEBYTES) Rf_error("Invalid nonce, must be exactly %d bytes", crypto_stream_salsa20_NONCEBYTES); unsigned long long clen = (unsigned long long) asReal(n); SEXP res = allocVector(RAWSXP, clen); crypto_stream_salsa20(RAW(res), clen, RAW(nonce), RAW(key)); return res; } SEXP R_stream_xsalsa20(SEXP n, SEXP key, SEXP nonce){ if(LENGTH(key) != crypto_stream_KEYBYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_stream_KEYBYTES); if(LENGTH(nonce) != crypto_stream_NONCEBYTES) Rf_error("Invalid nonce, must be exactly %d bytes", crypto_stream_NONCEBYTES); unsigned long long clen = (unsigned long long) asReal(n); SEXP res = allocVector(RAWSXP, clen); crypto_stream_xsalsa20(RAW(res), clen, RAW(nonce), RAW(key)); return res; } sodium/src/Makevars.in0000644000176200001440000000004613067251130014440 0ustar liggesusersPKG_CPPFLAGS=@cflags@ PKG_LIBS=@libs@ sodium/src/signing.c0000644000176200001440000000303013067251130014135 0ustar liggesusers#include #include SEXP R_sig_keygen(SEXP seed){ if(LENGTH(seed) != crypto_sign_SEEDBYTES) Rf_error("Invalid seed, must be exactly %d bytes", crypto_sign_SEEDBYTES); SEXP res = allocVector(RAWSXP, crypto_sign_SECRETKEYBYTES); unsigned char pk[crypto_sign_PUBLICKEYBYTES]; if(crypto_sign_seed_keypair(pk, RAW(res), RAW(seed))) Rf_error("keygen failed"); return res; } SEXP R_sig_pubkey(SEXP key){ if(LENGTH(key) != crypto_sign_SECRETKEYBYTES) Rf_error("Invalid key: must be exactly %d bytes", crypto_sign_SECRETKEYBYTES); SEXP res = allocVector(RAWSXP, crypto_sign_PUBLICKEYBYTES); if(crypto_sign_ed25519_sk_to_pk(RAW(res), RAW(key))) Rf_error("conversion failed"); return res; } SEXP R_sig_sign(SEXP msg, SEXP key){ if(LENGTH(key) != crypto_sign_SECRETKEYBYTES) Rf_error("Invalid key: must be exactly %d bytes", crypto_sign_SECRETKEYBYTES); SEXP res = allocVector(RAWSXP, crypto_sign_BYTES); if(crypto_sign_detached(RAW(res), NULL, RAW(msg), LENGTH(msg), RAW(key))) Rf_error("Failed to create signature"); return res; } SEXP R_sig_verify(SEXP msg, SEXP sig, SEXP pubkey){ if(LENGTH(pubkey) != crypto_sign_PUBLICKEYBYTES) Rf_error("Invalid pubkey: must be exactly %d bytes", crypto_sign_PUBLICKEYBYTES); if(LENGTH(sig) != crypto_sign_BYTES) Rf_error("Invalid sig: must be exactly %d bytes", crypto_sign_BYTES); if(crypto_sign_verify_detached(RAW(sig), RAW(msg), LENGTH(msg), RAW(pubkey))) Rf_error("Signature verification failed"); return ScalarLogical(TRUE); } sodium/src/keygen.c0000644000176200001440000000130613067251130013765 0ustar liggesusers#include #include SEXP R_keygen(SEXP seed){ if(LENGTH(seed) != crypto_box_SEEDBYTES) Rf_error("Invalid seed, must be exactly %d bytes", crypto_box_SEEDBYTES); unsigned char pubkey[crypto_box_PUBLICKEYBYTES]; SEXP res = allocVector(RAWSXP, crypto_box_SECRETKEYBYTES); crypto_box_seed_keypair(pubkey, RAW(res), RAW(seed)); return res; } SEXP R_pubkey(SEXP key){ if(LENGTH(key) != crypto_scalarmult_SCALARBYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_scalarmult_SCALARBYTES); SEXP res = allocVector(RAWSXP, crypto_scalarmult_BYTES); if(crypto_scalarmult_base(RAW(res), RAW(key))) Rf_error("Failed crypto_scalarmult_base"); return res; } sodium/src/messaging.c0000644000176200001440000000273013067251130014462 0ustar liggesusers#include #include SEXP R_secure_send(SEXP msg, SEXP key, SEXP pubkey, SEXP nonce) { if(LENGTH(key) != crypto_box_SECRETKEYBYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_box_SECRETKEYBYTES); if(LENGTH(pubkey) != crypto_box_PUBLICKEYBYTES) Rf_error("Invalid pubkey, must be exactly %d bytes", crypto_box_PUBLICKEYBYTES); if(LENGTH(nonce) != crypto_box_NONCEBYTES) Rf_error("Invalid nonce, must be exactly %d bytes", crypto_box_NONCEBYTES); int mlen = LENGTH(msg); int clen = mlen + crypto_box_MACBYTES; SEXP res = allocVector(RAWSXP, clen); if(crypto_box_easy(RAW(res), RAW(msg), LENGTH(msg), RAW(nonce), RAW(pubkey), RAW(key))) Rf_error("Authenticated encryption failed"); return res; } SEXP R_secure_recv(SEXP cipher, SEXP key, SEXP pubkey, SEXP nonce){ if(LENGTH(key) != crypto_box_SECRETKEYBYTES) Rf_error("Invalid key, must be exactly %d bytes", crypto_box_SECRETKEYBYTES); if(LENGTH(pubkey) != crypto_box_PUBLICKEYBYTES) Rf_error("Invalid pubkey, must be exactly %d bytes", crypto_box_PUBLICKEYBYTES); if(LENGTH(nonce) != crypto_box_NONCEBYTES) Rf_error("Invalid nonce, must be exactly %d bytes", crypto_box_NONCEBYTES); int clen = LENGTH(cipher); int mlen = clen - crypto_box_MACBYTES; SEXP res = allocVector(RAWSXP, mlen); if(crypto_box_open_easy(RAW(res), RAW(cipher), LENGTH(cipher), RAW(nonce), RAW(pubkey), RAW(key))) Rf_error("Authenticated decryption failed"); return res; } sodium/src/Makevars.win0000644000176200001440000000035413067251130014631 0ustar liggesusersPKG_CPPFLAGS= -I../windows/sodium-1.0.12/include PKG_LIBS= -L../windows/sodium-1.0.12/lib${R_ARCH} -lsodium all: clean winlibs winlibs: "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" "../tools/winlibs.R" clean: rm -f $(SHLIB) $(OBJECTS) sodium/src/init.c0000644000176200001440000000047213067251130013451 0ustar liggesusers#include #include #include void R_init_sodium(DllInfo *info) { if (sodium_init() < 0) Rf_error("Failed to initialize libsodium."); R_registerRoutines(info, NULL, NULL, NULL, NULL); R_useDynamicSymbols(info, TRUE); } void R_unload_sodium(DllInfo *info) { } sodium/src/helpers.c0000644000176200001440000000202713067251130014146 0ustar liggesusers#include #include #include SEXP R_sodium_bin2hex(SEXP bin){ size_t bin_len = LENGTH(bin); size_t hex_len = bin_len * 2 + 1; char hex[hex_len]; if(NULL == sodium_bin2hex(hex, hex_len, RAW(bin), bin_len)) Rf_error("Overflow error, failed to convert to hex"); SEXP res = PROTECT(allocVector(STRSXP, 1)); SET_STRING_ELT(res, 0, mkChar(hex)); UNPROTECT(1); return res; } SEXP R_sodium_hex2bin(SEXP hex, SEXP ignore){ int hex_len = LENGTH(STRING_ELT(hex, 0)); int max_len = hex_len / 2; unsigned char bin[max_len]; size_t bin_len; const char * hex_end; if(sodium_hex2bin(bin, max_len, CHAR(STRING_ELT(hex, 0)), hex_len, CHAR(STRING_ELT(ignore, 0)), &bin_len, &hex_end)) Rf_error("Overflow error, failed to parse hex."); SEXP res = allocVector(RAWSXP, bin_len); memcpy(RAW(res), bin, bin_len); return res; } SEXP R_randombytes_buf(SEXP length){ size_t size = asInteger(length); SEXP res = allocVector(RAWSXP, size); randombytes_buf(RAW(res), size); return res; } sodium/src/xor.c0000644000176200001440000000041413067251130013312 0ustar liggesusers#include SEXP R_xor(SEXP x, SEXP y){ if(LENGTH(x) != LENGTH(y)) Rf_error("x and y have different lengths"); SEXP z = allocVector(RAWSXP, LENGTH(x)); for(int i = 0; i < LENGTH(x); i++){ RAW(z)[i] = RAW(x)[i] ^ RAW(y)[i]; } return z; } sodium/NAMESPACE0000644000176200001440000000303613063263464013002 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(auth_decrypt) export(auth_encrypt) export(bin2hex) export(chacha20) export(data_decrypt) export(data_encrypt) export(data_tag) export(diffie_hellman) export(hash) export(hex2bin) export(keygen) export(password_store) export(password_verify) export(pubkey) export(random) export(salsa20) export(scrypt) export(sha256) export(sha512) export(shorthash) export(sig_keygen) export(sig_pubkey) export(sig_sign) export(sig_verify) export(simple_decrypt) export(simple_encrypt) export(xsalsa20) useDynLib(sodium,R_auth_sha256) useDynLib(sodium,R_auth_sha512) useDynLib(sodium,R_crypto_generichash) useDynLib(sodium,R_crypto_secret_auth) useDynLib(sodium,R_crypto_secret_decrypt) useDynLib(sodium,R_crypto_secret_encrypt) useDynLib(sodium,R_crypto_secret_verify) useDynLib(sodium,R_crypto_shorthash) useDynLib(sodium,R_diffie_hellman) useDynLib(sodium,R_keygen) useDynLib(sodium,R_password_hash) useDynLib(sodium,R_password_verify) useDynLib(sodium,R_pubkey) useDynLib(sodium,R_pwhash) useDynLib(sodium,R_randombytes_buf) useDynLib(sodium,R_seal_box) useDynLib(sodium,R_seal_open) useDynLib(sodium,R_secure_recv) useDynLib(sodium,R_secure_send) useDynLib(sodium,R_sha256) useDynLib(sodium,R_sha512) useDynLib(sodium,R_sig_keygen) useDynLib(sodium,R_sig_pubkey) useDynLib(sodium,R_sig_sign) useDynLib(sodium,R_sig_verify) useDynLib(sodium,R_sodium_bin2hex) useDynLib(sodium,R_sodium_hex2bin) useDynLib(sodium,R_stream_chacha20) useDynLib(sodium,R_stream_salsa20) useDynLib(sodium,R_stream_xsalsa20) useDynLib(sodium,R_xor) sodium/NEWS0000644000176200001440000000050713067251061012254 0ustar liggesusers1.1 - Fix autobrew for OSX Mavericks 1.0 - Remove the deprecated aes128() - Windows: update libsodium to 1.0.12 - OSX: autobrew script moved to separate repo 0.4 - Update Homebrew URL in configure script - Workaround for random WARNING in vignette for null strings - Add Travis and README file 0.2 - Add 2 vignettes sodium/R/0000755000176200001440000000000013062010614011744 5ustar liggesuserssodium/R/simple-encrypt.R0000644000176200001440000000271513062010614015047 0ustar liggesusers#' Anonymous Public-key Encryption (Sealed Box) #' #' Create an encrypted message (sealed box) from a curve25519 public key. #' #' Simple public key encryption allows for sending anonymous encrypted messages to #' a recipient given its public key. Only the recipient can decrypt these messages, #' using its private key. #' #' While the recipient can verify the integrity of the message, it cannot verify the #' identity of the sender. For sending authenticated encrypted messages, use #' \link{auth_encrypt} and \link{auth_decrypt}. #' #' @export #' @rdname simple #' @name Simple encryption #' @useDynLib sodium R_seal_box #' @references \url{http://doc.libsodium.org/public-key_cryptography/sealed_boxes.html} #' @param msg message to be encrypted #' @param key private key of the receiver #' @param pubkey public key of the receiver #' @param bin encrypted ciphertext #' @examples # Generate keypair #' key <- keygen() #' pub <- pubkey(key) #' #' # Encrypt message with pubkey #' msg <- serialize(iris, NULL) #' ciphertext <- simple_encrypt(msg, pub) #' #' # Decrypt message with private key #' out <- simple_decrypt(ciphertext, key) #' stopifnot(identical(out, msg)) simple_encrypt <- function(msg, pubkey){ stopifnot(is.raw(msg)) stopifnot(is.raw(pubkey)) .Call(R_seal_box, msg, pubkey) } #' @export #' @rdname simple #' @useDynLib sodium R_seal_open simple_decrypt <- function(bin, key){ stopifnot(is.raw(bin)) stopifnot(is.raw(key)) .Call(R_seal_open, bin, key) } sodium/R/utilities.R0000644000176200001440000000321213062010614014100 0ustar liggesusers#' Sodium Utilities #' #' The functions \code{bin2hex} and \code{hex2bin} convert between binary (raw) #' vectors and corresponding string in hexadecimal notation. The \code{random} #' function generates \code{n} crypto secure random bytes. #' #' @useDynLib sodium R_sodium_bin2hex #' @export #' @rdname helpers #' @name Sodium utilities #' @aliases helpers #' @family sodium #' @param bin raw vector with binary data to convert to hex string #' @examples # Convert raw to hex string and back #' test <- charToRaw("test 123") #' x <- bin2hex(test) #' y <- hex2bin(x) #' stopifnot(identical(test, y)) #' stopifnot(identical(x, paste(test, collapse = ""))) #' #' # Parse text with characters #' x2 <- paste(test, collapse = ":") #' y2 <- hex2bin(x2, ignore = ":") #' stopifnot(identical(test, y2)) bin2hex <- function(bin){ stopifnot(is.raw(bin)) .Call(R_sodium_bin2hex, bin) } #' @useDynLib sodium R_sodium_hex2bin #' @export #' @rdname helpers #' @param hex a string with hexadecimal characters to parse into a binary (raw) vector. #' @param ignore a string with characters to ignore from \code{hex}. See example. hex2bin <- function(hex, ignore = ":"){ stopifnot(is.character(hex)) stopifnot(length(hex) == 1) stopifnot(is.character(ignore)) stopifnot(length(ignore) == 1) .Call(R_sodium_hex2bin, hex, ignore) } #' @useDynLib sodium R_randombytes_buf #' @export #' @rdname helpers #' @param n number of random bytes or numbers to generate random <- function(n = 1){ stopifnot(is.numeric(n)) .Call(R_randombytes_buf, as.integer(n)) } #' @useDynLib sodium R_xor xor <- function(x, y){ stopifnot(is.raw(x)) stopifnot(is.raw(y)) .Call(R_xor, x, y) } sodium/R/auth-encrypt.R0000644000176200001440000000512113062010614014511 0ustar liggesusers#' Authenticated Encryption #' #' Exchange secure messages through curve25519 authenticated encryption. #' #' Authenticated encryption implements best practices for secure messaging. #' It requires that both sender and receiver have a keypair and know each #' other's public key. Each message gets authenticated with the key of the #' sender and encrypted with the key of the receiver. #' #' Even though public keys are not confidential, you should not exchange them #' over the same insecure channel you are trying to protect. If the connection #' is being tampered with, the attacker could simply replace the key with another #' one to hijack the interaction. #' #' Most people share their public key by posting them on their website or on a #' public keyserver. Another alternative is having your public key signed by a #' mutually trusted third party. HTTPS does this using Certificate Authorities. #' #' @export #' @useDynLib sodium R_secure_send #' @rdname messaging #' @name Authenticated encryption #' @references \url{http://doc.libsodium.org/public-key_cryptography/authenticated_encryption.html} #' @examples # Bob's keypair: #' bob_key <- keygen() #' bob_pubkey <- pubkey(bob_key) #' #' # Alice's keypair: #' alice_key <- keygen() #' alice_pubkey <- pubkey(alice_key) #' #' # Bob sends encrypted message for Alice: #' msg <- charToRaw("TTIP is evil") #' ciphertext <- auth_encrypt(msg, bob_key, alice_pubkey) #' #' # Alice verifies and decrypts with her key #' out <- auth_decrypt(ciphertext, alice_key, bob_pubkey) #' stopifnot(identical(out, msg)) #' #' # Alice sends encrypted message for Bob #' msg <- charToRaw("Let's protest") #' ciphertext <- auth_encrypt(msg, alice_key, bob_pubkey) #' #' # Bob verifies and decrypts with his key #' out <- auth_decrypt(ciphertext, bob_key, alice_pubkey) #' stopifnot(identical(out, msg)) #' @param msg message to be encrypted #' @param bin encrypted ciphertext generated by \code{secure_send} #' @param key your own private key #' @param pubkey other person's public key #' @param nonce non-secret unique data to randomize the cipher auth_encrypt <- function(msg, key, pubkey, nonce = random(24)){ stopifnot(is.raw(msg)) stopifnot(is.raw(key)) stopifnot(is.raw(pubkey)) stopifnot(is.raw(nonce)) res <- .Call(R_secure_send, msg, key, pubkey, nonce) structure(res, nonce = nonce) } #' @export #' @rdname messaging #' @useDynLib sodium R_secure_recv auth_decrypt <- function(bin, key, pubkey, nonce = attr(bin, "nonce")){ stopifnot(is.raw(bin)) stopifnot(is.raw(key)) stopifnot(is.raw(pubkey)) stopifnot(is.raw(nonce)) .Call(R_secure_recv, bin, key, pubkey, nonce) } sodium/R/data-encrypt.R0000644000176200001440000000546213062010614014471 0ustar liggesusers#' Symmetric Encryption and Tagging #' #' Encryption with authentication using a 256 bit shared secret. Mainly useful for #' encrypting local data. For secure communication use public-key encryption #' (\link{simple_encrypt} and \link{auth_encrypt}). #' #' Symmetric encryption uses a secret key to encode and decode a message. This can be #' used to encrypt local data on disk, or as a building block for more complex methods. #' #' Because the same \code{secret} is used for both encryption and decryption, symmetric #' encryption by itself is impractical for communication. For exchanging secure messages #' with other parties, use assymetric (public-key) methods (see \link{simple_encrypt} or #' \link{auth_encrypt}). #' #' The \code{nonce} is not confidential but required for decryption, and should be #' stored or sent along with the ciphertext. The purpose of the \code{nonce} is to #' randomize the cipher to protect gainst re-use attacks. This way you can use one #' and the same secret for encrypting multiple messages. #' #' The \link{data_tag} function generates an authenticated hash that can be stored #' alongside the data to be able to verify the integrity of the data later on. For #' public key signatures see \code{sig_sign} instead. #' #' @export #' @rdname symmetric #' @name Symmetric encryption #' @useDynLib sodium R_crypto_secret_encrypt #' @param msg message to be encrypted #' @param key shared secret key used for both encryption and decryption #' @param bin encrypted ciphertext #' @param nonce non-secret unique data to randomize the cipher #' @references \url{https://download.libsodium.org/doc/secret-key_cryptography/authenticated_encryption.html} #' @examples # 256-bit key #' key <- sha256(charToRaw("This is a secret passphrase")) #' msg <- serialize(iris, NULL) #' #' # Encrypts with random nonce #' cipher <- data_encrypt(msg, key) #' orig <- data_decrypt(cipher, key) #' stopifnot(identical(msg, orig)) #' #' # Tag the message with your key (HMAC) #' tag <- data_tag(msg, key) data_encrypt <- function(msg, key, nonce = random(24)){ stopifnot(is.raw(msg)) stopifnot(is.raw(key)) out <- .Call(R_crypto_secret_encrypt, msg, key, nonce) structure(out, nonce = nonce) } #' @export #' @rdname symmetric #' @useDynLib sodium R_crypto_secret_decrypt data_decrypt <- function(bin, key, nonce = attr(bin, "nonce")){ stopifnot(is.raw(bin)) stopifnot(is.raw(key)) .Call(R_crypto_secret_decrypt, bin, key, nonce) } #' @export #' @rdname symmetric #' @useDynLib sodium R_crypto_secret_auth data_tag <- function(msg, key){ stopifnot(is.raw(msg)) stopifnot(is.raw(key)) .Call(R_crypto_secret_auth, msg, key) } #' @useDynLib sodium R_crypto_secret_verify data_verify <- function(msg, key, tag){ stopifnot(is.raw(msg)) stopifnot(is.raw(tag)) stopifnot(is.raw(key)) .Call(R_crypto_secret_verify, msg, key, tag) } sodium/R/password.R0000644000176200001440000000233413062010614013733 0ustar liggesusers#' Password Storage #' #' Wrapper that implements best practices for storing passwords based on scrypt with #' a random salt. #' #' The \link{password_store} function returns an ASCII encoded string which contains #' the result of a memory-hard, CPU-intensive hash function along with the automatically #' generated salt and other parameters required to verify the password. Use #' \link{password_verify} to verify a password from this string. #' #' @export #' @rdname password #' @name Password storage #' @aliases password #' @param password a string of length one with a password #' @param hash a hash string of length one generated by \code{password_store} #' @useDynLib sodium R_password_hash #' @references \url{http://doc.libsodium.org/password_hashing/} #' @examples # Example password #' password <- "I like cookies" #' #' # Hash is what you store in the database #' hash <- password_store(password) #' #' # To verify the password when the user logs in #' stopifnot(password_verify(hash, password)) password_store <- function(password){ .Call(R_password_hash, password) } #' @export #' @rdname password #' @useDynLib sodium R_password_verify password_verify <- function(hash, password){ .Call(R_password_verify, hash, password) } sodium/R/diffie-hellman.R0000644000176200001440000000467713062010614014751 0ustar liggesusers#' Diffie-Hellman #' #' The Diffie-Hellman key exchange method allows two parties that have no prior knowledge #' of each other to jointly establish a shared secret key over an insecure channel. This #' key can then be used to encrypt subsequent communications using a symmetric key cipher. #' #' Encryption methods as implemented in \link{data_encrypt} require that parties have a #' shared secret key. But often we wish to establish a secure channel with a party we have #' no prior relationship with. Diffie-hellman is a method for jointly agreeing on a shared #' secret without ever exchanging the secret itself. Sodium implements #' \href{https://en.wikipedia.org/wiki/Curve25519}{Curve25519}, a state-of-the-art Diffie-Hellman #' function suitable for a wide variety of applications. #' #' The method conists of two steps (see examples). First, both parties generate a random private #' key and derive the corresponding public key using \link{pubkey}. These public keys are not #' confidential and can be exchanged over an insecure channel. After the public keys are exchanged, #' both parties will be able to calculate the (same) shared secret by combining his/her own private #' key with the other person's public key using \link{diffie_hellman}. #' #' After the shared secret has been established, the private and public keys are disposed, #' and parties can start encrypting communications based on the shared secret using e.g. #' \link{data_encrypt}. Because the shared secret cannot be calculated using only the public #' keys, the process is safe from eavesdroppers. #' #' @export #' @rdname diffie #' @name Diffie-Hellman #' @aliases diffie #' @useDynLib sodium R_diffie_hellman #' @references \url{http://doc.libsodium.org/advanced/scalar_multiplication.html} #' @param key your private key #' @param pubkey other person's public key #' @return Returns a shared secret key which can be used in e.g. \link{data_encrypt}. #' @examples # Bob generates keypair #' bob_key <- keygen() #' bob_pubkey <- pubkey(bob_key) #' #' # Alice generates keypair #' alice_key <- keygen() #' alice_pubkey <- pubkey(alice_key) #' #' # After Bob and Alice exchange pubkey they can both derive the secret #' alice_secret <- diffie_hellman(alice_key, bob_pubkey) #' bob_secret <- diffie_hellman(bob_key, alice_pubkey) #' stopifnot(identical(alice_secret, bob_secret)) diffie_hellman <- function(key, pubkey){ stopifnot(is.raw(key)) stopifnot(is.raw(pubkey)) .Call(R_diffie_hellman, key, pubkey) } sodium/R/hashing.R0000644000176200001440000000633513062010614013517 0ustar liggesusers#' Hash Functions #' #' Functions to calculate cryptographic hash of a message, with optionally a key for #' HMAC applications. For storing passwords, use \link{password_store} instead. #' #' The generic \code{hash} function is recommended most most applications. It uses #' dynamic length #' \href{https://download.libsodium.org/doc/hashing/generic_hashing.html}{BLAKE2b} #' where output size can be any value between 16 bytes (128bit) and 64 bytes (512bit). #' #' The \link{scrypt} hash function is designed to be CPU and memory expensive to protect #' against brute force attacks. This algorithm is also used by the \link{password_store} #' function. #' #' The \code{shorthash} function is a special 8 byte (64 bit) hash based on #' \href{https://download.libsodium.org/doc/hashing/short-input_hashing.html}{SipHash-2-4}. #' The output of this function is only 64 bits (8 bytes). It is useful for in e.g. #' Hash tables, but it should not be considered collision-resistant. #' #' Hash functions can be used for HMAC by specifying a secret \code{key}. They key size #' for \code{shorthash} is 16 bytes, for \code{sha256} it is 32 bytes and for \code{sha512} #' it is 64 bytes. For \code{hash} the key size can be any value between 16 and 62, #' recommended is at least 32. #' #' @rdname hash #' @name Hash functions #' @aliases hashing #' @references \url{https://download.libsodium.org/doc/hashing/generic_hashing.html} #' @useDynLib sodium R_crypto_generichash #' @param buf data to be hashed #' @param key key for HMAC hashing. Optional, except for in \code{shorthash}. #' @export #' @examples # Basic hashing #' msg <- serialize(iris, NULL) #' hash(msg) #' sha256(msg) #' sha512(msg) #' scrypt(msg) #' #' # Generate keys from passphrase #' passphrase <- charToRaw("This is super secret") #' key <- hash(passphrase) #' shortkey <- hash(passphrase, size = 16) #' longkey <- hash(passphrase, size = 64) #' #' # HMAC (hashing with key) #' hash(msg, key = key) #' shorthash(msg, shortkey) #' sha256(msg, key = key) #' sha512(msg, key = longkey) hash <- function(buf, key = NULL, size = 32){ stopifnot(is.raw(buf)) stopifnot(is.null(key) || is.raw(key)) .Call(R_crypto_generichash, buf, size, key) } #' @export #' @rdname hash #' @param salt non-confidential random data to seed the algorithm #' @useDynLib sodium R_pwhash scrypt <- function(buf, salt = raw(32), size = 32){ stopifnot(is.raw(buf)) stopifnot(is.raw(salt)) stopifnot(is.numeric(size)) .Call(R_pwhash, buf, salt, size) } #' @export #' @rdname hash #' @useDynLib sodium R_crypto_shorthash shorthash <- function(buf, key){ stopifnot(is.raw(buf)) stopifnot(is.raw(key)) .Call(R_crypto_shorthash, buf, key) } #' @rdname hash #' @useDynLib sodium R_sha512 R_auth_sha512 #' @export sha512 <- function(buf, key = NULL){ stopifnot(is.raw(buf)) if(length(key)){ stopifnot(is.raw(key)) .Call(R_auth_sha512, buf, key) } else { .Call(R_sha512, buf) } } #' @rdname hash #' @param size length of the output hash. Must be between 16 and 64 (recommended is 32) #' @useDynLib sodium R_sha256 R_auth_sha256 #' @export sha256 <- function(buf, key = NULL){ stopifnot(is.raw(buf)) if(length(key)){ stopifnot(is.raw(key)) .Call(R_auth_sha256, buf, key) } else { .Call(R_sha256, buf) } } sodium/R/stream.R0000644000176200001440000000552613063263707013410 0ustar liggesusers#' Stream Ciphers #' #' Generate deterministic streams of random data based off a secret key and random nonce. #' #' You usually don't need to call these methods directly. For local encryption #' use \link{data_encrypt}. For secure communication use \link{simple_encrypt} or #' \link{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 \link{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 \link{xor}'ing #' it back. See the examples. #' #' Each stream generator requires a \code{key} and a \code{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 \code{nonce} is not secret and should be stored or sent along #' with the ciphertext. The purpose of the \code{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. #' #' @export #' @useDynLib sodium R_stream_chacha20 #' @rdname stream #' @aliases stream #' @name Stream ciphers #' @param size length of cipher stream in bytes #' @param key secret key used by the cipher #' @param nonce non-secret unique data to randomize the cipher #' @references \url{https://download.libsodium.org/doc/advanced/xsalsa20.html} #' @examples # Very basic encryption #' myfile <- file.path(R.home(), "COPYING") #' message <- readBin(myfile, raw(), file.info(myfile)$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)) #' chacha20 <- function(size, key, nonce){ stopifnot(is.numeric(size)) stopifnot(is.raw(key)) stopifnot(is.raw(nonce)) .Call(R_stream_chacha20, size, key, nonce) } #' @export #' @useDynLib sodium R_stream_salsa20 #' @rdname stream salsa20 <- function(size, key, nonce){ stopifnot(is.numeric(size)) stopifnot(is.raw(key)) stopifnot(is.raw(nonce)) .Call(R_stream_salsa20, size, key, nonce) } #' @export #' @useDynLib sodium R_stream_xsalsa20 #' @rdname stream xsalsa20 <- function(size, key, nonce){ stopifnot(is.numeric(size)) stopifnot(is.raw(key)) stopifnot(is.raw(nonce)) .Call(R_stream_xsalsa20, size, key, nonce) } sodium/R/signatures.R0000644000176200001440000000443113062010614014255 0ustar liggesusers#' Create and Verify Signatures #' #' Cryptographic signatures can be used to verify the integrity of a message using #' the author's public key. #' #' A signature is an authenticated checksum that can be used to check that a message #' (any data) was created by a particular author and was not tampered with. The signature is #' created using a private key and can be verified from the corresponding public key. #' #' Signatures are used when the message itself is not confidential but integrity is #' important. A common use is for software repositories where maintainers include #' a signature of the package index. This allows client package managers to verify #' that the binaries were not modified by intermediate parties in the distribution #' process. #' #' For confidential data, use authenticated encryption (\link{auth_encrypt}) #' which allows for sending signed and encrypted messages in a single method. #' #' Currently sodium requires a different type of key pairfor signatures (ed25519) #' than for encryption (curve25519). #' #' @rdname sig #' @name Signatures #' @aliases sig #' @export #' @useDynLib sodium R_sig_sign #' @param msg message to sign #' @param key private key to sign message with #' @param sig a signature generated by \code{signature_sign} #' @param pubkey a public key of the keypair used by the signature #' @references \url{http://doc.libsodium.org/public-key_cryptography/public-key_signatures.html} #' @examples # Generate keypair #' key <- sig_keygen() #' pubkey <- sig_pubkey(key) #' #' # Create signature #' msg <- serialize(iris, NULL) #' sig <- sig_sign(msg, key) #' sig_verify(msg, sig, pubkey) sig_sign <- function(msg, key){ stopifnot(is.raw(msg)) stopifnot(is.raw(key)) .Call(R_sig_sign, msg, key) } #' @export #' @rdname sig #' @useDynLib sodium R_sig_verify sig_verify <- function(msg, sig, pubkey){ stopifnot(is.raw(msg)) stopifnot(is.raw(sig)) stopifnot(is.raw(pubkey)) .Call(R_sig_verify, msg, sig, pubkey) } #' @export #' @rdname sig #' @useDynLib sodium R_sig_keygen #' @param seed random data to seed the keygen sig_keygen <- function(seed = random(32)){ stopifnot(is.raw(seed)) .Call(R_sig_keygen, seed) } #' @export #' @rdname sig #' @useDynLib sodium R_sig_pubkey sig_pubkey <- function(key){ stopifnot(is.raw(key)) .Call(R_sig_pubkey, key) } sodium/R/keygen.R0000644000176200001440000000430313062010614013351 0ustar liggesusers#' Keypair Generation #' #' Functions to generate a random private key and calculate the corresponding curve25519 #' public key. #' #' Asymmetric methods rely on public-private keypairs. The private keys are secret and #' should never be shared with anyone. The public key on the other hand is not confidential #' and should be shared with the other parties. Public keys are typically published on the #' users's website or posted in public directories or keyservers. #' #' The two main applications for public key cryptography are encryption and authentication. #' #' In public key encryption, data that is encrypted using a public key can only be #' decrypted using the corresponding private key. This allows anyone to send somebody a #' secure message by encrypting it with the receivers public key. The encrypted message #' will only be readable by the owner of the corresponding private key. Basic encryption #' is implemented in \link{simple_encrypt}. #' #' Authentication works the other way around. In public key authentication, the owner of the #' private key creates a 'signature' (an authenticated checksum) for a message in a way that #' allows anyone who knows the user's public key to verify that this message was indeed signed #' by the owner of the private key. #' #' If both sender and receiver know each other's public key, the two methods can be combined #' so that each message going back and forth is signed by the sender and encrypted for the #' receiver. This protects both against eavesdropping and MITM tampering, creating a fully #' secure channel. #' #' @export #' @rdname keygen #' @name Key generation #' @param key private key for which to calculate the public key #' @param seed random data to seed the keygen #' @useDynLib sodium R_keygen #' @examples # Create keypair #' key <- keygen() #' pub <- pubkey(key) #' #' # Basic encryption #' msg <- serialize(iris, NULL) #' ciphertext <- simple_encrypt(msg, pub) #' out <- simple_decrypt(ciphertext, key) #' stopifnot(identical(msg, out)) keygen <- function(seed = random(32)){ stopifnot(is.raw(seed)) .Call(R_keygen, seed) } #' @export #' @rdname keygen #' @useDynLib sodium R_pubkey pubkey <- function(key){ stopifnot(is.raw(key)) .Call(R_pubkey, key) } sodium/vignettes/0000755000176200001440000000000013067251130013560 5ustar liggesuserssodium/vignettes/crypto101.rmd0000644000176200001440000002252613063263422016040 0ustar liggesusers--- title: "How does cryptography work?" output: html_document date: "`r Sys.Date()`" vignette: > %\VignetteIndexEntry{How does cryptography work} %\VignetteEngine{knitr::rmarkdown} \usepackage[utf8]{inputenc} --- ```{r, echo = FALSE, message = FALSE} knitr::opts_chunk$set(comment = "") library(sodium) # hack for printable bits random <- function(n = 1){ if(n != nchar("TTIP is evil")) return(sodium::random(n)) repeat { x <- sodium::random(n) y <- base::xor(charToRaw("TTIP is evil"), x) if(all(c(x,y) != 0)) return(x) } } ``` This page attempts to give a very basic conceptual introduction to cryptographic methods. Before we start the usual disclaimer: ___I am not a cryptographer. This document is only for educational purposes. Crypto is hard, you should never trust your home-grown implementation. Unless you're a cryptographer you will probably overlook some crucial details. Developers should only use the high-level functions that have been implemented by an actual cryptographer.___ Now that we got this is out of the way, let's start hacking :) ### The XOR operator The bitwise [XOR operator](https://en.wikipedia.org/wiki/Exclusive_or#Truth_table) outputs `true` only when both inputs differ (one is `true`, the other is `false`). It is sometimes called an *invertor* because the output of a bit in `x` gets inverted if and only if the corresponding bit in `y` is true: ```{r} # XOR two (8bit) bytes 'x' and 'y' x <- as.raw(0x7a) y <- as.raw(0xe4) z <- base::xor(x, y) dput(z) # Show the bits in each byte cbind(x = rawToBits(x), y = rawToBits(y), z = rawToBits(z)) ``` In cryptography we `xor` a message `x` with secret random data `y`. Because each bit in `y` is randomly `true` with probability 0.5, the `xor` output is completely random and uncorrelated to `x`. This is called *perfect secrecy*. Only if we know `y` we can decipher the message `x`. ```{r} # Encrypt message using random one-time-pad msg <- charToRaw("TTIP is evil") one_time_pad <- random(length(msg)) ciphertext <- base::xor(msg, one_time_pad) # It's really encrypted rawToChar(ciphertext) # Decrypt with same pad rawToChar(base::xor(ciphertext, one_time_pad)) ``` This method is perfectly secure and forms the basis for most cryptograhpic methods. However the challenge is generating and communicating unique pseudo-random `y` data every time we want to encrypt something. One-time-pads as in the example are not very practical for large messages. Also we should never re-use a one-time-pad `y` for encrypting multiple messages, as this compromises the secrecy. ### Stream ciphers The solution to this problem are stream ciphers. A *stream cipher* generates a unique stream of pseudo-random data based on a secret `key` and a unique `nonce`. For a given set of parameters the stream cipher always generates the same stream of data. Sodium implements a few popular stream ciphers: ```{r} password <- "My secret passphrase" key <- hash(charToRaw(password)) nonce <- random(8) chacha20(size = 20, key, nonce) ``` Each stream requires a `key` and a `nonce`. The key forms the shared secret and should only be known to trusted parties. The `nonce` is not secret and is 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. ```{r} salsa20(size = 20, key, nonce) ``` Over the years cryptographers have come up with many more variants. Many stream ciphers are based on a block cipher such as [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard): a keyed permutation of fixed length amount of data. The block ciphers get chained in a particular [mode of operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation) which repeatedly applies the cipher's single-block operation to securely transform amounts of data larger than a block. We are not going to discuss implementation details, but you could probably come up with something yourself. For example you could use a hash function such `sha256` as the block cipher and append counter which is incremented for each block (this is called CTR mode). ```{r} # Illustrative example. sha256_ctr <- function(size, key, nonce){ n <- ceiling(size/32) output <- raw() for(i in 1:n){ counter <- packBits(intToBits(i)) block <- sha256(c(key, nonce, counter)) output <- c(output, block) } return(output[1:size]) } ``` This allows us to generate an arbitrary length stream from a single secret key: ```{r} password <- "My secret passphrase" key <- hash(charToRaw(password)) nonce <- random(8) sha256_ctr(50, key, nonce) ``` In practice, you should never write your own ciphers. A lot of [research](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.58.1811&rep=rep1&type=pdf) goes into studying the properties of block ciphers under various modes of operation. In the remainder we just use the standard Sodium ciphers: [`chacha20`](https://download.libsodium.org/libsodium/content/advanced/chacha20.html), [`salsa20`](https://download.libsodium.org/libsodium/content/advanced/salsa20.html) or [`xsalsa20`](https://download.libsodium.org/libsodium/content/advanced/xsalsa20.html). ### Symmetric encryption Symmetric encryption means that the same secret key is used for both encryption and decryption. All that is needed to implement symmetric encryption is `xor` and a stream cipher. For example to encrypt an arbitrary length `message` using `password`: ```{r} # Encrypt 'message' using 'password' myfile <- file.path(R.home(), "COPYING") message <- readBin(myfile, raw(), file.info(myfile)$size) passwd <- charToRaw("My secret passphrase") ``` A hash function converts the password to a key of suitable size for the stream cipher, which we use to generate a psuedo random stream of equal length to the message: ```{r} # Basic secret key encryption key <- hash(passwd) nonce8 <- random(8) stream <- chacha20(length(message), key, nonce8) ciphertext <- base::xor(stream, message) ``` Now the `ciphertext` is an encrypted version of the message. Only those that know the `key` and the `nonce` can re-generate the same keystream in order to `xor` the ciphertext back into the original message. ```{r} # Decrypt with the same key key <- hash(charToRaw("My secret passphrase")) stream <- chacha20(length(ciphertext), key, nonce8) out <- base::xor(ciphertext, stream) # Print part of the message cat(substring(rawToChar(out), 1, 120)) ``` The Sodium functions `data_encrypt` and `data_decrypt` provide a more elaborate implementation of the above. This is what you should use in practice for secret key encryption. Symmetric encryption can be used for e.g. encrypting local data. However because the same secret is used for both encryption and decryption, it is impractical for communication with other parties. For exchanging secure messages we need public key encryption. ### Public-key encryption and Diffie-Hellman Rather than using a single secret-key, assymetric (public key) encryption requires a *keypair*, consisting of a *public key* for encryption and a *private-key* for decryption. Data that is encrypted using a given public key can only be decrypted using the corresponding private key. The public key is not confidential and can be shared on e.g. a website or keyserver. This allows anyone to send somebody a secure message by encrypting it with the receivers public key. The encrypted message will only be readable by the owner of the corresponding private key. ```{r} # Create keypair key <- keygen() pub <- pubkey(key) # Encrypt message for receiver using his/her public key msg <- serialize(iris, NULL) ciphertext <- simple_encrypt(msg, pub) # Receiver decrypts with his/her private key out <- simple_decrypt(ciphertext, key) identical(msg, out) ``` How does this work? Public key encryption makes use of [Diffie-Hellman](http://mathworld.wolfram.com/Diffie-HellmanProtocol.html) (D-H): a method which allows two parties that have no prior knowledge of each other to jointly establish a shared secret key over an insecure channel. In the most simple case, both parties generate a temporary keypair and exchange their public key over the insecure channel. Then both parties use the D-H function to calculcate the (same) shared secret key by combining their own private key with the other person's public key: ```{r} # Bob generates keypair bob_key <- keygen() bob_pubkey <- pubkey(bob_key) # Alice generates keypair alice_key <- keygen() alice_pubkey <- pubkey(alice_key) # After Bob and Alice exchange pubkey they can both derive the secret alice_secret <- diffie_hellman(alice_key, bob_pubkey) bob_secret <- diffie_hellman(bob_key, alice_pubkey) identical(alice_secret, bob_secret) ``` Once the shared secret has been established, both parties can discard their temporary public/private key and use the shared secret to start encrypting communications with symmetric encryption as discussed earlier. Because the shared secret cannot be calculated using only the public keys, the process is safe from eavesdroppers. The classical [Diffie-Hellman method](http://mathworld.wolfram.com/Diffie-HellmanProtocol.html) is based on the discrete logarithm problem with large prime numbers. Sodium uses [curve25519](http://cr.yp.to/ecdh/curve25519-20060209.pdf), a state-of-the-art D-H function by Daniel Bernsteinan designed for use with the elliptic curve Diffie–Hellman (ECDH) key agreement scheme. sodium/vignettes/intro.rmd0000644000176200001440000001750613062010614015423 0ustar liggesusers--- title: "Sodium: A Modern and Easy-to-Use Crypto Library" output: html_document: toc: false date: "`r Sys.Date()`" vignette: > %\VignetteIndexEntry{Introduction to Sodium for R} %\VignetteEngine{knitr::rmarkdown} \usepackage[utf8]{inputenc} --- ```{r, echo = FALSE, message = FALSE} knitr::opts_chunk$set(comment = "") library(sodium) ``` The sodium R package provides bindings to [libsodium](https://download.libsodium.org/doc/): a modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more. The goal of Sodium is to provide the core operations needed to build higher-level cryptographic tools. It is not intended for implementing standardized protocols such as TLS, SSH or GPG. Sodium only supports a limited set of state-of-the-art elliptic curve methods, resulting in a simple but very powerful tool-kit for building secure applications. | | Authenticated Encryption | Encryption only | Authentication only | |-----------------------------:|:--------------------------------:|:-----------------------------------:|:--------------------------:| | __Symmetric__ *(secret key)*: | [`data_encrypt` / `data_decrypt`](#secret-key-encryption) | | [`data_tag`](#secret-key-authentication) | | __Asymmetric__ *(public+private key)*: | [`auth_encrypt` / `auth_decrypt`](#public-key-authenticated-encryption) | [`simple_encrypt` / `simple_decrypt`](#public-key-encryption) | [`sig_sign` / `sig_verify`](#public-key-authentication-signatures) | | | | | | ### Using Sodium All Sodium functions operate on binary data, called 'raw' vectors in R. Use `charToRaw` and `rawToChar` to convert between strings and raw vectors. Alternatively `hex2bin` and `bin2hex` can convert between binary data to strings in hex notation: ```{r} test <- hash(charToRaw("test 123")) str <- bin2hex(test) print(str) hex2bin(str) ``` ### Random data generator The `random()` function generates n bytes of unpredictable data, suitable for creating secret keys. ```{r} secret <- random(8) print(secret) ``` Implementation is platform specific, see the [docs](https://download.libsodium.org/doc/generating_random_data/index.html) for details. ### Hash functions Sodium has several hash functions including `hash()`, `shorthash()`, `sha256()`, `sha512` and `scrypt()`. The generic `hash()` is usually recommended. It uses [blake2b](https://download.libsodium.org/doc/hashing/generic_hashing.html) with a configurable size between 16 bytes (128bit) and 64 bytes (512bit). ```{r} # Generate keys from passphrase passphrase <- charToRaw("This is super secret") hash(passphrase) hash(passphrase, size = 16) hash(passphrase, size = 64) ``` The `shorthash()` function is a special 8 byte (64 bit) hash based on [SipHash-2-4](https://download.libsodium.org/doc/hashing/short-input_hashing.html). The output of this function is only 64 bits (8 bytes). It is useful for in e.g. Hash tables, but it should not be considered collision-resistant. ### Secret key encryption Symmetric encryption uses the same secret key for both encryption and decryption. It is mainly useful for encrypting local data, or as a building block for more complex methods. Most encryption methods require a `nonce`: a piece of non-secret unique data that is used to randomize the cipher. This allows for safely using the same `key` for encrypting multiple messages. The nonce should be stored or shared along with the ciphertext. ```{r} key <- hash(charToRaw("This is a secret passphrase")) msg <- serialize(iris, NULL) # Encrypt with a random nonce nonce <- random(24) cipher <- data_encrypt(msg, key, nonce) # Decrypt with same key and nonce orig <- data_decrypt(cipher, key, nonce) identical(iris, unserialize(orig)) ``` Because the secret has to be known by all parties, symmetric encryption by itself is often impractical for communication with third parties. For this we need asymmetric (public key) methods. ### Secret key authentication Secret key authentication is called tagging in Sodium. A tag is basically a hash of the data together with a secret key. ```{r} key <- hash(charToRaw("This is a secret passphrase")) msg <- serialize(iris, NULL) mytag <- data_tag(msg, key) ``` To verify the integrity of the data at a later point in time, simply re-calculate the tag with the same key: ```{r} stopifnot(identical(mytag, data_tag(msg, key))) ``` The secret key protects against forgery of the data+tag by an intermediate party, as would be possible with a regular checksum. ### Public key encryption Where symmetric methods use the same secret key for encryption and decryption, asymmetric methods use a key-pair consisting of a public key and private key. The private key is secret and only known by its owner. The public key on the other hand can be shared with anyone. Public keys are often published on the user's website or posted in public directories or keyservers. ```{r} key <- keygen() pub <- pubkey(key) ``` In public key encryption, data encrypted with a public key can only be decrypted using the corresponding private key. This allows anyone to send somebody a secure message by encrypting it with the receivers public key. The encrypted message will only be readable by the owner of the corresponding private key. ```{r} # Encrypt message with pubkey msg <- serialize(iris, NULL) ciphertext <- simple_encrypt(msg, pub) # Decrypt message with private key out <- simple_decrypt(ciphertext, key) stopifnot(identical(out, msg)) ``` ### Public key authentication (signatures) Public key authentication works the other way around. First, the owner of the private key creates a 'signature' (an authenticated checksum) for a message in a way that allows anyone who knows his/her public key to verify the integrity of the message and identity of the sender. Currently sodium requires a different type of key-pair for signatures (ed25519) than for encryption (curve25519). ```{r} # Generate signature keypair key <- sig_keygen() pubkey <- sig_pubkey(key) # Create signature with private key msg <- serialize(iris, NULL) sig <- sig_sign(msg, key) print(sig) # Verify a signature from public key sig_verify(msg, sig, pubkey) ``` Signatures are useful when the message itself is not confidential but integrity is important. A common use is for software repositories where to include an index file with checksums for all packages, signed by the repository maintainer. This allows client package managers to verify that the binaries were not manipulated by intermediate parties during the distribution process. ### Public key authenticated encryption Authenticated encryption implements best practices for secure messaging. It requires that both sender and receiver have a keypair and know each other's public key. Each message gets authenticated with the key of the sender and encrypted with the key of the receiver. ```{r} # Bob's keypair: bob_key <- keygen() bob_pubkey <- pubkey(bob_key) # Alice's keypair: alice_key <- keygen() alice_pubkey <- pubkey(alice_key) # Bob sends encrypted message for Alice: msg <- charToRaw("TTIP is evil") ciphertext <- auth_encrypt(msg, bob_key, alice_pubkey) # Alice verifies and decrypts with her key out <- auth_decrypt(ciphertext, alice_key, bob_pubkey) stopifnot(identical(out, msg)) # Alice sends encrypted message for Bob msg <- charToRaw("Let's protest") ciphertext <- auth_encrypt(msg, alice_key, bob_pubkey) # Bob verifies and decrypts with his key out <- auth_decrypt(ciphertext, bob_key, alice_pubkey) stopifnot(identical(out, msg)) ``` Note that even though public keys are not confidential, you should not exchange them over the same insecure channel you are trying to protect. If the connection is being tampered with, the attacker could simply replace the key with another one to hijack the interaction. sodium/MD50000644000176200001440000000460613067274754012107 0ustar liggesusers5aef9b76604afe3217a1fa6350787277 *DESCRIPTION 1ee0683cce6d3479250337954c075d63 *LICENSE ca47c62b5a48fc8b16d3e86eff523c5c *NAMESPACE 54b7e63f175d3f50df8dd21491e00f4a *NEWS 37085c2c009cd22915222a7d3732aedf *R/auth-encrypt.R d1c37a131add702d15428fc72d757262 *R/data-encrypt.R 331b58e1c063ba21ab40c1bce37a67d1 *R/diffie-hellman.R 771a90aa61745f29046f62068cfd2cf3 *R/hashing.R b7d333c4fb6c142ca1c38373833a52b4 *R/keygen.R 35061c12240a78e325f8924ea67d1652 *R/password.R c08413414b04c3c96a58dad243b10eb4 *R/signatures.R dc12dbbac4b2607dd62874c7e4c52b81 *R/simple-encrypt.R 2cb039f48bc9c67d6b7fe700082aaca9 *R/stream.R edeae08ca942bcc88410f50c3e7762a1 *R/utilities.R c7584f9a03f4fde53f3394b1be113297 *build/vignette.rds 6071edd604dbeb75308cfbedc7790398 *cleanup 249e8ee0b1c2c0ab8fe4829a9034dbf0 *configure 7f49cdf1a21fa06deb003e5d96a10a90 *inst/doc/crypto101.R 28c6dc1e8c052c626b6c97d7a5acb697 *inst/doc/crypto101.html 2cad59741446d5aefccb92ebfe9eede2 *inst/doc/crypto101.rmd f628f8dc426d6445935123044cd5f5d4 *inst/doc/intro.R 8c889415a623379261500d08e02b6971 *inst/doc/intro.html e1a493edfd9f95fad6bdc89c8c619dd6 *inst/doc/intro.rmd 7e8dcd1a337fe349eeee7d10b9fa7ee8 *man/diffie.Rd 3868978e81c77c9e627cd22fe6fe8281 *man/hash.Rd d6a01ba99a23b7c5bc77e5164d584a64 *man/helpers.Rd ac85b83828dc66c7f2dca554cf2f5709 *man/keygen.Rd f5acc2abd5a6162002dd634f856d8f94 *man/messaging.Rd c9cfbf9d7e131347eb597a99c3fcedef *man/password.Rd 05e85f1abf8736dd69de0d62b0fdcc46 *man/sig.Rd 79d0a4d81f2ee9a7c95550e08be189aa *man/simple.Rd 91cf1b973c2812ee3604390d5909d78e *man/stream.Rd 435afbdae399753f4f5a92839bde89e7 *man/symmetric.Rd 111e1efb50ff675feb507ea42a24b300 *src/Makevars.in d1a90d32f601556d53c717e7af30683a *src/Makevars.win a1de47c99176ea50665a001c0ede1f67 *src/diffie.c 7119bf44decca9355943343bca344b24 *src/hashing.c 3c645c584cb730c1e8fd66ca28c2c29c *src/helpers.c 742bb5f53826fcf28d81892e14720182 *src/init.c 44cfefa5b9be0e18848e910002935c5b *src/keygen.c fcf6c0535982ff3782ad902145128547 *src/messaging.c c0e23fed7b267248b715c7ffe842ca9c *src/password.c 43da1e56866cade612a54783a575b3e9 *src/seal.c d7edc66c4affeb4f5199ab9cfe5aa325 *src/secret.c 8df02109a0703e5d67170355b8c07fa4 *src/signing.c aa3b35f466558d612021f8e86f8d4f6e *src/stream.c 9ff6caa79257e3fc6c58d16f153a3f15 *src/xor.c 076888fb2607f60a7c5f5d7bae4abbcf *tools/winlibs.R 2cad59741446d5aefccb92ebfe9eede2 *vignettes/crypto101.rmd e1a493edfd9f95fad6bdc89c8c619dd6 *vignettes/intro.rmd sodium/build/0000755000176200001440000000000013067251130012647 5ustar liggesuserssodium/build/vignette.rds0000644000176200001440000000040013067251130015200 0ustar liggesusersuMn0 NQUbX!n*EVl"DQ]ON:I& x7?O29rL[==l9X֡MAߤB @-;ZJQ=c^K e.8n'DvxCݿ'4nuyl+ؿ j66/LtN#ĺ3|wstp[d3C+| E ՛bQ˼ۨNsodium/DESCRIPTION0000644000176200001440000000163113067274754013300 0ustar liggesusersPackage: sodium Type: Package Title: A Modern and Easy-to-Use Crypto Library Version: 1.1 Author: Jeroen Ooms Maintainer: Jeroen Ooms Description: Bindings to 'libsodium': a modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more. Sodium uses curve25519, a state-of-the-art Diffie-Hellman function by Daniel Bernstein, which has become very popular after it was discovered that the NSA had backdoored Dual EC DRBG. License: MIT + file LICENSE URL: https://github.com/jeroen/sodium#readme (devel) https://download.libsodium.org/doc/ (upstream) BugReports: https://github.com/jeroen/sodium/issues SystemRequirements: libsodium (>= 1.0.3) VignetteBuilder: knitr Suggests: knitr, rmarkdown RoxygenNote: 6.0.1 NeedsCompilation: yes Packaged: 2017-03-30 18:45:44 UTC; jeroen Repository: CRAN Date/Publication: 2017-03-30 21:34:36 UTC sodium/configure0000755000176200001440000000535013067251022013462 0ustar liggesusers#!/bin/bash # Anticonf (tm) script by Jeroen Ooms (2017) # This script will query 'pkg-config' for the required cflags and ldflags. # If pkg-config is unavailable or does not find the library, try setting # INCLUDE_DIR and LIB_DIR manually via e.g: # R CMD INSTALL --configure-vars='INCLUDE_DIR=/.../include LIB_DIR=/.../lib' # Library settings PKG_CONFIG_NAME="libsodium" PKG_DEB_NAME="libsodium-dev" PKG_RPM_NAME="libsodium-devel" PKG_CSW_NAME="libsodium_dev" PKG_BREW_NAME="libsodium" PKG_TEST_HEADER="" PKG_LIBS="-lsodium" PKG_CFLAGS="" # Use pkg-config if available if [ $(command -v pkg-config) ]; then PKGCONFIG_CFLAGS=$(pkg-config --cflags --silence-errors ${PKG_CONFIG_NAME}) PKGCONFIG_LIBS=$(pkg-config --libs ${PKG_CONFIG_NAME}) fi # Note that cflags may be empty in case of success if [ "$INCLUDE_DIR" ] || [ "$LIB_DIR" ]; then echo "Found INCLUDE_DIR and/or LIB_DIR!" PKG_CFLAGS="-I$INCLUDE_DIR $PKG_CFLAGS" PKG_LIBS="-L$LIB_DIR $PKG_LIBS" elif [ "$PKGCONFIG_CFLAGS" ] || [ "$PKGCONFIG_LIBS" ]; then echo "Found pkg-config cflags and libs!" PKG_CFLAGS=${PKGCONFIG_CFLAGS} PKG_LIBS=${PKGCONFIG_LIBS} elif [[ "$OSTYPE" == "darwin"* ]]; then if [ $(command -v brew) ]; then BREWDIR=$(brew --prefix) else # autobrew in /tmp curl -sfL "https://jeroen.github.io/autobrew/$PKG_BREW_NAME" > autobrew source autobrew fi PKG_CFLAGS="-I$BREWDIR/opt/$PKG_BREW_NAME/include" PKG_LIBS="-L$BREWDIR/opt/$PKG_BREW_NAME/lib $PKG_LIBS" fi # For debugging echo "Using PKG_CFLAGS=$PKG_CFLAGS" echo "Using PKG_LIBS=$PKG_LIBS" # Find compiler CC=$(${R_HOME}/bin/R CMD config CC) CFLAGS=$(${R_HOME}/bin/R CMD config CFLAGS) CPPFLAGS=$(${R_HOME}/bin/R CMD config CPPFLAGS) # Test configuration echo "#include $PKG_TEST_HEADER" | ${CC} ${CPPFLAGS} ${PKG_CFLAGS} ${CFLAGS} -E -xc - >/dev/null 2>&1 || R_CONFIG_ERROR=1; # Customize the error if [ $R_CONFIG_ERROR ]; then echo "------------------------- ANTICONF ERROR ---------------------------" echo "Configuration failed because $PKG_CONFIG_NAME was not found. Try installing:" echo " * deb: $PKG_DEB_NAME (Debian, Ubuntu, etc)" echo " * rpm: $PKG_RPM_NAME (Fedora, EPEL)" echo " * csw: $PKG_CSW_NAME (Solaris)" echo " * brew: $PKG_BREW_NAME (OSX)" echo "If $PKG_CONFIG_NAME is already installed, check that 'pkg-config' is in your" echo "PATH and PKG_CONFIG_PATH contains a $PKG_CONFIG_NAME.pc file. If pkg-config" echo "is unavailable you can set INCLUDE_DIR and LIB_DIR manually via:" echo "R CMD INSTALL --configure-vars='INCLUDE_DIR=... LIB_DIR=...'" echo "--------------------------------------------------------------------" exit 1; fi # Write to Makevars sed -e "s|@cflags@|$PKG_CFLAGS|" -e "s|@libs@|$PKG_LIBS|" src/Makevars.in > src/Makevars # Success exit 0 sodium/man/0000755000176200001440000000000013062010614012316 5ustar liggesuserssodium/man/hash.Rd0000644000176200001440000000453113063263464013551 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/hashing.R \name{Hash functions} \alias{Hash functions} \alias{hash} \alias{hashing} \alias{scrypt} \alias{shorthash} \alias{sha512} \alias{sha256} \title{Hash Functions} \usage{ hash(buf, key = NULL, size = 32) scrypt(buf, salt = raw(32), size = 32) shorthash(buf, key) sha512(buf, key = NULL) sha256(buf, key = NULL) } \arguments{ \item{buf}{data to be hashed} \item{key}{key for HMAC hashing. Optional, except for in \code{shorthash}.} \item{size}{length of the output hash. Must be between 16 and 64 (recommended is 32)} \item{salt}{non-confidential random data to seed the algorithm} } \description{ Functions to calculate cryptographic hash of a message, with optionally a key for HMAC applications. For storing passwords, use \link{password_store} instead. } \details{ The generic \code{hash} function is recommended most most applications. It uses dynamic length \href{https://download.libsodium.org/doc/hashing/generic_hashing.html}{BLAKE2b} where output size can be any value between 16 bytes (128bit) and 64 bytes (512bit). The \link{scrypt} hash function is designed to be CPU and memory expensive to protect against brute force attacks. This algorithm is also used by the \link{password_store} function. The \code{shorthash} function is a special 8 byte (64 bit) hash based on \href{https://download.libsodium.org/doc/hashing/short-input_hashing.html}{SipHash-2-4}. The output of this function is only 64 bits (8 bytes). It is useful for in e.g. Hash tables, but it should not be considered collision-resistant. Hash functions can be used for HMAC by specifying a secret \code{key}. They key size for \code{shorthash} is 16 bytes, for \code{sha256} it is 32 bytes and for \code{sha512} it is 64 bytes. For \code{hash} the key size can be any value between 16 and 62, recommended is at least 32. } \examples{ # Basic hashing msg <- serialize(iris, NULL) hash(msg) sha256(msg) sha512(msg) scrypt(msg) # Generate keys from passphrase passphrase <- charToRaw("This is super secret") key <- hash(passphrase) shortkey <- hash(passphrase, size = 16) longkey <- hash(passphrase, size = 64) # HMAC (hashing with key) hash(msg, key = key) shorthash(msg, shortkey) sha256(msg, key = key) sha512(msg, key = longkey) } \references{ \url{https://download.libsodium.org/doc/hashing/generic_hashing.html} } sodium/man/keygen.Rd0000644000176200001440000000405113063263464014105 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/keygen.R \name{Key generation} \alias{Key generation} \alias{keygen} \alias{pubkey} \title{Keypair Generation} \usage{ keygen(seed = random(32)) pubkey(key) } \arguments{ \item{seed}{random data to seed the keygen} \item{key}{private key for which to calculate the public key} } \description{ Functions to generate a random private key and calculate the corresponding curve25519 public key. } \details{ Asymmetric methods rely on public-private keypairs. The private keys are secret and should never be shared with anyone. The public key on the other hand is not confidential and should be shared with the other parties. Public keys are typically published on the users's website or posted in public directories or keyservers. The two main applications for public key cryptography are encryption and authentication. In public key encryption, data that is encrypted using a public key can only be decrypted using the corresponding private key. This allows anyone to send somebody a secure message by encrypting it with the receivers public key. The encrypted message will only be readable by the owner of the corresponding private key. Basic encryption is implemented in \link{simple_encrypt}. Authentication works the other way around. In public key authentication, the owner of the private key creates a 'signature' (an authenticated checksum) for a message in a way that allows anyone who knows the user's public key to verify that this message was indeed signed by the owner of the private key. If both sender and receiver know each other's public key, the two methods can be combined so that each message going back and forth is signed by the sender and encrypted for the receiver. This protects both against eavesdropping and MITM tampering, creating a fully secure channel. } \examples{ # Create keypair key <- keygen() pub <- pubkey(key) # Basic encryption msg <- serialize(iris, NULL) ciphertext <- simple_encrypt(msg, pub) out <- simple_decrypt(ciphertext, key) stopifnot(identical(msg, out)) } sodium/man/sig.Rd0000644000176200001440000000352713063263464013414 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/signatures.R \name{Signatures} \alias{Signatures} \alias{sig_sign} \alias{sig} \alias{sig_verify} \alias{sig_keygen} \alias{sig_pubkey} \title{Create and Verify Signatures} \usage{ sig_sign(msg, key) sig_verify(msg, sig, pubkey) sig_keygen(seed = random(32)) sig_pubkey(key) } \arguments{ \item{msg}{message to sign} \item{key}{private key to sign message with} \item{sig}{a signature generated by \code{signature_sign}} \item{pubkey}{a public key of the keypair used by the signature} \item{seed}{random data to seed the keygen} } \description{ Cryptographic signatures can be used to verify the integrity of a message using the author's public key. } \details{ A signature is an authenticated checksum that can be used to check that a message (any data) was created by a particular author and was not tampered with. The signature is created using a private key and can be verified from the corresponding public key. Signatures are used when the message itself is not confidential but integrity is important. A common use is for software repositories where maintainers include a signature of the package index. This allows client package managers to verify that the binaries were not modified by intermediate parties in the distribution process. For confidential data, use authenticated encryption (\link{auth_encrypt}) which allows for sending signed and encrypted messages in a single method. Currently sodium requires a different type of key pairfor signatures (ed25519) than for encryption (curve25519). } \examples{ # Generate keypair key <- sig_keygen() pubkey <- sig_pubkey(key) # Create signature msg <- serialize(iris, NULL) sig <- sig_sign(msg, key) sig_verify(msg, sig, pubkey) } \references{ \url{http://doc.libsodium.org/public-key_cryptography/public-key_signatures.html} } sodium/man/messaging.Rd0000644000176200001440000000427713063263464014612 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/auth-encrypt.R \name{Authenticated encryption} \alias{Authenticated encryption} \alias{auth_encrypt} \alias{auth_decrypt} \title{Authenticated Encryption} \usage{ auth_encrypt(msg, key, pubkey, nonce = random(24)) auth_decrypt(bin, key, pubkey, nonce = attr(bin, "nonce")) } \arguments{ \item{msg}{message to be encrypted} \item{key}{your own private key} \item{pubkey}{other person's public key} \item{nonce}{non-secret unique data to randomize the cipher} \item{bin}{encrypted ciphertext generated by \code{secure_send}} } \description{ Exchange secure messages through curve25519 authenticated encryption. } \details{ Authenticated encryption implements best practices for secure messaging. It requires that both sender and receiver have a keypair and know each other's public key. Each message gets authenticated with the key of the sender and encrypted with the key of the receiver. Even though public keys are not confidential, you should not exchange them over the same insecure channel you are trying to protect. If the connection is being tampered with, the attacker could simply replace the key with another one to hijack the interaction. Most people share their public key by posting them on their website or on a public keyserver. Another alternative is having your public key signed by a mutually trusted third party. HTTPS does this using Certificate Authorities. } \examples{ # Bob's keypair: bob_key <- keygen() bob_pubkey <- pubkey(bob_key) # Alice's keypair: alice_key <- keygen() alice_pubkey <- pubkey(alice_key) # Bob sends encrypted message for Alice: msg <- charToRaw("TTIP is evil") ciphertext <- auth_encrypt(msg, bob_key, alice_pubkey) # Alice verifies and decrypts with her key out <- auth_decrypt(ciphertext, alice_key, bob_pubkey) stopifnot(identical(out, msg)) # Alice sends encrypted message for Bob msg <- charToRaw("Let's protest") ciphertext <- auth_encrypt(msg, alice_key, bob_pubkey) # Bob verifies and decrypts with his key out <- auth_decrypt(ciphertext, bob_key, alice_pubkey) stopifnot(identical(out, msg)) } \references{ \url{http://doc.libsodium.org/public-key_cryptography/authenticated_encryption.html} } sodium/man/symmetric.Rd0000644000176200001440000000422313063263464014640 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/data-encrypt.R \name{Symmetric encryption} \alias{Symmetric encryption} \alias{data_encrypt} \alias{data_decrypt} \alias{data_tag} \title{Symmetric Encryption and Tagging} \usage{ data_encrypt(msg, key, nonce = random(24)) data_decrypt(bin, key, nonce = attr(bin, "nonce")) data_tag(msg, key) } \arguments{ \item{msg}{message to be encrypted} \item{key}{shared secret key used for both encryption and decryption} \item{nonce}{non-secret unique data to randomize the cipher} \item{bin}{encrypted ciphertext} } \description{ Encryption with authentication using a 256 bit shared secret. Mainly useful for encrypting local data. For secure communication use public-key encryption (\link{simple_encrypt} and \link{auth_encrypt}). } \details{ Symmetric encryption uses a secret key to encode and decode a message. This can be used to encrypt local data on disk, or as a building block for more complex methods. Because the same \code{secret} is used for both encryption and decryption, symmetric encryption by itself is impractical for communication. For exchanging secure messages with other parties, use assymetric (public-key) methods (see \link{simple_encrypt} or \link{auth_encrypt}). The \code{nonce} is not confidential but required for decryption, and should be stored or sent along with the ciphertext. The purpose of the \code{nonce} is to randomize the cipher to protect gainst re-use attacks. This way you can use one and the same secret for encrypting multiple messages. The \link{data_tag} function generates an authenticated hash that can be stored alongside the data to be able to verify the integrity of the data later on. For public key signatures see \code{sig_sign} instead. } \examples{ # 256-bit key key <- sha256(charToRaw("This is a secret passphrase")) msg <- serialize(iris, NULL) # Encrypts with random nonce cipher <- data_encrypt(msg, key) orig <- data_decrypt(cipher, key) stopifnot(identical(msg, orig)) # Tag the message with your key (HMAC) tag <- data_tag(msg, key) } \references{ \url{https://download.libsodium.org/doc/secret-key_cryptography/authenticated_encryption.html} } sodium/man/password.Rd0000644000176200001440000000221113063263464014461 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/password.R \name{Password storage} \alias{Password storage} \alias{password_store} \alias{password} \alias{password_verify} \title{Password Storage} \usage{ password_store(password) password_verify(hash, password) } \arguments{ \item{password}{a string of length one with a password} \item{hash}{a hash string of length one generated by \code{password_store}} } \description{ Wrapper that implements best practices for storing passwords based on scrypt with a random salt. } \details{ The \link{password_store} function returns an ASCII encoded string which contains the result of a memory-hard, CPU-intensive hash function along with the automatically generated salt and other parameters required to verify the password. Use \link{password_verify} to verify a password from this string. } \examples{ # Example password password <- "I like cookies" # Hash is what you store in the database hash <- password_store(password) # To verify the password when the user logs in stopifnot(password_verify(hash, password)) } \references{ \url{http://doc.libsodium.org/password_hashing/} } sodium/man/simple.Rd0000644000176200001440000000245213063263464014117 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/simple-encrypt.R \name{Simple encryption} \alias{Simple encryption} \alias{simple_encrypt} \alias{simple_decrypt} \title{Anonymous Public-key Encryption (Sealed Box)} \usage{ simple_encrypt(msg, pubkey) simple_decrypt(bin, key) } \arguments{ \item{msg}{message to be encrypted} \item{pubkey}{public key of the receiver} \item{bin}{encrypted ciphertext} \item{key}{private key of the receiver} } \description{ Create an encrypted message (sealed box) from a curve25519 public key. } \details{ Simple public key encryption allows for sending anonymous encrypted messages to a recipient given its public key. Only the recipient can decrypt these messages, using its private key. While the recipient can verify the integrity of the message, it cannot verify the identity of the sender. For sending authenticated encrypted messages, use \link{auth_encrypt} and \link{auth_decrypt}. } \examples{ # Generate keypair key <- keygen() pub <- pubkey(key) # Encrypt message with pubkey msg <- serialize(iris, NULL) ciphertext <- simple_encrypt(msg, pub) # Decrypt message with private key out <- simple_decrypt(ciphertext, key) stopifnot(identical(out, msg)) } \references{ \url{http://doc.libsodium.org/public-key_cryptography/sealed_boxes.html} } sodium/man/helpers.Rd0000644000176200001440000000217213063263464014267 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/utilities.R \name{Sodium utilities} \alias{Sodium utilities} \alias{bin2hex} \alias{helpers} \alias{hex2bin} \alias{random} \title{Sodium Utilities} \usage{ bin2hex(bin) hex2bin(hex, ignore = ":") random(n = 1) } \arguments{ \item{bin}{raw vector with binary data to convert to hex string} \item{hex}{a string with hexadecimal characters to parse into a binary (raw) vector.} \item{ignore}{a string with characters to ignore from \code{hex}. See example.} \item{n}{number of random bytes or numbers to generate} } \description{ The functions \code{bin2hex} and \code{hex2bin} convert between binary (raw) vectors and corresponding string in hexadecimal notation. The \code{random} function generates \code{n} crypto secure random bytes. } \examples{ # Convert raw to hex string and back test <- charToRaw("test 123") x <- bin2hex(test) y <- hex2bin(x) stopifnot(identical(test, y)) stopifnot(identical(x, paste(test, collapse = ""))) # Parse text with characters x2 <- paste(test, collapse = ":") y2 <- hex2bin(x2, ignore = ":") stopifnot(identical(test, y2)) } sodium/man/stream.Rd0000644000176200001440000000447713063263714014130 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stream.R \name{Stream ciphers} \alias{Stream ciphers} \alias{chacha20} \alias{stream} \alias{salsa20} \alias{xsalsa20} \title{Stream Ciphers} \usage{ chacha20(size, key, nonce) salsa20(size, key, nonce) xsalsa20(size, key, nonce) } \arguments{ \item{size}{length of cipher stream in bytes} \item{key}{secret key used by the cipher} \item{nonce}{non-secret unique data to randomize the cipher} } \description{ Generate deterministic streams of random data based off a secret key and random nonce. } \details{ You usually don't need to call these methods directly. For local encryption use \link{data_encrypt}. For secure communication use \link{simple_encrypt} or \link{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 \link{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 \link{xor}'ing it back. See the examples. Each stream generator requires a \code{key} and a \code{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 \code{nonce} is not secret and should be stored or sent along with the ciphertext. The purpose of the \code{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. } \examples{ # Very basic encryption myfile <- file.path(R.home(), "COPYING") message <- readBin(myfile, raw(), file.info(myfile)$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)) } \references{ \url{https://download.libsodium.org/doc/advanced/xsalsa20.html} } sodium/man/diffie.Rd0000644000176200001440000000455313063263464014060 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/diffie-hellman.R \name{Diffie-Hellman} \alias{Diffie-Hellman} \alias{diffie_hellman} \alias{diffie} \title{Diffie-Hellman} \usage{ diffie_hellman(key, pubkey) } \arguments{ \item{key}{your private key} \item{pubkey}{other person's public key} } \value{ Returns a shared secret key which can be used in e.g. \link{data_encrypt}. } \description{ The Diffie-Hellman key exchange method allows two parties that have no prior knowledge of each other to jointly establish a shared secret key over an insecure channel. This key can then be used to encrypt subsequent communications using a symmetric key cipher. } \details{ Encryption methods as implemented in \link{data_encrypt} require that parties have a shared secret key. But often we wish to establish a secure channel with a party we have no prior relationship with. Diffie-hellman is a method for jointly agreeing on a shared secret without ever exchanging the secret itself. Sodium implements \href{https://en.wikipedia.org/wiki/Curve25519}{Curve25519}, a state-of-the-art Diffie-Hellman function suitable for a wide variety of applications. The method conists of two steps (see examples). First, both parties generate a random private key and derive the corresponding public key using \link{pubkey}. These public keys are not confidential and can be exchanged over an insecure channel. After the public keys are exchanged, both parties will be able to calculate the (same) shared secret by combining his/her own private key with the other person's public key using \link{diffie_hellman}. After the shared secret has been established, the private and public keys are disposed, and parties can start encrypting communications based on the shared secret using e.g. \link{data_encrypt}. Because the shared secret cannot be calculated using only the public keys, the process is safe from eavesdroppers. } \examples{ # Bob generates keypair bob_key <- keygen() bob_pubkey <- pubkey(bob_key) # Alice generates keypair alice_key <- keygen() alice_pubkey <- pubkey(alice_key) # After Bob and Alice exchange pubkey they can both derive the secret alice_secret <- diffie_hellman(alice_key, bob_pubkey) bob_secret <- diffie_hellman(bob_key, alice_pubkey) stopifnot(identical(alice_secret, bob_secret)) } \references{ \url{http://doc.libsodium.org/advanced/scalar_multiplication.html} } sodium/cleanup0000755000176200001440000000003513062010614013116 0ustar liggesusers#!/bin/sh rm -f src/Makevars sodium/tools/0000755000176200001440000000000013063266144012717 5ustar liggesuserssodium/tools/winlibs.R0000644000176200001440000000055313063266144014514 0ustar liggesusers# Build against mingw-w64 build of libsodium if(!file.exists("../windows/sodium-1.0.12/include/sodium.h")){ if(getRversion() < "3.3.0") setInternet2() download.file("https://github.com/rwinlib/sodium/archive/v1.0.12.zip", "lib.zip", quiet = TRUE) dir.create("../windows", showWarnings = FALSE) unzip("lib.zip", exdir = "../windows") unlink("lib.zip") } sodium/LICENSE0000644000176200001440000000005113063047551012557 0ustar liggesusersYEAR: 2017 COPYRIGHT HOLDER: Jeroen Ooms