GPG
General commands
Generate a new key pair
# Generate a new key pair
gpg --full-generate-keyList keys
# List keys
gpg --list-keys
# List secret keys
gpg --list-secret-keys
# List secret keys long format
gpg --list-secret-keys --keyid-format=long
# Will give you something like this (depending on your GPG version):
# Version 1 (with key ID on a separate line):
# pub rsa3072 2024-10-01 [SC] [expires: 2027-10-01]
# 3F7C5A1C9D8E6B2E34B673EB9F1A3B72A6D4C7F1
# uid [ultimate] Random User <random.user@example.com>
# sub rsa3072 2024-10-01 [E] [expires: 2027-10-01]
#
# - Primary key ID: The full fingerprint is `3F7C5A1C9D8E6B2E34B673EB9F1A3B72A6D4C7F1`
# - The primary key ID used for encryption is the last 8 characters: `A6D4C7F1`
# - Subkey ID (used for encryption): appears on the sub line, which will also have its own ID.
# Version 2 (with the `/` format):
# sec rsa3072/A6D4C7F1 2024-10-01 [SC] [expires: 2027-10-01]
# 3F7C5A1C9D8E6B2E34B673EB9F1A3B72A6D4C7F1
# uid [ultimate] Random User <random.user@example.com>
# ssb rsa3072/B9F1C3D2 2024-10-01 [E] [expires: 2027-10-01]
#
# - Primary key ID: `A6D4C7F1` (after the `/` on the `sec` line).
# - Subkey ID: `B9F1C3D2` (after the `/` on the `ssb` line).
# - Full fingerprint: The full fingerprint of the primary key is still `3F7C5A1C9D8E6B2E34B673EB9F1A3B72A6D4C7F1`.
# Export a public key (using primary key ID or fingerprint)
# e.g. gpg --armor --export A6D4C7F1
gpg --armor --export <key-id>
# Export a private key
gpg --armor --export-secret-keys <key-id>
# Encrypt a file
gpg --encrypt --recipient <key-id> <file>
# Encrypt a file with ASCII armor (base64) instead of binary
gpg --encrypt --armor --recipient <key-id> <file>
# Decrypt a file
gpg --decrypt <file>Edit a key
# Edit a key
gpg --edit-key <key-id>
# Add email
gpg adduid
# Delete email
gpg uid <old-email-address>
gpg deluid
# Set trust level
gpg 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 ultimatelyReload or restart the GPG agent
# Reload the GPG agent
gpg-connect-agent reloadagent /bye
# Restart the GPG agent
gpgconf --kill gpg-agent
gpg-connect-agent /byeUsing GPG with Git
Pinentry
Install on MacOS
brew install pinentry-mac
# or
sudo port install pinentry-mac
echo "pinentry-program $(which pinentry-mac)" >> ~/.gnupg/gpg-agent.conf
killall gpg-agentWhich will add the folowing lines in your ~/.gnupg/gpg-agent.conf:
# ~/.gnupg/gpg-agent.conf
# if you're using Homebrew
pinentry-program /usr/local/bin/pinentry-mac
# if you're using MacPorts
pinentry-program /Applications/MacPorts/pinentry-mac.app/Contents/MacOS/pinentry-macSet up GPG with Git
# Set up GPG with Git
git config --global user.signingkey <key-id>
git config --global commit.gpgsign trueEmail address and signing commits on GitHub
When creating a new key and being asked for an email address, it can be a fake one, but then it will be more difficult to use it for signing commits on GitHub.
From ChatGPT:
The fake or placeholder email linked to your GPG key doesn't introduce any direct security risks, but there are a few points you should consider, especially when pushing commits to a public repository:
1. Email in GPG Key and Commit Verification:
Email Doesn't Need to Be Real: Technically, the email associated with a GPG key doesn't need to be real. You can use a placeholder or a "fake" email (e.g., no-reply@example.com), and the key will still work for encryption and signing commits.Commit Signing and GitHub: If you sign commits with GPG and push to a public GitHub repo, GitHub will display a verified badge if the GPG key is associated with your GitHub account. However, GitHub matches this based on the email tied to the GPG key, so if you use a fake or unrelated email, GitHub will not recognize the key, and your commits will not show as verified.
2. Implications of Using a Fake Email:
Commit Verification: If your goal is to ensure your commits are recognized as verified (for security, authenticity, or trust), you should use a real email address that is linked to your GitHub account. If you use a fake email, GitHub won’t recognize it, and the commits won’t be marked as “verified.”Trust and Authenticity: If you're contributing to a public project or repository, others might expect that your commits are verified and associated with your real identity. Using a real email ensures that other developers can trust the authenticity of the commits.
Public Exposure: If you’re worried about exposing your real email address in public commits (to avoid spam or for privacy reasons), you can use GitHub’s noreply email address. GitHub provides an option to hide your real email in public commits:
Example: username@users.noreply.github.com. You can set this up in your GitHub settings under Emails → Keep my email address private.
(TODO: WIP) Automation environment / use in a CI/CD pipeline
If you're using GPG in an automation environment, you have a few options:
1. "loopback" mode and Pinentry
In an interactive shell and/or automation environment, it can be useful to use the loopback mode to avoid the Pinentry prompt. This means that the passphrase will be asked directly from the calling application (like a terminal) instead of using a GUI prompt.
In the ~/.gnupg/gpg-agent.conf (to create or edit) add:
# ~/.gnupg/gpg-agent.conf
allow-loopback-pinentryThen reload or restart the GPG agent:
gpg-connect-agent reloadagent /byeINFO
You should normally already have it but in case check your ~/.gnupg/gpg.confthat should contains:
# ~/.gnupg/gpg.conf
use-agent
pinentry-mode loopbackTo cache the passphrase for a certain amount of time, you can add the following to the ~/.gnupg/gpg-agent.conf:
# ~/.gnupg/gpg-agent.conf
default-cache-ttl 3600 # 1 hour
max-cache-ttl 3600 # 1 hour2. Remove the passphrase
Having a GPG key without a passphrase in an automation environment can be risky, but avoid additional complexity configuration
# Remove the passphrase
gpg --edit-key <key-id>
gpg> passwd
# Enter the passphrase
# Enter a blank passphrase for the new oneThen tell git to use the key without a passphrase:
git config --global commit.gpgsign true
git config --global user.signingkey <key-id>