GPG 101

What is gpg??

What is gpg2 : GnuPG is a complete and free implementation of the OpenPGP standard as defined by RFC4880 (also known as PGP). GnuPG allows you to encrypt and sign your data and communications; it features a versatile key management system, along with access modules for all kinds of public key directories. GnuPG, also known as gpg2, is a command line tool with features for easy integration with other applications. A wealth of frontend applications and libraries are available. GnuPG also provides support for S/MIME and Secure Shell (ssh). gpg2 uses the method of “public” and “private” keys for the encryption and signing of messages or data.

Why we need gpg??

gpg2 is an excellent method to ensure secure communication between two parties. It allows sensitive information to be easily shared across an insecure network.

Assymetric Encryption

Asynchronous key cryptography uses public and private keys to encrypt/decrypt messages. This is called asymmetric encryption. It allows you to send or publish your public key out in the open on an insecure network. The party looking to send you a secure message uses your public key to encrypt a message using that key. The message is then sent to you where you then use your private key to decrypt it. You can then reply using the sender’s public key which allows you to securely encrypt messages to them. They then use their private key to decrypt messages encrypted by you.

Daily use cases for gpg

  • Encrypt and sign email
  • Back-up data to commercial clouds for long term encryption at rest
  • Transfer secrets between devices
  • Password manager
  • Random password generation
  • File encryption on USB
  • Signing software and documents; integrity check from user’s side
  • Passing authentication for various applications and API tokens to GPG keys stored on hardware keys (using Pass password manager)
  • Authentication into SSH servers, desktop computers, possibly phones, etc
  • Flexible authentication of TLS/SSL communications using Monkeysphere utilities and the standard tools such as web browser or SSH
  • Authentication for groups via OpenPGP CA

Installation

# Installation is very basic, you need to install a gnupg package from your os pkg manager.

# Ubuntu/Debain
$ sudo apt install gnupg
$ sudo apt install gnupg2

# Arch
$ sudo pacman -S gnupg / gnupg2

# Set Permission on ~/.gnupg folder
$ find ~/.gnupg -type d -exec chmod 700 {} \;
$ find ~/.gnupg -type f -exec chmod 600 {} \;

Create a Key Pair

## Primary Key Generation

# Secure Encryption keys ( As per community )
  # 1.0 RSA 4096
  # 2.0 ED25519

================================================================================================
RSA 4096 Key
================================================================================================
$ gpg2 --full-generate-key
# Choose Default RSA and RSA
# Key Size 4096
# Enter Details
# Type a Secure Passphrase

# You successfully create a RSA 4096 Key

================================================================================================
ED25519 Key
================================================================================================

$ gpg2 --expert --full-generate-key
# Select Option 9 : ECC and ECC
# For Elliptic Curve : Curve 25119
# Set expiry and details
# Enter Passphrase

# You Successfully create a ED25519 Key

----

## To List keys

# List public Keys
$ gpg2 --list-keys --keyid-format LONG
pub   rsa4096/C4BF71D56499C98D 2020-11-12 [SC]
      37A28886D3E92661AD0242EFC3BF71D56499C98D
uid   [ultimate] test-user <hi@example.com>
sub   rsa4096/0A9B69E6C4BF2378 2020-11-12 [E]

# List Private Keys
$ gpg2 --list-secret-keys --keyid-format LONG
sec   rsa4096/C3BF71D56499C98D 2020-11-12 [SC]
      37A38886D3E92661AE0242EFC3BF71D56499C98D
uid   [ultimate] test-user <hi@example.com>
ssb   rsa4096/0A9B69E6C4BF2369 2020-11-12 [E]

----

## To Delete keys

# Delete Private Key
$ gpg2 --delete-secret-keys {keyID}

# Delete Public Key
$ gpg2 --delete-keys {keyID}

Create a Sub Key

What is a subkey?

Subkeys are like the normal keys, except they're bound to a master key pair. A subkey can be used for signing or for encryption. The really useful part of subkeys is that they can be revoked independently of the master keys, and also stored separately from them. In other words, subkeys are like a separate key pair, but automatically associated with your main key pair. GnuPG actually uses a signing-only key as the master key, and creates an encryption subkey automatically. Without a subkey for encryption, you can't have encrypted e-mails with GnuPG at all.

What is a use case for subkey?

  • Primary Key: Keep safe your primary key in safer place ( Don't put it your Laptop/PC ). That makes your primary key very inconvenient to use. To ease the process we use subkeys.

  • Subkey: For Day to Day operations, we need a key that is not such a big problem to replace if it gets compromised. A subkey is still a public/private key pair and is secure as long as only you have the private key. It is, cryptographically, just as secure as your primary key. The difference is that your reputation is only attached to it by your own signature, the signature from your private key. Subkeys make key management much easier by separating the cryptographic functions of public keys from the trust and identity functions of (primary) public keys. That's why we use subkeys.

Create a Subkey Pair


$ gpg2 --expert --edit-key {key--id}
> addkey
> Option 11 : ( ECC ( Set your own capabilities ))
> 1. (A) Toggle the authenticate capability
> 2. (S) Toggle the sign capability
> 3. (Q) Finished
# Elliptic Curve : Curve 25519
# Add a passphrase and other details
> save

Backup & Restore Keys

# Backup Public Key
# --armor = ASCII Version of Key
$ gpg2 --export --armor --output user--ED25519--public.key {fingerprint-without-space}

# Backup Private Key
$ gpg2 --export-secret-keys --armor --output user--ED25519--private-key.asc {fingerprint-without-space}

---

# Restore/Import Public Key
$ gpg2 --import user--ED25519--public.key

# Restore/Import Private key
$ gpg2 --import user--ED25519--private-key.asc

# Backup Subkey
  # list subkey fingerprint
  $ gpg2 --list-secret-keys --with-subkey-fingerprint

  # Export Private Key
  $ gpg2 --armor --export-secret-keys {fingerprint}! > user--private--subkey-ED25519.asc

Revocation Certificate

This certificate can be used to revoke a key if it is ever lost or compromised. The backup will be useful if you have no longer access to the secret key and are therefore not able to generate a new revocation certificate with the above command. It is short enough to be printed out and typed in by hand if necessary. So if your key is compromised, superseded, no longer used, or you forget your passphrase. This is done by merging the key with the revocation certificate of the key.

If you have no longer access to your keypair, first #Import a public key to import your own key. Then, to revoke the key, import the file saved in #Backup your revocation certificate:

# Create a Revoke Cert
$ gpg2 --gen-revoke --armor --output user--ED25519--revert.asc {key-fingerprint}

# Import to Revoke a Key
$ gpg2 --import user--ED25519--revert.asc

Encryption/Decryption

  • Asymetric Encryption
Asymetric Encryption: A public-private key pair is used to encrypt-decrypt the data

# Encryption
$ gpg2 --armor --recipient {fingerprint} --encrypt {file}

# Decryption
$ gpg2 --output {output file} --decrypt {encrypted file}
  • Symmetric Encryption
Symmetric Encryption: Single key is used for encryption and decryption

# Encryption:
  # Encrypts file with a symmetric cipher using a passphrase
  # Uses the AES-256 cipher algorithm to encrypt the passphrase
  # Uses the SHA-512 digest algorithm to mangle the passphrase
  # Mangles the passphrase for 65536 iterations

# Encrypt a file
$ gpg2 -c --s2k-cipher-algo AES256 --s2k-digest-algo SHA512 --s2k-count 65536 {file}

# Encrypt a folder
$ gpgtar -c -o {dir.gpg} {dir}

# Decrypt a file
$ gpg2 --output {file} --decrypt {file.gpg}

# Decrypt a folder
$ gpgtar -d {dir.gpg}

Key Server

# Two Main key Servers
- https://keys.openpgp.org/
- https://pgp.mit.edu

# Sending Keys to Server ( https://keys.openpgp.org/ )
$ gpg2 --send-keys {fingerprint=keyId}

# Search Keys on Server
$ gpg2 --search-keys {keyId}

# Import a key from Key Server
$ gpg2 --recv-keys {keyID}

Day To Day Guide With GPG

Enable SSH Access Using a GPG Key for Authentication

# Note: For this we need a authentication subkey ( create a subkey with authentication ability )

# 1.0 Create a gpg-agent.conf ( ~/.gnupg/gpg-agent.conf )
pinentry-program /usr/bin/pinentry-curses
default-cache-ttl 600
max-cache-ttl 7200
enable-ssh-support

# 2.0 Create a gpg.conf ( ~/.gnupg/gpg.conf )
use-agent

# 4.0 SSH config file ( ~/.ssh/config )
Host
ForwardAgent yes
AddKeysToAgent ask
Match host * exec "gpg-connect-agent UPDATESTARTUPTTY /bye"

# 3.0 Add pubkey to server
$ gpg2 -K --with-keygrip

# Copy keygrip of your authentication key & put it in ~/.gnupg/sshcontrol
$ echo 6299DB7B753D6D14B3B23CE5M824D0F5DC01B639 >> ./sshcontrol

# Push KEY to server
$ ssh-add -L >> authorized_keys
$ scp authorized_keys user@ip:.ssh/

# 5.0 To Lauch gpg agent automatically
# Add this to ~/.bashrc || ~/.zshrc

export GPG_TTY=$(tty)
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
gpgconf --launch gpg-agent

$ source ~/.bashrc

# Now you are able to login to server with your gpg key,
# I use pinentry-curses as for my password entry program, if you want another pinentry ( as below in image ), you can change it.

SSH Access


Use GPG for Minimal Password Manager

Pass: Password management should be simple and follow Unix philosophy. With pass, each password lives inside of a gpg encrypted file whose filename is the title of the website or resource that requires the password. These encrypted files may be organized into meaningful folder hierarchies, copied from computer to computer, and, in general, manipulated using standard command line file management utilities.

pass is a simple password manager for the command line. pass is a shell script that makes use of existing tools like GnuPG, tree and Git.

# Here, I use linux server to host pass ( bare repo ), so i can access my passwors an any machine ( If you don't have any linux server or pi running, no problem: you can use pass on your machine )

---------------------------------------------------------------------------------
# On server create a bare git repo
$ git init --bare ~/.password-store

---------------------------------------------------------------------------------
# On client
# Install pass as per your distro ( for eg: Ubuntu )
$ sudo apt install pass

# Note: Before proceding add a pasword less authentication between client and Server

# Intialize pass repo
$ pass init {KEY_ID}
$ pass git init

# Insert some dummy username/password
$ pass insert NAS/username
$ pass insert NAS/password

$ pass
Password Store
└── NAS
    ├── password
    └── username

# To access a password
# -c will automatically copy your password to clipboard
$ pass -c NAS/password

# Tip: You can also generate a password with pass
$ pass generate NAS/password
[master be5fbe4] Add generated password for NAS/password.
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 NAS/password.gpg
The generated password for NAS/pass is:
>g+vayxKMMuc1a1e7{Yhn[d3

# Add Remote Origin
$ pass git remote add origin user@ip:~/.password-store

# Push your passwords to Remote Repo
# To check status of files
$ pass git status

$ pass git push -u --all

----------------------------------------------------------------------------------
# On 3rd Client
# Newly setup machine: You want all of you password and usernames

# 1.0 Import your gpg keys
# 2.0 Add trust level :
$ gpg2 --edit-key {Key-id}
> trust
  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

Select Trust ( 5 )
> quit

# Check with
$ gpg2 -K

# Note: If you don't add trust to your keys, you will see error like this: There is no assurance this key belongs to the named user

# 3.0 Clone the your password repo to your new machine
$ git clone user@ip:~/.password-store
$ pass
Password Store
└── NAS
    ├── password
    └── username

Use GPG To Sign Your Commits and Tags

Note: Before moving further put your GPG public key to github ( user → settings → SSH & GPG Keys → Add your key)

  • Benfits of using GPG Key with Github
    • Signed Commits
    • Signed Tags

Signed Commits

# Add Signed Option + Signin KEY to your global git config

# To get signing key
$ gpg --list-secret-keys --keyid-format LONG

$ git config --global --edit
[user]
  name = user
  email = user@example.com
  signingKey = E6A95651901C42B317FD4B4AEA67ED6F75A98
[commit]
  gpgsign = true

# Cli option
git config --global user.signingKey {REPLACE_THIS_WITH_YOUR_KEY_ID}
git config --global commit.gpgSign true

# To sign commits
$ git commit -S -m "Message"

# Note: if you don't want to add the "-S" argument every time you commit you can edit the Git local configuration (git config --local --edit or git config --local commit.gpgsign true).

# To sign tags
$ git tag -s -m "Message"

# To check a tag
$ git tag -v tag_name

Use GPG To Manage Secrets In Your Code

SOPS: sops is an editor of encrypted files that supports YAML, JSON, ENV, INI and BINARY formats and encrypts with AWS KMS, GCP KMS, Azure Key Vault and PGP.

# Install SOPS as per your distro

# For eg: ubuntu
$ wget https://github.com/mozilla/sops/releases/download/v3.6.1/sops_3.6.1_amd64.deb
$ sudo dpkg -i ./x.deb

# Export the fingerprints of the public keys, comma separated, in the SOPS_PGP_FP env variable
$ export SOPS_PGP_FP="Key_ID1, Key_ID2"

# Ex: I encrypt a YAML file in this ex
---docker-compose.yml
version: '3.1'

services:
  mongo:
    image: mongo
    container_name: 'mongo_db'
    restart: always
    ports:
      - 27017:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password
    volumes:
      - /home/containers/mongodb/data:/data/db

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: password
---

# Encrypt
$ sops --encrypt --in-place --encrypted-regex 'PASSWORD|USERNAME' docker-compose.yaml

# Encrypted Version
---
version: "3.1"
services:
    mongo:
        image: mongo
        container_name: mongo_db
        restart: always
        ports:
        - 27017:27017
        environment:
            MONGO_INITDB_ROOT_USERNAME: ENC[AES256_GCM,data:c7k+xQ==,iv:9eKifn+qiIvNIY0XwNnbwQ3+YZGiEnL34dRrQlZaynw=,tag:RnYRGtUJQql1hRH/9YIJ+Q==,type:str]
            MONGO_INITDB_ROOT_PASSWORD: ENC[AES256_GCM,data:Eux1tMJzmK0=,iv:DAAvQBqblAtyQk7rZ1wR6JqinQ7/Vc4fg3oHApuRK6M=,tag:OyzXV+wr29YH8p1EE692Xw==,type:str]......
---

# Decrypt
$ sops -d -i ./docker-compose.yaml

# for further, read the docs - https://github.com/mozilla/sops

Use GPG To Sign Your Documents

# Ex: You have a file config.txt

# Create a Signature
$ gpg2 --output config.txt.sig --detach-sig config.txt

# Verify a Signature
$ gpg2 --verify config.txt.sig config.txt

# Note: If both the files in same dir, than you can also run gpg2 --verify config.txt.sig

Use GPG as Random Password Generator

$ gpg2 --gen-random --armor 1 17
dZnN99cpvfy2zf/q6UCvE7c=