Last active
May 20, 2017 22:32
-
-
Save aclemen1/3fcc508cb40ddac6c1e3 to your computer and use it in GitHub Desktop.
'modulr/vault' -- Encrypt and Decrypt Sensitive Data.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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