在这里记录一下SSH和GPG的简单介绍和基础配置,主要针对的应用是git,不过并不局限于git,其他不少应用也是一样的。
基础介绍
SSH
SSH(Secure Shell) 是一个基于TCP的加密网络协议,相较于普通的TCP协议,可以保证通信的安全性,比较常用的两个应用是登录远程服务器和推送本地git仓库到远程。SSH可以使用密码或者密钥登录,但是由于密码被破解的风险是不确定的,如果设置了像123456
这种弱口令,那么SSH的安全性就形同虚设了,所以通常推荐设置SSH密钥来代替密码,比如Debian系统默认情况下是不允许root用户SSH登录用密码的;还有GitHub也已经禁止了使用密码来推送代码。另外,SSH密钥本身也可以再加一层密码。
GPG
首先简单解释一下几个容易混淆的名词,PGP
OpenPGP
GPG
:
- PGP(Pretty Good Privacy)是一个闭源软件的名字
- OpenPGP是一个标准,这个标准是基于PGP这个软件的一些格式签名等衍生而来的
- GPG(GNU Privacy Guard)是一个实现了OpenGPG标准的开源软件,大多数人用到的就是它
GPG有四个主要功能,加密(encryption)、签名(signing)、证书(certification)、认证(authentication),比较常用的是加密和签名。本文用到的是签名这个功能,以给git提交记录签名为例,由于git的用户名和邮箱是用户可以随便定义的,那么在开源项目中,就有可能会出现冒充他人提交代码的恶意行为,通过gpg为git commit签名就可以解决这个问题,这种签名的记录在GitHub上会显示一个绿色的Verfied
的tag。
SSH 配置
生成 SSH 密钥对
这里用到的命令是ssh-keygen
,如果你的系统没有这个命令,需要安装openssh,可以在command-not-found 来查看自己系统安装对应的软件包安装命令。我目前使用的版本是9.6p1-1
,是当下的最新版本。
打开终端,在命令行输入ssh-keygen -t ed25519
,其中ed25519
是生成密钥对的类型,除了ed25519
还有dsa
ecdsa
ecdsa-sk
ed25519-sk
rsa
,具体可以通过man ssh-keygen
查看,上述命令输出如下:
|
|
如果是第一次生成,那么直接回车即可,接着会出现以下内容:
|
|
这里的密码可以为空,如果不为空,那么在使用这个密钥的时候会提示验证密码。
一个完整的输出如下:
|
|
在这次操作中,我们得到了两个文件,id_ed25519.pub
是公钥,id_ed25519
是私钥,其中公钥稍后会上传到 GitHub 上,私钥则保存在本地,注意不能泄露。
这一对密钥也可以用于SSH登录远程服务器,通常情况下,没有必要生成很多对密钥。我个人的习惯是一台设备一对密钥,增加设备就新生成密钥,更换设备就继承旧设备的密钥
添加 SSH 公钥至 GitHub
登录 GitHub 之后访问 Add new SSH keys 页面,填写表单即可完成添加,公钥的内容类似下面的代码:
|
|
接下来还需要在本地配置ssh的config配置文件,对域名和密钥进行关联,补充下述内容到~/.ssh/config
文件中,其中#
后的为注释,可删除:
|
|
在命令行输入ssh -T [email protected]
来验证是否添加成功,首次输入会得到这样的一个输出:
|
|
输入yes
并回车,如果添加成功,会出现类似的结果:
|
|
SSH 密钥的备份
SSH 公钥刚才已经上传到了github,但是密钥只在本地保存,建议对两个文件进行备份。如果保存到U盘、移动硬盘等可以直接复制过去;如果要上传要云盘,建议对文件进行加密。
GPG 配置
生成 GPG 密钥对
如果没有gpg命令,需要先安装,方法和上面的ssh一样,不再赘述。
打开终端,输入gpg --full-generate-key
命令,输出如下:
|
|
建议保持默认,直接回车,接着需要选择密钥长度:
|
|
这里我直接输入4096,然后需要设置过期时间:
|
|
过期时间后续是可以改的,如果不想过一阵子就重新生成一次,那么可以直接输入 0,永不过期。
接着需要填写真实名字,邮箱地址,和评论三个字段,分别来说明下:
- 真实名字(Real name):我个人不太倾向于填写真名,可以用自己的常用网名代替,或者github用户名,我这两个是一样的
- 邮箱地址(Email address): 可以选择公布或不公布自己的邮箱,公布邮箱的好处是这个
GPG Key
可以用于很多个场合,比如GitHub、博客、邮件等等,坏处就是暴露了自己的邮箱;而不公布的好处就是保持匿名,坏处则是这一对密钥只能用于特定的服务,比如GitHub有自己的noreply 邮箱,GitLab也有一个,同时使用这两个服务的话就比较麻烦。我这里用的是 GitHub的 noreply 邮箱 。 - 评论(Comment): 这个就随意了,我直接留空
|
|
接着,和SSH类似,为密钥对设置密码,这个密码会在使用密钥对的时候验证,然后一路确认,最终得到的输出如下:
|
|
这个输出的内容不包含key的ID等,这里我对前4行解释一下:
- 我这台机器没有任何的gpg key,所以第一次会创建这么一个trustdb,用来存放本机信任的gpg key
- ultimate是最高的信任级别,一共有五个等级,ultimate是5,none是1,因为这是当前机器生成的,所以级别默认是最高,如果是从其他地方导入的key,那么默认的信任等级会是1,这个信任级别是可以修改的,下文会提到
- 创建了一个
openpgp-revocs.d
的目录,这个目录用于存放撤销证书,这个证书一定要保存好,因为它可以用来撤销整个GPG Key - 撤销证书保存到了上面的目录
通过命令gpg --list-keys --keyid-format LONG
可以获取本机的GPG Key的详细信息:
|
|
这里末四行的信息比上面的更全一些,我逐行解释一下:
- pub是public公钥,如果命令是
list-secret-keys
那么会显示sec
,实际上后面的内容是一样的,代表这行是主密钥的信息,GPG是有主密钥和子密钥的,一个主密钥可以有多个子密钥,接着rsa4096
就是前面选过的算法,DCA603FF70CDCDD0
则是key ID,末尾的[SC]
代表这个主密钥有两个功能signing和certification - 这个是主密钥的指纹,或者说是这个GPG Key的指纹
- uid就是user ID,
[ultimate]
是前面提到过的信任等级,后面的信息对应真实姓名、邮箱和评论 - sub是subkey,
57D615B2EC5D45C1
是子密钥的key ID,末尾的[E]
代表这个子密钥的功能是encryption。注意,这个子密钥不能用于git签名,因为它没有S
的标志
添加 GPG 公钥至 GitHub
首先要得到GPG Key的公钥,输入gpg --armor --export DCA603FF70CDCDD0
命令,整个key的公钥部分,如下所示(有截断):
|
|
将这部分内容完整的复制下来,然后访问GPG Key 的添加页面,填写表单即可。
设置 git 提交签名
通过运行命令git config --global user.signingkey DCA603FF70CDCDD0
命令,可以为 git 设置全局的签名密钥,去掉--global
就仅会为当前目录下的 git 仓库设置。然后输入git config --global commit.gpgsign true
,设置所有的 git 提交都需要签名。
然后一般还需要在.bashrc
或者其他 shell 配置文件中添加如下环境变量:
|
|
接着运行killall gpg-agent
杀掉 gpg 进程,然后可以随便提交一次,可以通过git log --show-signature
命令查看到Good signature
的字样就是可以了,最后 push 到 GitHub 就可以看到绿色的认证了。
我的最佳实践
实际上,上述的操作是最为简单的一种操作方式,直接使用主密钥进行签名。但是我个人不太推荐,因为如果碰到泄露什么的就要撤销整个密钥才行,而且由于我有多台电脑,每台电脑都是一样的签名会让我分不清楚,所以我会为每一台设备生成一个用于签名的子密钥,由于子密钥是可以单独导出和导入的,这样的话,我家里台式机存放着所有信息,我外出携带的笔记本可以只放一个subkey,假设笔记本丢失了,撤销掉对应的subkey就可以了。
输入gpg --edit-key DCA603FF70CDCDD0
命令来生成一个subkey,该命令的输出如下:
|
|
输入 help
查看帮助,前面提到的改过期时间的命令是expire
,改信任等级的命令是trust
,退出是quit
,我们输入增加子密钥对的命令addkey
,和生成主密钥类似:
|
|
因为要用于签名,所以只能选3或4,确认之后最终输出如下:
|
|
6D27CF5A5037DE52
就是新生成的子密钥ID,然后还要输入save
保存并退出。运行git config --global user.signingkey 6D27CF5A5037DE52
,可以把子密钥作为全局的签名密钥。
然后还要用同样的方法再生成一个,给我的笔记本用,那么就涉及到导出和导入了,这部分内容合并到备份一起讲。
GPG 密钥的备份
无论是否和我一样有多设备的需求,生成了 subkey 用于专门的用途,都建议进行备份。
首先说需要备份那些内容:
- 撤销证书,也就是前面存放到
openpgp-revocs.d
文件夹的那个文件,这个证书无论生成多少个 subkey 都不会改变,而且一旦使用是不可逆的,因此这个文件建议多备份到几个地方,同时本机的建议删除,避免不小心撤销掉。 - GPG Key 的公钥和私钥,这个就和 SSH 类似
撤销证书直接复制对应文件就可以了,公钥和私钥需要手动导出,输入gpg --armor --export DCA603FF70CDCDD0 --output public.asc
命令导出公钥,输入gpg --armor --export-secret-keys DCA603FF70CDCDD0 --output private.key
命令导出私钥。后缀是无所谓的,asc就是ascii的意思,改成pub也可以。
前面提到的仅导出subkey的命令是gpg --armor --export-secret-keys 6D27CF5A5037DE52! --output laptop-private.key
,注意结尾的!
符号,如果不加的话,导出的还是整个的密钥。另外,公钥其实无所谓主密钥子密钥的,单独导出一个子密钥是没有意义的,一般公钥只有一份就可以,并且这个公钥可以上传到公钥服务器,这里不展开了,可以自行查询。
然后,复制到新设备之后,导入的命令如下
|
|
其他配置
如果是 MacOS,并且想要让设备记住 gpg 密码,那么需要安装 pinentry-mac
这个包,然后运行 echo "pinentry-program $(which pinentry-mac)" >> ~/.gnupg/gpg-agent.conf
命令,并 killall gpg-agent
。
Command Cheat Sheet
|
|
总结
以上是基础的一些操作,无论是SSH还是GPG,都还有很多用法或玩法,比如SSH在服务器上的配置,GPG撤销子密钥等等,后续有时间再写好了。