| Title: | High Level Encryption Wrappers |
| Version: | 1.1.7 |
| Description: | Encryption wrappers, using low-level support from 'sodium' and 'openssl'. 'cyphr' tries to smooth over some pain points when using encryption within applications and data analysis by wrapping around differences in function names and arguments in different encryption providing packages. It also provides high-level wrappers for input/output functions for seamlessly adding encryption to existing analyses. |
| License: | MIT + file LICENSE |
| URL: | https://github.com/ropensci/cyphr,https://docs.ropensci.org/cyphr/ |
| BugReports: | https://github.com/ropensci/cyphr/issues |
| Imports: | getPass, openssl (≥ 0.9.9), sodium (≥ 1.2.1) |
| Suggests: | knitr, rmarkdown, testthat (≥ 3.0.0) |
| RoxygenNote: | 7.2.3 |
| VignetteBuilder: | rmarkdown, knitr |
| Encoding: | UTF-8 |
| Language: | en-GB |
| Config/testthat/edition: | 3 |
| NeedsCompilation: | no |
| Packaged: | 2025-02-07 10:14:06 UTC; rfitzjoh |
| Author: | Rich FitzJohn [aut, cre], Jai Ranganathan [ctb] |
| Maintainer: | Rich FitzJohn <rich.fitzjohn@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2025-02-07 12:30:07 UTC |
High Level Encryption Wrappers
Description
Encryption wrappers, using low-level support from sodium and openssl.
Details
It isstrongly recommended that you readboth vignettes beforeattempting to usecyphr.
introduction;in R:
vignette("cyphr", package = "cyphr")data vignette;in R:
vignette("data", package = "cyphr")
Author(s)
Rich FitzJohn (rich.fitzjohn@gmail.com)
See Also
Useful links:
Report bugs athttps://github.com/ropensci/cyphr/issues
Encrypted data administration
Description
Encrypted data administration; functions for setting up, addingusers, etc.
Usage
data_admin_init(path_data, path_user = NULL, quiet = FALSE)data_admin_authorise( path_data = NULL, hash = NULL, path_user = NULL, yes = FALSE, quiet = FALSE)data_admin_list_requests(path_data = NULL)data_admin_list_keys(path_data = NULL)Arguments
path_data | Path to the data set. We will store a bunch ofthings in a hidden directory within this path. By default inmost functions we will search down the tree until we find the.cyphr directory |
path_user | Path to the directory with your ssh key.Usually this can be omitted. |
quiet | Suppress printing of informative messages. |
hash | A vector of hashes to add. If provided, each hash canbe the binary or string representation of the hash to add. Oromit to add each request. |
yes | Skip the confirmation prompt? If any request isdeclined then the function will throw an error on exit. |
Details
data_admin_init initialises the system; it will create adata key if it does not exist and authorise you. If it alreadyexists and you do not have access it will throw an error.
data_admin_authorise authorises a key by creating a key tothe data that the user can use in conjunction with their personalkey.
data_admin_list_requests lists current requests.
data_admin_list_keys lists known keys that can access thedata. Note that this isnot secure; keys not listed heremay still be able to access the data (if a key was authorised andmoved elsewhere for example). Conversely, if the user has deletedor changed their key they will not be able to access the datadespite the key being listed here.
See Also
data_request_access() for requesting accessto the data, and anddata_key for using the dataitself. But for a much more thorough overview, see the vignette(vignette("data", package = "cyphr")).
Examples
# The workflow here does not really lend itself to an example,# please see the vignette instead.# First we need a set of user ssh keys. In a non example# environment your personal ssh keys will probably work well, but# hopefully they are password protected so cannot be used in# examples. The password = FALSE argument is only for testing,# and should not be used for data that you care about.path_ssh_key <- tempfile()cyphr::ssh_keygen(path_ssh_key, password = FALSE)# Initialise the data directory, using this key path. Ordinarily# the path_user argument would not be needed because we would be# using your user ssh keys:path_data <- tempfile()dir.create(path_data, FALSE, TRUE)cyphr::data_admin_init(path_data, path_user = path_ssh_key)# Now you can get the data keykey <- cyphr::data_key(path_data, path_user = path_ssh_key)# And encrypt things with itcyphr::encrypt_string("hello", key)# See the vignette for more details. This is not the best medium# to explore this.# Cleanupunlink(path_ssh_key, recursive = TRUE)unlink(path_data, recursive = TRUE)User commands
Description
User commands
Usage
data_request_access(path_data = NULL, path_user = NULL, quiet = FALSE)data_key( path_data = NULL, path_user = NULL, test = TRUE, quiet = FALSE, cache = TRUE)Arguments
path_data | Path to the data. If not given, then we lookrecursively down below the working directory for a ".cyphr"directory, and use that as the data directory. |
path_user | Path to the directory with your user key.Usually this can be omitted. This argument is passed in as both |
quiet | Suppress printing of informative messages. |
test | Test that the encryption is working? (Recommended) |
cache | Cache the key within the session. This will beuseful if you are using ssh keys that have passwords, as if thekey is found within the cache, then you will not have tore-enter your password. Using |
Examples
# The workflow here does not really lend itself to an example,# please see the vignette.# Suppose that Alice has created a data directory:path_alice <- tempfile()cyphr::ssh_keygen(path_alice, password = FALSE)path_data <- tempfile()dir.create(path_data, FALSE, TRUE)cyphr::data_admin_init(path_data, path_user = path_alice)# If Bob can also write to the data directory (e.g., it is a# shared git repo, on a shared drive, etc), then he can request# accesspath_bob <- tempfile()cyphr::ssh_keygen(path_bob, password = FALSE)hash <- cyphr::data_request_access(path_data, path_user = path_bob)# Alice can authorise Bobcyphr::data_admin_authorise(path_data, path_user = path_alice, yes = TRUE)# After which Bob can get the data keycyphr::data_key(path_data, path_user = path_bob)# See the vignette for more details. This is not the best medium# to explore this.# Cleanupunlink(path_alice, recursive = TRUE)unlink(path_bob, recursive = TRUE)unlink(path_data, recursive = TRUE)Easy encryption and decryption
Description
Wrapper functions for encryption. These functions wrapexpressions that produce or consume a file and arrange to encrypt(for producing functions) or decrypt (for consuming functions).The forms with a trailing underscore (encrypt_,decrypt_) do not use any non-standard evaluation and may bemore useful for programming.
Usage
encrypt(expr, key, file_arg = NULL, envir = parent.frame())decrypt(expr, key, file_arg = NULL, envir = parent.frame())encrypt_(expr, key, file_arg = NULL, envir = parent.frame())decrypt_(expr, key, file_arg = NULL, envir = parent.frame())Arguments
expr | A single expression representing a function call thatwould be called for the side effect of creating or reading afile. |
key | A |
file_arg | Optional hint indicating which argument to |
envir | Environment in which |
Details
These functions will not work for all functions. For examplepdf/dev.off will create a file but we can't wrapthose up (yet!). Functions thatmodify a file (e.g.,appending) also will not work and may cause data loss.
Examples
# To do anything we first need a key:key <- cyphr::key_sodium(sodium::keygen())# Encrypted write.csv - note how any number of arguments to# write.csv will be passed alongpath <- tempfile(fileext = ".csv")cyphr::encrypt(write.csv(iris, path, row.names = FALSE), key)# The new file now exists, but you would not be able to read it# with read.csv because it is now binary data.file.exists(path)# Wrap the read.csv call with cyphr::decrypt()dat <- cyphr::decrypt(read.csv(path, stringsAsFactors = FALSE), key)head(dat)file.remove(path)# If you have a function that is not supported you can specify the# filename argument directly. For example, with "write.dcf" the# filename argument is called "file"; we can pass that alongpath <- tempfile()cyphr::encrypt(write.dcf(list(a = 1), path), key, file_arg = "file")# Similarly for decryption:cyphr::decrypt(read.dcf(path), key, file_arg = "file")Encrypt and decrypt data and other things
Description
Encrypt and decrypt raw data, objects, strings and files. Thecore functions here areencrypt_data anddecrypt_data which take raw data and decrypt it, writingeither to file or returning a raw vector. The other functionsencrypt and decrypt arbitrary R objects (encrypt_object,decrypt_object), strings (encrypt_string,decrypt_string) and files (encrypt_file,decrypt_file).
Usage
encrypt_data(data, key, dest = NULL)encrypt_object(object, key, dest = NULL, rds_version = NULL)encrypt_string(string, key, dest = NULL)encrypt_file(path, key, dest = NULL)decrypt_data(data, key, dest = NULL)decrypt_object(data, key)decrypt_string(data, key)decrypt_file(path, key, dest = NULL)Arguments
data | (for |
key | A |
dest | The destination filename for the encrypted ordecrypted data, or |
object | (for |
rds_version | RDS serialisation version to use (seeserialize. The default in R version 3.3 and below is version2 - in the R 3.4 series version 3 was introduced and is becomingthe default. Version 3 format serialisation is not understoodby older versions so if you need to exchange data with older Rversions, you will need to use |
string | (for |
path | (for |
Examples
key <- key_sodium(sodium::keygen())# Some super secret data we want to encrypt:x <- runif(10)# Convert the data into a raw vector:data <- serialize(x, NULL)data# Encrypt the data; without the key above we will never be able to# decrypt this.data_enc <- encrypt_data(data, key)data_enc# Our random numbers:unserialize(decrypt_data(data_enc, key))# Same as the never-encrypted version:x# This can be achieved more easily using `encrypt_object`:data_enc <- encrypt_object(x, key)identical(decrypt_object(data_enc, key), x)# Encrypt strings easily:str_enc <- encrypt_string("secret message", key)str_encdecrypt_string(str_enc, key)Symmetric encryption with openssl
Description
Wrap an openssl symmetric (aes) key. This can be used with thefunctionsencrypt_data() anddecrypt_data(), along with the higher level wrappersencrypt() anddecrypt(). With a symmetrickey, everybody uses the same key for encryption and decryption.
Usage
key_openssl(key, mode = "cbc")Arguments
key | An openssl aes key (i.e., an object of class |
mode | The encryption mode to use. Options are |
Examples
# Create a new keykey <- cyphr::key_openssl(openssl::aes_keygen())key# With this key encrypt a stringsecret <- cyphr::encrypt_string("my secret string", key)# And decrypt it again:cyphr::decrypt_string(secret, key)Symmetric encryption with sodium
Description
Wrap a sodium symmetric key. This can be used with the functionsencrypt_data() anddecrypt_data(), alongwith the higher level wrappersencrypt() anddecrypt(). With a symmetric key, everybody uses thesame key for encryption and decryption.
Usage
key_sodium(key)Arguments
key | A sodium key (i.e., generated with |
Examples
# Create a new keykey <- cyphr::key_sodium(sodium::keygen())key# With this key encrypt a stringsecret <- cyphr::encrypt_string("my secret string", key)# And decrypt it again:cyphr::decrypt_string(secret, key)Asymmetric encryption with openssl
Description
Wrap a pair of openssl keys. You should pass your private key andthe public key of the person that you are communicating with.
Usage
keypair_openssl( pub, key, envelope = TRUE, password = NULL, authenticated = TRUE)Arguments
pub | An openssl public key. Usually this will be the pathto the key, in which case it may either the path to a public keyor be the path to a directory containing a file |
key | An openssl private key. Usually this will be the pathto the key, in which case it may either the path to a privatekey or be the path to a directory containing a file. You mayspecify |
envelope | A logical indicating if "envelope" encryptionfunctions should be used. If so, then we use |
password | A password for the private key. If |
authenticated | Logical, indicating if the result should besigned with your public key. If |
See Also
keypair_sodium() for a similar function usingsodium keypairs
Examples
# Note this uses password = FALSE for use in examples only, but# this should not be done for any data you actually care about.# Note that the vignette contains much more information than this# short example and should be referred to before using these# functions.# Generate two keypairs, one for Alice, and one for Bobpath_alice <- tempfile()path_bob <- tempfile()cyphr::ssh_keygen(path_alice, password = FALSE)cyphr::ssh_keygen(path_bob, password = FALSE)# Alice wants to send Bob a message so she creates a key pair with# her private key and bob's public key (she does not have bob's# private key).pair_alice <- cyphr::keypair_openssl(pub = path_bob, key = path_alice)# She can then encrypt a secret message:secret <- cyphr::encrypt_string("hi bob", pair_alice)secret# Bob wants to read the message so he creates a key pair using# Alice's public key and his private key:pair_bob <- cyphr::keypair_openssl(pub = path_alice, key = path_bob)cyphr::decrypt_string(secret, pair_bob)# Clean upunlink(path_alice, recursive = TRUE)unlink(path_bob, recursive = TRUE)Asymmetric encryption with sodium
Description
Wrap a pair of sodium keys for asymmetric encryption. You shouldpass your private key and the public key of the person that youare communicating with.
Usage
keypair_sodium(pub, key, authenticated = TRUE)Arguments
pub | A sodium public key. This is either a raw vector oflength 32 or a path to file containing the contents of the key(written by |
key | A sodium private key. This is either a raw vector oflength 32 or a path to file containing the contents of the key(written by |
authenticated | Logical, indicating if authenticatedencryption (via |
Details
NOTE: the order here (pub, key) is very important; if thewrong order is used you cannot decrypt things. Unfortunatelybecause sodium keys are just byte sequences there is nothing todistinguish the public and private keys so this is a pretty easymistake to make.
See Also
keypair_openssl() for a similar function usingopenssl keypairs
Examples
# Generate two keypairs, one for Alice, and one for Bobkey_alice <- sodium::keygen()pub_alice <- sodium::pubkey(key_alice)key_bob <- sodium::keygen()pub_bob <- sodium::pubkey(key_bob)# Alice wants to send Bob a message so she creates a key pair with# her private key and bob's public key (she does not have bob's# private key).pair_alice <- cyphr::keypair_sodium(pub = pub_bob, key = key_alice)# She can then encrypt a secret message:secret <- cyphr::encrypt_string("hi bob", pair_alice)secret# Bob wants to read the message so he creates a key pair using# Alice's public key and his private key:pair_bob <- cyphr::keypair_sodium(pub = pub_alice, key = key_bob)cyphr::decrypt_string(secret, pair_bob)Register functions to work with encrypt/decrypt
Description
Add information about argument rewriting so that they can be usedwithencrypt anddecrypt.
Usage
rewrite_register(package, name, arg, fn = NULL)Arguments
package | The name of the package with the function tosupport (as a scalar character). If your function has nopackage (e.g., a function you are working on outside of apackage, use "" as the name). |
name | The name of the function to support. |
arg | The name of the argument in the target function thatrefers to the file that should be encrypted or decrypted. Thisis the value you would pass through to |
fn | Optional (and should be rare) argument used to workaround functions that pass all their arguments through to asecond function as dots. This is how |
Details
If your package uses cyphr, it might be useful to add this asan.onLoad() hook.
Examples
# The saveRDS function is already supported. But if we wanted to# support it we could look at the arguments for the function:args(saveRDS)# The 'file' argument is the one that refers to the filename, so# we'd write:cyphr::rewrite_register("base", "saveRDS", "file")# It's non-API but you can see what is supported in the package by# looking atls(cyphr:::db)Refresh the session key
Description
Refresh the session key, invalidating all keys created bykey_openssl(),keypair_openssl(),key_sodium() andkeypair_sodium().
Usage
session_key_refresh()Details
Running this function will invalidateall keys loaded withthe above functions. It should not be needed very often.
Examples
# Be careful - if you run this then all keys loaded from file will# no longer work until reloadedif (FALSE) { cyphr::session_key_refresh()}Create ssh keypairs
Description
Create openssl key pairs in the manner ofssh-keygen(1).In general this should not be used (generate keys yourself withssh-keygen at the command line. However this is useful fortesting and demonstration so I have included it to make thateasier. Once a keypair has been generated it can be used withkeypair_openssl().
Usage
ssh_keygen(path = tempfile(), password = TRUE, use_shell = FALSE)Arguments
path | A directory in which to create a keypair. If the pathdoes not exist it will be created. |
password | The password for the key. The default will promptinteractively (but without echoing the password). Other validoptions are |
use_shell | Try to use |
Value
Thepath, invisibly. This is useful in the casewherepath istempfile().
Examples
# Generate a new key in a temporary directory:path <- cyphr::ssh_keygen(password = FALSE)dir(path) # will contain id_rsa and id_rsa.pub# This key can now be used via keypair_openssl:key <- cyphr::keypair_openssl(path, path)secret <- cyphr::encrypt_string("hello", key)cyphr::decrypt_string(secret, key)# Cleanupunlink(path, recursive = TRUE)