Technology Inside Out!

Index ¦ Archives ¦ Atom ¦ RSS

Hands-on Guide on GPG Keys

GPG or GNU Privacy Guard is a complete and free implementation of the OpenPGP standard as defined by RFC4880 (also known as PGP). It is a tool that provides encryption and signing services, using which, you can encrypt or sign your files, messages, emails and can even sign your github commits. In this guide, let's get a walk through GPG keys and its use cases.

GPG is basically an implementation of a cryptosystem that you can use to exchange encrypted or signed messages and it is based on asymmetric cryptography. It fulfills the CIA of security where "C" stands for "Confidentiality", "I" stands for "Integrity" and "A" stands for "Availability".

Before Generating a Key Pair

In this tutorial, I am using "gpg2", but you may go with "gpg" as well, because most of the commands are same for both. However, a comparison between both the versions is available at the end of this post.

To generate a key pair, first make sure you can run the following command.

$ gpg2 --version
gpg (GnuPG) 2.1.11
libgcrypt 1.6.5
Copyright (C) 2016 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, 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

It gives the version number of gpg like 2.1.11. If not, then you need to install it, the package is gnupg (for gpg) or gnupg2 (for gpg2).

$ sudo apt-get update
$ sudo apt-get install gnupg2

Generate a Key Pair

Simply run the following command to generate a new key pair.

$ gpg2 --full-gen-key

You may try this command with "sudo" if required.

Note:- Either use "gpg", "gpg2", "sudo gpg" or "sudo gpg2". But whatever you use, keep that same. That means, if "sudo gpg2" worked for you, then keep it same for all the upcoming commands.

This command will ask you the following questions.

  • What kind of key do you want (RSA, DSA, etc)?
    You should go with default selection.
  • Key size?
    The longer, the better.
  • How long should the key be valid?
    It is good to give here some value e.i "2y" (2 years) as it is suggested to all people that start with PGP to use an expiring key. Because at some point, you are likely to lose access to the private key, and then you can't revoke the key so that other people stop using it. But if it expires, everyone will stop using it at the expiration date.
  • Your real name?
  • Your email address?
  • Any comment?
    For now, you may leave the comment empty. But comments are used to distinctly identify a key, in case you have multiple GPG keys.
  • Final confirmation (y/n)?
  • Your passphrase?
    Enter a strong passphrase twice and proceed ahead.

At this point, GPG will generate the keys using entropy. Entropy describes the amount of unpredictability and nondeterminism that exists in a system. This entropy is needed to generate a secure set of keys. This process may take some time depending on how active your system is, and the key size you selected. The terminal may look like this.

$ gpg2 --full-gen-key 
gpg (GnuPG) 2.1.11; Copyright (C) 2016 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

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? 1

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096

Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years

Key is valid for? (0) 2y
Key expires at Tuesday 03 March 2020 02:08:15 PM IST
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Your Name
Email address: your.email@example.com
Comment: 
You selected this USER-ID:
"Your Name <your.email@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
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.

Generate an Authentication Subkey

An authentication subkey is used if you want to use your GPG key for SSH authentication. To generate this, just follow these steps:

  • \$ gpg2 --expert --edit-key your_key_id
  • Enter addkey (to select the operation)
  • Select the type of key (e.i select "8" for RSA)
  • Enter 'S' to toggle signing to OFF.
  • Enter 'E' to toggle encrypting to OFF.
  • Enter 'A' to toggle authentication to ON.
  • Enter 'Q' to quit.
  • Enter key size. (e.i 4096)
  • Enter validity period. (e.i "2y")
  • Confirm your entries.
  • Confirm creation.
  • Enter Passphrase twice.

After some time your authentication subkey would be generated. Output of the process is shown below.

$ gpg2 --expert --edit-key 123EE456
gpg (GnuPG) 2.1.11; Copyright (C) 2016 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec rsa4096/123EE456
 created: 2017-04-03 expires: 2019-02-02 usage: SC 
 trust: ultimate     validity: ultimate
ssb rsa4096/7891EEFF
 created: 2017-04-03 expires: 2019-02-02 usage: E 
[ultimate] (1). Real Name your.email@gmail.com

gpg> addkey
Please select what kind of key you want:
 (3) DSA (sign only)
 (4) RSA (sign only)
 (5) Elgamal (encrypt only)
 (6) RSA (encrypt only)
 (7) DSA (set your own capabilities)
 (8) RSA (set your own capabilities)
 (10) ECC (sign only)
 (11) ECC (set your own capabilities)
 (12) ECC (encrypt only)
 (13) Existing key
Your selection? 8

Possible actions for a RSA key: Sign Encrypt Authenticate 
Current allowed actions: Sign Encrypt

 (S) Toggle the sign capability
 (E) Toggle the encrypt capability
 (A) Toggle the authenticate capability
 (Q) Finished

Your selection? S

Possible actions for a RSA key: Sign Encrypt Authenticate 
Current allowed actions: Encrypt

(S) Toggle the sign capability
 (E) Toggle the encrypt capability
 (A) Toggle the authenticate capability
 (Q) Finished

Your selection? E

Possible actions for a RSA key: Sign Encrypt Authenticate 
Current allowed actions:

(S) Toggle the sign capability
 (E) Toggle the encrypt capability
 (A) Toggle the authenticate capability
 (Q) Finished

Your selection? A

Possible actions for a RSA key: Sign Encrypt Authenticate 
Current allowed actions: Authenticate

(S) Toggle the sign capability
 (E) Toggle the encrypt capability
 (A) Toggle the authenticate capability
 (Q) Finished

Your selection? Q
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
 0 = key does not expire
 <n> = key expires in n days
 <n>w = key expires in n weeks
 <n>m = key expires in n months
 <n>y = key expires in n years
Key is valid for? (0) 2y
Key expires at Thursday 05 March 2020 02:30:01 AM IST
Is this correct? (y/N) y
Really create? (y/N) y
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.

sec rsa4096/123EE456
 created: 2017-04-03 expires: 2019-02-02 usage: SC 
 trust: ultimate validity: ultimate
ssb rsa4096/7891EEFF
 created: 2017-04-03 expires: 2019-02-02 usage: E 
ssb rsa4096/6A127E44
 created: 2018-03-05 expires: 2020-03-04 usage: A

Last 2 lines of the output show newly created authentication [A] subkey.

List Keys

To list all the public GPG keys. Give the following command.

$ gpg2 --list-keys

To obtain the key id in LONG (complete) format, use this flag "--keyid-format LONG".

$ gpg2 --list-keys --keyid-format LONG

To list all the private GPG keys.

$ gpg2 --list-secret-keys

All these commands give you the following information about your GPG keys and subkeys.

  • Which algorithm your keys use, e.i rsa.
  • Key size, e.i 4096 bits.
  • Key IDs, e.i 123AB456 (this is the short key id of 8-bytes, in the long format you get the complete key id of 16-bytes).
  • Date of creation.
  • Their usage e.i

    'E'=encryption, 'S'=signing, 'C'=certification, 'A'=authentication.

  • Their expiry date.
  • Their trust level, e.i Ultimate, unknown, etc.
  • Name and Email associated with them that's also known as UID "User ID".

Exporting Keys

Exporting means, to bring out the keys from GPG database so that we may see or store them in files.

If you want to see your GPG key in ASCII characters, then you need to export it to a file by the following command.

$ gpg2 --output public.key --armor --export your.email@example.com

--output: specifies the output file.
--export: to instruct GPG to export your public key.
--armor: to export in ASCII characters.

Similarly, to export a private key directly on the terminal just change one flag.

$ gpg2 --armor --export-secret-keys your.email@example.com

This will ask for your passphrase. Here you may also add the --output flag to put its output in a file as done in the previous command.

Note: Never give/share your private key anywhere. Keep it as secure as you can. The private key is required to decrypt the data encrypted just for you. So, compromising this key may result in security issues whose severity depends on the data you deal with.

Fingerprints

A key can be verified by a number of ways. One such way is to use its fingerprint. The fingerprint is a shorter number (usually expressed as a 40-hexadecimal-digit number) that contains a cryptographically strong hash of the public key.

To see the fingerprint of any GPG key associated with an email. Use this command.

$ gpg2 --fingerprint email@example.com

You can cross check this fingerprint with the person to verify if it is trustworthy.

Now when you have seen and understand your GPG keys. It's time to generate a revocation certificate.

Generating a Revocation Certificate

It is vital to have revocation certificate to declare your keys invalid in case your private key has been compromised or lost. It should be generated as soon as you generate your key pair, not when you need it. So, let's generate it with the following command.

$ gpg2 --output ~/revocation.crt --gen-revoke your.email@example.com
Please select the reason for the revocation: 
 0 = No reason specified
 1 = Key has been compromised
 2 = Key is superseded
 3 = Key is no longer used
 Q = Cancel 
(Probably you want to select 1 here) 
Your decision? 0

It would ask for your confirmation for generating the certificate and the reason for which you are creating this. It is also suggested that you should have revocation certificates for every possibility listed there for maximum flexibility, but for now, you may go for "0: No reason specified".

Now give a comment (I left it empty) and your passphrase. Soon, your certificate is generated. You should keep this as secure and hidden as you keep your private keys. Here is the output.

Enter an optional description; end it with an empty line:
> 
Reason for revocation: No reason specified
(No description given)
Is this okay? (y/N) y
ASCII armored output forced.
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable. But have some caution: The print system of
your machine might store the data and make it available to others!

In order to save this file from unauthorized access, you may immediately put restrictions (if not present by default).

$ chmod 600 ~/revocation.crt

In case you want to revoke your key, then you would have to upload this revocation certificate to a public keyserver (assuming that you have already sent your public key to a keyserver. See below.)

Sending and Importing Keys

Sending:

Why are you using GPG keys in the first place?
Because with GPG you can sign messages or other people can encrypt messages to you.

Therefore, to make your key publicly available might be of great help. So that, anyone can take your public key to encrypt messages to you. For this, we can send our public key to a keyserver.

Would it be safe to upload your public key on keyservers?
Absolutely yes, as I have already mentioned before that GPG works on asymmetric cryptography, therefore having your public key to someone doesn't make a threat to your security. Because it is practically impossible to generate a private key from a public key.

There are multiple keyservers available to hold public keys like, keys.fedoraproject.org, keyserver.ubuntu.com, etc. and they regularly synchronize among themselves. So if you send your key on keyserver.ubuntu.com, then after some time, it would also be available at keys.fedoraproject.org.

To send your key to the keyserver use the following command.

$ gpg2 --send-keys --keyserver keyserver_url key_id

If you don't want to upload your key to a keyserver (in case your communication is limited to a group of people) then you can also send your public key to them through email.

Importing:

Importing means to include the key in your GPG database, so that you may use them in future. For example, if you wanna send your friends an encrypted message, which can be done with their public keys. Therefore, first, you would need to import their keys into your GPG system and then only you may use them for encryption.

You can import the key of someone from a file, with the following command. For this, you must have their public key in a file say "their_gpg.key".

$ gpg2 --import their_gpg.key

Now when you would list-keys with "gpg2 --list-keys", this imported key will also be listed.

But if the person's key is available at a keyserver, then you can also directly pull their keys from there. Because keyservers distribute public keys to anyone who requests them. Once you have sent your key to a keyserver, others can request your key using the command.

$ gpg2 --keyserver keyserver_url --recv-keys key_id

To refresh all your keys from a keyserver, to obtain new signatures, new UIDs and new key revocations, use this.

$ gpg2 --refresh-keys

And to pull from specific servers, use this.

$ gpg2 --keyserver keyserver_url --refresh-keys

You should do this regularly. But you may receive error messages if any of your keys cannot be found on the key server.

Signing Keys

A major benefit of GPG is that you can sign a file to prove that it is genuinely coming form you. Because signs are created using private keys and only the person who owns the GPG keys, have its private key (if not compromised or lost).

Your key is already signed by you when it was created. That you may verify with.

$ gpg2 --list-sig your.email@example.com

In the output, the line after "sig" shows the UID of those people who have signed your key.

You can also sign keys of other people (assuming that you have already imported the key of that person). Signing a key means you verify that you trust the person, who they claim to be. If you sign a person's key then sending the signed key back to him/her is a good idea, otherwise, they won't be able to take advantage of your sign. For this, you have 2 methods.

Method 1:

$ gpg2 --sign-key person.email@example.com
$ gpg2 --output ~/signed.key --sign-key person.email@example.com

Then you can send this "signed.key" file to the person via mail.

Once that person receives your signed key, then s//he can update their own GPG database to include your signature.

$ gpg2 --import signed.key

Method 2:

$ gpg2 --sign-key person.email@example.com
$ gpg2 --keyserver key_server --send-key person_keyid

This will directly upload your sign to the keyserver (assuming that the person has sent his key to a keyserver). So when next time that person would refresh his/her GPG database, your sign would be included.

Why should you sign a person's key?
Because this can help other people decide whether to trust that person too or not. If someone trusts you, and they see that you've signed this person's key, they may be more likely to trust their identity too. There is a concept behind signing a key known as
Web of Trust.** (see below)

Trust Levels and Validity

Trust levels is a medium by which we can inform GPG that how much we trust a UID of a person associated with a key.

There are following trust levels available

  • Unknown: This is the default level that is set on validity and trust.
  • Undefined: This is explicitly defining trust level to be unknown. Means you would like to confirm it later on.
  • Never: This indicates that you do not trust the UID of that key.
  • Marginal: This means you have half trust on the UID of that key.
  • Full: This means you fully trust that person.
  • Ultimate: There is only one UID that is marked with Ultimate trust, and that is of yourself.

More detail about trust-levels is available here.

You may check the trust and validity levels of any UID among the keys you have imported, with this command.

$ gpg2 --edit-key email@example.com
gpg (GnuPG) 2.1.11; Copyright (C) 2016 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

pub rsa2048/4A5N1031
 created: 2016-10-10 expires: 2018-10-10 usage: SC 
 trust: unknown         validity: unknown
sub rsa2048/73E6DB92
 created: 2016-10-10 expires: 2018-10-10 usage: E 
[ unknown ] (1). Person Name email@example.com

gpg: Q

To modify trust of the key, enter "trust" instead of "Q" (in the last line of output). And you'll get a prompt like this.

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

 1 = I don't know or won't say
 2 = I do NOT trust
 3 = I trust marginally
 4 = I trust fully
 5 = I trust ultimately
 m = back to the main menu

Your decision? m

Enter your decision, and that trust level would be set for that key.

Why do we have trust levels?

To understand this, first, you must understand validity. When you sign a key, you say that the key is valid. But you sign a key if and only if you are sure, that the key belongs the person whose UID is attached to the key. This verification could be done by personally contacting that person and cross-checking the fingerprint of the key.

Isn't it a tedious task to every time contacting people just to confirm the fingerprint of their GPG key? Especially, in the case when you haven't met that person before. Therefore, we have something called "Web of Trust".

Suppose you trust "Mike" and "John" that they sign GPG keys of other people only after completely verifying a UID. Then giving following Trust-levels to them would affect your key as follows.

  • Unknown/Undefined to Mike: Keys signed by Mike won't be valid for you.
  • Never to Mike: Same as above, but here you have explicitly given that you don't trust Mike.
  • Marginal to Mike: Keys signed by Mike will be marginally valid for you.
  • Marginal to Mike and John: Keys signed by both Mike and John will be valid for you (if the marginal limit is set to 2, otherwise if the marginal limit is set to "n" then a key becomes valid if it is signed by "n" UIDs).
  • Full to Mike: Keys signed by Mike will be valid for you as well.

I recommend you to read this document to get a better understanding of trust-levels and validity.

Encryption-Decryption with GPG

Encrypting a file

To encrypt and sign a file for a recipient you must have his/her public key imported.

$ gpg2 -r email.of.recipient@example.com -r your.email@example.com --encrypt --sign --armor file_name
  • gpg2: command
  • -r: to give email_address to possible recipients (who can decrypt this file).
  • -r: adding yourself as one of the recipients so that you can also decrypt the file otherwise after encrypting, even you won't be able to decrypt it.
  • --encrypt: instructing to encrypt.
  • --sign: instructing to sign the file as well.
  • --armor: to encrypt in ASCII characters. 
  • file_name: complete path of the file, If you omit this part, then after giving this command, the terminal will wait for you to enter the text. When you are done with entering your message, press CTRL + d (Linux). It would generate the encrypted form of your message, which you may copy to clipboard and paste in any file.

If you haven't set any trust level for that recipient, then you are likely to get here a confirmation prompt for using the recipient's public key for encryption. And finally, it would prompt you for your passphrase.

Soon an encrypted file would be created with .asc extension. But still, that unencrypted file is available. You are yourself responsible to delete the original file.

Decrypting a file

To decrypt a file that was encrypted by your public key just use.

$ gpg2 file_name.asc

It would ask for your passphrase and a decrypted file would be available to you without ".asc" extension.

If the encrypted file was also signed by the sender, then the output of above command would also give information about signature like date_of_signature and status_of_signature (good or bad) otherwise not.

Signed messages

Clearsign:

Using GPG you may send signed files without encryption. Create a file say "newfile", add some message to it and sign it.

$ echo "Hello World" >> newfile
$ gpg2 --clearsign newfile

--clearsign: wraps the message without encryption with your armored signature, so that any non-GPG user can read the message and any GPG user can verify it (if needed).

Soon "newfile.asc" would be created and anyone can verify, that it is signed by you.

$ gpg2 --verify newfile

But it can give you warning of not having a detached signature.

gpg: WARNING: not a detached signature; file 'newfile' was NOT verified!

(if yes, see below)

Detached signature:

Till now newfile.asc consisted both unencrypted message and signature in the same file. To solve this issue, we can sign a file with a detached signature so that the file and the signature can be kept separately.

$ gpg2 --detach-sign newfile

Now a new file with name "newfile.sig" is created which contains just your signature. You may verify that with.

$ gpg2 --verify newfile.sig

This will return verification statement and signature's information, together with the attached file's name. Now, if you change the file's (newfile) content and again check for verification, then it would fail. Because the new content wasn't signed by the signer. This way GPG maintains "Integrity".

In case the signature verification failed, then understand that the content of the message has been modified in between.

Integrated with GPG

Thunderbird

You can use an email client like Thunderbird to automatically encrypt and sign your emails. For this, you would need to install an addon "Enigmail" in your Thunderbird and configure it. To configure Thunderbird proceed as follows.

  • Open Thunderbird.
  • From Menu Bar -> Tools -> Add-ons, install Enigmail.
  • From Menu Bar -> Enigmail -> Setup Wizard, configure it.
  • Choose Standard Configuration then Next.
  • Now Select your GPG key and Complete the wizard.

Now whenever you would send any mail to the email ID that you have already imported in GPG, your Thunderbird will itself encrypt it. You may explore more configuration options at Menu Bar -> Enigmail.

Github and Git

You can add your GPG key to your GitHub profile and can configure your Git to sign your commits. Follow these steps or refer this.

To add your key to Github:

  • Login to your Github account.
  • At upper-right corner, click your profile photo and select Settings.
  • From left panel select SSH and GPG keys.
  • Click on New GPG key button.
  • Paste your GPG public key there.
    You can export your GPG public key to your terminal with
    \$ gpg2 --armor --export
    Select your complete GPG public key and CTRL + SHIFT + C to copy.

To configure git with GPG key:

  • \$ gpg2 --list-keys --keyid-format LONG
  • Copy your complete key ID.
  • \$ git config --global user.signingkey your_key_id

Now to sign your commits you may use -S flag in your git commit command.

$ git commit -S -m "commit message"

You will be prompted to enter your passphrase while making commits.

A Brief Comparison of GPG and GPG2

  • GPG2 is extended version of GPG. Where changes are mostly in internal levels, thus commands are same.
  • A major change between GPG and GPG2 is that all the crypto operations have been moved to the GPG agent, so without an agent, GPG2 can't work.
  • man gpg2 command gives the following statement "In contrast to the standalone version gpg, which is more suited for server and embedded platforms, this version is commonly installed under the name gpg2 and more targeted to the desktop as it requires several other modules to be installed."
  • An important change came with GPG 2.1, which combines the formerly separated public and private keyrings (pubring.gpg and secring.gpg) into the public keyring.
  • Explore more about what's new in GPG2 here.

Conclusion

GPG is a recommended tool if you don't want to compromise security in your communication with people over an unsecured network like our Internet.

Regardless whether you are sending a sensitive information or a friendly message, using GPG keys is extremely helpful to verify that the author of the message is genuine. Thanks for reading, and in case of a query or suggestions to improve this post, please feel free to write in the comments section below.

© The Geeky Way. Built using Pelican. Theme by Giulio Fidente on github.

Disclaimer Privacy policy