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 NA
$ gpg : chr "/private/var/folders/gz/rwkfg8wx1wqgcr0ccpz42dyc0000gn/T/Rtmpehxy0M/Rinst86347f71bfd9/gpg/bin/gpg"
$ version:Class 'numeric_version' hidden list of 1
..$ : int [1:3] 1 4 23
$ home : chr NA
$ gpgme :Class 'numeric_version' hidden list of 1
..$ : int [1:3] 1 16 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) 1.4.23
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-E, RSA-S, ELG-E, 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()
[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] "9E5830E9E897F1CC"
gpg_list_keys()
id name email
1 9E5830E9E897F1CC 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 9E5830E9E897F1CC 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 9E5830E9E897F1CC 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 201 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 520E0C8369B003EF 2013-08-20 12:31:55 FALSE
8 D56E1B4C135D47A1 2013-08-29 13:36:03 FALSE
9 31CC32CEF78F3EE4 2013-08-29 13:37:52 FALSE
10 9439E86389D0AF41 2013-08-29 13:55:01 FALSE
11 C5CFD08B22247CDF 2013-09-24 15:00:05 FALSE
12 20B7283AFE254C69 2013-09-28 22:44:02 FALSE
13 A866D7CCAE087291 2013-09-29 17:59:25 FALSE
14 6D33FBF5B5E4C71A 2013-09-30 15:52:36 FALSE
15 8916CADF8ACD372A 2013-10-02 13:17:17 FALSE
16 8E549D02234CC324 2013-10-03 09:36:24 FALSE
17 D605848ED7E69871 2013-10-04 11:03:23 FALSE
18 758EAEC123F62336 2013-10-13 00:53:08 FALSE
19 7B585B30807C2A87 2013-10-18 21:27:08 FALSE
20 E4A6D8A25310523C 2013-10-23 02:53:11 FALSE
[ reached 'max' / getOption("max.print") -- omitted 187 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-----
mQENBGGU+hMBCAC7BbPnzdAwghcFcg8xD1eqg7TJd1pUqHRyhmMxd6YkXLLAiUE4
9mRZkcss4MBybYNtk0K6xbJzHKhRfCnIf2MXUPX6prbpleCCyuF7bd4QdLLky52g
2qwNqg+v7H5P+pTaY6e3MzT10XOJg5cqzKW20XdXefZTNlMLMAXjy0bNXECYseJI
bIsc/IrpSTSSnA48GGyZ6GQ71E2VGhw4S2JKkjB1fMsGE0XYJEaEObpGjcsGz9D3
IKtnL5CDr5brQf8TJ2/oY1gDEpMcu9HzmckeDJ1itiv+uQJqe9yhDvN20lIxIJLi
jpKWsiuZr0dDkzDJCDGKmje+8jqJoZCoQmhpABEBAAG0F0plcnJ5IDxqZXJyeUBn
bWFpbC5jb20+iQE4BBMBAgAiBQJhlPoTAhsvBgsJCAcDAgYVCAIJCgsEFgIDAQIe
AQIXgAAKCRCeWDDp6JfxzA08B/40u2D1cKVPuuiAh22a+LWIZyUxwRrQUqKW8P+l
uzLDjTcWiuSKcunMuFUkQXKc8XBvSQFx0BGtXMiRzlnTca755Un91rTI2LAPgp34
qg827ApouxG0tTyDZ/a5+KrjJnhKKUZbdjW/OeLLAyNe9jSu/mmgTxPa/o7gLQIp
DgI5c4THrTR8yYIWwGCdIVxuHnR/rjMaCvbZPF4dRNO6pRReLI62tIW8VdSauzdp
Q7ilFzpS3kR3+kDJkYKYCUikT6apNGkMXPhaS3Cd5LkH0t90Tqs1IJdxdNxnieIC
p5P9odgC9HwocgxXLKIuwLVwsVQXysEiA+Kl6DOSwPn9gpLd
=xhrG
-----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-----
lQOYBGGU+hMBCAC7BbPnzdAwghcFcg8xD1eqg7TJd1pUqHRyhmMxd6YkXLLAiUE4
9mRZkcss4MBybYNtk0K6xbJzHKhRfCnIf2MXUPX6prbpleCCyuF7bd4QdLLky52g
2qwNqg+v7H5P+pTaY6e3MzT10XOJg5cqzKW20XdXefZTNlMLMAXjy0bNXECYseJI
bIsc/IrpSTSSnA48GGyZ6GQ71E2VGhw4S2JKkjB1fMsGE0XYJEaEObpGjcsGz9D3
IKtnL5CDr5brQf8TJ2/oY1gDEpMcu9HzmckeDJ1itiv+uQJqe9yhDvN20lIxIJLi
jpKWsiuZr0dDkzDJCDGKmje+8jqJoZCoQmhpABEBAAEAB/0U98SV8XKdD6a8WO94
VwGjh8jn+gJGAc1tbiD2obUeOEjfsnu+Isy5KJH8hfW5lorgyPz3IvVY985stVSb
aqHN0klDuPeCrIerbkrVq2mVU3ofke8KIt4dmZKQ7R0zwxK3gesCrIJsaXdQRHE5
LpDJNIaSZ4V9CpcIpvGQGqElYphYPe+85I1Dm31m8mB6H/sPNaqHgLIC+9mbinFJ
17NKq25+7B6Gn56zLrXUJfL00o6bs7DFKsCP+7GTXAUZJQonMDkspjj/yecHGD+D
LuokkZ8X8anI2Pb94AboFlSgKtm6ZfbO9UHoJXaTh4qEEGRNrAa3qZ59zPKuTH9C
pchxBADLrI9+9zNg+bailf1X+USk+nVnKPdk2/sHQ1NQlekCY4+bcMp3NvZjLTEK
ruA/08GWwo/PchnHJdWnJZaJaJbO5dU0VpbjqSZwraxrs/DS5fcAUXoT+TNocMqT
cBlIBZ7y5Jd8lsK4Ai3Nd91fX5b1/rgV9TxGfcft/GH6MiM9kQQA6xH4hKzJ9qZo
DlAtUluYerfgJoeyq6dLn+idiU77ywoKGzxuBeVK+k5CHj6+P5ryg7RGm/v7kIlp
SrvZCtJpOTOgnxbQFfvGtncmr9/2ZwN+2Z1baHlO0b1qpyrCJA/9f5RRrrG0WXUr
O1kI58lnl9GCW2E7md3vbl6dr/gFcVkD/2FiiIA5L3OdKLJytXCC/wT+o6c7FU8I
W8Vi32+rJYh5n9hAPhfyb3AR93wrZhbvYWyN8xYS8GL3Yrt+0wM4x0mHbQjcWAhF
doPWtkc+Rl3iUbyhqjgW65RGfAXDGqabT5LZqiPrEIk76y2t0900mHxkNpRpQtBP
JeA6ChAoza8KTO60F0plcnJ5IDxqZXJyeUBnbWFpbC5jb20+iQE4BBMBAgAiBQJh
lPoTAhsvBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRCeWDDp6JfxzA08B/40
u2D1cKVPuuiAh22a+LWIZyUxwRrQUqKW8P+luzLDjTcWiuSKcunMuFUkQXKc8XBv
SQFx0BGtXMiRzlnTca755Un91rTI2LAPgp34qg827ApouxG0tTyDZ/a5+KrjJnhK
KUZbdjW/OeLLAyNe9jSu/mmgTxPa/o7gLQIpDgI5c4THrTR8yYIWwGCdIVxuHnR/
rjMaCvbZPF4dRNO6pRReLI62tIW8VdSauzdpQ7ilFzpS3kR3+kDJkYKYCUikT6ap
NGkMXPhaS3Cd5LkH0t90Tqs1IJdxdNxnieICp5P9odgC9HwocgxXLKIuwLVwsVQX
ysEiA+Kl6DOSwPn9gpLd
=O1mr
-----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 9E5830E9E897F1CC 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-----
iQEcBAABAgAGBQJhlPoUAAoJEJ5YMOnol/HMGRQH/AoERMX8UA64Y1SDucyxx8N+
ta3drFtqegli5TRN5fHAo7DsYyz1Ki/cg1VcQeTSeH9xyiD+PX3svdycNfx8sDui
Fd7eYMg+cs1M3Wn+jZFr1AO5InzhgZXmEW8S0QisPSXh1/gL4r6K3GUhyDPoYHB3
045s7DCNZEFsDtt4em8PEfGfcRFA8KuPn9XwpKrCM2R4GEtds0jLZL1yuL5zVrUx
wU1HZF09VcTiJzU4kPngzmEtVOeIeIcG7n+bB8YHeX3HoE/NXLmlTtUi9kd/xcPU
clbMr4jYKNqSg3/+g45z/lHTm2gTo6OmAqbGLOQuWpjguV3Jqr7j0Lt+rcu0K00=
=/0+W
-----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: SHA1
This is a signed message
-----BEGIN PGP SIGNATURE-----
iQEcBAEBAgAGBQJhlPoUAAoJEJ5YMOnol/HMVSoIAIkhtB+4ym84r5rUfmqsGFDh
jsboYgU3eO2c11oxDvDKyDgNipGETJYDfTy5bgmHxT5XVdWG2IAy69NXuA+IWQa+
ScuSKZjl8+unCPgF5yYsTmGfIMptp1kEqQ3eFCnQreLSb0gIcswMFvjzgNTGC92/
glyLZLanOtei9tV8VOYFiTCil8NkfU8KZHlglDu8RsVWfS+QoI5t70YjtU/8u2Wh
wlLwDqSx29DFGzqdBzEqHH/Jlfne4B/yJIQ9WKk25nnDNu/Mr04ev1EPdghkUu9c
5Vm0nSEopgZaJhVlIJ1kaLX0Ve0eW9tsGLjaMt3px1r8vS2M7QjaxxndKTQ9X0I=
=mnyT
-----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 5E1C30626F5052C76BCC77F49E5830E9E897F1CC 2021-11-17 13:48:20 SHA1 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 5E1C30626F5052C76BCC77F49E5830E9E897F1CC 2021-11-17 13:48:20 SHA1 RSA TRUE
Let’s verify a Debian file. The Debian page on CRAN says the following:
Since 16th of November 2021, the buster40 and bullseye40 repositories are signed with a new key with the key ID 0xB8F25A8A73EACF41, fingerprint 95C0FAF38DB3CCAD0C080A7BDC78B2DDEABC47B7 and user ID Johannes Ranke johannes.ranke@jrwb.de.
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 <- "0xB8F25A8A73EACF41"
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 DC78B2DDEABC47B7 2021-11-16 11:17:18 Johannes Ranke johannes.ranke@jrwb.de TRUE
Now lets verify the release files:
# Verify the file
library(curl)
Using libcurl 7.77.0 with LibreSSL/2.8.3
curl_download('https://cran.r-project.org/bin/linux/debian/bullseye-cran40/Release', 'Release')
curl_download('https://cran.r-project.org/bin/linux/debian/bullseye-cran40/Release.gpg','Release.gpg')
gpg_verify('Release.gpg', 'Release')
fingerprint timestamp hash pubkey success
1 7BA040A510E4E66ED3743EC1B8F25A8A73EACF41 2021-11-16 12:23:37 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/mdnc2saAQf6Aln1jiAhvCd8Pan2k4g3M6EFq7YCm8SsxOfyguSHmE6y
qtWGR6HbxJasdMSrlO6Jnmfn0wpQRrpSH7ryZJeamsVU7e82h+5fct8Y9gZJtl+A
ViT10a0jKfZsW+X6UmQ7C6iYmPJ6gL7p7BZdtDfNvAR86K1R4lTJILCRHIzJgpNk
+whmfV39XUcfxwS3zm3GR7ETGHwXX1rzDMgrfJO8rElKyH5g6mkmPzdivbWTM7k7
bgoMP1aga2RjpwH3tttPOpQDdhLKNZr2e9IjYJlqinZRIAc5Vde7YNwQIz1hx7TB
StS29OhPfIHk5ydZ1Uv36avZ7M26k3BwdEqStFswotJeAYmYj8shZHIlVrJV4i5+
NYPtdxjupkJ+TGZ2kBkdtGeKqRUfcYiHQTSudh055D64l5k5Cxk1j0bpbHnxcvax
E+e0TC52OJiH80vLAZv20o/eNiQTKP2Uyxb9Lo+79g==
=cmUx
-----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-----
hQEMA55YMOnol/HMAQf/TRILvyCYbv8C5d2AiyR7j5GKen1Q3Yf2pyR8wqi+yzmP
nIyCqcmfZVDhtLgIPb7/FAcytkIpvZ2DtugdIq9YtPWvTyYecaoe2Koon1LUKn9r
iBxGQzLzevsU4Fcsi8uymVt5Qrm9b7nChQaO0Zr+QET1E4WoV3DVsjuIjEGMu4xh
+mMyawW0fnRdOG2fP19++RJWyUKpMqAlNX/3Bj0xgXE51hDtzvWkO3V+hreTkgD9
y8jOdwtAhmkHffeaFjv1WCng2zPmeuoTYvMcBVI3+pynpD+9DEA+oPKYTtt1kYUQ
HPEIdJaDHCQbgs3xv4Tqm4wuFeakGRcJyD+A4FO+A9JOARFxqH2Atn8gANOUAGww
1NBQfV8a7CPb8gfU4HgOg6GQmMY2+n3Rf2ezOZVvytB6s1qtOA8Et0YaHQc80dgs
/HkixMs8+MPPe0/SEprg
=GFJF
-----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/mdnc2saAQgAi3dL5I0azw5famHewnxKoPdxfFU+FGJIcZLKRSJyQMK3
9Vust8Q0bfzVBF412eFvHMxRv6OL3APvEtYju778eumTcalsVOLu65QDPmvCmpCd
DJttYGMHqrRAESp3SjI4aQX7L+Ly9ZQZt9bqDFGv2kIx3WVrvrE1oXc2tEuLNBGv
r/kLxsLDB8qsso57/mI7huhEVkYfki2VC5IZkP9GIJ1w5n45UmZGLQbUK1orUMsF
GOi7LuulIxhvrrQIlMKo5yXvwAdbpH37FS92aobxvz4zv79JuY8iEC4bD2PVhsgB
IC0+nOKpQcR/2+DYx+qAKJgyfwYioUAc0PJcJ3iZXdLAwAGFzc3KvcFL3fPE9T2V
UiUjWZvKxL2RvbViEyJJMvl0/KkOBY7JFOQnmCaIW9ZOfY3mElcK8BSX4VrDPzsO
3P+SMXbEeBIuZ5auIdOK+6pMTzoSk6awGMMdcfukgw9qeirew8hJ5zmBm4C9bfQD
X1t9imUIGzMrFmFBXx+hEoTsuTCw6Rvi+mnQOPwHtCrG3TZZm16EYUFAaetsbGfp
uRo+U+y4U2OmOPXycVhMMSZAna6OcBlvCeHPHdp/BdSfDH+SfjR7LqIKEV+tRroZ
Oa9OGvUBrCjuG/stRkE3Xwnb3ZKcK1pPchSH+sjLZ6UeJzgVIlk1jDp4fL/2jXwF
HZ0CkCBXackc8aeRk5sVrPV3+n0jLCo7XAgHznNLyy0bS2Js+/5BpUe7aH4NMsxo
UFuDiHfW74G4X266ZKREmTDAprjWXh1cOIjWbGpJbSIDLV9R2TiR80QOOtal2pff
/feLYJGkyFB5+jny0w6F0YkbUTy1W46yE2+q+hiap/mxcA==
=zq9/
-----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] "5E1C30626F5052C76BCC77F49E5830E9E897F1CC"
The signer fingerprint (if any) will be added as an attribute to the decrypted message.