
If you want to learn how to encrypt/decrypt emails, please read the Install Thunderbird and use it to encrypt/decrypt emails chapter of our Complete Guide to a Complete Linux Server.
If you want to encrypt/decrypt files and directories on your remote server, it’s recommended to use the GNU Privacy Guard (GnuPG or GPG) tool, which is a free software replacement for Symantec’s proprietary PGP cryptographic software suite. GPG is part of the minimal installation of Debian, so, there is no need to install it (otherwise, you would have had to run apt-get install gnupg
). The steps presented below can be applied for encrypting/decrypting files or directories stored on a remote Debian server, using a SSH connection, but they can be also used to encrypt/decrypt files and directories stored on a laptop/desktop computer running Debian.
1. Encrypt/Decrypt files and directories for your own use
1.1. Encrypt files
To encrypt a file on a computer with GPG, so that only you will have access to the content of that file (you don’t intend to send that file over the Internet to some remote recipient), the easiest method is to use symmetric encryption, which means that the same key will be used for encryption and decryption.
First, you should create a long string of random characters, that you can use as a passphrase. You can achieve this with the openssl
command like this:
openssl rand -base64 48
The result will be a string of random characters similar to this:
UsTrkygIo7N5ILbh+1I8v3YB020GyDvtOtdfxRaGTj8GQGVuwWmuOZvjgpMSagzJ
Copy this string to a safe location. (To store passwords and passphrases securely, you can use the free and open source application KeePassX.)
If you want to encrypt the sensitivefile.txt
file, run:
gpg --symmetric sensitivefile.txt
You will see a prompt inside the terminal, asking you to enter the passphrase. Copy the passphrase that you created earlier, right-click in the ‘Passphrase’ field, choose ‘Paste’, then press Enter to enter the passphrase. After you enter the passphrase two times, the command will create the encrypted file sensitivefile.txt.gpg
. It will encrypt the original file using a key generated from the given passphrase. Once a user obtains the passphrase, (s)he can decrypt the encrypted file, even on a different computer, logged in as a different user.
After the encryption is completed, you can use the shred -u
command, which overwrites, then deletes the file, to completely delete the unencrypted file:
shred -u sensitivefile.txt
1.2. Decrypt files
To decrypt the file run:
gpg sensitivefile.txt.gpg
The command will create the decrypted file sensitivefile.txt
.
If you want to give the decrypted file a custom name, run:
gpg --decrypt sensitivefile.txt.gpg > customname.txt
where customname.txt
is the custom name of the decrypted file.
1.3. Encrypt/Decrypt directories
If instead of a file you want to encrypt a directory, the easiest method is to first create an archive of that directory. Navigate to the parent directory:
cd /path/to/parent
Archive the target directory:
tar cf directoryname.tar.gz directoryname
Then encrypt the new archive file directoryname.tar.gz
like any other file, as described above. After you decrypt it as you would a regular file, you extract the archive by running:
tar xf directoryname.tar.gz
1.4. Changing the default symmetric encryption algorithm
The default algorithm used for symmetric encryption is CAST5. If you want to change the default algorithm when encrypting a file, you should first run gpg --version
to list all the encryption algorithms available. On the ‘Cipher:’ row of the output you will see all the supported algorithms (Eg: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256). If you want for example to change the default CAST5 algorithm to AES256 when encrypting a file, just add --cipher-algo AES256
before the --symmetric
parameter. Thus, the encryption command becomes:
gpg --cipher-algo AES256 --symmetric /path/to/sensitivefile.txt
2. Encrypt/Decrypt files and directories for remote recipients
If you want to send a file to a remote recipient safely, so that only the recipient can see its content and nobody can read it while it is in transit, you can use asymmetric encryption. This means that you use GnuPG to generate a key pair: a public key that can be made public and shared with anyone and a private key that you have to keep secret.
When you want to send a secret file to a specific recipient, you first encrypt the file using that person’s public key and you send the encrypted file to the recipient. The recipient uses his/her private key to decrypt the file. So, such is the relation between the public key and the private key, that a message encrypted with the public key of a person can be decrypted only by that person using his/her private key.
2.1. Create your public/private key pair
Before generating a key pair with gpg
you have to be aware that during the key generation, the random number generator needs a lot of entropy. The Linux kernel maintains a pool of entropy by gathering data from the system, like the interval between keystrokes or the interval between interrupts of network devices. Using this pool, it offers a sources of random numbers for programs to use. You can see the level of entropy available at a certain moment by running:
cat /proc/sys/kernel/random/entropy_avail
Usually the above command will show a low level of entropy, like some number below 100. In this situation the key generation will not succeed. GnuPG will hang for ever, waiting for the entropy level to increase. To avoid this problem and increase the available entropy to a high enough level, you have to install a small service called haveged
(some recommend isntalling rng-tools
but this is wrong because this won’t produce high quality random numbers). So, install haveged
by running:
apt-get install haveged libhavege1
You can check if the service is running like this:
systemctl status havaged
The level of entropy will be automatically increased by havaged
. You can check the new level of entropy by running again:
cat /proc/sys/kernel/random/entropy_avail
Before generating the key pair you should create a long string of random characters, which you can use later as a passphrase. You can achieve this with the openssl
command like this:
openssl rand -base64 64
The result will be a random string of characters that will look like this:
9yzZw7vbeJByWV9ri4s7agQmTsK0FXk+wa37yJIZzGxytNicAd9vCUoDvYajARkV
ieBLjGp58OWJNe1g1zyELQ==
As can be seen, there are two lines of characters. Copy all the random characters on one single line and store that string in a safe location, to use it later. (We already mentioned that you can use the free and open source application KeePassX to store passwords and passphrases.)
Next, you can proceed with the key generation. To generate a cryptographic key pair run:
gpg --full-generate-key
First you will be asked:
...
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection?
Type 1
, then press Enter to choose the default RSA and RSA option.
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072)
Type 4096
, since this will produce a stronger key, then press Enter.
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
= key expires in n days
w = key expires in n weeks
m = key expires in n months
y = key expires in n years
Key is valid for? (0)
Type 0
, then press Enter, so that the key will never expire.
Key does not expire at all
Is this correct? (y/N)
Type y
then press Enter.
GnuPG needs to construct a user ID to identify your key.
Real name:
The ‘Real name’ can be your real name, the name of your company, or even the name of a product. It will be accessible to the public along with the public key. Enter it, then press Enter.
Email address:
The ‘Email address’ is the contact email address for the public key. Enter it, then press Enter.
Comment:
The ‘Comment’ is optional and it is a word or group of words that can identify a person or company, the use of the key, etc. If you generate multiple key pairs, the comment can help you to identify the typical use of a key. You can enter a comment then press Enter or, if you want to leave the comment blank, just press Enter.
You selected this USER-ID:
"Example Name email@example.com"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?
Press o
, then Enter.
You will see a screen where you will have to enter your passphrase:

Enter the passphrase that you have generated earlier with the openssl rand -base64 64
command. You can copy the passphrase to clipboard from where you stored it, then right-click in the Passphrase
field from the screen shown above, choose ‘Paste’ to paste the passphrase, then press Tab to select OK, then press Enter to enter the passphrase.
After you enter the passphrase two times, you will see the message:
We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy.
Then, after a few seconds, the key pair will be generated.
When you see:
gpg: key ........ marked as ultimately trusted
gpg: directory '/root/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/..........rev'
public and secret key created and signed.
pub rsa4096 2019-11-18 [SC]
........
........
uid Example Name <email@example.com>
sub rsa4096 2019-11-18 [E]
it means that the key pair has been generated. The public key is stored in the ~/.gnupg/pubring.kbx
file. The private key is stored in the ~/.gnupg/private-keys-v1.d
directory. You can see that the public key generated above exists by running:
gpg --list-keys
The result should look like this:
sec rsa4096 2019-11-18 [SC]
B85FBA5C9B9EA18B8B4623FCE24AC981C604279C
uid [ultimate] Example Name email@example.com
ssb rsa4096 2019-11-18 [E]
If you want to see the name of the private key associated with the public key from above and the name of the private key associated with the subkey of the public key (the ‘subkey’ is a sub-component of the public key that is automatically generated), so that you can identify them in the ~/.gnupg/private-keys-v1.d
directory, you can run:
gpg --list-keys --with-keygrip
The result will look similar to this:
pub rsa4096 2019-11-18 [SC]
B85FBA5C9B9EA18B8B4623FCE24AC981C604279C
Keygrip = 36B2CC79A202416B12D29F73F1F9F74CF3099D25
uid [ultimate] Example Name email@example.com
sub rsa4096 2019-11-18 [E]
Keygrip = 828CA07F2A5759CF1FDAD91B42921A527BC4432D
where the strings next to ‘Keygrip’ indicate the name of the private keys, so that in the ~/.gnupg/private-keys-v1.d
directory you will find the private key: 36B2CC79A202416B12D29F73F1F9F74CF3099D25.key
and the private key associated with the subkey: 828CA07F2A5759CF1FDAD91B42921A527BC4432D.key
When managing keys, you will find that sometimes you will need the public key’s ID. For example, to delete a key from the keyring you have to run apt-key del keyID
.
The problem is that the gpg --list-keys
command from above only shows the long hexadecimal string which is the key’s ‘fingerprint’ and not its ID. The key ID for a RSA GPG key is the last 8 characters of the key’s fingerprint. In the case from above, the key ID is: C604279C
. (The last 8 characters of the key’s fingerprint are also called the ‘short key ID’, while the last 16 characters of the key’s fingerprint are called the ‘long key ID’. When they are displayed in Thunderbird and other similar applications, these key IDs are preceded by 0x
, because the characters that they are made of are hexadecimal digits.)
The key fingerprint is in fact a hash of the public key. If anything inside the public key is changed, the fingerprint changes, so the old fingerprint becomes invalid.
When you want to search for a public key on a key server using its key ID, as we’ll show below, you will have to prepend 0x
to it, so, the search will be for 0xC604279C
.
When generating the key pair, GnuPG also automatically generates a revocation certificate stored in the ~/.gnupg/openpgp-revocs.d
directory.
The revocation certificate, with a name of the form publickeyfingerprint.rev
, can be later used if you want to revoke a public key for various reasons: the private key has been lost/compromised, the passphrase has been lost, etc. You have to make sure that your ~/.gnupg
directory with all its content, but especially the private keys and revocation certificates, are kept secret and only accessible to you at all times.
If you want to see the actual public key associated with the email@example.com email address, you can ‘export’ it to the terminal by running:
gpg --armor --export email@example.com
The command from above will show the public key in the terminal. If you want to write it to a file run:
gpg --armor --export email@example.com > mypubkey.asc
The same thing can be achieved with:
gpg --armor --output mypubkey.asc --export email@example.com
This will write the public key to the mypubkey.asc
file.
The --armor
option means that the output of the command will be in the ASCII armored format. This is why the file format termination is .asc
.
If you want to export the private key associated with the email address email@example.com
to a file, run:
gpg --export-secret-keys --armor email@example.com > privatekey.asc
You will be prompted to enter the passphrase. After you enter the passphrase and press Enter, the public key will be exported to the privatekey.asc
file.
In the commands from above, instead of using the email address to identify the key, you can use the key ID (the last 8 digits of the key’s fingerprint, which can be found with the gpg --list-keys
command) preceded by 0x
. For example, to export the public key to a file, the command can be:
gpg --armor --export 0xC604279C > mypubkey.asc
where C604279C
is the key ID. (The command will also work if you don’t prepend 0x
to the key ID.)
2.2. Make your public key available to remote correspondents
2.2.1. Send the public key as a file to remote correspondents
One way to send the public key to a remote recipient so as to begin encrypted correspondence, is to first export your public key to a file (as showed above), then send that file as an email attachement, or by other means, to the remote correspondent. Run:
gpg --armor --export email@example.com > mypubkey.asc
In this way, the public key associated with email@example.com
will be exported to the mypubkey.asc
file, which can be sent to any correspondent.
2.2.2. Import the public key from a file
To import the public key of a correspondent that was sent as a file to you, run:
gpg --import recipient-pubkey.asc
Please note that you can import public keys from files with other extensions, such as .txt
. To see if the key has been imported to your keyring run:
gpg --list-keys
When you write to a few remote correspondents, sending your public key by email or by other means to each of them is doable, but when you want to communicate with many remote correspondents, sending the key to each of them individually may not be feasible. In this situation, many recommend uploading the public key to a public key server, but we will show that this is not actually the best way to make your public key available to the public.
A key server is a server that can store and distribute public keys to anyone who requests them. There are many public key servers that you can upload your public key to. Most of them are synchronized with each other, so that sending your key to one of them is like sending it to all of them. Any correspondent can request your public key from a keyserver, import the key to their keyring, and then they are ready for encrypted correspondence with you.
However, uploading the public key to a key server presents the following problems:
- Anyone can post a public key to a public key server in your name, with your email address. Then if (s)he, can intercept a message sent to you, that the sender encrypted using the fake public key, the interceptor can decrypt the message, since (s)he has the private key of the fake public key. The key server system was designed with the intention that the public keys uploaded to them will be cross-signed, and by this verified as authentic by other users or by trusted third parties, like companies. This was called the ‘web of trust’. Unfortunately, even some public keys signed by third parties can be fake. The cross-signing of the public key can also lead to the next problem;
- Others can sign your public key with a text that you don’t want to see associated with your public key;
- It is very difficult, and sometimes nearly impossible to remove a public key from one of the public key servers. When an uploaded public key becomes invalid because the private key has been lost, compromised, etc, the standard procedure is to upload the revocation certificate, so as to make public the fact that the respective public key is not valid anymore.
- Spammers can use the email address associated with the public key uploaded to the key server, to send you spam. There are also data mining tools that can automatically gather data from key servers.
The key servers are also full of old, compromised, expired, and revoked keys. In general, it’s very difficult to verify that a given key on a key server is the correct and current key for communication with the person or organization listed on the key. So, generally it’s not a good idea to blindly trust keys found on public key servers.
Some recommend that after uploading a public key to a key server you send the fingerprint of the key to the remote correspondent by using a different channel, such as by phone. This way the other person can verify that the public key is really yours. However, this involves an additional step and raises the question: why not send to the correspondent the entire public key instead of just its fingerprint and thus avoid uploading the key to the public key server ?
2.2.3. Upload the public key to a key server (not recommended)
Anyway, if you want to know how to upload a key to a public key server, this is how it can be done:
gpg --keyserver keys.gnupg.net --send-keys 0xC604279C
where keys.gnupg.net
is the URL of the public key server and C604279C
is the 8 character ID of the public key.
2.2.4. Import the public key from a public key server (not recommended)
To import a public key from a public key server just run:
gpg --keyserver keys.gnupg.net --search-key your.friend@yourfriendsdomain.com
then follow the prompts to import the key to your keyring (Type 1
followed by Enter if you want to import the first key listed, type 2
and Enter if you want to import the second listed key, etc.).
You can search by the key ID, so, instead of the correspondent’s email, you can use 0xC604279C
, where C604279C
is the key ID, or you can search by the whole key fingerprint preceded by 0x
.
When you communicate with many correspondents and sending your public key to each of them is not feasible, the best alternative to uploading the public key to a key server is to publish your key on your own website.
2.2.5. Publish your public key on your own website (recommended)
When you publish your public key on a page of your own website (it can be linked to from the Contact page for example), you have the following advantages:
- When the remote correspondents find the public key on your own website, this will be an assurance that it’s your real key, since you control the domain. Of course an Extended Verification (EV) SSL certificate for the domain will offer even more guarantees that the website is really yours and hence the public key is authentic, but even a regular SSL certificate will be enough.
- You can remove and replace the key whenever you want.
- Placing the public key visibly on your website will advertise the usage of GnuPG and secure communication which will increase the trust of privacy-minded visitors.
When somebody wants to encrypt messages using your public key published on your website, they can copy your key to a file, let’s call it copied-public-key.pgp
(or download the public key as a file), then import the public key from the file to their keyring by running:
gpg --import copied-public-key.pgp
2.3. Encrypt files
When you have the public key of a remote receiver imported in your keyring and you want to encrypt a file and then send it to them, run:
gpg --default-key email@example.com --encrypt --sign --recipient your.friend@yourfriendsdomain.com myfile.txt
where email@example.com
is the email associated with your private key, taking into consideration that you can have multiple private keys on your system, each with its own use, and you tell gpg which private key it should use (if you have multiple private keys and you don’t specify the one that should be used, gpg will just use the first private key found in the keyring), your.friend@yourfriendsdomain.com
is the email associated with the public key of the recipient and myfile.txt
is the name of the file to be encrypted. You can specify the public key of the recipient by its key ID preceded by 0x
instead of the email address associated with it, like for other gpg
commands.
The command from above encrypts the file with the receiver’s public key and signs the encrypted file with your private key, to prove that the encrypted file is coming from you. It creates the encrypted file myfile.txt.gpg
, which can be sent to the remote correspondent and decrypted as explained in the next chapter.
If you want to encrypt the file in ASCII text format, you can add the --armor
option like this:
gpg --default-key email@example.com --encrypt --sign --armor --recipient your.friend@yourfriendsdomain.com myfile.txt
The command from above will generate the encrypted file myfile.txt.asc
. If you want a custom name for the encrypted file, even one without any termination, you can specify it when running the command like this:
gpg --default-key email@example.com --output customfilename --encrypt --sign --recipient your.friend@yourfriendsdomain.com myfile.txt
2.4. Decrypt files
Once a correspondent receives an encrypted file by email, FTP, etc., (s)he has to ensure that (s)he has the public key of the sender imported in the keyring, then, to decrypt the file (s)he has to run:
gpg myfile.txt.gpg
where myfile.txt.gpg
is the name of the encrypted file (the encrypted file can also have the .asc
termination). The command will verify the signature and will create the decrypted file myfile.txt
.
Decryption can also be done by running:
gpg --decrypt myfile.txt.gpg > customname.txt
where customname.txt
is the decrypted file.
If the passphrase hasn’t been entered recently, before the decryption, the correspondent will be prompted to enter the passphrase associated with the private key that has to be used to decrypt the file.
The signature verification takes place along with the decryption. If the signature gets verified, the output will look like this:
gpg: Good signature from "Example Name email@example.com" [ultimate]
It should be noted that the receiver can trust the sender of the encrypted file only in so far as (s)he trusts that the public key used to verify the signature, was really the sender’s public key.
2.5. Encrypt/Decrypt directories
The only difference when encrypting a directory is that the directory has to be first archived (by running commands like tar czf directory.tar.gz
); then, it can be treated like any regular file.
If you want to encrypt multiple files, you can place them inside a directory and archive that directory. If you want to encrypt multiple directories, you can place them inside a parent directory and archive that directory. Of course, after the archived directory is decrypted by the recipient, (s)he has to extract the archive (tar xf directory.tar.gz
)
2.6. Revoke a public key
If you loose your private key or someone else gets hold of it, you cannot use it any more and you have to revoke it before generating a new key pair. A revoked public key is a public key that is declared invalid by using a revocation certificate. As we mentioned, when generating the private/public key pair, a revocation certificate is generated automatically. This certificate is located in the ~/.gnupg/openpgp-revocs.d
directory and is called keyfingerprint.rev
, where keyfingerprint
is the actual fingerprint of the public key.
You can open the revocation certificate with:
nano ~/.gnupg/openpgp-revocs.d/keyfingerprint.rev
You will see that it contains the following warning:
To avoid an accidental use of this file, a colon has been inserted
before the 5 dashes below. Remove this colon with a text editor
before importing and publishing this revocation certificate.
:-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: This is a revocation certificate
This means that to be able to use that revocation certificate, you will have to delete the colon from the beginning of that line, to make it look like this:
-----BEGIN PGP PUBLIC KEY BLOCK-----
You can also generate a revocation certificate for a public key manually by running:
gpg --output keyfingerprint.rev --gen-revoke 0xC604279C
where C604279C
is the key ID and keyfingerprint
is the fingerprint of the public key.
Once you have the revocation certificate for the public key that you want to revoke and you have removed the colon from the beginning of the line as explained above, you have to import that certificate into your keyring by running the following command, while you are in the directory where the revocation certificate is located:
gpg --import keyfingerprint.rev
After you have revoked the public key in your keyring, if you (or someone else) have uploaded your public key to a public key server, the next step is to revoke it on the public key servers. To revoke the key on the network of public key servers run:
gpg --keyserver keys.gnupg.net --send-keys 0xC604279C
where C604279C
is the key ID. This command sends the revoked public key from your keyring to the keys.gnupg.net
key server. If the upload succeeds you’ll see the message
gpg: success sending to 'keys.gnupg.net' (status=200)
then the key server will display the revocation status to users searching for the key, so that they know they can’t use it to encrypt messages in the future. After a few hours, the revocation information will propagate to the other key servers.
If you have published the public key on your website, the next step is to publish a note about the revocation of the public key, mentioning its fingerprint. Then, replace the old public key with the new public key on that web page.
It’s a good idea also to inform as many users of your old public key as possible that the public key has been revoked and a new public key has been issued. You can send them the new public key or a link to it, by email or by other means.
The next step is to remove the revoked key from your keyring. After the public key has been revoked and the subsequent steps have been taken as described above, it’s recommended to remove the public key from your keyring by running:
gpg --delete-key C604279C
where C604279C
is the key ID (found by running gpg --list-keys
)
If you want to remove the private key, run:
gpg --delete-secret-key C604279C
If you have removed both the public and the private key, you can also remove the revocation certificate by running:
cd ~/.gnupg/openpgp-revocs.d
rm keyfingerprint.rev
where keyfingerprint
is the fingerprint of the revoked key.
2.7. Sign someone’s public key
Any public key can be signed by any third party. If you want to sign somebody’s public key and by doing this to certify that it belongs to that respective person, first you have to verify their identity (this is usually done by seeing their government issued ID and confirming the key’s fingerprint). Then you have to import that key in your keyring from a file or from a public key server as shown above. Then run:
gpg --default-key email@example.com --sign-key name@theirdomain.com
where email@example.com
is the email associated with the private key that you want to use to sign the public key of the correspondent, taking into account that you can have multiple private keys on your system, each with its own use and name@theirdomain.com
is the email associated with the public key of the correspondent. You can run the same command replacing the email addresses with the key IDs preceded by 0x
.
When you sign a public key this can influence other people to also trust that respective key. This is in fact the whole purpose of signing public keys.
After you sign the public key of a person, the next step is to send the signed key to that person so as to allow them to benefit from the signature. To do this first export the signed key to a file:
gpg --armor --export name@theirdomain.com > signedkey.asc
After entering your passphrase, the signed public key will be exported to the signedkey.asc
file. Then, you can send this file to that respective person by email or by other means. After receiving the signed key, that person can add the signing information to their GPG database by importing the key with:
gpg --import signedkey.asc
2.8. Key maintenance
The most important thing when it comes to key maintenance is to remember to keep your private key and revocation certificate in a secure place, so that no one except you has access to them. If you leave them on your server, in the default ~/.gnupg
directory, you have to make sure that your server isn’t accessed by somebody else. Generally it’s a good idea to keep a copy of the revocation certificate, or even a copy of the whole ~/.gnupg
directory, on a USB flash drive or a memory card, so that if the private key ever falls into the wrong hands or gets lost, you can use the revocation certificate to revoke it. This is a good option only if you are sure that you can keep the USB drive or memory card safe and private. Otherwise it’s actually a security risk to store such sensitive information on a device that you can easily loose or that can get stolen.
As mentioned, to list all the public keys that you have in your keyring at a given moment run:
gpg --list-keys
If in your keyring you have public keys imported from public key servers, it’s recommended to refresh the keys from time to time, so that to update their data, such as user ID, revocation status, etc, with the current information from the public key servers.
To refresh all the keys that you have in your keyring, pulling their respective information from the public key server keys.gnupg.net,
run:
gpg --keyserver keys.gnupg.net --refresh-keys
2.9. Signing files and verifying file signatures
A gpg signature can be used to certify the sender of a file and to timestamp the file. If the file is modified in any way after it has been signed, the verification of the signature will fail. Therefore, a gpg signature guarantees both the authenticity and the integrity of the file. If used for a digital document, such as an odt, docx or pdf file, this kind of signature can have a similar function with that of a hand-written signature on a paper document.
Creating and verifying signatures uses the public and private keys in an operation that is different from encryption/decryption. A signature is created using the private key of the signer and is verified using the signer’s public key.
We’ll use as example a file called importantfile.odt
, but the file that you sign can be in any other format, including a compressed file format such as zip
or tar.gz
. To sign the importantfile.odt
file, run:
gpg --default-key email@example.com --sign importantfile.odt
where email@example.com
is the email address associated with the private key that you want to use to sign the file. (If you have only one private key in your gpg keyring, you can run the command without the --default-key email@example.com
part, because gpg will choose the only key available, but if you have multiple private keys on your system, each with its own use, you will have to specify which one you want to use to sign the file.) The file will be compressed before being signed and the ouput file importantfile.odt.gpg
will be in binary format.
If you want to give a custom name to the signed file, add the --output
option like this:
gpg --default-key email@example.com --output customname.gpg --sign importantfile.odt
To just verify the signature of the signed file, the receiver has to make sure that (s)he has the public key of the sender in her/his keyring, then run:
gpg --verify importantfile.odt.gpg
If the signature gets verified, the output of the command will look like this:
gpg: Signature made Mon 12 Apr 2021 03:25:38 PM EDT
gpg: using RSA key A5E06512A98ED54E487FDA48615B20E7E468DACD
gpg: issuer "email@example.com"
gpg: Good signature from "Example Name <email@example.com>" [ultimate]
If the Good signature
message from above is followed by this warning:
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
you can ignore it as long as you are certain that you have the correct public key in your keyring. This warning just signals that the public key is not signed by third parties.
To verify the signature and extract the file, the receiver has to run:
gpg --decrypt importantfile.odt.gpg > decrypteddocument.odt
If the sender doesn’t want to compress the file while signing it, (s)he can create a detached signature using the option --detach-sign
:
gpg --default-key email@example.com --detach-sign importantfile.odt
This command creates the detached signature as a separate file (importantfile.odt.sig
) that has to be sent to the receiver along with the original file. The signature file is not readable since it’s a binary file. To verify the signature, the receiver has to have both the original file and the signature file in the current directory. The command to verify the signature is:
gpg --verify importantfile.odt.sig importantfile.odt
If the signature gets verified, the output will specify Good signature
, like in the example given above.
The --detach-sign
option is often accompanied by the --armor
option which generates a readable ASCII text file containing the signature:
gpg --default-key email@example.com --detach-sign --armor importantfile.odt
The result will be the importantfile.odt.asc
signature file. To verify the signature, the receiver has to run:
gpg --verify importantfile.odt.asc importantfile.odt
The --clearsign
option can be also used instead of --sign
or --detach-sign
. --clearsign
wrapps the content of the file in an ASCII-armored signature but it doesn’t modify it in any way. This method is used in general for text files. The command to sign the file becomes:
gpg --default-key email@example.com --clearsign importantfile.txt
In this case, the resulting file will have the termination .asc
(importantfile.txt.asc
). To verify the signature and extract the file, the receiver will run:
gpg --decrypt importantfile.txt.asc > decrypteddocument.txt
Please note that in addition to signing a file as explained above, it can be also encrypted. In this case, the signing command will have to include the --encrypt
and --recipient
options, like this:
gpg --default-key email@example.com --encrypt --sign --recipient recipient@domain.com importantfile.odt
where recipient@domain.com
is the email address associated with the public key of the recipient to which the file will be sent (It is assumed that the public key of the recipient has already been imported into the sender’s keyring. The public key of the recipient can be also specified by its key ID preceded by 0x
). To verify the signature and decrypt and extract the file, the receiver will have to run:
gpg --decrypt importantfile.odt.gpg > decrypteddocument.odt
2.9.1. Verifying the integrity and authenticity of a software package using a signed checksum hash file
When you receive a software package, you want to make sure that the package comes from the right sender (authenticity) and that it hasn’t been modified in any way since it has been created (integrity). As mentioned above, a file’s authenticity and integrity can be verified by having the file signed and then verifying the signature. For example, if you have a software package called softpack.tar.gz
you can sign it by running:
gpg --default-key email@example.com --detach-sign softpack.tar.gz
This command will generate the softpack.tar.gz.sig
signature file which has to be sent along with the original file, softpack.tar.gz
, to the receiver. To verify the signature, the receiver has to first import the sender’s public key into her/his keyring, then run:
gpg --verify softpack.tar.gz.sig softpack.tar.gz
If the signature gets verified, the output will specify Good signature
.
However, in the case of a large file, a signed checksum hash file can be used to verify file authenticity and integrity. This method is in general faster than signing the file directly, and the signature also prevents changing the name of the original file. So, to allow the receiver to verify the authenticity and integrity of a file, the creator of the file can send 2 files to the receiver:
- the original file:
softpack.tar.gz
- the checksum hash file signed with a GPG key:
softpack.tar.gz.sha512sum.asc
The checksum hash file of the original file is obtained by generating a cryptographic hash of the file’s bytes, as shown below. Then the checksum file is signed with the private key of the sender. When receiving the original file and the signed checksum hash file, the recipient first verifies the signature of the signed file (using the public key of the sender, imported in the keyring in advance); if the signature gets verified, it means that the signed checksum hash file comes from the right sender; next, the recipient checks the signed checksum file against the received file and if the checksum in the signed file matches the original file, this means that the original file hasn’t been modified after it has been created. In this way, both the authenticity and the integrity of the received file are verified.
The hash file is a simple text file which is usually assigned a name similar to the name of the original file, but with a termination that depends on the algorithm used to generate the hash. The MD5 and SHA1 algorithms are considered weak, so the algorithm used for hashing the original file is usually SHA256 or even SHA512.
To generate the hash of a file called softpack.tar.gz
run:
shasum -a 512 softpack.tar.gz > softpack.tar.gz.sha512sum
This will generate the checksum hash file softpack.tar.gz.sha512sum
(you can choose a different name if you want). If you open this file with a text editor, you will find that it contains a long hexadecimal string followed by the name of the original file, like this:
c031d1a58eafd6c54d66f4b75f087f2250fa1a22ea087b832cc49a2c32635262dd80055bada668feef643aec83b71e6b7ec85d107c6ca1c075b8944519113168 softpack.tar.gz
If you modify the original file just a bit, let’s say by deleting one character, and you generate the checksum hash again, you will find that the long hexadecimal string is different from the original one. This means that the same hash can be obtained only if the original file hasn’t been modified in any way. This is a method to verify the integrity of a file (provided that a strong hashing algorithm, like SHA512, has been used. There were cases in which two different files produced identical hashes when hashed with a weak algorithm).
To sign the softpack.tar.gz.sha512sum
checksum hash file with your private key in a way that doesn’t compress it, so that the checksum string remains readable, use the --clearsign
option:
gpg --default-key email@example.com --clearsign softpack.tar.gz.sha512sum
where email@example.com
is the email associated with the private key that you want to use to sign the file. The command will create the signed checksum file softpack.tar.gz.sha512sum.asc
. This file will have the content of the checksum file wrapped in the signature, which means that the long hexadecimal string which is the actual checksum of the original file will be preceded and succeded by some lines of text, remaining perfectly readable.
Otherwise, you can use the --sign
option, that will compress the file while signing it:
gpg --default-key email@example.com --sign softpack.tar.gz.sha512sum
This command will create the signed checksum file softpack.tar.gz.sha512sum.gpg
.
After receiving the original file (softpack.tar.gz
) and the signed checksum file (softpack.tar.gz.sha512sum.asc
or softpack.tar.gz.sha512sum.
gpg), the receiver has to first verify the authenticity of the signed checksum file by running:
gpg --verify softpack.tar.gz.sha512sum.asc
if the checksum file has been signed with the --clearsign
option, or
gpg --verify softpack.tar.gz.sha512sum.gpg
if the checksum file has been signed with the --sign
option.
If the output of the above command indicates a good signature (gpg: Good signature from …
) this means that the signature has been verified. The receiver should ignore the warning: WARNING: not a detached signature
;
Now that the receiver knows that the signed checksum file comes from the right sender (as long as (s)he trusts that the public key used to verify the signature is indeed the real sender’s public key), it remains to verify that the signed checksum file contains the checksum of the received file (softpack.tar.gz
) and not of a different file. To check the signed checksum file against the received file, the receiver has to make sure that both files are in the current directory. If the checksum file has been signed with the --clearsign
option, the receiver has to run:
shasum -c softpack.tar.gz.sha512sum.asc
If the checksum file has been signed with the --sign
option, the file has to be first decompressed with the command:
gpg --decrypt softpack.tar.gz.sha512sum.gpg > softpack.tar.gz.sha512sum
Then, to check the signed checksum file against the received file, the receiver has to run:
shasum -c softpack.tar.gz.sha512sum
In both cases, if the output looks like this:
softpack.tar.gz: OK
it means that the checksum of the received file is the same as that contained in the signed checksum file. The warning: shasum: WARNING: 20 lines are improperly formatted
can be ignored, because it just signals that along the actual checksum line, there are other lines that are not properly formatted checksums. These lines are the signature lines that wrap the checksum.
Please note that the sender can use the --detach-sign
option to sign the checksum file instead of the --clearsign
or --sign
option. In this case, the sender has 3 files which (s)he has to send to the receiver:
- the original file:
softpack.tar.gz
- the checksum hash file:
softpack.tar.gz.sha512sum
- the checksum hash file signed using the
--detach-sign
option:softpack.tar.gz.sha512sum.sig
The receiver has to first verify the detached signature file with:
gpg --verify softpack.tar.gz.sha512sum.sig softpack.tar.gz.sha512sum
Please note that the unsigned checksum file has to be passed as a parameter to the --verify
command after the detached signature file, for the verification to work. Then, having both the original file (softpack.tar.gz
) and the checksum file (softpack.tar.gz.sha512sum
) in the current directory, the receiver has to check the checksum file against the received file by running:
shasum -c softpack.tar.gz.sha512sum
2.10. Add a public key to the apt sources keyring with apt-key add
When downloading Debian packages signed with cryptographic keys, from online repositories, before downloading the package, you’ll have to add that package’s public key to the apt sources keyring using the apt-key add
command. Usually, the organization offering the Debian package will also display the command needed to import the public key. That command is similar to the following:
wget -qO - https://nightly.example.com/softwarepackage.key | apt-key add -
The command above adds the public key softwarepackage.key
to the apt sources keyring, which is different from the gpg keyring mentioned in the previous chapters.
The option -O -
used with wget
prints the downloaded file to the standard output instead of an ordinary file. The -
option after apt-key add
reads from the standard output. The -q
option stands for ‘quietly’ and means: don’t show the wget
output.
List all gpg keys added with apt-key add
:
apt-key list
Remove a gpg key that was added using apt-key add
:
apt-key del C465BFA2
Where C465BFA2
is the key ID.
To conclude, we should add that the different methods used for digital encryption/decryption have their utility and they offer proven protection in many use cases, but they shouldn’t be trusted blindly. Even if the technical aspects of a cryptographic system seem perfect, there is always the ‘human factor’ and the complexity and unpredictability of life that have to be taken into consideration. Prudent minds will always use cryptography cautiously, since no cryptographic system is totally unbreakable.