tl;dr
You can knit an R Markdown file to an encrypted HTML with {encryptedRmd} and put it online with GitHub Pages. Users must enter the decryption key to download and view the content.
TinkR TailR
I’m working on a personal project that outputs an HTML document rendered from an R Markdown file. I want to password-protect and share it with a specific person somehow. Also, sharing a hard copy by email is tedious; I’d rather they always had the latest version from a URL.
More importantly, I watched Tinker Tailor Soldier Spy over the weekend and I wanted to feign top-secret document handling.
Invest in encrypto
I’m a simple fellow. I don’t want to download or handle any extra software; I don’t want to configure anything; I like ‘free’ as in ‘I don’t have to pay for it’; I want minimal friction for the person accessing the content; I want the file to be standalone and self-contained.
There’s probably many ways to achieve this with R, but I decided to try out Dirk Schumacher’s {encryptedRmd} package, which I starred on GitHub a while ago and then forgot about. I’ve used GitHub Pages for hosting a bunch of stuff at no cost; might as well pop it there.
Example
I made a simple GitHub repo containing a demo of this approach. The encrypted HTML output is available online. I’ve embedded it below as well.
You’ll be asked for a key to decrypt it. For this demo, the key is: 9ebf5d40b061c59330b9fce16703e4c2fb2fbf90a773996e43e49d562ea17039
.
Your browser will prompt you to save and view the decrypted document if you enter the correct key. Prepare to see some extremely top secret information when you open that file.
How to
How was this created? In short, you knit an R Markdown as usual, but replace the output type in the YAML header. Here’s the steps:
- Install {encryptedRmd} from CRAN if you haven’t already, using
install.packages("encryptedRmd")
- Write an R Markdown file (i.e. extension .Rmd) where the
output:
field in the YAML header is set to encryptedRmd::encrypted_html_document
- Knit the file to render (i) an unencrypted ‘normal’ version HTML, (ii) an encrypted HTML version, and (iii) a text file containing a randomised decryption key, all of which are generated by default in the same folder that the Rmd is in
- To serve, commit and push only the encrypted file to GitHub and then activate GitHub Pages for the repo (go to ‘Settings’ > ‘Pages’)
Of course, you should add the R Markdown file, the unencrypted HTML and the decryption key to your .gitignore file, otherwise the content will be available for people to see.
I’ve retained all the output files in the demo repo so you can see them all. You can find them in the docs/
folder:
docs/
├── encrypt-test.Rmd
├── encrypt-test.html
├── encrypt-test.enc.html
└── encrypt-test.enc.html.key
I told GitHub Pages to serve this docs/
folder from the main
branch, so that the URL ends up as https://matt-dray.github.io/encrypt-rmd-test/encrypt-test.html.enc.html.
Now I can share the URL with someone and send them the key via a separate means of communication, like via a fax or a pigeon.
‘Get a job in cyber’
Surprise, I am not a cyber security expert. You can read more about the libsodium encryption method underlying {encryptedRmd} if you’re wondering how it works, etc.
As noted by Dirk in the {encryptedRmd} README: use at your own risk.
For me, the outlined approach does what I need and does it painlessly. I have no intention to share actually-sensitive information via this method, so I have little to worry about. I’m Smiley as George Smiley in Tinker Tailor Soldier Spy.
Environment
Session info
Last rendered: 2023-07-21 18:39:35 BST
R version 4.3.1 (2023-06-16)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.2.1
Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
time zone: Europe/London
tzcode source: internal
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] htmlwidgets_1.6.2 compiler_4.3.1 fastmap_1.1.1 cli_3.6.1
[5] tools_4.3.1 htmltools_0.5.5 rstudioapi_0.15.0 yaml_2.3.7
[9] rmarkdown_2.23 knitr_1.43.1 jsonlite_1.8.7 xfun_0.39
[13] digest_0.6.33 rlang_1.1.1 evaluate_0.21