-
Notifications
You must be signed in to change notification settings - Fork 41
Revise GPG commit signing guide for macOS & Windows #361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 17 commits
64d6b81
9ac0b03
d122fe8
71b7899
ab0d3b6
95e4aa2
551e4e3
bffd81b
fe12d50
6851f87
39bd085
d3bb721
88aed16
c073060
504743f
d0c38e0
abeaf15
069f07d
9373fb5
8b2a05b
2ec33a6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,92 +1,202 @@ | ||
| # Git commit signing setup guide | ||
|
|
||
| - [Git commit signing setup guide](#git-commit-signing-setup-guide) | ||
| - [From Workstations](#from-workstations) | ||
| - [macOS](#macos) | ||
| - [Windows](#windows) | ||
| - [From Pipelines](#from-pipelines) | ||
| - [GitHub Actions](#github-actions) | ||
| - [AWS CodePipeline](#aws-codepipeline) | ||
| - [Troubleshooting](#troubleshooting) | ||
| Using GPG, SSH, or S/MIME, you can sign commits and tags locally. These commits and tags are marked as verified on GitHub so other people can be confident that the changes come from a trusted source. | ||
|
|
||
| ## From Workstations | ||
| The instructions on this page focus on GPG and SSH. | ||
|
|
||
| ### macOS | ||
| > You should only set up **one** of these options - **don't attempt to set up GPG and SSH commit signing**! | ||
|
|
||
| - Install the [Brew package manager](https://brew.sh) | ||
| See the full GitHub documentation [here](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification). | ||
|
|
||
| ```bash | ||
| brew upgrade | ||
| brew install gnupg pinentry-mac | ||
| gpg --full-generate-key | ||
| ``` | ||
| ## GPG commit signing | ||
|
|
||
| - Accept the defaults, Curve 25519 etc. | ||
| - Enter your GitHub account name as the Real Name | ||
| - Enter your GitHub account email as the Email Address | ||
| - Avoid adding a comment (this *may* prevent git from auto-selecting a key - see Troubleshooting section below) | ||
| - You can use the privacy *@users.noreply.github.com* email address listed in the GitHub profile: *Settings > Email* | ||
| - Define a passphrase for the key and keep it in your password manager | ||
| ### From Workstations | ||
|
|
||
| ```bash | ||
| gpg --armor --export ${my_email_address} | pbcopy | ||
| ``` | ||
| If you have already committed and need to retrospectively sign commits, follow the instructions below, then follow the [retrospective commit signing instructions](./retrospective-commit-signing.md). | ||
|
|
||
| - Public key is now in your clipboard - in your GitHub account add it to your profile via *Settings > SSH and GPG Keys> Add New GPG Key* | ||
| - Paste it in | ||
| #### macOS | ||
|
|
||
| ```bash | ||
| git config --global user.email ${my_email_address} # same one used during key generation | ||
| git config --global user.name ${my_username} | ||
| git config --global commit.gpgsign true | ||
| sed -i '' '/^export GPG_TTY/d' ~/.zshrc | ||
| echo export GPG_TTY=\$\(tty\) >> ~/.zshrc | ||
| source ~/.zshrc | ||
| PINENTRY_BIN=$(whereis -q pinentry-mac) | ||
| sed -i '' '/^pinentry-program/d' ~/.gnupg/gpg-agent.conf | ||
| echo "pinentry-program ${PINENTRY_BIN}" >> ~/.gnupg/gpg-agent.conf | ||
| gpgconf --kill gpg-agent | ||
| ``` | ||
| 1. Install `gnupg` & `pinentry-mac` with [Brew](https://brew.sh): | ||
|
|
||
| The first time you commit you will be prompted to add the GPG key passphrase to the macOS Keychain. Thereafter signing will happen seamlessly without prompts. | ||
| ```bash | ||
| brew upgrade | ||
| brew install gnupg pinentry-mac | ||
| sed -i '' '/^export GPG_TTY/d' ~/.zshrc | ||
| echo export GPG_TTY=\$\(tty\) >> ~/.zshrc | ||
| source ~/.zshrc | ||
| PINENTRY_BIN=$(whereis -q pinentry-mac) | ||
| mkdir -p ~/.gnupg | ||
| touch ~/.gnupg/gpg-agent.conf | ||
| sed -i '' '/^pinentry-program/d' ~/.gnupg/gpg-agent.conf | ||
| echo "pinentry-program ${PINENTRY_BIN}" >> ~/.gnupg/gpg-agent.conf | ||
| gpgconf --kill gpg-agent | ||
| ``` | ||
|
|
||
| Most of the published solutions for this don't work because *brew* seems to have moved the default folder for binaries, plus many guides contain obsolete settings for *gpg-agent*. | ||
| 1. Create a new GPG key: | ||
|
|
||
| ### Windows | ||
| ```bash | ||
| gpg --full-generate-key | ||
| ``` | ||
|
|
||
| - Install [Git for Windows](https://git-scm.com/download/win), which includes Bash and GnuPG | ||
| - Right-click on the Desktop > *Git Bash Here* | ||
| 1. Pick `RSA and RSA`, or `RSA (sign only)` (there is no elliptic curve cryptography (ECC) support at the time of writing) | ||
| 1. `keysize` `4096` bits (the minimum accepted for GitHub) | ||
| 1. Select a key expiry time (personal choice) | ||
| 1. `Real name` Your GitHub handle | ||
| 1. `Email address` Your GitHub account email [listed on your GitHub profile](https://github.com/settings/emails) (you can use the privacy *@users.noreply.github.com* email address): `Settings` -> `Emails` -> `Keep my email addresses private`) | ||
|
|
||
| ```bash | ||
| gpg --full-generate-key | ||
| ``` | ||
| > If you go for the private email option, consider enabling `Block command line pushes that expose my email`. | ||
|
|
||
| - Pick *RSA and RSA*, or *RSA (sign only)* - there is no elliptic curve cryptography (ECC) support at the time of writing | ||
| - Set key size to 4096 bit, the minimum accepted for GitHub | ||
| - Enter your GitHub account name as the Real Name | ||
| - Enter your GitHub account email as the Email Address | ||
| - Avoid adding a comment (this *may* prevent git from auto-selecting a key - see Troubleshooting section below) | ||
| - You can use the privacy *@users.noreply.github.com* email address listed in the GitHub profile: *Settings > Email* | ||
| - Define a passphrase for the key and keep it in your password manager | ||
| 1. Avoid adding a comment (this *may* prevent git from auto-selecting a key - see Troubleshooting section below) | ||
| 1. Review your inputs and press enter `O` to confirm | ||
| 1. Define a passphrase for the key | ||
|
|
||
| ```bash | ||
| gpg --armor --export ${my_email_address} | clip | ||
| ``` | ||
| 1. Test the key is visible and export the PGP PUBLIC KEY (to your clipboard): | ||
|
|
||
| - Public key is now in your clipboard - in your GitHub account add it to your profile via *Settings > SSH and GPG Keys> Add New GPG Key* | ||
| - Paste it in | ||
| ```bash | ||
| gpg -k # This should list the new key | ||
| gpg --armor --export <my_email_address> | pbcopy | ||
| ``` | ||
|
|
||
| ```bash | ||
| git config --global user.email ${my_email_address} # same one used during key generation | ||
| git config --global user.name ${my_username} | ||
| git config --global commit.gpgsign true | ||
| ``` | ||
| > Your PGP PUBLIC KEY is now in your clipboard! | ||
|
|
||
| 1. [Add the public key to your GitHub account](https://github.com/settings/gpg/new) (`Settings` -> `SSH and GPG keys` -> `New GPG key`) | ||
|
|
||
| > Note the `Key ID` as you'll need this in the next step. | ||
|
|
||
| 1. Set your local git config to use GPG signing: | ||
|
|
||
| ```bash | ||
| git config --global user.email <my_email_address> # same one used during key generation | ||
| git config --global user.name <github_handle> | ||
| git config --global user.signingkey <key_id> | ||
| git config --global commit.gpgsign true | ||
| git config --global tag.gpgsign true | ||
| ``` | ||
|
|
||
| 1. Test it works: | ||
|
|
||
| 1. Create a temporary branch of your favourite repository. | ||
| 1. Make an inconsequential whitespace change. | ||
| 1. Commit the change. | ||
| 1. You will be prompted for your GPG key passphrase - optionally select to add it to the macOS Keychain. | ||
| 1. Check the latest commit shows a successful signing: | ||
|
|
||
| ```bash | ||
| $ git log --show-signature -1 | ||
| ... | ||
| gpg: Good signature from "<github_handle> <<my_email_address>>" [ultimate] | ||
| ... | ||
| ``` | ||
|
|
||
| #### Windows/WSL | ||
|
|
||
| 1. Install (as administrator) [Git for Windows](https://git-scm.com/download/win) (which includes Bash and GnuPG) | ||
| 1. Open `Git Bash` | ||
| 1. Create a new GPG key: | ||
|
|
||
| ```bash | ||
| gpg --full-generate-key | ||
| ``` | ||
|
|
||
| 1. Pick `RSA and RSA`, or `RSA (sign only)` (there is no elliptic curve cryptography (ECC) support at the time of writing) | ||
|
||
| 1. `keysize` = `4096` bits (the minimum accepted for GitHub) | ||
| 1. Select a key expiry time (personal choice) | ||
| 1. `Real name` = Your GitHub handle | ||
| 1. `Email address` = Your GitHub account email [listed on your GitHub profile](https://github.com/settings/emails) (you can use the privacy *@users.noreply.github.com* email address): `Settings` -> `Emails` -> `Keep my email addresses private`) | ||
|
|
||
| > If you go for the private email option, consider enabling `Block command line pushes that expose my email`. | ||
|
|
||
| 1. Avoid adding a comment (this *may* prevent git from auto-selecting a key - see Troubleshooting section below) | ||
| 1. Review your inputs and press enter `O` to confirm | ||
| 1. A new window called pinentry will appear prompting you to enter a passphrase. | ||
|
|
||
| 1. Test the key is visible and export the PGP PUBLIC KEY (to your clipboard): | ||
|
|
||
| ```bash | ||
| gpg -k # This should list the new key | ||
| gpg --armor --export <my_email_address> | clip | ||
| ``` | ||
|
|
||
| > Your PGP PUBLIC KEY is now in your clipboard! | ||
|
|
||
| 1. [Add the public key to your GitHub account](https://github.com/settings/gpg/new) (`Settings` -> `SSH and GPG keys` -> `New GPG key`) | ||
|
|
||
| > Note the `Key ID` as you'll need this in the next step. | ||
|
|
||
| 1. Set your local git config to use GPG signing: | ||
|
|
||
| When you commit you will be prompted to enter the GPG key passphrase into a Pinentry window. | ||
| ```bash | ||
| git config --global user.email <my_email_address> # same one used during key generation | ||
| git config --global user.name <github_handle> | ||
| git config --global user.signingkey <key_id> | ||
| git config --global commit.gpgsign true | ||
| git config --global tag.gpgsign true | ||
| ``` | ||
|
|
||
| ## From Pipelines | ||
| 1. Now your key is created, make it available within Windows: | ||
|
|
||
| ### GitHub Actions | ||
| 1. Export the key: | ||
|
|
||
| ```bash | ||
| gpg --output <GitHub handle>.pgp --export-secret-key <my_email_address> | ||
| ``` | ||
|
|
||
| 1. Install (as administrator) [Gpg4win](https://www.gpg4win.org/) (which includes GnuPG and Kleopatra) | ||
|
|
||
| > **Ensure both `GnuPG` and `Kleopatra` are installed!** | ||
|
|
||
| 1. Open Kleopatra -> `Import` -> Select the `<GitHub handle>.pgp` file created in the first step | ||
| 1. In `cmd`, test the key is visible and set your local git config to use GPG signing: | ||
|
|
||
| ```bash | ||
| gpg -k # This should list the new key | ||
| git config --global user.email <my_email_address> # same one used during key generation | ||
| git config --global user.name <github_handle> | ||
| git config --global user.signingkey <key_id> | ||
| git config --global commit.gpgsign true | ||
| git config --global tag.gpgsign true | ||
| ``` | ||
|
|
||
| 1. Now make it available within WSL: | ||
|
|
||
| 1. Within Ubuntu: | ||
|
|
||
| ```bash | ||
| sudo ln -s /mnt/c/Program\ Files\ \(x86\)/GnuPG/bin/gpg.exe /usr/local/bin/gpg | ||
| sudo ln -s gpg /usr/local/bin/gpg2 | ||
| ``` | ||
|
|
||
| 1. Close and reopen your Ubuntu terminal | ||
|
|
||
| 1. Test the key is visible and set your local git config to use GPG signing: | ||
|
|
||
| ```bash | ||
| gpg -k # This should list the new key | ||
| git config --global user.email <my_email_address> # same one used during key generation | ||
| git config --global user.name <github_handle> | ||
| git config --global user.signingkey <key_id> | ||
| git config --global commit.gpgsign true | ||
| git config --global tag.gpgsign true | ||
| ``` | ||
|
|
||
| 1. Test it works: | ||
|
|
||
| 1. Create a temporary branch of your favourite repository. | ||
| 1. Make an inconsequential whitespace change. | ||
| 1. Commit the change. | ||
| 1. You will be prompted for your GPG key passphrase. | ||
| 1. Check the latest commit shows a successful signing: | ||
|
|
||
| ```bash | ||
| $ git log --show-signature -1 | ||
| ... | ||
| gpg: Good signature from "<github_handle> <<my_email_address>>" [ultimate] | ||
| ... | ||
| ``` | ||
|
|
||
| ### From Pipelines | ||
|
|
||
| #### GitHub Actions | ||
|
|
||
| A GitHub Actions workflow will by default authenticate using a [GITHUB_TOKEN](https://docs.github.com/en/actions/security-guides/automatic-token-authentication) which is generated automatically. | ||
|
|
||
|
|
@@ -97,7 +207,7 @@ The workflow would then use a Personal Access Token, stored with the GPG private | |
| ```yaml | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v3 | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| token: ${{ secrets.BOT_PAT }} | ||
| ref: main | ||
|
|
@@ -121,7 +231,7 @@ git commit ${GITHUB_SIGNING_OPTION} -am "Automated commit from GitHub Actions: $ | |
| git push | ||
| ``` | ||
|
|
||
| ### AWS CodePipeline | ||
| #### AWS CodePipeline | ||
|
|
||
| The cryptographic libraries in the default Amazon Linux 2 distro are very old, and do not support elliptic curve cryptography. When using pre-existing solution elements updating the build container is not always an option. This restricts the GPG key algorithm to RSA. You should use RSA-4096, which is the required minimum for GitHub. | ||
|
|
||
|
|
@@ -138,7 +248,7 @@ if [[ ${BOT_SSH_KEY} != "None" ]]; then | |
| echo "StrictHostKeyChecking yes" >> ~/.ssh/config | ||
| echo "UserKnownHostsFile=~/.ssh/known_hosts" >> ~/.ssh/config | ||
| echo "${BOT_SSH_KEY}" > ~/.ssh/ssh_key | ||
| echo -e "\n\n" >> ~/.ssh/ssh_key | ||
| echo -e "\n\n" >> ~/.ssh/ssh_key | ||
| chmod 600 ~/.ssh/ssh_key | ||
| eval "$(ssh-agent -s)" | ||
| ssh-add ~/.ssh/ssh_key | ||
|
|
@@ -174,10 +284,51 @@ git commit ${GITHUB_SIGNING_OPTION} -am "Automated commit from ${SCRIPT_URL}" | |
| git push | ||
| ``` | ||
|
|
||
| ## Troubleshooting | ||
| ### Troubleshooting | ||
|
|
||
| Re-run your git command prefixed with `GIT_TRACE=1`. | ||
|
|
||
| A failure to sign a commit is usually because the name or email does not quite match those which were used to generate the GPG key, so git cannot auto-select a key. Ensure that these are indeed consistent. (If you added a comment when creating your GPG key, this *may* cause a mismatch: the comment will be visible when listing your GPG keys, e.g. `RealName (Comment) <EmailAddress>`.) You are able to [force a choice of signing key](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key), though this should not be necessary. | ||
|
|
||
| ## SSH commit signing | ||
|
||
|
|
||
| 1. If you do not already have SSH key access set up on your GitHub account, first [generate a new SSH key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent). To create a new SSH key, you need to run the following command. This will generate a new SSH key of the type `ed25519` and associate it with your email address (replace `<my_email_address>` with your actual email address): | ||
|
|
||
| ```shell | ||
| ssh-keygen -t ed25519 -C "<my_email_address>" -f "~/.ssh/github-signing-key" | ||
| ``` | ||
|
|
||
| > When you run this command, it will ask you to enter a passphrase. Choose a strong passphrase and make sure to remember it, as you will need to provide it when your key is loaded by the SSH agent. | ||
|
|
||
| 1. Signing commits with an SSH key is not the default method, so you need to [configure Git](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key#telling-git-about-your-ssh-key) accordingly: | ||
|
|
||
| 1. Run the following command to instruct Git to use the SSH signing key format, instead of the default GPG: | ||
|
|
||
| ```shell | ||
| git config --global gpg.format ssh | ||
| ``` | ||
|
|
||
| 1. Next, specify the private key for Git to use: | ||
|
|
||
| ```shell | ||
| git config --global user.signingkey ~/.ssh/github-signing-key | ||
| ``` | ||
|
|
||
| 1. Lastly, instruct Git to sign all of your commits: | ||
|
|
||
| ```shell | ||
| git config --global commit.gpgsign true | ||
| ``` | ||
|
|
||
| 1. [Add the SSH public key to your GitHub account](https://github.com/settings/ssh/new) (`Settings` -> `SSH and GPG keys` -> `New SSH key`) | ||
|
|
||
| 1. `Key type` = `Signing Key` | ||
| 1. Copy the contents of your public key file and paste it into the `Key` field. | ||
|
|
||
| Re-run your git command prefixed with GIT_TRACE=1 | ||
| ```shell | ||
| cat ~/.ssh/github-signing-key.pub | ||
| ``` | ||
|
|
||
| A failure to sign a commit is usually because the name or email does not quite match those which were used to generate the GPG key, so git cannot auto-select a key. Ensure that these are indeed consistent. (If you added a comment when creating your gpg key, this *may* cause a mismatch: the comment will be visible when listing your gpg keys, e.g. `RealName (Comment) <EmailAddress>`.) You are able to [force a choice of signing key](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key), though this should not be necessary. | ||
| 1. `Add SSH key` | ||
|
|
||
| If you have already committed and need to retrospectively sign this commit [please follow the instructions here](./retrospective-commit-signing.md). | ||
| 1. To ensure your configuration works as expected, make a commit to a branch locally and push it to GitHub. When you view the commit history of the branch on GitHub, [your latest commit](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification#about-commit-signature-verification) should now display a `Verified` tag, which indicates successful signing with your GPG or SSH key. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we suggest the ECDSA (over Curve25519) algorithm to be used as default? It's considered being more modern and more often used these days.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I run:
gpg --full-generate-keyI get the following output:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated :)