This error occurs when GPG cannot verify a Git commit or tag signature because the signer's public key is missing from your keyring or an unsupported cryptographic algorithm was used. The fix involves importing the required public key from a keyserver or the signer directly.
This error indicates that GPG (GNU Privacy Guard) failed to verify a cryptographic signature on a Git commit or tag. The signature verification process requires two things: the signer's public key in your GPG keyring and support for the cryptographic algorithm used to create the signature. When you run commands like `git verify-commit`, `git verify-tag`, `git log --show-signature`, or `git pull` on a repository with signed commits, Git invokes GPG to check the signatures. If GPG cannot find the public key that corresponds to the private key used to create the signature, it reports "Can't check signature: No public key." The "unavailable algorithm" variant of this error means the signature was created using a cryptographic algorithm that your version of GPG does not support or has disabled for security reasons. This commonly happens with older signatures that used SHA-1 or other deprecated algorithms, or when there's a version mismatch between the GPG that created the signature and yours.
First, find the key ID that GPG is looking for:
# Check the signature on a specific commit
git log --show-signature -1 <commit-hash>
# Or verify a specific tag
git tag -v <tag-name>Example output:
gpg: Signature made Mon Jan 15 10:30:00 2024 UTC
gpg: using RSA key 4AEE18F83AFDEB23
gpg: Can't check signature: No public keyThe key ID is 4AEE18F83AFDEB23. Note this for the next steps.
To see all unverified commits:
git log --show-signature --oneline | grep "Can't check"Use the key ID to fetch the public key from a public keyserver:
# Import from Ubuntu keyserver (most reliable)
gpg --keyserver keyserver.ubuntu.com --recv-keys <KEY_ID>
# Or from keys.openpgp.org
gpg --keyserver keys.openpgp.org --recv-keys <KEY_ID>
# Example with a real key ID:
gpg --keyserver keyserver.ubuntu.com --recv-keys 4AEE18F83AFDEB23Expected output:
gpg: key 4AEE18F83AFDEB23: public key "User Name <[email protected]>" imported
gpg: Total number processed: 1
gpg: imported: 1If the keyserver is unreachable, try alternatives:
# MIT keyserver
gpg --keyserver pgp.mit.edu --recv-keys <KEY_ID>
# keys.gnupg.net
gpg --keyserver hkps://keys.gnupg.net --recv-keys <KEY_ID>When commits are made via GitHub's web interface (editing files, merge buttons, squash merges), GitHub signs them with its own GPG key. Import this key to verify those commits:
# Download and import GitHub's web-flow GPG key
curl https://github.com/web-flow.gpg | gpg --importExpected output:
gpg: key 4AEE18F83AFDEB23: public key "GitHub (web-flow commit signing) <[email protected]>" imported
gpg: Total number processed: 1
gpg: imported: 1For GitLab:
GitLab does not currently sign web commits with a GPG key, so web edits on GitLab will not have GPG signatures.
Verify the import worked:
gpg --list-keys --keyid-format long | grep -A 1 "github"If the signer provides their public key as a file (common in organizations):
# Import from a .asc or .gpg file
gpg --import colleague-key.asc
# Import from a URL
curl https://example.com/team-member.gpg | gpg --importAsk the signer to export their key:
# They run this command:
gpg --export --armor [email protected] > their-public-key.asc
# Then share the .asc file with youFor project-wide keys stored in the repository:
# Some projects store maintainer keys in a KEYS file
gpg --import KEYSAfter importing the key, verify the signature works:
# Verify a specific commit
git verify-commit <commit-hash>
# Verify with detailed output
git log --show-signature -1 <commit-hash>
# Verify a tag
git verify-tag <tag-name>Expected successful output:
gpg: Signature made Mon Jan 15 10:30:00 2024 UTC
gpg: using RSA key 4AEE18F83AFDEB23
gpg: Good signature from "User Name <[email protected]>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!The "WARNING: This key is not certified" message is normal - it means you haven't personally verified and signed the key (Web of Trust). The signature is still cryptographically valid.
Set up GPG to automatically fetch missing keys from keyservers:
# Edit GPG configuration
nano ~/.gnupg/gpg.confAdd these lines:
# Automatically retrieve keys from keyserver
auto-key-retrieve
# Use Ubuntu keyserver by default
keyserver hkps://keyserver.ubuntu.comSave and test:
# Now verification will auto-fetch missing keys
git log --show-signature -1 <commit-with-unknown-key>Note: Auto-retrieval may be slow and can leak information about what you're verifying to the keyserver.
If you see "Signature made with unavailable algorithm" or "Invalid digest algorithm", the signature may use deprecated cryptography:
Check your GPG version:
gpg --versionFor GPG 2.3+ with SHA-1 signatures:
Modern GPG versions may reject SHA-1 signatures. You can temporarily allow them:
# Add to ~/.gnupg/gpg.conf (use with caution)
allow-weak-digest-algosOr verify with a specific flag:
gpg --allow-weak-digest-algos --verify signature.asc fileBetter solution: Contact the signer and ask them to re-sign with SHA-256 or SHA-512:
# Signer should use stronger digest
gpg --digest-algo SHA512 --sign fileFor unsupported key algorithms, you may need to upgrade GPG:
# Ubuntu/Debian
sudo apt update && sudo apt upgrade gnupg
# macOS
brew upgrade gnupg
# Fedora/RHEL
sudo dnf upgrade gnupg2If signature verification isn't critical for your workflow, you can disable or bypass it:
Disable for a single operation:
# Clone without verifying signatures
git clone --config gpg.program=/bin/true https://github.com/user/repo.git
# Pull without verification
git -c gpg.program=/bin/true pullDisable globally (not recommended for security-sensitive work):
# Don't require valid signatures on merge
git config --global merge.verifySignatures false
# Skip tag verification
git config --global tag.gpgSign falseNote: Disabling signature verification removes an important security layer. Only do this if you understand the implications and trust the source through other means.
### Understanding GPG Signature Status Codes
When using git log --show-signature or the %G? format specifier, GPG reports these status codes:
| Code | Meaning |
|------|---------|
| G | Good (valid) signature |
| B | Bad signature |
| U | Good signature with unknown validity |
| X | Good signature that has expired |
| Y | Good signature made by an expired key |
| R | Good signature made by a revoked key |
| E | Cannot check signature (missing key) |
| N | No signature |
# Show status code for each commit
git log --format='%h %G? %s' --show-signature### Trust Levels and the Web of Trust
After importing a key, you may want to set its trust level:
# Edit key trust
gpg --edit-key <KEY_ID>
gpg> trust
# Select trust level (1-5)
# 5 = ultimate trust (for your own keys)
# 4 = full trust (for keys you've verified)
# 3 = marginal trust
gpg> quit### Keyserver Configuration
If you frequently work with signed commits, configure your preferred keyserver:
# ~/.gnupg/gpg.conf
keyserver hkps://keyserver.ubuntu.com
keyserver-options auto-key-retrieve
keyserver-options honor-keyserver-url### Working with Expired Keys
Signatures made before a key expired are still valid. To verify old signatures:
# Check when the key expired
gpg --list-keys <KEY_ID>
# The signature date matters, not current key status
# If signed before expiration, it's still a valid historical signature### Corporate/Enterprise Key Distribution
In enterprise environments, distribute team GPG keys via:
1. Internal keyserver: Host a SKS or Hockeypuck keyserver
2. Git repository: Store team keys in a KEYS file
3. Configuration management: Deploy keys via Puppet, Ansible, or similar
# Import all team keys from repository
git clone internal/team-keys.git
gpg --import team-keys/*.asc### Debugging GPG Issues
For detailed GPG debugging:
# Set debug output
export GPGME_DEBUG=9
git log --show-signature -1
# Check GPG agent status
gpg-connect-agent 'GETINFO version' /bye
# Restart GPG agent if needed
gpgconf --kill gpg-agent
gpgconf --launch gpg-agent### Verifying Signatures in CI/CD
For CI/CD pipelines that verify commit signatures:
# .gitlab-ci.yml example
verify_signatures:
script:
- apt-get update && apt-get install -y gnupg
- gpg --import ${TEAM_GPG_KEYS}
- git verify-commit HEAD# GitHub Actions example
- name: Import GPG keys
run: |
curl https://github.com/web-flow.gpg | gpg --import
gpg --keyserver keyserver.ubuntu.com --recv-keys ${{ vars.TEAM_KEY_IDS }}warning: BOM detected in file, this may cause issues
UTF-8 Byte Order Mark (BOM) detected in file
fatal: Server does not support --shallow-exclude
Server does not support --shallow-exclude
warning: filtering out blobs larger than limit
Git partial clone filtering large blobs warning
fatal: Server does not support --shallow-since
Server does not support --shallow-since in Git
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server