Installation

You first need to install the goldfinger package from our drat repo, as well as the package dependencies from CRAN. The easiest way to do this is as follows:

install.packages("goldfinger", repos=c("https://cran.rstudio.com/","https://ku-awdc.github.io/drat/"))

As well as the source package, there are binaries available for Windows and macOS (currently intel only). But the package should compile from source on all systems. The package is still being developed, so it may become necessary to install updates: you will be notified of this by the goldfinger package and given instructions for how to update.

Setup

Before you can send or receive any encrypted data, you must first have a user profile. To do this, run the following code:

library("goldfinger")
## Loading required package: tidyverse
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✓ ggplot2 3.3.5     ✓ purrr   0.3.4
## ✓ tibble  3.1.6     ✓ dplyr   1.0.7
## ✓ tidyr   1.1.4     ✓ stringr 1.4.0
## ✓ readr   2.1.1     ✓ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
## Attaching goldfinger version 0.4.3-1
gy_setup()

You will be asked for the following information:

  1. Setup link: this will be sent to you via email, and contains an encryption code that protects the personal information (names and email addresses) that need to be stored online

  2. Name: your name as you wish it to appear on the user list e.g. “Joe Bloggs”

  3. Email: the email address that you want to use for this user (e.g. your KU email address)

  4. Username: a username that will be used to uniquely identify you. Note that this is primarily used by other people when encrypting data for your use, so you should use a username that clearly identifies you. The recommendation is to use the first part of your email address, and the software will suggest this option if it is valid (just hit enter to accept it). Note that spaces, punctuation, and non-ASCII characters (å ø æ etc) are not allowed.

  5. Password: the password that you want to use (enter the same password twice for verification). See below for more information on how passwords are handled.

  6. User file: the name of the private key file to store on your computer. The recommendation is to accept the default (just press enter to accept it).

  7. Location: the place on your computer (or network drive) to store the private key file. You can change the location of this later if needed.

  8. Permission to amend your .Rprofile: this stores the location of your private key file between R sessions so that you don’t need to enter it again if you restart R. The recommendation is to accept this i.e. type y and then hit enter.

Once you have completed user setup, two files will be created for you:

You can now see a list of the currently available users in goldfinger using this code (email addresses are obscured here because this document is online):

gy_users()
## User set to 'md' of group 'goldfinger' (from file '~/Documents/Personal/gy_md_private.gyp')
## Downloading user list...
## Verification succeeded
## # A tibble: 8 × 4
##   user    name                  email    user_since
##   <chr>   <chr>                 <chr>    <date>    
## 1 md      Matt Denwood          **@**.** 2021-09-24
## 2 makg    Maya Gussmann         **@**.** 2021-10-01
## 3 mossa   Mossa Merhi Reimert   **@**.** 2021-11-03
## 4 saxmose Søren Saxmose Nielsen **@**.** 2022-02-08
## 5 seges   SEGES server          **@**.** 2022-02-10
## 6 bcon    Beate Conrady         **@**.** 2022-02-27
## 7 liza    Liza RN               **@**.** 2022-03-08
## 8 vgr853  Lars Pedersen         **@**.** 2022-03-10

When the function is run, an updated list of users is downloaded from a shared resource on the internet. By default this file is only fetched once per R session, but you can force an update using:

gy_users(refresh=TRUE)
## Downloading user list...
## Verification succeeded
## # A tibble: 8 × 4
##   user    name                  email    user_since
##   <chr>   <chr>                 <chr>    <date>    
## 1 md      Matt Denwood          **@**.** 2021-09-24
## 2 makg    Maya Gussmann         **@**.** 2021-10-01
## 3 mossa   Mossa Merhi Reimert   **@**.** 2021-11-03
## 4 saxmose Søren Saxmose Nielsen **@**.** 2022-02-08
## 5 seges   SEGES server          **@**.** 2022-02-10
## 6 bcon    Beate Conrady         **@**.** 2022-02-27
## 7 liza    Liza RN               **@**.** 2022-03-08
## 8 vgr853  Lars Pedersen         **@**.** 2022-03-10

Once Matt has received and processed your public file, then your details will be included in this list.

A note on passwords

The goldfinger package stores your password using the keyring package. On Windows, this means using the Credential Store, on macOS it uses Keychain, and on Linux it uses the Secret Service API. These passwords are safely stored as part of the user settings on your computer, and can only be read by processes running under your user account when you are physically logged in. This provides a relatively strong safety mechanism in a highly convenient way. You can see the usernames that have a password saved with goldfinger using the keyring package:

keyring::key_list("goldfinger")
## [1] service  username
## <0 rows> (or 0-length row.names)

You will need to re-enter your password in the following situations:

It is therefore highly important that you don’t forget your password. If you do forget it, then you will have to create a new user profile and you will permanently lose access to the datasets you have saved for the old profile. So don’t let that happen: either make a secure note of the password (for example in your eBoks “kodehusker”: [https://brugersupport.e-boks.dk/hc/da/articles/360008564399-Kodehusker]) or (even better) start using a secure password manager [https://uk.pcmag.com/password-managers/137639/why-you-need-a-password-manager-and-how-to-choose-the-right-one]

A note on the private key file

Your username and password are used to encrypt the private keys that are stored in your private key file, but it is the private keys that are used to encrypt the data. So, if you lose your private key file then your password is useless, and you can no longer decrypt your data files. You must therefore keep your private key file (gy_user_private.gyp) somewhere safe and where it is backed up so that you don’t lose it if e.g. your hard drive fails. You can also move the private key file to a different folder, and/or use the same private key file on multiple computers, as needed. But don’t put it anywhere public, such as the internet or a shared network drive, as it represents a small security risk (it is much easier to brute force the decryption used to store your private key than to brute force the private key itself).

Basic usage

The goldfinger package uses the following concepts in combination:

Each of these processes is encapsulated into the simple user-facing functions gy_save and gy_load. For example, let’s say that we have two data files that we need to keep safe:

data(cars)
str(cars)
## 'data.frame':    50 obs. of  2 variables:
##  $ speed: num  4 4 7 7 8 9 10 10 10 11 ...
##  $ dist : num  2 10 4 22 16 10 18 26 34 17 ...
text <- "Don't tell anybody!"

In this case it is a data frame and a string, but it could be any R object or external file. To save them safely for your use only, use gy_save in exactly the same way you would use save:

gy_save(cars, text, file="secret_data.rdg")

Then you can re-load them in a new R session using gy_load (in the same way that you would use load):

library("goldfinger")
(gy_load("secret_data.rdg"))
## [1] "cars" "text"

To encrypt something for multiple people to use, you need to use the user argument, where user is one or more valid usernames obtained from gy_users. For example, the following will be usable by Maya and Søren as well as yourself (the overwrite=TRUE argument is needed because the file already exists):

gy_save(cars, text, file="secret_data.rdg", user=c("makg","saxmose"), overwrite=TRUE)

To save something that you cannot open (but Maya and Søren can), then use local_user=FALSE as follows:

gy_save(cars, text, file="not_for_me.rdg", user=c("makg","saxmose"), local_user=FALSE)

You (and any other user other than Maya and Søren) will get the following message when attempting to load this file:

(gy_load("not_for_me.rdg"))
## Error: You are not authorised to decrypt this file

How does it work?

Let’s look “under the hood” at the file we created for the local user (in this case Matt), Maya and Søren:

readRDS("secret_data.rdg")
## $group
## [1] "goldfinger"
## 
## $metadata
## $metadata$user
## [1] "md"
## 
## $metadata$public_curve
##  [1] 8e 2a e1 a9 fc 06 07 ba 25 46 96 6b 20 e9 5c 13 01 2c 7e ed dc 63 0a c3 69
## [26] fc d1 b2 f0 47 c8 02
## 
## $metadata$comment
## [1] ""
## 
## $metadata$versions
##                actual                sodium                    qs 
##             "0.4.3-1"               "1.2.0"              "0.25.2" 
##                  rcpp                     R             date_time 
##               "1.0.8"               "4.1.2" "2022-03-10 23:02:15" 
##                  type               minimum 
##             "decrypt"             "0.4.2-0" 
## 
## $metadata$date_time
## [1] "2022-03-10 23:02:15 CET"
## 
## $metadata$gy_type
## [1] "gy_save"
## 
## 
## $decrypt
## $decrypt$makg
##   [1] 8d 3a f0 4d 11 b6 85 1b 8d a0 15 c4 89 bd 2a 01 80 a5 89 a8 e1 96 0c 21 fb
##  [26] dc 09 36 51 0e e5 ed be 28 2a 17 63 98 dc 49 c5 3a c6 cf 8f 70 5d 2e cb 76
##  [51] 46 d0 11 e2 29 7a 41 38 90 8d d1 43 ad fe f9 d6 30 ec 4f d7 66 f3 d5 53 0e
##  [76] f3 e6 14 bf 6d da 29 1f d6 8b c6 c6 35 91 ba 2f d7 2f e5 6e d0 d7 53 2a 4d
## [101] ee 9c 43 c0 fd f4 04 b9 8f 0c 9c fa d4 d6 0d 69 80 ee 3c e5 86 69 79 95 55
## [126] 97 1c 92 d4 0c 5f b6 bd be 48 14 ae c7 1b 58 6b ec 78 fd a4 7f 75 71 a7 ca
## [151] 00 19 bc 8c 56 34 e5 f7 6b 62 82 0a 6e 65 ce 31 00 56 fd 8a 17 71 b4 70 89
## [176] 95 2a 4a 02 38 ae 56 b4 da 5a af 19 bc f1 58 9c f8 92 25 cd bd db 71 72 e8
## [201] df 3a 9b 00 a5 2f 35 94 cb 17 6d 9b 18 2c 3d ac 13 19 99 ae 15 36 bb 28 d2
## [226] a6 6c ed 6d 48 8c b9 4b 49 d4 12 f1 e8 c8 01 e7 d4 75 70 e3 cf a2 32 c7 67
## [251] c8 e4 92 4c 59 54 b4 c4 4c 70 ab 08 2d d8 5b 1f 07 ca fb 8b b6 80 f1 fa b1
## [276] 84 4d 88 e8 ad 10 7d 86 38 f6 a5 e7 c3 8a c7 61 c7 ee b6 19 fc bb 5a c4 a4
## [301] 60 0f 18 09 0e 32 4e 24 5b 08 5c 04 17 e9 86 31 4b 0e 49 11 b3 5d 8d 67 40
## [326] 0e c3 99 87 72 48 fd 24 64 95 cf 0c 34 7e dc 80 00 6b 0c 92 ae 66 17 31 9f
## [351] 30 3d aa 44 9a fb e7 e0 59 53 52 25 c1 5c 80 24 a5 98 f8 40 6d 5a 7a 5e f8
## [376] b3 e4 bd 01 af 4b 27 03 08 a0 a2 d6 c1 0f c0 8b dd ba eb 7b 5f e0 ea 87 cc
## [401] df d1 bc 74 65 31 96 09 d6 a2 89 97 d5 eb a8 bd 8f a9 df f6 d2 eb 72 b2 6b
## [426] 11 63 93 bb 82 2f d6 d3 a7 93 98 09 9b 28 8c bd ea 83 fe f0 74 be 20 48 4f
## [451] e5 4e fd 0e 9b a4 d1 b4 4c 36 d8 4e 07 0d bb b2 36 9d 1b 35 7a 9b ad a8 47
## [476] e2 ce 3d e0 f1 94 b8 5f e8 19 32 8c 54 09 14 72 e2 93 80 15 74 41 4c 61 fb
## [501] e3 cd 3c c0 88 e6 5e 6c 41 d2 44 d5 a7 0d be 02 da 4d 30 54 50 92 52 2a 5c
## [526] 96 01
## attr(,"nonce")
##  [1] 53 6b 6d 06 ed c1 8b 76 65 85 d5 bb 7c 83 95 eb 1c f3 0e d8 74 33 da cb
## 
## $decrypt$saxmose
##   [1] 24 de 41 0d 37 a7 c8 28 e1 8d e1 9c ea b6 fa 09 7f af 28 12 6b 1c 06 51 03
##  [26] 9c c3 57 c5 e8 32 2f 29 93 d9 99 ac 1f c4 ad 64 71 f1 34 8a 53 86 dd cd c0
##  [51] ae ab 04 62 83 cd e7 64 51 d8 7c f1 59 6a a7 8a 5a 5b 2f 89 aa c3 51 59 83
##  [76] e1 e1 7e 4d 83 17 46 d9 12 32 03 04 e7 35 ff e2 0c 13 17 3a 4c 06 ae 7b a1
## [101] 89 b1 f1 5f d3 89 39 58 d6 8a bc 14 47 c6 cf 07 b0 45 61 99 c2 e9 d2 3a 64
## [126] cd dd 43 1d fc 79 20 68 b4 be ee 68 a7 d1 96 55 b4 0c 36 49 13 87 d7 2e b6
## [151] d3 10 3e ad f6 2a b9 b3 69 05 f9 80 9c 9d 9f 1b f9 30 3c f8 cc 2d 25 c2 92
## [176] 47 4a 49 4c 20 ec dd a3 08 98 0a 9d 01 15 b2 95 6b a8 f3 e0 3a 61 9d 44 90
## [201] 4d 7d 91 b8 47 25 21 4e 84 52 86 57 97 ff 79 55 5e b7 62 f7 f1 e8 91 e7 e4
## [226] 28 7f 52 07 e3 49 d6 7b 7e b7 40 3a 12 ff b9 2f 86 20 f2 96 b9 8a 12 b3 67
## [251] d6 e4 59 4f 11 48 79 31 fb ce 79 a8 63 03 cc aa 5c bb 7f 06 07 bb 41 38 89
## [276] 3e 93 d8 51 c5 11 6b ef 3e 83 fd b6 d3 04 20 fc aa 85 84 a6 78 64 1f 09 2a
## [301] 6b 14 4c e0 0f ec 67 eb b3 eb 47 cd 5b 51 af ab b7 7f 86 78 c3 0f b1 92 40
## [326] 56 09 35 00 c0 1a c6 35 a6 19 15 8f 74 b2 ce ea a2 bf d3 d1 b5 97 e7 60 c5
## [351] 0c 42 79 43 65 04 c7 e5 30 5f ab bf d9 09 aa 80 ea a3 7b c7 8f 2c 26 21 54
## [376] d7 0d 0d ab 9c 34 ce 54 2a c2 b6 c8 c0 46 b8 04 7b 15 2a 75 0c f0 56 fd 0e
## [401] 5b d0 a2 ee ea 76 dc a9 ae a1 ae 38 aa 9e ee f6 9e 47 3c 98 09 9b 81 ee 48
## [426] 65 40 ff 4d ca 3c 41 45 20 c3 9c 80 3a b2 9b 19 93 7b 47 4e a6 ca d4 ee a3
## [451] 64 85 da e0 29 4b e1 9b f0 3c c9 bb 14 73 15 11 78 a2 ca e3 d3 f7 ca 65 c3
## [476] 97 84 14 ec af ee a0 7b e8 04 cf 7a 37 40 d5 9e a0 7f c0 10 56 8f ea 4d f3
## [501] 98 4c c0 f3 74 fb 65 53 cb 6f d5 cc 26 dc 3b 55 7d ea 59 43 dc c9 4b 3a 01
## [526] 0e bc 9e 31 a2
## attr(,"nonce")
##  [1] 40 65 e8 bc 2b b0 f1 37 3f 0f d8 b9 fc af 89 2b 19 9d 2b b9 43 6e f2 6a
## 
## $decrypt$md
##   [1] 6f 36 2f dd 8b c5 b0 75 0e cd 47 eb ca d2 2e 82 3d d7 73 44 83 b1 30 d9 88
##  [26] 94 1b 85 45 88 a5 a0 6d ef cc 5b 56 32 11 7c 45 10 b4 b7 b4 d3 f6 36 20 50
##  [51] e7 37 48 3f 90 7e 77 af f5 13 1b 40 02 21 31 67 28 d3 16 4a 64 50 9f c9 e4
##  [76] 40 2d 7c 63 ff 84 18 d4 b7 8f 66 2d ac 08 bb 9f 98 e1 6f 9f 1c 3b d3 dd 78
## [101] 54 cb d8 4c 7f 86 a6 08 b2 73 9f 9d 76 c7 c6 fb b6 c2 09 a0 43 86 88 a0 58
## [126] ef d1 6e ac 76 5d fd 21 05 32 f9 41 24 62 df 72 a9 5c 4c 9c 10 58 58 2a 60
## [151] 38 28 d4 ad 3c 98 75 e2 15 3d ce 5e d3 a5 f0 ea fd 62 41 46 8b d7 0e a2 91
## [176] 46 8d 42 0d d8 76 9c 7b f4 c0 0d 6a 6e 44 8e de d1 08 7b 37 0c dc 7e 98 e3
## [201] f0 fb 7d c1 56 ca 6d c6 56 af ed be 69 fd 74 1d 14 f2 95 83 8a 51 6d 49 10
## [226] 28 46 90 9d 4f a2 ba 89 f1 3d 06 56 19 89 db 2f 01 a7 dd f1 09 84 8d be 44
## [251] 3c 11 7e 75 c1 d8 15 bb 55 87 96 31 4c e9 3e a1 e6 7d f5 ca 3c 40 70 9c 10
## [276] 4e da b9 3e 45 bc 54 4d b2 13 34 c0 24 40 89 34 40 fe 2f 7f 64 dd 9a 28 20
## [301] 76 ee 71 51 89 f9 4d b3 af 33 d1 06 be 91 0d 04 f3 bb 70 05 8b 3c 3e 49 a6
## [326] 6c 78 58 fc c1 77 9e 16 d4 be aa 4f ee cd fe 15 93 37 2f f3 65 0e ca bb f7
## [351] 95 00 2f 1d d7 a6 ef 89 7f fd 25 f7 7b c7 d8 24 1a 30 a9 37 0f f8 cc c6 ea
## [376] d4 8a 45 db d0 ac f0 1a 3c 27 7d b4 bc 70 3b ea 8b 11 ac eb dc 27 31 26 b6
## [401] 8b f1 dd c1 bc 63 01 60 9f 58 67 12 7f 77 22 d5 d0 70 f5 75 15 0f b2 30 ab
## [426] 2b 1b 8f 71 f6 ea 4d e8 ce a5 c3 1b 48 4e 2a af 3d dc e7 37 9c c4 0f da 5a
## [451] 7a 9f b5 9b 1d 57 76 cd 41 d7 31 2e 5e 75 33 b6 4b ca 67 79 67 e2 8e 10 b2
## [476] 1d 03 0f 52 47 d9 7c 6e b1 a9 ee 82 94 2c 47 9a 86 9f c6 33 17 9d 49 76 dd
## [501] 1d 0b 9b 4e 80 f7 1a f3 e8 e1 c8 26 f3 66 11 fc fb 82 58 d3 2e 6f c1 cf 8a
## attr(,"nonce")
##  [1] f0 8b 6d 88 d9 44 9c 83 6d e1 f6 b7 5f ac ed 79 bd 03 c4 d2 7f 75 04 ac
## 
## 
## $object_encr
##   [1] 22 6a 80 d3 9a 36 e4 ea c8 e6 5b fb 50 6e 8a 96 6d 19 6f 42 62 d1 3e e2 0a
##  [26] d7 19 f5 c6 ac 6f 4a 5e 0e 95 11 1d 0b d8 0b ec 6b 0d ef 0d 7f 69 18 97 1d
##  [51] 65 61 51 04 b6 3b 9c 5c 17 da e6 5b 5c 1b dd 72 de bf 53 d2 77 b9 25 70 99
##  [76] f6 ec 51 20 51 e9 7f e8 a0 7b 3f 40 e1 88 01 a7 fd 2a c7 d4 ce d5 4a 78 57
## [101] 1b cc ab 44 ec 42 88 2a 0f d0 96 14 6a 0e 27 3e 02 aa f0 df 93 0c 36 a0 b5
## [126] c4 ee 1a 4a 4e ce c2 43 27 46 8e 8c ed 52 bc 96 1e ce 15 c2 d8 87 16 59 fd
## [151] ed 2b ce bb ff 43 6b c1 4a 01 41 49 fa 59 90 95 ea e9 9e 0d 6e b7 3a 80 c2
## [176] 87 6a 2e 7b 55 04 98 bc 1f 18 8c ea 72 f4 1f 31 45 50 8a ea 67 4b a0 17 00
## [201] ba 91 3f d8 eb d7 b3 b9 fc 3b c7 06 ff 71 f1 37 dd ad 7c 46 e6 75 2e 2f 3e
## [226] 47 e4 c5 02 8b 31 9d 9f 79 7a 1a d8 c2 f9 41 31 f5 57 aa 9c 1f c4 d3 9f b0
## [251] 08 74 2b ad 4f 49 ba 69 77 94 23 ee 19 fa 74 4e 91 eb 46 48
## attr(,"nonce")
##  [1] 63 7e 40 32 6c 75 ee 75 d8 bc 88 4b 8e 7c 58 0e 59 22 2a 3b d4 ca ff 95
## attr(,"ser_method")
## [1] "qs"
## attr(,"versions")
##                actual                sodium                    qs 
##             "0.4.3-1"               "1.2.0"              "0.25.2" 
##                  rcpp                     R             date_time 
##               "1.0.8"               "4.1.2" "2022-03-10 23:02:15" 
##                  type               minimum 
##         "deserialise"             "0.4.2-0" 
## 
## attr(,"class")
## [1] "goldeneye" "list"

The file contains a list of the following elements:

Without a private key corresponding to one of the listed users, decrypting the data contained in this file is only possible by guessing the symmetric encryption key (which is itself generated using sodium::keygen, then encrypted for specific users, and then discarded). This key is 32 bytes (256 bits), i.e. there are over 10^77 possible combinations for an attacker to try.

Ultra-safe usage

For some particularly sensitive data, a “kill switch” may be required so that the data owner can rescind permission to decrypt a data file under certain conditions (e.g. after a particular date, or if a security breach is suspected). To facilitate this, goldfinger allows an extra layer of security using user-specified supplementary encrypt and decrypt functions.

For example, let’s set up a decryption scheme that requires external information to decrypt the data. We can start by writing an external key (generated using sodium) to an external file:

library("sodium")
dput(keygen(), file="external_key.txt")

This is the contents of the file:

cat(readLines("external_key.txt"))
## as.raw(c(0x92, 0x2a, 0x06, 0x12, 0x4f, 0x7b, 0x39, 0xcb, 0x54,  0x29, 0x6e, 0x39, 0x45, 0x6a, 0x2b, 0x5c, 0x01, 0x1f, 0x20, 0xd0,  0xc9, 0xb5, 0x68, 0xf0, 0x07, 0xfd, 0xce, 0x13, 0x83, 0x82, 0x2c,  0x4a))

Then we can write a pair of functions that take an input, and encrypt/decrypt this input using the key in the file. The important point is that the file is read every time the function is run, and the external key is never stored:

encfun <- function(x){
  cat("Reading external key for encryption...\n")
  ss <- try({
    conn <- file("external_key.txt")
    extkey <- dget(conn)
    close(conn)
  })
  if(inherits(ss, "try-error")) stop("External key not available - cannot encrypt!")
  sodium::data_encrypt(x, extkey)
}

decfun <- function(x){
  cat("Reading external key for decryption...\n")
  ss <- try({
    conn <- file("external_key.txt")
    extkey <- dget(conn)
    close(conn)
  })
  if(inherits(ss, "try-error")) stop("External key not available - cannot decrypt!")
  sodium::data_decrypt(x, extkey)
}

The encryption function can be used to encrypt any raw data using this key, for example the raw encoding of my name:

name <- charToRaw("Matt")
name
## [1] 4d 61 74 74
rawToChar(name)
## [1] "Matt"
enc_name <- encfun(name)
## Reading external key for encryption...
rm(name)

We now have an encrypted version of the raw data, which is not the same as the original:

rawToChar(enc_name)
## [1] "\f\xfa;\xbaH#`\016\xf4V*>LRG\022kO\xc9\xd5"

But we can recover the original using the corresponding decryption function that uses the same key:

name <- decfun(enc_name)
## Reading external key for decryption...
rawToChar(name)
## [1] "Matt"

To use this with goldfinger we could do the following to encode the file for Søren and ourselves:

gy_save(cars, text, file="killswitch_data.rdg", user=c("saxmose"), funs = list(type="custom", encr_fun=encfun, decr_fun=decfun))
## Reading external key for encryption...
## Reading external key for decryption...

Note that inspecting the encrypted data does not tell us that an external key is needed, as this information is all hidden behind the asymetric encryption strategy:

# Not run for this vignette as the output is quite long:
# readRDS("killswitch_data.rdg"))

The only sign that something is more complex is that each element of the decrypt element of the list is longer than it was for the simple encryption.

To decrypt, we just use gy_load as usual (i.e. the end user:

(gy_load("killswitch_data.rdg"))
## Reading external key for decryption...
## [1] "cars" "text"

But if we remove the external key file, then the data can no longer be decrypted:

file.remove("external_key.txt")
## [1] TRUE
(gy_load("killswitch_data.rdg"))
## Reading external key for decryption...
## Warning in parse(file = file, keep.source = keep.source): cannot open file
## 'external_key.txt': No such file or directory
## Error in parse(file = file, keep.source = keep.source) : 
##   cannot open the connection
## Error in funs[["decr_fun"]](funs[[".x"]]): External key not available - cannot decrypt!

Note that the “external_key.txt” file would normally be placed on a webserver by the data owner, so that they can remove the file at any point and effectively shut all users out of the data. This is achieved simply by replacing the file handle in the two functions with a url handle (but as before, the location of this file is hidden within the .rdg file using asymetric encryption).

Of course this does not prevent an authorised user from extracting the data when they have permission to do so and storing it elsewhere in an unencrypted format for later use - however this type of deliberate misuse of the system could be explicitly prohibited by the terms of use of the data source.

Session information

This guide was produced on the following date and system:

Sys.time()
## [1] "2022-03-10 23:02:15 CET"
sessionInfo()
## R version 4.1.2 (2021-11-01)
## Platform: aarch64-apple-darwin20 (64-bit)
## Running under: macOS Monterey 12.2.1
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/lib/libRlapack.dylib
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] sodium_1.2.0       goldfinger_0.4.3-1 forcats_0.5.1      stringr_1.4.0     
##  [5] dplyr_1.0.7        purrr_0.3.4        readr_2.1.1        tidyr_1.1.4       
##  [9] tibble_3.1.6       ggplot2_3.3.5      tidyverse_1.3.1   
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_1.0.8          lubridate_1.8.0     getPass_0.2-2      
##  [4] assertthat_0.2.1    digest_0.6.29       utf8_1.2.2         
##  [7] R6_2.5.1            cellranger_1.1.0    backports_1.4.1    
## [10] reprex_2.0.1        evaluate_0.14       httr_1.4.2         
## [13] pillar_1.6.5        rlang_1.0.0         readxl_1.3.1       
## [16] rstudioapi_0.13     jquerylib_0.1.4     rmarkdown_2.11     
## [19] qs_0.25.2           munsell_0.5.0       broom_0.7.12       
## [22] compiler_4.1.2      modelr_0.1.8        xfun_0.29          
## [25] pkgconfig_2.0.3     htmltools_0.5.2     tidyselect_1.1.1   
## [28] fansi_1.0.2         crayon_1.4.2        tzdb_0.2.0         
## [31] dbplyr_2.1.1        withr_2.4.3         grid_4.1.2         
## [34] jsonlite_1.7.3      gtable_0.3.0        lifecycle_1.0.1    
## [37] DBI_1.1.2           magrittr_2.0.2      scales_1.1.1       
## [40] RcppParallel_5.1.5  cli_3.1.1           stringi_1.7.6      
## [43] fs_1.5.2            xml2_1.3.3          ellipsis_0.3.2     
## [46] keyring_1.3.0       generics_0.1.1      vctrs_0.3.8        
## [49] stringfish_0.15.5   RApiSerialize_0.1.0 tools_4.1.2        
## [52] glue_1.6.1          hms_1.1.1           fastmap_1.1.0      
## [55] yaml_2.2.2          colorspace_2.0-2    rvest_1.0.2        
## [58] knitr_1.37          haven_2.4.3