环境
系统为Windows 11 23H2。
SSH是Windows系统自带的OpenSSH,不是自行安装的,也不是Git Bash里的ssh。
GPG是gnupg-w32,由scoop安装,不是Git Bash里的gpg。
SSH和GPG的版本如下:
> ssh -V
OpenSSH_for_Windows_8.6p1, LibreSSL 3.4.3
> gpg --version
gpg (GnuPG) 2.4.3
...
Home: C:\Users\liwenshen\scoop\apps\gpg\current\home
...
注意这里的GPG的Home文件夹,下文涉及的GPG的所有配置文件都放在这个Home文件夹中。
准备工作
GIT 配置
Git在默认情况下,使用Git Bash里自带的ssh和gpg程序。 我们需要强制其使用Windows内置的SSH和gnupg-w32的gpg程序。
先在PowerShell查看当前Windows下的程序路径:
> (Get-Command ssh).Path
C:\Windows\System32\OpenSSH\ssh.exe
(Get-Command gpg).Path
C:\Users\liwenshen\scoop\apps\gpg\current\bin\gpg.exe
PS C:\Users\liwenshen>
然后根据上面的路径,指定Git使用的程序:
git config --global core.sshCommand C:\\Windows\\System32\\OpenSSH\\ssh.exe
git config --global gpg.program C:\\Users\\liwenshen\\scoop\\apps\\gpg\\current\\bin\\gpg.exe
密钥情况
查看密钥的基本情况:
> gpg -k
C:\Users\liwenshen\scoop\apps\gpg\current\home\pubring.kbx
----------------------------------------------------------
pub ed25519/82EF9F38F02BCA14 2023-06-04 [C]
Key fingerprint = 7460 79A9 2447 E38D 1AF8 A7ED 82EF 9F38 F02B CA14
Keygrip = 11C9D151D94FD5C4F5612CF1D79FB735E9EE08C6
uid [ultimate] liwenshen (git) <git@liwenshen.com>
sub ed25519/1B3B3B59E5427BF0 2023-06-04 [SA] [expires: 2025-06-03]
Keygrip = E57DFA139A46760699AB482039CC3443EB0EAB22
sub cv25519/9556AA6A5BCDE6EC 2023-06-04 [E] [expires: 2025-06-03]
Keygrip = 4DCA3FE1E8779FF9D1A6C773BD66E6CF8BE0FA63
在Git签名中,需要使用S(Signing签名)类型子密钥。 在SSH连接认证中,需要使用A(Authenticating认证)类型子密钥。
可以看到,在我的情况下,一个主密钥下挂两个子密钥。 其中第一个子密钥符合签名和认证的要求。因此就用这个子密钥进行SSH认证和Git签名。
这个子密钥对应的ID是1B3B3B59E5427BF0,Keygrip是E57DFA139A46760699AB482039CC3443EB0EAB22。 还需要记一下主密钥的ID是82EF9F38F02BCA14,后面需要用到这3个值。
如果密钥ID和Keygrip显示不完全。 可以在gpg.conf中加上下列内容后,重新执行
gpg -k
keyid-format long
fingerprint
with-keygrip
或者直接执行
gpg -k --keyid-format long --fingerprint --with-keygrip
SSH 认证
GPG子密钥的SSH公钥
使用子密钥的ID,导出子密钥的SSH格式公钥,将其粘贴至Github或者服务器等SSH远程服务器上。
> gpg --export-ssh-key 1B3B3B59E5427BF0
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJXESXaFJse2EE4IJ8BVbwSoSLezT2uAHIDVz4N3mkhi openpgp:0xE5427BF0
GPG agent
GPG Agent是SSH Agent的实现,可以将SSH登录的过程中的认证环节,委托给GPG进行认证。 因此想要在SSH连接中使用GPG密钥,需要先配置GPG agent。
配置GPG agent
网络上许多文章,都有用到wsl-ssh-pageant,还要书写各种的powershell启动脚本进行配置。 实际上没有必要,gnupg-w32已经内置了对Windows OpenSSH的支持。 只需要在gpg-agent.conf中加上下列内容就可以开启支持。
enable-ssh-support
enable-putty-support
enable-win32-openssh-support
然后将用来进行SSH认证的密钥的Keygrip写入sshcontrol文件,如:
E57DFA139A46760699AB482039CC3443EB0EAB22
警告:sshcontrol文件里新增Keygrip后务必换行,且新一行不能有空格!!!
运行GPG Agent
以下两条命令,任选一条,启动GPG agent
gpgconf --launch gpg-agent
gpg-connect-agent /bye
以下两条命令,任选一条,可以关闭GPG agent
gpgconf --kill gpg-agent
gpg-connect-agent killagent /bye
为了自动启动GPG agent,可以将GPG agent启动命令,加入计划任务中,并设置开机启动。
测试SSH
启动GPG agent后,执行命令,查询SSH能否正常使用GPG密钥。
> ssh-add -L
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJXESXaFJse2EE4IJ8BVbwSoSLezT2uAHIDVz4N3mkhi (none)
可以看到,这个公钥和上文gpg --export-ssh-key导出的公钥是一致的,说明SSH已经可以使用GPG的子密钥了。
再测试一下SSH连接Github或者其他远程服务器,出现下列相似内容说明SSH已经认证成功。
> ssh -vT git@github.com
...
debug1: Next authentication method: publickey
debug1: Offering public key: (none) ED25519 SHA256:6aRZPwhjxDNgVIaXwaE9US9ZvUON3kzepoNH976w5vY agent
debug1: Server accepts key: (none) ED25519 SHA256:6aRZPwhjxDNgVIaXwaE9US9ZvUON3kzepoNH976w5vY agent
debug1: Authentication succeeded (publickey).
...
Hi liwenshen2000! You've successfully authenticated, but GitHub does not provide shell access.
...
如果出现下列报错,请优先检查上文涉及的配置文件内容,如换行符类型,末尾是否换行等。
> ssh-add -L
error fetching identities: agent refused operation
Git 签名
GPG密钥的GPG公钥
将GPG密钥的公钥导出。 然后将输出内容粘贴至Github或者其他远程代码库等GPG配置中。 就可以让代码库在推送代码后,认可这个GPG密钥签名的commits和tags。
> gpg --armor --export 82EF9F38F02BCA14
-----BEGIN PGP PUBLIC KEY BLOCK-----
...
-----END PGP PUBLIC KEY BLOCK-----
导出时是导出整个GPG密钥的公钥,包括主密钥和子密钥,因此无论使用的是主密钥ID还是子密钥ID,输出结果都是一样的。
配置Git
配置Git的GPG签名较为简单,首先在Git里设置用于签名的密钥的ID:
git config --global user.signingkey 1B3B3B59E5427BF0!
我这里指定了一个具体的GPG密钥进行签名,因此需要在在密钥ID的末尾加上感叹号。 也可以使用主密钥,让Git自动选择其下的签名密钥用于签名,那么可以设置成主密钥的ID,不必加感叹号:
git config --global user.signingkey 82EF9F38F02BCA14
配置默认对所有commits和tags签名
git config --global commit.gpgsign true
git config --global tag.gpgSign true
后记
实际上在Windows上使用GPG密钥进行Git签名和SSH认证,还是较为繁琐的。
推荐使用GpgFrontend等GUI前端进行GPG密钥生成和管理。
如果仅仅是为了在Github上给自己加上一个小绿勾,可以使用更为简单易用的SSH密钥进行签名和认证1。
评论列表 (0条):
加载更多评论 Loading...