DISCLAIMER: Author is not an expert in cryptography (he is not an expert in anything really). Use this stuff at your own risk. If you find bugs or inaccuracies, please create an issue or PR on the github repository.

GPG basics

The GNU Privacy Guard, also known as GnuPG or simply GPG, is a popular open source OpenPGP (RFC4880) implementation. The system is widely trusted for securing integrity and confidentiality of internet communications through various cryptographic methods. GPG is used in Debian and Redhat to verify downloads from package managers (apt, yum) and people like Edward Snowden and Glenn Greenwald use it to encrypt confidential emails.

Public key crypto

Like most modern crypto systems, GPG makes use of public key methods. You can easily generate a personal keypair which consists of a private key and corresponding public key.

pubkey

Your private key is to be kept secret and needed to sign or decrypt messages. The corresponding public key should be made available to anyone that needs to verify your signature, or encrypt messages which can only be decrypted by you.

Once we have someone’s public key, we can send them secure messages and verify their signatures. However how do we find and authenticate the public key of a person or server if we have not talked to them before?

Web of trust

The complexity in public key systems derives from authenticating public keys. If we can not trust our communication channel to be safe, we can only be sure that a public key belongs to given person if it has been signed by someone that we do trust.

The major difference between GPG and PKI systems (such as HTTPS) is how we authenticate public keys. HTTPS is based on a system with Certificate Authorities (CA). Anyone can create a keypair for any domain/personal name, however we only trust public keys which have been signed by an official CA. This CA is typically a commercial vendor which verifies your identity (e.g. via a copy of your passport) and then uses their own keypair to sign a certificate containing your public key and your personal name / email / domain.

trust

GPG uses a different system which does not distinguish between peers and authorities. In GPG, anyone can sign another persons key. The GPG user determines which peers they choose to trust in their personal keyring. For new peers, the GPG software helps you figure out which of your current peers has verified the identity of the new peer, perhaps indirectly via a third or fourth peer, and so on: a “web of trust”.

The easiest way to exchange public keys and key signatures is via a keyserver. GPG is compatible with existing PGP key servers. These servers mirror each other so most keys are available on either one. This package automatically retrieves keys and signatures via the gpg_recv function.

GPG keyservers do not need HTTPS. One should only trust GPG keys on basis of GPG signatures, regardless of how they were obtained. For this reason it is also valid to share GPG public keys via e.g. a website or email.

Your keyring

It is important to know which version of GPG you are running and where your home dir is. Your home directory contains your configuration and the keyrings. GPG defaults to your system keyring, which is the same as the gpg command line utility and system package manager use.

str(gpg_info())
List of 5
 $ gpgconf: chr "/usr/local/bin/gpgconf"
 $ gpg    : chr "/usr/local/Cellar/gnupg2/2.0.30_3/bin/gpg2"
 $ version:Class 'numeric_version'  hidden list of 1
  ..$ : int [1:3] 2 0 30
 $ home   : chr "/private/var/folders/pv/clp8mkdn6qqf5d04qqfw4xj80000gn/T/RtmpmpNj9h"
 $ gpgme  :Class 'numeric_version'  hidden list of 1
  ..$ : int [1:3] 1 7 0

Use gpg_restart to switch to another home directory, e.g. for a client which uses its own configuration and keyrings. For this example we store keys in a temporary directory.

gpg_restart(home = tempdir())
gpg (GnuPG) 2.0.30
libgcrypt 1.7.6
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

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

Use gpg_list_keys() to see the current contents of your keyring. It is empty to start with:

gpg_list_keys()
                id            name                            email
1 CF72E25EF6C0B2B4           Jerry                  jerry@gmail.com
2 51716619E084DAB9  Michael Rutter               marutter@gmail.com
3 06F90DE5381BA480  Johannes Ranke             jranke@uni-bremen.de
4 A4A928C769CD6E44 Glenn Greenwald Glenn.Greenwald@theintercept.com
5 2C40A61BD78FA8A3           Jerry                  jerry@gmail.com

Generate keys

Use gpg_keygen() to generate a new public private keypair:

(mykey <- gpg_keygen(name = "Jerry", email = "jerry@gmail.com"))
[1] "D6154FEC22C9BCD8"
gpg_list_keys()
                id            name                            email
1 CF72E25EF6C0B2B4           Jerry                  jerry@gmail.com
2 51716619E084DAB9  Michael Rutter               marutter@gmail.com
3 06F90DE5381BA480  Johannes Ranke             jranke@uni-bremen.de
4 A4A928C769CD6E44 Glenn Greenwald Glenn.Greenwald@theintercept.com
5 2C40A61BD78FA8A3           Jerry                  jerry@gmail.com
6 D6154FEC22C9BCD8           Jerry                  jerry@gmail.com

Import from keyserver

Use the gpg_recv function to download a given key and all available signatures for this key from a keyserver. For example let’s import the public key from Michael Rutter which is used to sign the Ubuntu r-base packages from CRAN:

gpg_recv(id ="E084DAB9")
Searching: https://pgp.mit.edu
     found   imported    secrets signatures    revoked 
         1          0          0          0          0 
(keyring <- gpg_list_keys())
                id            name                            email
1 CF72E25EF6C0B2B4           Jerry                  jerry@gmail.com
2 51716619E084DAB9  Michael Rutter               marutter@gmail.com
3 06F90DE5381BA480  Johannes Ranke             jranke@uni-bremen.de
4 A4A928C769CD6E44 Glenn Greenwald Glenn.Greenwald@theintercept.com
5 2C40A61BD78FA8A3           Jerry                  jerry@gmail.com
6 D6154FEC22C9BCD8           Jerry                  jerry@gmail.com

Note that for imported keys, we do not have the private key:

(secring <- gpg_list_keys(secret = TRUE))
                id  name           email
1 CF72E25EF6C0B2B4 Jerry jerry@gmail.com
2 2C40A61BD78FA8A3 Jerry jerry@gmail.com
3 D6154FEC22C9BCD8 Jerry jerry@gmail.com

Import from file

The gpg_import function reads an armored GPG key from a file or URL:

gpg_import("https://stallman.org/rms-pubkey.txt")
     found   imported    secrets signatures    revoked 
         1          1          0          0          0 

However this file does not contain any signatures for this key. If we import it from a keyserver we also get the signatures:

(rms_id <- gpg_list_keys("rms")$id)
[1] "2C6464AF2A8E4C02"
gpg_recv(rms_id)
Searching: https://pgp.mit.edu
     found   imported    secrets signatures    revoked 
         1          0          0        117          0 
gpg_list_signatures(rms_id)
                  id           timestamp             name       email success
1   2C6464AF2A8E4C02 2013-07-20 18:32:38 Richard Stallman rms@gnu.org    TRUE
2   624DC565135EA668 2013-07-20 18:37:45                                FALSE
3   F05DDAE40371FCE5 2013-09-15 23:18:46                                FALSE
4   231696C3EAE0078A 2013-09-24 23:15:58                                FALSE
5   7B585B30807C2A87 2013-09-28 22:59:04                                FALSE
6   7CEF29847562C516 2013-09-29 04:59:53                                FALSE
7   9C19DB3C039ACDF0 2014-01-07 01:15:13                                FALSE
8   1777288D64D0EEB6 2014-03-12 09:17:31                                FALSE
9   B30B28D729AEFC28 2014-04-26 05:08:37                                FALSE
10  37908B4CF343E5FC 2014-11-01 18:39:25                                FALSE
11  1EB69819D7877A20 2015-11-02 07:07:28                                FALSE
12  31CC32CEF78F3EE4 2013-08-29 13:37:52                                FALSE
13  8E549D02234CC324 2013-10-03 09:36:24                                FALSE
14  22EEE0488086060F 2014-10-30 22:58:00                                FALSE
15  72B93490AFB5BB0D 2014-07-22 05:25:48                                FALSE
16  520E0C8369B003EF 2013-08-20 12:31:55                                FALSE
17  8916CADF8ACD372A 2013-10-02 13:17:17                                FALSE
18  C4D748C31C0E017F 2013-11-02 14:13:29                                FALSE
19  22A73C6B32388E27 2014-03-26 15:24:53                                FALSE
20  7468A7AAC0B08E7F 2014-06-02 12:23:32                                FALSE
 [ reached getOption("max.print") -- omitted 101 rows ]

The signature only contains the key ID of the signer. You would need to download the corresponding pubkeys to actually verify these signatures.

Export a key

To export our newly created public key:

str <- gpg_export(id = mykey)
cat(str)
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2

mQENBFjRTHcBCADOo/bDVvCkAVkE3d47mZtEv2tNKsXYTAFvPs6oWkVDR8eL7tkw
FBAGS6cvbEv3QU+cDrk/qOPsMNuyv7DKL5g6v0gc2I7yqY9JdGu0+hKStig2XOnt
82SIabEYJL74kL4vr+Y4K82tbsHB1CctTIGelnjX0ri8g0ZnEPYVI407ggVV5Xq3
/ORzLyjF0VKU+L0ng+sieTnGtwfXM9z+Hw2UJF7IRPmWg/yFe54xvd4K3B/Sq9a+
2X7t5dTC2ykxHEet2WrxFWaVt1WFKz9wfAglFhDex7I57Uwvvw6+3/N47b+QBCvx
VsNEnwvNqG3pByXsledCJ3+U3QB1GCw5hy9zABEBAAG0F0plcnJ5IDxqZXJyeUBn
bWFpbC5jb20+iQE5BBMBCAAjBQJY0Ux3AhsvBwsJCAcDAgEGFQgCCQoLBBYCAwEC
HgECF4AACgkQ1hVP7CLJvNgyQwgAvxNj0DLCrwZhXPKZiFeyYlsFvrUowu3TTzVr
pzk8JQcoqk09OIkeU7iYJ3DaXk/o0hXwdfEe5NgiHYODzSKeiBnyIES+8bvXf+km
1wA16CmjWdQy5Y/5cWoVQyvtP6N3+/Wp7RaQHeeYQw/vR1MG1TFnh4Ghy24UXQbs
2Rl5Vl4nP5f182iWqMB/e8+vfIjpmnfevaNoAkRw1ANEMqoNtbUH66BMrgzYijuM
PxjIJ6lhgyBevIBMbVbUZQsN10zpQ7GmKn5wzbcOa4PKM7usnUDQKr0Pjf4GK04v
63UEj/zGn1ccvDLnoVdCjJ+CDr8T9cwbkl20ZbRrnQjizmyQiA==
=7rPr
-----END PGP PUBLIC KEY BLOCK-----

If you also own the private key you can export this as well:

str <- gpg_export(id = mykey, secret = TRUE)
cat(str)
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v2

lQOYBFjRTHcBCADOo/bDVvCkAVkE3d47mZtEv2tNKsXYTAFvPs6oWkVDR8eL7tkw
FBAGS6cvbEv3QU+cDrk/qOPsMNuyv7DKL5g6v0gc2I7yqY9JdGu0+hKStig2XOnt
82SIabEYJL74kL4vr+Y4K82tbsHB1CctTIGelnjX0ri8g0ZnEPYVI407ggVV5Xq3
/ORzLyjF0VKU+L0ng+sieTnGtwfXM9z+Hw2UJF7IRPmWg/yFe54xvd4K3B/Sq9a+
2X7t5dTC2ykxHEet2WrxFWaVt1WFKz9wfAglFhDex7I57Uwvvw6+3/N47b+QBCvx
VsNEnwvNqG3pByXsledCJ3+U3QB1GCw5hy9zABEBAAEAB/0U9KIkOi9fj8wYHGtF
Q7Uaz4dmr8/uOPsA7e965Dis84e5hFMzNyhO3czfws2guVdaSKX3COjK/ZjHc6gj
65gLsR/ziO9U4ubR41lpj4i4Uc/Ef5Sw7w4YGrvSanuRbUBUSV7WqHPhwt8ptHBK
qD0Rjknv/SyDNZQ7Wd19fvmmJJZdH/lsLoFL+PIn2p6Hv31cbaaTHC0pMEb/B0LC
voB71qAuc3bqJCeFj43AgGTWRuMby+8YIlV39x5fLTFsnbHF9JxxbaGHmMY851jI
aKAx5+8Rt6YxJKZppESo02o0R8n8NoUss+Cdid3HsDGWaZjRdRNjap0+a+gSytoF
BjO1BADQg4HulnOnNqrTYWqDtvZu+GXo00B/fZMMc9SFegZE925BkgsQU7wEgCpD
QeVtcu+IdBmXdIyD1VnGb+gE3cj0Y+2UxGwYaei5CsdDNKNxYr5z0yFZZf4H0QN/
ScUMw94FOL9mc13ZUVCnVxvMcDLc9kxSljjX8B29PsEWu76VRQQA/bM/G2uGwW68
UlTNyqXs5dWWSgb1LntWwUi/DI8VbiAqCNu4tMtvfFYP+JCpKIGK8ez1oQc19Kh/
/+GOLmE2lqOO4FKSz+ywds5+CSwsLSWS2W/FI7mwvjmJQAdenY9EyIJZ72x1DzUY
r3nEQpCbdh9yzs8gCsuJK4Wtn3TTcVcD/R+UsQ/upXfiSS/YmyBJ3gEs8wwd0esL
v8YzRHG/w0DMxjwNExo398HdzfLCRU0jglqex3jWkdgYYDNDLoyxdhVCDtifwPge
0nZK8eRBL7oFGHlGIxh0ywzoIa1MvcP32l6Sa4KpjWUm5TeazYlbumI+/A/u574M
29Y9haF/WIKUSHW0F0plcnJ5IDxqZXJyeUBnbWFpbC5jb20+iQE5BBMBCAAjBQJY
0Ux3AhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQ1hVP7CLJvNgyQwgA
vxNj0DLCrwZhXPKZiFeyYlsFvrUowu3TTzVrpzk8JQcoqk09OIkeU7iYJ3DaXk/o
0hXwdfEe5NgiHYODzSKeiBnyIES+8bvXf+km1wA16CmjWdQy5Y/5cWoVQyvtP6N3
+/Wp7RaQHeeYQw/vR1MG1TFnh4Ghy24UXQbs2Rl5Vl4nP5f182iWqMB/e8+vfIjp
mnfevaNoAkRw1ANEMqoNtbUH66BMrgzYijuMPxjIJ6lhgyBevIBMbVbUZQsN10zp
Q7GmKn5wzbcOa4PKM7usnUDQKr0Pjf4GK04v63UEj/zGn1ccvDLnoVdCjJ+CDr8T
9cwbkl20ZbRrnQjizmyQiA==
=EVTJ
-----END PGP PRIVATE KEY BLOCK-----

Delete a key

Delete a key from its ID or fingerprint. Let’s delete the RMS key:

gpg_delete('2C6464AF2A8E4C02')
[1] "2C6464AF2A8E4C02"
gpg_list_keys()
                id            name                            email
1 CF72E25EF6C0B2B4           Jerry                  jerry@gmail.com
2 51716619E084DAB9  Michael Rutter               marutter@gmail.com
3 06F90DE5381BA480  Johannes Ranke             jranke@uni-bremen.de
4 A4A928C769CD6E44 Glenn Greenwald Glenn.Greenwald@theintercept.com
5 2C40A61BD78FA8A3           Jerry                  jerry@gmail.com
6 D6154FEC22C9BCD8           Jerry                  jerry@gmail.com

Digital Signatures

A digital signature is a mathematical scheme for demonstrating the authenticity of a digital message or document. If you sign a file using your personal secret key, anyone can verify that this file has not been modified (i.e. the hash matches the one in your signature) via your public key.

GPG signatures are widely used by Linux package managers such as apt to verify the integrity of downloaded files. Typically the public key is shipped with the OS, and the private key is owned by the repository maintainers. This way we can safely install software from any mirror or network.

Sign a file

Let’s use the private key we generated earlier to sign a file:

myfile <- tempfile()
writeLines("This is a signed message", con = myfile)
sig <- gpg_sign(myfile)
writeLines(sig, "sig.gpg")
cat(sig)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAABCAAGBQJY0Ux4AAoJEM9y4l72wLK0+JoIAIwGA/9Waybh/7Tr8RvucEbw
uCSuTSeJKEU9g5GsTksW35Am7NsIPLf8b/ozWJ3oWH2Psp8P9tAlgu8DrmhAlGTV
aLoAPzeU2HGdtq0xxudFXAyg6lFTmNx0DyfpN36zT+jEGsP4nsvdrFGsdbHX4wSe
+QUQzuC8c7XaUApypinxpQLFWyCtkYmHrYyWOu3ruowvhsgUhoRYcWD/NMbdKAZ0
k8obsLMLrOqdMiKSmfe0oXZXnEsCAXQVrlFuhHriFRj2JWdkzq34sV6s2hoWzran
9QeXzExnFPONg7K592/ZZCilzRHFNmh0er7te9FCs0Xv9SKBMttqu5CvxYdAAqo=
=Y53G
-----END PGP SIGNATURE-----

You can also create a signed message which includes the data itself by setting mode to normal or clear, which is useful for email:

clearsig <- gpg_sign(myfile, mode = "clear")
writeLines(clearsig, "clearsig.gpg")
cat(clearsig)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

This is a signed message
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAEBCAAGBQJY0Ux4AAoJEM9y4l72wLK0pSIH/Aw3efET4EDvxiFpeXQrNDTg
JeU3GgEf0OfGXGGwWjSTZneJngXzaZWT5l5cwWxUeLuSvMQyMiCVa3VzWTsr2SU1
f1BNGnXBpB9AxAGAtPAmp1Sv/FGsExOXOuz5JSkJWfI6ZqhOBY+lb6u07GbS+5X9
N+im14rc2lQX1xV91uyOA/45L7zbtxmft5ezSRhmEqr6kdE5PBKKkIzYd03EGVk3
nuaUlr1LWYJ/7tz428qe8O1XaofFfBGAQJWNSETjH76Glf+09Q4LN0mpipFzpLcL
zafb/NYfRKXaRbroozgDSUrvjejxP3Mkf38tXrUIX2lq9RstGpIXMs7RrYSoyTM=
=vJjp
-----END PGP SIGNATURE-----

Verify a signature

The gpg_verify function will see if a signature is valid for any of the keys in the keyring:

gpg_verify("sig.gpg", data = myfile)
                               fingerprint           timestamp   hash pubkey success
1 C346F8083E475B5E33D9B111CF72E25EF6C0B2B4 2017-03-21 16:53:28 SHA256    RSA    TRUE

If the signature is in clear or normal mode, the signature file contains both the message and signature:

gpg_verify("clearsig.gpg")
                               fingerprint           timestamp   hash pubkey success
1 C346F8083E475B5E33D9B111CF72E25EF6C0B2B4 2017-03-21 16:53:28 SHA256    RSA    TRUE

Debian example

Let’s verify a Debian file. The Debian page on CRAN says the following:

The Debian backports archives on CRAN are signed with the key of Johannes Ranke (CRAN Debian archive) jranke@uni-bremen.de with key fingerprint 6212 B7B7 931C 4BB1 6280 BA13 06F9 0DE5 381B A480

Let’s import his key so that we can verify the Release file, which contains checksums for all files in the repository:

# take out the spaces
johannes <- "6212B7B7931C4BB16280BA1306F90DE5381BA480"
gpg_recv(johannes)
     found   imported    secrets signatures    revoked 
         1          0          0          0          0 

If you don’t trust the CRAN homepage, you could check who has signed this key. You’d need to import the corresponding peer keys for more information.

gpg_list_signatures(johannes)
                id           timestamp           name                email success
1 2F0F4E14F649AF90 2007-02-15 12:06:05                                       FALSE
2 EF7CDA710BAEFEE5 2010-02-24 18:55:22                                       FALSE
3 06F90DE5381BA480 2007-02-15 09:13:25 Johannes Ranke jranke@uni-bremen.de    TRUE

Now lets verify the release files:

# Verify the file
library(curl)
curl_download('https://cran.r-project.org/bin/linux/debian/jessie-cran3/Release', 'Release')
curl_download('https://cran.r-project.org/bin/linux/debian/jessie-cran3/Release.gpg', 'Release.gpg')
gpg_verify('Release.gpg', 'Release')
                               fingerprint           timestamp hash pubkey success
1 6212B7B7931C4BB16280BA1306F90DE5381BA480 2017-03-13 00:23:14 SHA1    DSA    TRUE

Looking good! We can trust the checksums in the Release file to be legitimate.

Anonymous Encryption

GPG uses public key encryption. You can use someone’s public key to encrypt a message or document, in a way that only the owner of the corresponding private key will be able to decrypt. This is a great way to send somebody highly confidential data.

Encrypt a message

For example we want to send an email Glenn Greenwald containing top secret information that may not be snooped by our ISP or government. His homepage at the intercept shows his GPG key in long form.

glenn <- '734A3680A438DD45AF6F5B99A4A928C769CD6E44'
gpg_recv(glenn)
     found   imported    secrets signatures    revoked 
         1          0          0          0          0 
writeLines("TTIP is super evil!", "secret.txt")
msg <- gpg_encrypt("secret.txt", receiver = glenn)
writeLines(msg, "msg.gpg")
unlink("secret.txt")
cat(msg)
-----BEGIN PGP MESSAGE-----
Version: GnuPG v2

hQIMAzCzOshC83uFAQ/8C5ImUpBVMEwkBlLmY/oFB8MSo11PTC2KSxniXMacCRPK
aPZu3Oz6hNHeEBFMzGKU1WQ4VEheZZB1ZaCj/EZ0kBCNCXody1mRpiTLua8j6QTD
8ryB/lwQ6HANuM1C4281Ioid3rxqP5PsrZw23HrwA38lD+ZxUQ+vSexHtEimLoPU
k/be2xfiYjvoT8lomQ8MYv+VdLwRZ3/s2CDkbFFJKXBI1xHVnOYiqfQx4MvTdGsj
6fZA0VXRp+0FNZyJng2fyx1CiBFN/T2OQRgPGAIJurV9b/knz2OSTpPlpFyo7zo/
huR4JE9OqHu9WpsYyBD6cuuO4obG1d+u5YjFsMwfBqes4B07uhcLokU9GcQ5218R
9ikKc/1F1nOFg2xTDWfNJXSMte+vsC/K7URHXX7moIkiGyl4rV+N+Hq2/ASFsnT+
38Q2F5Z4+neuouZORZqI/urrgUB2njcYrBiv5Ghd6sxF3U0yB4neXF6fcg0zNvup
e8lODrC32GdF4oxx05bYxslL7BSaEV6jNkGcdnlzbQwTnQjXeIDzXVXLbx5WJTdr
DPhlanQ6J5QJvgFr7qrPT668A2garEn90pTcYVEEKRIlTmE9Ou4cWIJ/Z0G67AWg
LYwBuAZkrMj1IRZAtKQ3qN9YSYr6QIcLVUouMwCtow31JMiN3ShTC728ZFqItjfS
TwFXShfXBIsDsrfTD0I4rPvSDZJ5YBartykD83ZxOPckEOrsYvOAeaELp/D2L08d
vy8dRL5jf5cHptlWz3umwqgHXA0zX7yySkJES9F8ULk=
=+5Wq
-----END PGP MESSAGE-----

You can safely send this message over any channel (email, twitter, etc). Nobody in the world (not even ourselves) will be able to decipher this message, except for Glenn Greenwald.

Decrypt a message

Decrypting a message is even easier, you don’t have to specify a key. GPG will automatically pick the correct private key from your keyring, and error if you don’t have it. For example we will not be able to decrypt the message we created above for Glenn Greenwald.

# This will error, we do not have this private key
gpg_decrypt("msg.gpg")
Error: GPGME verify signatures and decrypt message error: Decryption failed

To demonstrate decryption, we encrypt a message using our own keypair (for which we own the private key).

writeLines("This is a test!", "secret.txt")
msg <- gpg_encrypt("secret.txt", receiver = mykey)
writeLines(msg, "msg.gpg")
cat(msg)
-----BEGIN PGP MESSAGE-----
Version: GnuPG v2

hQEMA9YVT+wiybzYAQf/XMmW3IqmtAM41gbCjUw7frzQ0CI9s3JPHa+64IcJJgwn
fthLZYhMq+rOv9KKMn1h7Z16XvR+mc4rNVMEHdOtKPw3pVD3cn/HHP4/GeoxGpAu
zXLjSq0igGQwjR19rVqzQKwOhRMLuovTugtXUbc6sBWctUJKv9EuOtMqnG2ddm7i
gGB9xgwQNWvcmyp01Xfqh/8TTav3TaNr5ao3VaVtlE47BjFF+76P1+X6fpRNq17E
+0h4wvEljTYdfmyjmgfAdjCAPhTiwtmPznYNZMuH1YugP4NRBVxa/iwOVuGxVQOx
EPaYX5Do8ExEVbBbyYsod39FtbAUuQHR5sNCb3/HmdJJASwmze1iPgLtyA8llTxk
0ZPaqWe39L+ahIV+uGbz3/U24DCMSSbcMSvIrLDCo9RxFfEEL82/ddhyrAnYHooJ
R6swwCc4ff1bpw==
=y+W0
-----END PGP MESSAGE-----

Decryption is simple, given that we own the secret key for the message:

gpg_decrypt("msg.gpg")
[1] "This is a test!\n"

Authenticated Encryption

So we showed how to encrypt a message so that it can only be read by the receiver. But how does Glenn Greenwald verify the sender of this information? Perhaps someone is trying to leak fake documents?

Sign and Encrypt

In signed encryption, also known as authenticated encryption, uses combined encryption and signing. The public key of the receiver is used to encrypt the message, and the private key of the sender to sign the message. This way the message is both confidential and the integrity of the sender can be checked and verified, only by the receiver.

msg <- gpg_encrypt("secret.txt", receiver = glenn, signer = mykey)
writeLines(msg, "msg.gpg")
cat(msg)
-----BEGIN PGP MESSAGE-----
Version: GnuPG v2

hQIMAzCzOshC83uFAQ/9GwsV5O5vLbe0OgAJEvM7+7+vlKU8Onrvjqf2xreug1KE
fWYoZSczoGF7Yx24akkj4iRYebqLTVGmXzLjAwiYDoTywYbVzVlF/SZDLImDA2gX
beyypI5hFFa5nve4kvFnjXGdHTClcQDcBBUyTaytiDo29V9AEMtUQZrMR4zeRVVw
MLnNiQhC8HZzhRqHskJcsbAUIRq/QgboBa4221RQKkjPXwzasOgt4drIJ3IdHeRj
cvhrNXQGeZdnUj5QUKNJ4VVdEdAiS56EKrujrp5PYMf/+D3Vu8idYkNhUbUrg3we
KCo5CZ+DnQBBXYTMj2YjRbFWZZ8U7rAEKqVvSPzaywmcxOVJNgGfRTwB/JUlaVX1
Zaiz+V99J+S3Kq7U9JIc8phvvEGht+o5onpyvwFn3CRAmmc88od9Zlj7X2LXIZ26
ptlDhTwglfww1mAIMx5r4hAHnsa8vuZBPhneR3e0HFj6SjIQ9pt6fJwn9Xusfe+D
AQM7UrcX0AXEr4BmHzAbOJDBCRi98FIr3mEkiBmXreTRt6l/OFh1OO+3MFwWUe5J
+lTkNH37/A857upMPSK2MOikqbIrVDj64DZGbfs5vjLF0n8m7QOlYVVtxRepj32K
KcaFHIrhrQVqguIZW7OzCd/Q3nIpXsQaz3xjZpEbFhz4KkKqnBIJ21F7b6hbFHnS
wLwBuTF3AKInKwpv+lHF4HpV1QIQFOBsXUkkx6MSyMDYlTJ3c+iCtRRDsh19zUKK
1btqve1zptx89lo1YnVXB4umaEWsJQe6fjSTOeFnCRc2ShhZarFOzU7Lf0YMkaKe
Xuzxfmjd4FKMm8HBmTJ2DyWRkKMFxpjtuU4s0LVp0Tzy4x6oOyM3EyA3Z39ef42x
WDEjvyZuDZWB79m6139yp3mRo0vEIu2A/9FtUfnJQYQ0HL17g3CO5s+1L21N8Cdi
4gCAvd0D5mp0VIlZO/jIN02GQzNlblZxwa6l3o/egCbStagscUw6fAWCxvlh21Se
3oyR1IiuRCK3e7exHSPz3lJrHSPZvRhItP3boDd6NIXYnSj9L/V88xVclLxoNpoS
ICWZitQfl0BA0LKl/ymTjwe8t2rcKmINgFRRI+00mHkH6l1uTG1GP2NbcWqDXEIP
NWM8hM3d23YcAcR+kEX75+0RcBMeRDRSPTfnZtfDhhIsI2QGbueHyDLJbW4U2w==
=2yz+
-----END PGP MESSAGE-----

Decrypt and Verify

If the encrypted message contains a signature, it will automatically be verified when the message is decrypted. The function raises an error otherwise.

For purpose of illustrating authenticated decryption, we encrypt and sign using our own key (which usually does not make sense):

msg <- gpg_encrypt("secret.txt", receiver = mykey, signer = mykey)
writeLines(msg, "msg.gpg")
gpg_decrypt("msg.gpg")
[1] "This is a test!\n"
attr(,"signer")
[1] "A49422E6B1B5619D7BCD5EE4D6154FEC22C9BCD8"

The signer fingerprint (if any) will be added as an attribute to the decrypted message.