Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

In a previous post I documented what I had learned while trying to understand the structure of encrypted emails. I then took an informal Twitter poll to gauge how many people are using encrypted email messages.

It’s by no means a statistically representative sample, but I’ll go out on a limb and state that not many people are actually encrypting their email. I have a few hypotheses which might explain this:

• Maybe that’s because they don’t feel it’s necessary?
• Perhaps they find it inconvenient or difficult to set up?
• Possibly they didn’t even know that it was possible?

I think that securing your personal communications is becoming progressively more important. So I’m going to be using GnuPG to encrypt and sign emails in future.

In this post I’m going to demonstrate a new feature in {emayili}, which makes it possible to easily send encrypted messages from R. This feature leans heavily on the excellent {gpg} package developed by Jeroen Ooms.

First let’s load {emayili}.

library(emayili)

packageVersion("emayili")

The encryption feature is only available from version 0.7.0.

You don’t need to explicitly load {gpg} to use encryption with {emayili}, but we’ll do so just to check on the version of GPG and create some keys to play with.

library(gpg)

gpg_version()
gpg (GnuPG) 2.2.19
libgcrypt 1.8.5
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/wookie/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

## Creating Keys

We’ll set the scene by creating a few keys in a temporary location so that we don’t clobber our existing keyring.

gpg_restart(home = tempdir(), silent = TRUE)

For entertainment we’ll simulate encrypted communications around the D-Day landings. We’ll need some (obviously fictitious) email addresses and keys.

FLOTILLA  <- "[email protected]"
BORCHERS  <- "[email protected]"
SCHUNK  <- "[email protected]"
gpg_keygen(name = "Flotilla", email = FLOTILLA)
gpg_keygen(name = "U 276 Borchers", email = BORCHERS)
gpg_keygen(name = "U 348 Schunk", email = SCHUNK)

Now take a look at our keyring.

gpg_list_keys() %>% select(id, fingerprint, name)
id                              fingerprint           name
1 A54509CACB0F295E CE08B765CA067CAA57764F5EA54509CACB0F295E       Flotilla
2 0897DF3055C00B2F AAA3971869729272BBD61F730897DF3055C00B2F U 276 Borchers
3 0665C3E83FBB901B EF5AA9E78B78836AD16399180665C3E83FBB901B   U 348 Schunk

## Publishing Keys

Publishing those keys could be done as follows (although we won’t actually publish the keys for obvious reasons!):

gpg --keyserver keyserver.ubuntu.com --send-key CE08B765CA067CAA57764F5EA54509CACB0F295E
gpg --keyserver pgp.mit.edu --send-key AAA3971869729272BBD61F730897DF3055C00B2F
gpg --keyserver keys.openpgp.org --send-key 0665C3E83FBB901B

The keys can be reference by id or fingerprint.

## Creating a Message

What about a message body? The message below was intercepted at 04:30 UTC on 6 June 1944 and subsequently decrypted by the codebreakers at Bletchley Park.

SUBJECT <- "Attention"
TEXT <- "Immediate readiness. There are indications that the invasion has begun."

Create an {emayili} message object.

msg <- envelope(
from = FLOTILLA,
to = c(BORCHERS, SCHUNK),
subject = SUBJECT,
text = TEXT
)
Date:                        Mon, 06 Dec 2021 15:58:54 GMT
X-Mailer:                    {emayili}-0.7.0
MIME-Version:                1.0
To:                          [email protected],
[email protected]
From:                        [email protected]
Subject:                     Attention
Content-Type:                text/plain;
charset=utf-8;
format=flowed
Content-Disposition:         inline
Content-Transfer-Encoding:   7bit
Content-MD5:                 HvL4qIrj5lMuW+E5BW4APA==

Immediate readiness. There are indications that the invasion has begun.

This is a simple, unsecured text massage.

## Sign a Message

To add a digital signature to the message use the encrypt() function and set encrypt = FALSE but sign = TRUE. It’s also possible to enable a signature using the sign option to envelope().

msg %>% encrypt(encrypt = FALSE, sign = TRUE)
Date:                        Mon, 06 Dec 2021 15:58:54 GMT
X-Mailer:                    {emayili}-0.7.0
MIME-Version:                1.0
To:                          [email protected],
[email protected]
From:                        [email protected]
Subject:                     Attention
Content-Type:                multipart/signed;
micalg="{micalg}";
protocol="application/pgp-signature";
boundary="9c3b0106"

This is an OpenPGP/MIME signed message (RFC 4880 and 3156).
--9c3b0106
Content-Type:                multipart/mixed;
boundary="dab92f94"

--dab92f94
Content-Type:                text/plain;
charset=utf-8;
format=flowed
Content-Disposition:         inline
Content-Transfer-Encoding:   7bit
Content-MD5:                 HvL4qIrj5lMuW+E5BW4APA==

Immediate readiness. There are indications that the invasion has begun.
--dab92f94
Content-Type:                application/pgp-keys;
name="keys.asc"
Content-Description:         OpenPGP public key
Content-Disposition:         attachment; filename="keys.asc"
Content-Transfer-Encoding:   quoted-printable
Content-MD5:                 Jm6SWeTLKhlhcxTSoIKPIg==

-----BEGIN PGP PUBLIC KEY BLOCK-----

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
Dpwp3bn54OyYKhdrHLSbrk/F/IHC4w=3D=3D
=3DWWtP
-----END PGP PUBLIC KEY BLOCK-----

--dab92f94--
--9c3b0106
Content-Type:                application/pgp-signature;
name="signature.asc"
Content-Description:         OpenPGP digital signature
Content-Disposition:         attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----

I9Z7VTit+PWrIUbFZDzdqI9N7SBbayYeFoLuC7OoC9hwNEqdFCU0DjRr7LWBxutQ
24G2l5PQRZm6hEWBw/eOnY0AHuERAmyf3Q72S7tSMO0x9wCc3EzOZ61JFXiIK4nT
vRmjcQWAxmzujZs6fLk0o2ZaCLZzprG62qlMOYYpKXB6yA+Wjg/+daWokYiNnlbn
GGSccCbKV0XGEOU8u/yOql8oW9ziSWSuMjEg/xYbl7IQkls0STzW5brGiCfWe+w4
HBf8Gf+9ohmlYhvyJHYVpysMJGBdVGUc5gfFm1aJ0DyN++dzQ9OWiz1oTphiBT6Q
8N1Vc8vX0uJ9aiWyOWTOfS1vzua7u0edfmJ2FrTbwBSBnLbvTf8O75ztvrKKuslc
CKRevsLS
=I6ZJ
-----END PGP SIGNATURE-----

--9c3b0106--

The resulting message now includes:

• the public key for the sender (PGP PUBLIC KEY) and
• a digital signature (PGP SIGNATURE).

The structure of the MIME message is such that the signature covers both the message and the public key. In this way the sender is also authenticating the validity of the public key that they are sharing. For brevity you can omit the public key by setting the public_key = FALSE option to encrypt().

The commanders of U 276 and U 348 could validate the authenticity of the message by using the published public key for .

## Encrypt a Message

Signing a message establishes its authenticity, but for secure communications you’d want to encrypt the contents of the message too. Again, use the encrypt() function with encrypt = TRUE (this is the default). It’s also possible to enable encryption using the encrypt option to envelope().

msg %>% encrypt(encrypt = TRUE)
Date:                        Mon, 06 Dec 2021 15:58:54 GMT
X-Mailer:                    {emayili}-0.7.0
MIME-Version:                1.0
To:                          [email protected],
[email protected]
From:                        [email protected]
Subject:                     Attention
Content-Type:                multipart/encrypted;
protocol="application/pgp-encrypted";
boundary="0ae1ea20"

This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156).
--0ae1ea20
Content-Type:                application/pgp-encrypted
Content-Description:         PGP/MIME version identification

Version: 1
--0ae1ea20
Content-Type:                application/octet-stream;
name="encrypted.asc"
Content-Description:         OpenPGP encrypted message
Content-Disposition:         inline; filename="encrypted.asc"

-----BEGIN PGP MESSAGE-----

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
bfNfHuNZZmNufw==
=P4tl
-----END PGP MESSAGE-----

--0ae1ea20--

The resulting message is now essentially opaque. All of the useful information (the public key of the sender, the signature and the message content) are all encrypted using the public keys of the recipients. A recipient would need to have a valid private key to decrypt the contents.

## Conclusion

At Fathom Data we routinely use {emayili} for sending messages from R. This forms a core component of many of our automated workflows. Being able to encrypt those messsages, ensuring that the data we’re sending is secure, is going to be very useful indeed.

I’m very interested in feedback on this new feature. Please give it a try and let me know if there are any issues. If you find this useful, please tweet about and don’t forget to tag [@datawookie](https://twitter.com/datawookie) and [@fathomdata](https://twitter.com/fathomdata).

The {emayili} package is developed & supported by Fathom Data.