Gpg and Digital Signatures

A brief introduction to GPG, a utility for encryption.

security linux

Introduction

Getting software off the internet is great, until you’re not getting it from the actual distributor. Being able to securely transmit data and verify the entity you’re receiving it from is a major issue that is solved by PKI (Public Key Infrastructure).

GPG (GnuPG) is a utility that is based on OpenPGP (Pretty Good Privacy) which is an encryption standard for signing and encrypting data.

So basically we’re able to sign, encrypt, decrypt data with gpg. Unlike SSL/TLS, there are no “Authorities” that you put your trust in by default, rather, a “web of trust”. I might generate a key pair and stating it belongs to me, but you might not trust me. You may trust a friend of mine who signed my key, if not, you can always trust a friend of his and so on. Key Signing Parties are events that people coming together in person with their legal documents stating their identity and then proceed to sign other people’s keys and getting theirs signed.

gpg key pairs are used to identify a person. Private keys are kept in secret, public ones shared to anyone to be communicated with. A message signed by private key can only be encrypted by the corresponding public key, and vice versa. This is called asymmetric encryption, in contrast to symmetric encryption, where a single key is used to encrypt and decrypt data.

gpg keys come with a bundle where the person has a primary and subordinate key pairs. To make the key management easy this bundle is just called a key pair.

Generating a GPG key pair is fairly simple:

gpg --full-gen-key

gpg (GnuPG) 2.4.4; Copyright (C) 2024 g10 Code GmbH
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
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
   (9) ECC (sign and encrypt) *default*
  (10) ECC (sign only)
  (14) Existing key from card

For most use cases, the default option which is Elliptic Curve Cryptography should suffice.

Please select which elliptic curve you want:
   (1) Curve 25519 *default*
   (4) NIST P-384
   (6) Brainpool P-256

Proceeding with the default:

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) 3y

You should choose a expiration date greater than zero, but you can always update this later as well for the key.

Now, you have generated a gpg key pair for yourself! Which is visible with gpg --list-keys

Digital Signatures

Now that we have key pair, we can start to sign any kind of message we’d like.

echo "Some important message" > message.txt

Now, at a later point in time, we’ll want to make sure of this messages integrity. Thus, let’s get the hash of the file as well:

sha256sum message.txt

31d1104978e7f73a0da6375f1b0d9add90bf96fbc5ef4dc9fb16804697ef2894  message.txt

The process of digitally signing messages includes hashing the content and then encrypting this hash with the private key. If one trusts my public key belongs to me, they will be able to verify that this message belongs to me and has not been tampered with.

Signing a message

gpg --sign message.txt will produce a message.txt.gpg. The message is compressed then signed, this signature file is in binary format and includes the message signed.

The signature can be verified with gpg --verify message.txt.gpg

Clearsign

Another way of signing a message is clearsign:

gpg --clearsign message.txt which outputs the signature in ASCII armored plaintext format, thus the .asc extension. This doesn’t compress the message and is in human readable format.

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

S1ome important message
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQRBrsRfnEkrg1+zF5+Om9gJHQccpwUCZsL1FgAKCRCOm9gJHQcc
p1AXAQCgkI3FykZdG1S1+X5lejmjMRFCuEkKVniMKNXZIFZjLgD/S/WrpuLA2Q0t
D17oNhH13r5v5c9j0lpfMfhrEJS8awc=
=G5hr
-----END PGP SIGNATURE-----

Detached signatures

The previous 2 signatures include the actual message within the signature. There is this 3rd method where the signature does not include the messsage, meaning you would need the actual message content as well in order to verify the message. This is created with:

gpg --detach-sign message.txt which outputs message.txt.sig. Now, with message.txt and message.txt.sig at hand, the signature can be verified: gpg --verify message.txt.sig message.txt

gpg: Signature made Mon 19 Aug 2024 10:00:40 AM +03
gpg:                using EDDSA key 41AEC45F9C492B835FB3179F8E9BD8091D071CA7
gpg: Good signature from "Teoman Yuksel <root@teoman.sh>" [ultimate]

Try to change the content of message.txt and then verify the signature.

gpg: Signature made Mon 19 Aug 2024 10:00:40 AM +03
gpg:                using EDDSA key 41AEC45F9C492B835FB3179F8E9BD8091D071CA7
gpg: BAD signature from "Teoman Yuksel <root@teoman.sh>" [ultimate]

gpg will no longer verify the signature.

Conclusion

gpg is a great tool utilizing PKI in the real world making possible secure communication that is still used by masses today.