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.
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.
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.
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?
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.
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.
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/gnupg/2.2.12/bin/gpg"
$ version:Class 'numeric_version' hidden list of 1
..$ : int [1:3] 2 2 12
$ home : chr "/Users/jeroen/.gnupg"
$ gpgme :Class 'numeric_version' hidden list of 1
..$ : int [1:3] 1 12 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.2.12
libgcrypt 1.8.4
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://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: /Users/jeroen/.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
Use gpg_list_keys()
to see the current contents of your keyring. It is empty to start with:
gpg_list_keys()
[1] id name email
<0 rows> (or 0-length row.names)
Use gpg_keygen()
to generate a new public private keypair:
(mykey <- gpg_keygen(name = "Jerry", email = "jerry@gmail.com"))
[1] "DB3E329BA63F1E6F"
gpg_list_keys()
id name email
1 DB3E329BA63F1E6F Jerry jerry@gmail.com
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 ="51716619E084DAB9")
Searching: https://keyserver.ubuntu.com
found imported secrets signatures revoked
1 1 0 0 0
(keyring <- gpg_list_keys())
id name email
1 DB3E329BA63F1E6F Jerry jerry@gmail.com
2 51716619E084DAB9 Michael Rutter marutter@gmail.com
Note that for imported keys, we do not have the private key:
(secring <- gpg_list_keys(secret = TRUE))
id name email
1 DB3E329BA63F1E6F Jerry jerry@gmail.com
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://keyserver.ubuntu.com
found imported secrets signatures revoked
1 0 0 183 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 3955E1A812646DD4 2015-11-14 19:14:18 FALSE
13 94D5E8FA467094BC 2017-02-08 22:58:19 FALSE
14 2D79DF2BB6E28B6D 2018-03-31 01:37:43 FALSE
15 31CC32CEF78F3EE4 2013-08-29 13:37:52 FALSE
16 8E549D02234CC324 2013-10-03 09:36:24 FALSE
17 BD834C53D73E3D29 2015-01-30 22:34:26 FALSE
18 6ED515FB1B282E9A 2015-01-30 22:35:03 FALSE
19 22EEE0488086060F 2014-10-30 22:58:00 FALSE
20 72B93490AFB5BB0D 2014-07-22 05:25:48 FALSE
[ reached 'max' / getOption("max.print") -- omitted 166 rows ]
The signature only contains the key ID of the signer. You would need to download the corresponding pubkeys to actually verify these signatures.
To export our newly created public key:
str <- gpg_export(id = mykey)
cat(str)
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBFwuOewBCADMHT7vN7PpTq0TQDc32fNtDZQos+zdSqdMbHuNDJ6/Vc2wVmQA
wWq5rkfUtNJHvHf9fdeHUtBZzWXevwzbkU0LOjTiw/b/+l4fuZZJM/OhYC90UW9I
FDDRw379s735HF7GCpdMEdJ1nl8o4PCpt5FYHtytH04aTbs/CHp7m7JD7QxCW2a3
V7BkPeK394u3cHgqCOon4gFk9blKxdiC+ABdAMICkq1v+l0FLB+d1jGooY9aKlQm
DvnipLkpjO75clzgO7xoR3oes6ilaGRUODCNLVkELYseZK73m5kRpcJYRvCGqr0A
55r3AtXi+Cz6klQhVlTxjQXPkryoAXiAbilFABEBAAG0F0plcnJ5IDxqZXJyeUBn
bWFpbC5jb20+iQFUBBMBCAA+FiEEigkTG8VECNa+/S9a2z4ym6Y/Hm8FAlwuOewC
Gw8FCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ2z4ym6Y/Hm8jKgf8
DCdD+tJnP+ddlcMXypGS1Y6hnSFh64Tpfs1owdfv6L/pILuIsvDHAj4fERi8ukzf
nLnIhVgCVtxMiuBx6rQOny2GIJyWsS7+YBSsHeOsjOmhPQitxaxWBo6HXROMRyWU
2zkKvKfz2sGZC0I5JbwbKVgaWT2KuBOl2oHnuzmQYqBXrrWraLbpUv3nPvYRccdg
d+E66megf8E1fk9V8O07pHQVZs7isgLK+Xc8EIkMvgUs2vpEqC5BDUnnYk2tIMaP
6554uzxyk2eTqbNY2md0bXLKKC501Ay+v/WPwCCn7rt9t9QMz4Wi4AAz1DNrqQUB
yzkAeAq+UcQ7QYR47LPzpQ==
=J4f3
-----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-----
lQOYBFwuOewBCADMHT7vN7PpTq0TQDc32fNtDZQos+zdSqdMbHuNDJ6/Vc2wVmQA
wWq5rkfUtNJHvHf9fdeHUtBZzWXevwzbkU0LOjTiw/b/+l4fuZZJM/OhYC90UW9I
FDDRw379s735HF7GCpdMEdJ1nl8o4PCpt5FYHtytH04aTbs/CHp7m7JD7QxCW2a3
V7BkPeK394u3cHgqCOon4gFk9blKxdiC+ABdAMICkq1v+l0FLB+d1jGooY9aKlQm
DvnipLkpjO75clzgO7xoR3oes6ilaGRUODCNLVkELYseZK73m5kRpcJYRvCGqr0A
55r3AtXi+Cz6klQhVlTxjQXPkryoAXiAbilFABEBAAEAB/0b0fake0ahy4/qekus
aJ/1oq6pd5CWvtiboYObf3dZo9PDr5q0wagOw9LVionIrkb6fX71WlO8kbLLT+Xs
PVsvZxETQVt2m0Td9RknRBX2TlpZc8oDnIDk7kzuPmPrwrKmMoZZn2o8jsfwlewn
bbY5OQeh7wzhp+uYFUtAcsGy4SteAUy5pJt9iUOtvNqudaHjtmPRW/5vywc4Burv
RhATotoQTdVugNAqJpBm3fvmyuzhb/k3bP/tWfC+zOvPMC0jvMZ7NIqAbEqCJnWI
FcEwwUwVakP7c4zy7YPHBFfLSQPvv1ewS5+8WJMbO3phgfpKusXuUTLgJkfEjPN8
AsdxBADVK8N45C9o5xlTK7mHK649biTaJWQUdAsr1vHNNaeoOZSYJ0NoWVgNtLZO
Hpri9sAamc63sPOYj67agb49gtNNe6myKZV8exgbQHsuFs9cZuz6Rp0j/tSX1uf5
R3JrFuK+Yp9TLNVO3oSAAA/5Yi2pQEdW2PnxWhdi50i8lpA2SQQA9R+ozYNU1z1/
UaEP9uUjavGIgl4tvg93187CuHw3CtaaYqe2G3rKpKJkD/ZM5YVzAxtFBe1Irjiy
qSQ6NK1gIQkBk3sfemFPYKxGbGBO9KnIuMSTW5E9SCohsvKfBQN+GPwSMXOQ/DVf
joIt3ojdKEW5CdgAT0W3bEzfxGIr6x0EALMP5SQfp1adNErW8j1htP84hSBlIdAB
dxDRK/PpuJuaaAJ0hVSi/hUIxDO+0mqYD/bT8WWigESDcG6D5E7tf1WjqwAr3xPb
HVi8yMubjip+l9de5bL0zyn7zrjLJ+INIQIAXPGcs1JERb5pXYdaoYdjS4BCriUZ
IiJOW78oWPjiRYq0F0plcnJ5IDxqZXJyeUBnbWFpbC5jb20+iQFUBBMBCAA+FiEE
igkTG8VECNa+/S9a2z4ym6Y/Hm8FAlwuOewCGw8FCQPCZwAFCwkIBwIGFQoJCAsC
BBYCAwECHgECF4AACgkQ2z4ym6Y/Hm8jKgf8DCdD+tJnP+ddlcMXypGS1Y6hnSFh
64Tpfs1owdfv6L/pILuIsvDHAj4fERi8ukzfnLnIhVgCVtxMiuBx6rQOny2GIJyW
sS7+YBSsHeOsjOmhPQitxaxWBo6HXROMRyWU2zkKvKfz2sGZC0I5JbwbKVgaWT2K
uBOl2oHnuzmQYqBXrrWraLbpUv3nPvYRccdgd+E66megf8E1fk9V8O07pHQVZs7i
sgLK+Xc8EIkMvgUs2vpEqC5BDUnnYk2tIMaP6554uzxyk2eTqbNY2md0bXLKKC50
1Ay+v/WPwCCn7rt9t9QMz4Wi4AAz1DNrqQUByzkAeAq+UcQ7QYR47LPzpQ==
=sIrs
-----END PGP PRIVATE KEY BLOCK-----
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 DB3E329BA63F1E6F Jerry jerry@gmail.com
2 51716619E084DAB9 Michael Rutter marutter@gmail.com
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.
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-----
iQEzBAABCAAdFiEEigkTG8VECNa+/S9a2z4ym6Y/Hm8FAlwuOe0ACgkQ2z4ym6Y/
Hm+d6Af8Crbm3fnxw2U4xxQ8GIm1lEMj9+5wBjaVm1xIrBMIQZNisEAuaHz1djoo
Jhv7OBUpZnKdFkthtL4KGaBrdmXLa1r3OTXIo4ysCrCCxK/vEQjOxgCK5WLQmxNe
E+3eohEFYU5H3WmQsxrltHZeQJmSIfk5ML5RIDq03n+xNtBdYtwFRVH2QSG2B8C3
IqiARsqA+keZ6/MwppZI45LZJfYayWUAf7Zn2qpv5HiLNEFn6vRLapHr3fy282B8
B5ZK5TxU/oPV4M4Wj7rUsI9lgoYZWNZvI0Tv4pDBrcGK4c4IGLfY9rwkvET0jUDb
Ps6z+iuRAaJ5/bDItIjM1EZHOitk+w==
=+yhr
-----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-----
iQEzBAEBCAAdFiEEigkTG8VECNa+/S9a2z4ym6Y/Hm8FAlwuOe0ACgkQ2z4ym6Y/
Hm+5mQgAt/sF7/vRT0JCODYMXDE704cKYaWiICrhOU1l7sS9VlhZrMJkwJM9P7+I
ZcUTh3UTn83OGxan1BTItrmiBctoDMho+a+psPyyuhzS9VIC39gbJZcYfBc6KdQH
fY4UHioFIo4i5ww8RD4Jg47/HAdbUi0riN7pxyM1F2YN3/L9oSPsi1+NQGfqNcYr
/bUZYUFtXM/u95PZfNwzi4raUoFJYI7dl6wls8z/i7k5BW1CcB/FUiaUTPvdG131
U14pjHfjUfzYp/+sSre0olfQeEQPtkka7KbPSy4jDa9MpB+DVA0uCzZfqm/VRMix
3XyBU4Gagpd2I4A8Jm/0qhQ4YB+sOg==
=hx4b
-----END PGP 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 8A09131BC54408D6BEFD2F5ADB3E329BA63F1E6F 2019-01-03 17:35:57 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 8A09131BC54408D6BEFD2F5ADB3E329BA63F1E6F 2019-01-03 17:35:57 SHA256 RSA TRUE
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 1 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-05-12 17:18:43 SHA1 DSA TRUE
Looking good! We can trust the checksums in the Release
file to be legitimate.
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.
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 1 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-----
hQIMAzCzOshC83uFAQ/+KjFJjjRPdRuQYjmXa5sCaWOdmZJFNtFfB+941XUCFzh4
TocGNdIhRSLW0GBm7xV+OkmMqg4MmvkrSiEVvfSOrfofT5qkQ49HCtOYaOSjwace
+7oPpPKKpKvx+JjUfA5B8eRcvzVzjMBWBF5B3+Ixor9Nl7DHE3Fa8oEV5WKKgvwD
nLvhxOH+BZ0fheo5oTZIFyHyRTgAcPmA+zBzmEDHAi0vGwhf2Ts2j7fBFtK7HPqt
ubFGCCWjHNXZMpzA6K/VkpIHFTju0VlAvuRv3LPK4IHyocEcQHEhZrHjufd3yqQd
+0TRhUv6Q/nH01M14PqC+tBdvRud9FrZggooCLMMZqV4sbIaJ8+f+HYcj3VUpXW4
5TjMd5w1W7grxgqG7a0q6DC6dtzLBFBX8gRdM8tiMPBp6AksPkJii0SP7tHWB2bx
d7LK3VwpBWaG9M33Mi+BwHyCfJECbpoShV22F96xE6OwMqrQYsoXrxmEQC6q+NJ8
NWq1kS7jjp9T/KXZzvdEkqNatsKcCrLjPlOBQ1tZ/2L7P1+rp0DQWdFHb5dVplHo
gxUXVObvuHtUu5KJS9sHD2xPpcQdc0to89Px+XwEdBFPVz0lhxY1lyOKIj7Saa9G
FRXJYXwNat+blj1HLpbZDyDub2r+Fyxa4ipeE15sEmN064yUcAfOX0gZF9bPKGfS
TwHWwUeckGfwDG/JwVTNkRXy2Yb4ZU/cmY6nGLV9ObSz/b0TbF8UBw9x9t60SFgK
PXk5iqCZGpQdqX/Jaq1JcPfvIY/tEluBfpkpYpZ63Us=
=sYFf
-----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.
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: No secret key
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-----
hQEMA9s+MpumPx5vAQgAjfXpYgFyed55opGiIP6DTIf6NlOH90vygIf7/7XPRHTv
e7rQfx4vPZzovylHKIRm7Itrp2UuxP3ULVtDag3RwlYRLE8rZ73hDJZ+emS9Z2a+
FvchAW/Th3gzO+fHMTbKBcOaJBvbBJykb87Mqjz0Ml3Lhz/m0RJcoZ+NgBKTn3AZ
V3LqLgO04LFjXPhtMRopa8qFwc+q3QDM9AEyrfcChbArhZW21W51aBdmVAnyf2nF
Pi0RdfDhZXK3tkaQV8tSHuIibl75LquCJe+oEyVmh+d/fEN2LP/PhjBrI9VpewXI
N48dzZ5vtGq8lVjqf3EzHYMUtK1m3rLXUlbwigkh89JJAauNBoNf9+geFx3I22Z0
6PbDC1ndxFKqpG4LYwlakC/4IbQWrt2UDnO95DudCbtZStFdCqGW9nECVS2vvBGv
Mqhyy9ylOdfnSg==
=LyL9
-----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"
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?
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-----
hQIMAzCzOshC83uFAQ/8CfS1VnBdqHBdzleOvmnYF2QyDEKtyrR6RWtv4AeNiqDR
PXjDTlw89cuIhQ8lT4dCZpUmQ1gS5Cz8jgkyl2s4f+aJk9ijv47A69NyPwuighRa
0SmBXnwteSHn2AWt1hu4y0PsV3kQTpNYme2Gx6mKyi5I/T7Tn1ylyi27zaFjyeYR
7GL0ZtemkgzE0k+8g8u9jp3hQKgA5SQ32pa8MluCmUJEGItmtiDF+6CP7VLPQWLs
7SWaKAOJ7Qao6ufmr8RibdtajIKwB9Wfi/8HieKJKR8qvsXO+76/FB6azwZNhaE4
m3F/3HvBqoXtnRmO9bTcA3dHUyiQjlHT1sZNcIKtZHhceMms68udNNw0GA7IgjMz
9s2+7UFs+A/nna9QBzbJQgG+oEwlMdQAoUgXWzi78FC/M+savikXoEsxFTaeIbtj
UYS3nlyD72fq9nkT8TB5HbkvX9p5UD883ORyzVBO/L18LSNpVUg4p1YGenx0rR0m
CeWIwQpx2t8QnK1jNs+Kr9fDTY8VDtYulHMJYEtErsc3fU0yt4qaFhVm8nsYX6yH
IBm3TPuypktOjlwaPx+PzmzmGTgn9oyf8HikY7OHLlXxpsEZgI2vXwnIkyO7qF4h
GjOlo1gX6bzslQXxCcvWOILd3eBOyxWl4F4uBRON5rg3HknQaiC0XLvWcI2dTuPS
wNABrYrKbubz8AQ8lWikD8hOTUYyiT2d2ZHf0vEhg/CdQTEL6IYDfGdlINz0NR8N
dU/9eoLtSzCg2l6FXzOAzx6KJ+egtvXymiw15hjyOzyC1NSH9E4FuNDCBWwqEF7s
old+ukVLD75bEoJPaxVjRCkEPlSPM/l3KO88HnYbvMZqRYIOm8MTMhr9MhApMR/D
VvTtdzbYigtY2xLNoFKjyQnKW+3IyKNe1fngBVc9EaoY1tf0NaubN1sCi/EOihE4
PczgQSktciB5w4jzmYH0D/HQ8AeRtdiUuxPYEVEcaptjY5DSEW60am/VRjUwuF7H
bF5rWHfMGPCGshTw4dUaFbB61PV7tNS3Tg9B6JatPYuEn/DWNjlsrGhYKSO9k4nk
NjjY3kaNqUjaqKZImEXkV/yvn2mAXErQDlKAPEXJdx935qQKrErTy4IAa5SCMgB3
uxEc+mv4qmn6EppzEc9cCuWI6VHXNij1e/I3D3i6XhTloO4fylWUIJVR5ht9j44s
3lEk1YYmk7gEYp9k38DflJ1y
=m7mG
-----END PGP MESSAGE-----
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] "8A09131BC54408D6BEFD2F5ADB3E329BA63F1E6F"
The signer fingerprint (if any) will be added as an attribute to the decrypted message.