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.15/bin/gpg"
$ version:Class 'numeric_version' hidden list of 1
..$ : int [1:3] 2 2 15
$ home : chr "/Users/jeroen/.gnupg"
$ gpgme :Class 'numeric_version' hidden list of 1
..$ : int [1:3] 1 13 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.15
libgcrypt 1.8.4
Copyright (C) 2019 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] "02FE605DBDC0E008"
gpg_list_keys()
id name email
1 02FE605DBDC0E008 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 02FE605DBDC0E008 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 02FE605DBDC0E008 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 188 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 171 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-----
mQENBFzIxzQBCAChDThZVqKQNXp4dA6DDmmRHAKDTa93ptv7pM1IwZuGZUwWhVYt
WabS6t1e/5fG7rUjBfPyNw/sUCqKS3txTS0Ob/w//o2gNF0UQE9oPuVp0qJYMWh/
hHkiAjRi9Usp6OGdRiJWxlIkYfeZHs2cZGatjIKpJ4SIlmCvTIMqXJ4GSPi6O5dE
mVmEWfdXxxKwFluS53pGxIhtkjHZKRu7al02xSYGmYYuwvIozTnZ1JXH4VlsvXmz
cB7dt/8aICf7NFDZowTACCIuumNdIiM2OTS1odJEyf2JKcBXr5Vg0zEh2QFoQ2D1
LNsRSCAnMgtGLe8RtWtkvKZ95LtX+8VoLCYtABEBAAG0F0plcnJ5IDxqZXJyeUBn
bWFpbC5jb20+iQFUBBMBCAA+FiEEAZ/HDj4CES15BKoAAv5gXb3A4AgFAlzIxzQC
Gw8FCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQAv5gXb3A4AiI2gf+
NL+M9kphsMFOZjnt8HwXRbL6r/4MKle2xv1lJs/+mpMvRMsTY+BkXkf4P5TUVSHI
lWDiPGlwkZRf+912DSLKwvsUCMR2eWdOUphaCZjWx0aD/prb//KUHPzDi6v7oR5M
KFEw/sdHIvJ/9GVh7oyuRipQTWIXkpBarJOo34ciobO5kFfu1Xdqa4tTZDLp2HQi
vL4X157XRX85GYrmq8NEKUJCxV8QKNKdWzXFpec2foz/mnwLJYxTCm/tAIs+gEsS
k+c2/7mCudZbT1Kkzvd1GciWKJgFsq/l7yh5UuvEK6e4FMKNnD7GxVcKN3gvYW8H
75gzTWuqIv7UdCJQlOlZuQ==
=nEW5
-----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-----
lQOYBFzIxzQBCAChDThZVqKQNXp4dA6DDmmRHAKDTa93ptv7pM1IwZuGZUwWhVYt
WabS6t1e/5fG7rUjBfPyNw/sUCqKS3txTS0Ob/w//o2gNF0UQE9oPuVp0qJYMWh/
hHkiAjRi9Usp6OGdRiJWxlIkYfeZHs2cZGatjIKpJ4SIlmCvTIMqXJ4GSPi6O5dE
mVmEWfdXxxKwFluS53pGxIhtkjHZKRu7al02xSYGmYYuwvIozTnZ1JXH4VlsvXmz
cB7dt/8aICf7NFDZowTACCIuumNdIiM2OTS1odJEyf2JKcBXr5Vg0zEh2QFoQ2D1
LNsRSCAnMgtGLe8RtWtkvKZ95LtX+8VoLCYtABEBAAEAB/47obN9kNB8aPDB7Ob6
q7l221Iq3/babNQDJxBDojw91QAJTrGL9SgJ7KCu7iB6riQvpaKfyreAnmZB8pTw
bM0EDX7vCwfRi9HzD6TXSoKTXkRyN0kj/h8D8qEHCyAbknkHTNKmIqSDiCqvbXJg
N+S02dP/Yfx2vodqIQBoDQcN+BxzAJiiqXDCHYCiAxJUpH7EzDXKrE/S+k6fnD/b
Ma1JdIumwM6rXtqXXTy0IKYD1ZuTOhb3H9Rp4MZEh/0aGx2tEO8FgVOx1h7S3sfE
j/MfosaM/nEb8NR93hvmaRQ+dkp54DhR4g3/sUngZbonKmhs5aiBh4mZLqPCGvnq
rgeZBADC+JWJP04xSMZHXplissgfQi2JyQvudI9VpC3kNq8LVZNAV6fFWHg7cago
aJrb784viK1m2lGr/7FfYcmhVXzZKVGkWMvPhydf04i8G4xfZUbPuRPYzpqj26Kp
bvvAYUl9GrWuekvq7FUGDptomXMU+Bpq22YZSCBeH5glXOZUMwQA03abnUXbcQfW
lgFIpiOXqwK7eTTXp5bgSEeEv7i0ZOZCs6n1xKzg69zZ9AlL2VHCcXj8iJIGwkSJ
JM1EFsF7NbAJgsUKTe/nvgvkiAFWbyeSPxUknogx+T23XZ+LExNJOXuANmn5WfX9
XF9x1Qee23UtJLWlg9r5NVsBcvVEPB8D/RMF85V0w8azUBNyKHesmlsfLu36VaCQ
wekjaXbEBuA6eNjWPNezYJoTHXWK9FbBeMrqUm1h227cV7F1JlvaVrTIpA+jkx0s
ywXd5BP6wzX53l5M7pymlDAupxc3VnJaOG6gAs/+96lb5Wjy7PfwpTkAr3/o1odK
2Nc9lDrp9gJsRzi0F0plcnJ5IDxqZXJyeUBnbWFpbC5jb20+iQFUBBMBCAA+FiEE
AZ/HDj4CES15BKoAAv5gXb3A4AgFAlzIxzQCGw8FCQPCZwAFCwkIBwIGFQoJCAsC
BBYCAwECHgECF4AACgkQAv5gXb3A4AiI2gf+NL+M9kphsMFOZjnt8HwXRbL6r/4M
Kle2xv1lJs/+mpMvRMsTY+BkXkf4P5TUVSHIlWDiPGlwkZRf+912DSLKwvsUCMR2
eWdOUphaCZjWx0aD/prb//KUHPzDi6v7oR5MKFEw/sdHIvJ/9GVh7oyuRipQTWIX
kpBarJOo34ciobO5kFfu1Xdqa4tTZDLp2HQivL4X157XRX85GYrmq8NEKUJCxV8Q
KNKdWzXFpec2foz/mnwLJYxTCm/tAIs+gEsSk+c2/7mCudZbT1Kkzvd1GciWKJgF
sq/l7yh5UuvEK6e4FMKNnD7GxVcKN3gvYW8H75gzTWuqIv7UdCJQlOlZuQ==
=2N/Y
-----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 02FE605DBDC0E008 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-----
iQEzBAABCAAdFiEEAZ/HDj4CES15BKoAAv5gXb3A4AgFAlzIxzYACgkQAv5gXb3A
4Aij6Qf+LtFtKyI/UtO5dJEXfPmsMZf8La18hsAkgesP8VnBMef2EgwAnVz58A6a
dEds5jcMTMWcnv1UwTkyaDqdCGpbElwlAyZaT1e9CdjK/RmKXfRzfO1We+z/vRAf
f9kSvw77y+V6rlZ+8aMN0YEGTSBuIzevctZZWAoQV3A+2FTML+Ta+bikvP4Y5+bk
qufUvXLRdM1ERAzBqobWBTCyxfn0s+Zpc2fXdupc9OIyUO0Kw1YrfmBF527zwa1F
Ao3QDUhc4UdsC9QG6wOtcFIl/j9Hf4n7yQZadxdeKU5K/jDCt7jYpb4wdvnff8u2
Qvfv2QU+WCwz4T1LHqamnorbUQe/6Q==
=F0xo
-----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-----
iQEzBAEBCAAdFiEEAZ/HDj4CES15BKoAAv5gXb3A4AgFAlzIxzYACgkQAv5gXb3A
4AgzsggAlGSEJAegMOTCLYX6beIxbjATOK5HcSvfO/WvomwK5U0Ywp0mNbKF2RX+
jqtV3BjIB3vScIWjpokzbHA2kaUjZaf+3VIFJ4KG93zcqnoniIabmghF12Cz0aEI
urncwC0qnTl0IJ+BZdowRngYxr3/81cGK8RsqGdQGKJ+QhlRd7dBmDpN0kXAJ37R
wsKh7L0HP/72dZ7CWNQzxFkHAey/+tCusOCtHzfOiEslo3TyIqqHk35NQ3NyIxyc
B03aMiZEjZT3fUpPvdywbbJZCKretjyAVElsN5cmdFH1XOckgvZ+qlRo/4jQILIV
flD58SnS/V7qLwt+Y9ovs5Bcr5cKHA==
=zqgd
-----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 019FC70E3E02112D7904AA0002FE605DBDC0E008 2019-05-01 00:07:50 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 019FC70E3E02112D7904AA0002FE605DBDC0E008 2019-05-01 00:07:50 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 <- "E19F5F87128899B192B1A2C2AD5F960A256A04AF"
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 AD5F960A256A04AF 2016-11-16 01:18:06 Johannes Ranke johannes.ranke@jrwb.de TRUE
2 2F0F4E14F649AF90 2016-11-16 01:29:16 FALSE
3 06F90DE5381BA480 2016-11-16 01:35:39 FALSE
Now lets verify the release files:
# Verify the file
library(curl)
curl_download('https://cran.r-project.org/bin/linux/debian/buster-cran35/Release', 'Release')
curl_download('https://cran.r-project.org/bin/linux/debian/buster-cran35/Release.gpg','Release.gpg')
gpg_verify('Release.gpg', 'Release')
fingerprint timestamp hash pubkey success
1 AD7B5162BA456BE3526F8D92FCAE2A0E115C3D8A 2019-04-29 09:27:24 SHA512 RSA 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 Jeroen containing top secret information that may not be snooped by our ISP or email provider. First we import Jeroen’s public key using the ID as listed e.g. here:
jeroen <- '16C019F96112961CEB4F38B76094FC5BDA955A42'
gpg_recv(jeroen)
found imported secrets signatures revoked
1 1 0 0 0
writeLines("Pizza delivery is on it's way!", "secret.txt")
msg <- gpg_encrypt("secret.txt", receiver = jeroen)
writeLines(msg, "msg.gpg")
unlink("secret.txt")
cat(msg)
-----BEGIN PGP MESSAGE-----
hQEMA4BQ/mdnc2saAQf9HkivaMcNSXlybmPPpolmLZxb5Uyb7yTu/dYpVQzPVu4n
TsQjNFJOsuWt+z4EXehjjEBTZJNeVpq7pNZbMi5RxZyE92UA9M3Fh+eBIAnAUclT
xsq6npBSRLcqdROkbibyInY4LXaPlcMVv6IXGADF253Wc2TitGM3QYlExfl09An9
U1hyijSx/LqjDKxrAd/3ac5FmPV3DBqlacZrRoZI0wjZwjbum3+jluOLYwd3ouZu
qw37j9Y2JnlsY203HbMIbH45y4EBx8bnSh9Ds4uk4w5g1fKkDlH21SyPXoT6ZZp4
GTN9Jmnn8NxUaLThylujKNcfDUd2gdwvObDN+qu8c9JaAQgGJAxdkKHdky3eSYg7
9JiG4+tNoJAs7Z9ceS8Cl/CZ/XYRy1619kAniPnrSah7c0XEbh3ZIAhSMB6C7jY6
R4HJLY13P4E25/oYwsr8qV6MNVOuWaAdzfGn
=VVQN
-----END PGP MESSAGE-----
Now you can safely send this message over any channel (email, twitter, etc). Nobody in the world besides Jeroen will be able to decipher this message (not even you).
Decrypting a message is just as easy. GPG will automatically find the correct private key from your keyring, or raise an error if you don’t have it. For example we will not be able to decrypt the message we created above for Jeroen
# 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-----
hQEMAwL+YF29wOAIAQgAl1iKOkTRVQsVx4tmUNSAPybco35mPv/5+GdhQgwuWwsI
EpwcAVQpQS5so+0o0kCJLv8j2PghNwy5SxaWyYQNlL8ZR0rUSqplwylFhmU9R5FZ
II5bBKS0SE0/Z0Qtt36RKPUhvxTEgObGtgnw55BlSufKbwgGdxaTyvSiM2ZDthlP
bO7ak9sBLtERjD+HPRkySK3THyjwAz7vvjgoy5Yz70PL4iDgebgBcC4T0gMIHjGm
EUe67NInZPpQEnQr1mudqicIAHYSZI36eBR7qu3ue6CjBqjhyiPZV9OquIkgACLr
OXtnERfEVHnhs5g6mEJlAcJ1Xku8cFx9GuMwWyZuW9JKARpFpo3QS+ezRFdshCdl
4V+EK/qbHbIzp2Q1qiC8iR1Wk7MduEKCmdrZYOT/l3yO4U4sOnqSZpXPO8LDMm4d
dJsbnqTS8CKCUPM=
=Va1Y
-----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 Jeroen verify the sender identity?
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 = jeroen, signer = mykey)
writeLines(msg, "msg.gpg")
cat(msg)
-----BEGIN PGP MESSAGE-----
hQEMA4BQ/mdnc2saAQf/fJGnaIfmSvSSptBM1rkAzj2W11NVibaNjIPi4Hy5OQPe
5peB0+b7hCn0p04opTxPV3X6g8E+U2jNw6rlvGg3y0fpqOV5E1kFz5ncDhKNHSy8
tBajNUiHzSxypkirv4SuLzq0j6D18lLwzSuCMoM74yFmnfuwKXvWY2423EvIjj9X
HA+t6bfAXt0OcplKhgmREGyVF0fY8zdO3NoJFRhgjtsTzbj+DugxnUTv8/yAUkQ/
qX6YCzGc7rv2PGBEBfIRAyKrn1BIqgtbhypxTfVn7G3UeaAe4IzM5OmtZ99XKA9C
ohvDcaoEKnXI0/Y1AgsVbsjj7Meyab+6Ce1FZ0dCN9LA0QFN1FI/cT97oXLs6HEM
gVXprJEEV7X4MmR+TWM6JSgN3iNyinx235oLBdlfUz7pp09E/BjwPbNQpIEprEYi
mXAnlb0828LleYm23O8qM/fbekdt22P06oh5D94o8MkDAWZdw3ieq7Jn+9Im4Rj5
WT1N+iBHB4EDgfpjFDP7vB6/7aK1CJ/oJ4B1NSZoPSlLL/ZdgMfI52axqBeec1q1
8o4r+ap5eH1x8ukaBnI+LflWHADZPfGWNDL+6Xp3++ERj6hYrqKfy13emYUvitci
ROROuj7B8YloYc7QdW/0TqQ2ZRKOwOJDB9E+C9b/JiYjjv13w8SPYWs1oo/62e8T
A3+ZnvUv3j4zgEr5GFT1Trhtvyz0p2ltTnyx0t7F7S1kUYpvIBPnhDvu3b41isY/
RCNmF2Hexk3r+GqWGw+SrwXyOcEj9ScKUsdTrNIIhahcMSQF22Q+4gWlLhY/+lOh
sHqmGSYcdLh/Y1J79Y3Vtd+5zk3+JsUR6ze7eCGaL/gb7L5fzB73Tjdk7Szz0muX
bZoz
=p7WX
-----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] "019FC70E3E02112D7904AA0002FE605DBDC0E008"
The signer fingerprint (if any) will be added as an attribute to the decrypted message.