Skip to content

Instantly share code, notes, and snippets.

@aclemen1
Last active May 20, 2017 22:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aclemen1/3fcc508cb40ddac6c1e3 to your computer and use it in GitHub Desktop.
Save aclemen1/3fcc508cb40ddac6c1e3 to your computer and use it in GitHub Desktop.
'modulr/vault' -- Encrypt and Decrypt Sensitive Data.
# modulr/vault
`modulr/vault` allows to encrypt sensitive data (username, password,
credentials, etc.), which then can be safely embedded in a shareable or publicly
exposed module, and decrypted at runtime only. `modulr/vault` also takes care of
generating the cryptographic key required to cipher and decipher the data.
`modulr/vault` uses the
[AES-256 algorithm](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard).
## Installation
```r
# install.packages(c(
# "PKI",
# "base64enc",
# "assertthat",
# "testthat" # Suggested
# ))
library(modulr)
"modulr/vault#0.1.0" %imports% "3fcc508cb40ddac6c1e3"
# "modulr/vault#0.1.0" %digests%
# "6b2a00764c52533acbec74608ae9375917f9d69d" %imports%
# "3fcc508cb40ddac6c1e3"
```
## Usage
* `$generate_key()`: Generate a cryptographic key.
* `$encrypt(text, key)`: Encrypt some `text` with a cryptographic `key`.
* `$decrypt(cipher, key)`: Decrypt some `cipher`-ed text with a cryptographic `key`.
## Example
The following example shows how to embed a password in a publicly available
module, and how to preserve the cryptographic key in a private module.
1) Load modulr.
```{r, result=FALSE, message=FALSE}
library(modulr)
```
2) Generate a cryptographic key.
```{r, eval=FALSE}
vault %<=% "modulr/vault#^0.1.0"
key <- vault$generate_key()
key
#> [1] "EaJWzAZjjphu9CoA+MPUVCL8mmMAGp0j6Nbga29kV/A="
```
3) Define a **private** module to preserve the cryptographic key.
```{r, results='hide', message=FALSE}
# This is a *private* module containing the key necessary to decrypt the password.
"modulr/vault/example_SECRET_" %provides% "EaJWzAZjjphu9CoA+MPUVCL8mmMAGp0j6Nbga29kV/A="
```
**IMPORTANT NOTE**: Add a line like `*_SECRET_*` to the `.gitignore` file (if any) to avoid committing secret modules.
4) Encrypt a sensitive password.
```{r, eval=FALSE}
vault$encrypt("passw0rd", key)
#> [1] "TWUnCkRAlP70XvmRlnAFrw=="
```
5) Expose the ciphered password in a **public** module.
```{r, results='hide', message=FALSE}
# This is a *public* module containing an encrypted password.
"modulr/vault/example" %requires% list(
vault = "modulr/vault#^0.1.0",
key = "modulr/vault/example_SECRET_"
) %provides% {
password <- vault$decrypt(
"TWUnCkRAlP70XvmRlnAFrw==", # ciphered password
key)
message("The encrypted password is:", password)
return(password)
}
```
6) Enjoy!
```{r, eval=FALSE}
make("modulr/vault/example")
#> ...
#> The encrypted password is: passw0rd
```
## Definition
```{r definition, results='hide', message=FALSE}
library(modulr)
"modulr/vault#0.1.0" %provides% {
library(PKI)
library(base64enc)
library(assertthat)
generate_key <- function() {
base64encode(
PKI.digest(
as.raw(sample(0:255, 256, replace = TRUE)),
"SHA256"))
}
encrypt <- function(text, key) {
assert_that(
is.string(text),
is.string(key))
base64encode(
PKI.encrypt(
charToRaw(text),
base64decode(key),
"aes256"))
}
decrypt <- function(secret, key) {
assert_that(
is.string(secret),
is.string(key))
rawToChar(
PKI.decrypt(
base64decode(secret),
base64decode(key),
"aes256"))
}
list(
generate_key = generate_key,
encrypt = encrypt,
decrypt = decrypt
)
}
```
## Tests
```{r tests, results='hide', message=FALSE}
"modulr/vault#0.1.0/mock" %provides% get_provider("modulr/vault#0.1.0")
"modulr/vault#0.1.0/test" %requires% list(
vault = "modulr/vault#0.1.0/mock"
) %provides% {
library(testthat)
context("modulr/vault")
test_that("$encrypt() encrypts correctly", {
expect_equal(
vault$encrypt(
"Hello World", "m5tE4TKm738bGmPMxw0F6L0nADxH+DCdUC6ZHSkVepk="),
"EYckFN/ekhcx3TiUwENUfw==")
})
test_that("$decrypt() decrypts correctly", {
expect_equal(
vault$decrypt(
"EYckFN/ekhcx3TiUwENUfw==",
"m5tE4TKm738bGmPMxw0F6L0nADxH+DCdUC6ZHSkVepk="),
"Hello World")
})
test_that("$decrypt() is a retract of $encrypt()", {
replicate(100, {
key <- vault$generate_key()
replicate(100, {
text <- paste0(sample(c(0:9, letters, LETTERS), 10, replace = TRUE),
collapse = "")
expect_equal(vault$decrypt(vault$encrypt(text, key), key), text)
})
})
})
}
```
---
© 2014-2017 Alain Clément-Pavon
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment