Last active
January 19, 2022 16:54
-
-
Save darianmiller/9de8aeb1979ef2eba9ea6069c669bca1 to your computer and use it in GitHub Desktop.
Setup code signing git commits on Windows using GPG
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
echo Use GnuPG on Windows for Code Signing git commits | |
@echo off | |
SETLOCAL | |
rem useful if running batch file from Explorer with hard-coded passphrase | |
rem cd /d %~dp0 | |
cls | |
echo SetupSignedCommits.bat | |
echo https://gist.github.com/darianmiller/9de8aeb1979ef2eba9ea6069c669bca1 | |
echo Created December 5, 2021 | |
echo Related blog article: https://www.ideasawakened.com/post/configure-git-for-signed-commits-on-windows-using-gpg | |
echo. | |
echo Author: Darian Miller | |
echo https://github.com/darianmiller | |
echo https://www.linkedin.com/in/darianm/ | |
echo. | |
echo This batch file will attempt to: | |
echo A) Optionally, run GPG to create a new keypair (RSA 4096-bit key length) for signing purposes | |
echo Run once to create keypair and then run again in different directory to configure other local repos | |
echo Alternatively, run once to create keypair and set the Global git config for all your local repos | |
echo B) Optionally, navigate to GitHub or GitLab so you can paste your public key into their web interface | |
echo Will also launch notepad containing your exported Public Key cert | |
echo C) Optionally, configure your git config on your machine | |
echo This sets your git user info and enables code signing with your new private key on each commit | |
echo Settings can be configured "Global" for all repositories or "Local" for the current repository | |
echo NOTE: If updating LOCAL settings, ensure you run this batch file within a repository workspace folder | |
echo D) Optionally, extend the GPG agent TTL setting | |
echo Cached passwords used by the GPG agent expire after 10 minutes of inactivity and cached for a max of 2 hours | |
echo For ease of use, you can extend this to 1-year to prevent having to repeatedly re-input your passphrase | |
echo. | |
echo Directions before use: | |
echo 1. Customize your user information and certificate parameters within this batch file | |
echo 2. Optionally verify paths to git.exe and gpg.exe (default Git for Windows installs should work as-is) | |
echo 3. Comment out or delete the next EXIT /B line and save your changes when ready | |
echo 4. At a command prompt within a git workspace run: SetupSignedCommits.bat your-secret-passphrase-here | |
EXIT /B | |
echo. | |
REM ---------------------- | |
REM 1. CUSTOMIZE YOUR INFO | |
REM ---------------------- | |
set FirstName=John | |
set LastName=Smith | |
set EmailAddress=johnsmith@yourhost.com | |
set CertComment=For signing Git commits | |
set CertExpires=0 | |
rem Note: set CertExpires = 0 for no expiration or set to specific number of seconds (or optionally use days/weeks/months/years designator) | |
rem #d= days, #w = weeks, #m = months, #y = years. Example: 180 means the cert will expire in 180 seconds, 1y means 1 year | |
rem Assume passwphrase is first parameter | |
IF ["%~1"]==[""] ( | |
echo. | |
echo Usage: SetupSignedCommits.bat passphrase | |
echo. | |
echo Please enter your passphrase | |
EXIT /B | |
) | |
rem If desired, remove the IF empty check block above and hard-code password here | |
rem Also note: passphrase is only used when creating new keypair | |
set Passphrase=%1 | |
REM ---------------- | |
REM 2. VERIFY PATHS | |
REM ---------------- | |
rem if you have a custom install, set default locations manually. If git/gpg is in the system PATH, simply remove the path designation. | |
rem Download and install if missing: https://gitforwindows.org/ | |
rem You can test at a command prompt by typing in the path configured here with a version parameter: | |
rem "%PROGRAMFILES%\Git\usr\bin\gpg.exe" --version | |
rem "%PROGRAMFILES%\Git\bin\git.exe" --version | |
SET GPGCommand="%PROGRAMFILES%\Git\usr\bin\gpg.exe" | |
if NOT EXIST %GPGCommand% ( | |
echo Could not find gpg.exe, terminating | |
exit /b | |
) | |
SET GITCommand="%PROGRAMFILES%\Git\bin\git.exe" | |
if NOT EXIST %GITCommand% ( | |
echo Could not find git.exe, terminating | |
exit /b | |
) | |
REM ------------------------------------- | |
REM A. OPTIONALLY GENERATE A NEW KEYPAIR | |
REM ------------------------------------- | |
CHOICE /C:YN /M "Create a new keypair for %EmailAddress%?" | |
IF ERRORLEVEL = 2 GOTO NavigateOption | |
%GPGCommand% --batch --pinentry-mode=loopback --passphrase "%Passphrase%" --quick-generate-key "%FirstName% %LastName% (%CertComment%) <%EmailAddress%>" rsa4096 sign %CertExpires% | |
REM ----------------------- | |
REM B. OPTIONALLY NAVIGATE | |
REM ----------------------- | |
:NavigateOption | |
CHOICE /N /C:HLO /M "Adding new Public Key to GitHub, GitLab, or Other? [Enter H, L, or O]: " | |
IF ERRORLEVEL == 3 GOTO SkipPublicKeyExport | |
IF ERRORLEVEL == 2 GOTO GitLab | |
IF ERRORLEVEL == 1 GOTO GitHub | |
GOTO SkipPublicKeyExport | |
:GitHub | |
rem Auto-navigate to github add GPG key page - Sign on to github as needed and then paste the public key and hit the Add gpg key button | |
start https://github.com/settings/gpg/new | |
rem Consider enabling vigilant mode | |
rem start https://github.com/settings/keys | |
GOTO ExportPublicKey | |
:GitLab | |
start https://gitlab.com/-/profile/gpg_keys | |
GOTO ExportPublicKey | |
:ExportPublicKey | |
set TempPKFileName=%TEMP%\MyNewPublicKey_%RANDOM%.txt | |
%GPGCommand% -ao %TempPKFileName% --export %EmailAddress% | |
start notepad.exe %TempPKFileName% | |
echo. | |
echo Copy your PUBLIC KEY now shown in Notepad and paste into the website to add a new GPG key to your account. | |
echo If this temp file is empty, upgrade your old version of GPG by installing the latest Git for Windows version | |
echo. | |
rem pause, wait to delete temp file export | |
pause | |
del %TempPKFileName% | |
:SkipPublicKeyExport | |
REM ---------------------------- | |
REM C. OPTIONALLY CONFIGURE GIT | |
REM ---------------------------- | |
CHOICE /N /C:GLS /M "Configure Global, Local, or Skip updating your Git config? [Enter G, L, or S]: " | |
IF ERRORLEVEL == 3 GOTO ConfigureGitFinished | |
IF ERRORLEVEL == 2 GOTO ConfigureLocalGit | |
IF ERRORLEVEL == 1 GOTO ConfigureGlobalGit | |
GOTO ConfigureGitFinished | |
:ConfigureGlobalGit | |
SET GITScope=--global | |
GOTO ConfigureGit | |
:ConfigureLocalGit | |
SET GITScope=--local | |
GOTO ConfigureGit | |
:ConfigureGit | |
%GITCommand% config %GITScope% user.name "%FirstName% %LastName%" | |
%GITCommand% config %GITScope% user.email %EmailAddress% | |
rem tell Git where to find GPG so it can sign commits | |
%GITCommand% config %GITScope% gpg.program %GPGCommand% | |
rem ask Git to sign all commits | |
%GITCommand% config %GITScope% commit.gpgsign true | |
rem Export the public key id to put into Git's config | |
rem Example output for the command: gpg --with-colons --list-keys %EmailAddress%' | |
rem tru:o:1:1638593381:1:3:1:5 | |
rem pub:u:4096:1:8F660347585C99DA:1638593497:1654145497::u:::scSC::::::23::0: | |
rem fpr:::::::::07024D220A0BE54695F3A4808F660347585C99DA: | |
rem uid:u::::1638593497::DAF7992F9D19CC7B0B084F559DAAB09FBA90CA47::John Smith <johnsmith@null.com>::::::::::0: | |
rem Lets grab the third line of text which contains key signature | |
set "linethree=" | |
for /F "skip=2 delims=" %%i in ('"%GPGCommand%" --with-colons --list-keys %EmailAddress%') do set "linethree=%%i"&GOTO DoneParsingKeyList | |
:DoneParsingKeyList | |
rem now extract the 160-bit, 40 hex character fingerprint 07024D220A0BE54695F3A4808F660347585C99DA from the third line of text fpr:::::::::07024D220A0BE54695F3A4808F660347585C99DA: | |
set keysignature=%linethree:~12,40% | |
rem configure Git to use the key just created | |
%GITCommand% config %GITScope% user.signingkey %keysignature% | |
rem view Global git settings if desired: | |
rem notepad "%USERPROFILE%\.gitconfig" | |
GOTO ConfigureGitFinished | |
:ConfigureGitFinished | |
REM ------------------------- | |
REM D. OPTIONALLY EXTEND TTL | |
REM ------------------------- | |
rem don't change existing settings if any found | |
SET AgentConfigFile="%USERPROFILE%\.gnupg\gpg-agent.conf" | |
IF NOT EXIST %AgentConfigFile% ( | |
rem by default you will be asked to re-input your password after 10 minutes of inactivity, or at least every 2 hours... extend this as desired | |
CHOICE /C:YN /M "Extend default gpg-agent timeout? " | |
IF ERRORLEVEL == 2 GOTO AgentFinished | |
IF ERRORLEVEL == 1 GOTO ConfigureAgent | |
GOTO AgentFinished | |
) | |
:ConfigureAgent | |
rem default-cache-ttl max age in seconds of cached passphrase (timer is reset on each use) Default is 600 seconds | |
rem max-cache-ttl max age in seconds of cached passphrase regardless of use (force re-entry of passhprase on next use) Default is 7200 seconds | |
rem https://www.gnupg.org/documentation/manuals/gnupg/Agent-Options.html | |
( | |
echo default-cache-ttl 31536000 | |
echo max-cache-ttl 31536000 | |
) > %AgentConfigFile% | |
rem to view current settings: | |
rem gpgconf --list-options gpg-agent | |
rem | |
rem technically, should reload the agent if it's running so it gets new config values: | |
rem gpgconf.exe --reload gpg-agent | |
:AgentFinished | |
REM ------------- | |
REM E. ALL DONE! | |
REM ------------- | |
rem for verifying current list of keys found in the ".gnupg" folder in your user homepath | |
echo. | |
echo Current GPG keys for %EmailAddress%: | |
%GPGCommand% --list-keys %EmailAddress% | |
rem Useful for testing purposes - delete new keyring after creating it | |
rem pause | |
rem %GPGCommand% --delete-secret-keys %EmailAddress% | |
rem %GPGCommand% --delete-key %EmailAddress% | |
rem for more info: | |
rem gpg commands https://www.gnupg.org/documentation/manuals/gnupg/Operational-GPG-Commands.html | |
rem GitHub Vigilant mode changelog: https://github.blog/changelog/2021-04-28-flag-unsigned-commits-with-vigilant-mode/ | |
rem GitHub help page: https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification | |
rem GitLab help page: https://docs.gitlab.com/ee/user/project/repository/gpg_signed_commits/index.html | |
rem GitHub desktop currently does not support signing: https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-tags | |
rem Azure DevOps currently not supported in display: https://github.com/MicrosoftDocs/azure-devops-docs/issues/1381 also https://developercommunity.visualstudio.com/t/can-we-have-signed-commits/486953 | |
echo Process complete! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment