GPG密钥的配置

发布于 更新于
每个人自主可控、也得到业界广泛支持的签名机制

背景

今天突然发现我设置在gitea上的gpg密钥不知怎的消失了,我看了下我2022写的文章,当时写得比较乱,今天把它删了重新整理一遍。

GPG 全称 GNU Privacy Guard ,GNU就是那个GNU,它是 GNU 官方项目之一,是 Linux 安全体系的基础依赖,与 bash、glibc、coreutils 同级别地位。一些软件源的官方GPG公钥会被安装在系统中,形成类似HTTPS证书体系的根证书的作用,可用于校验.deb安装包等常见用途。

它本质上是提供了一套标准的非对称加密的工具链,或者具体说是一套去中心化的签名证书机制。GNU软件源可以发布公钥用于验证安装包确实来自于官方,每个程序员个人也可以发布自己的公钥用于验证某些东西确实出自他本人之手。最常见的用途是用于给git提交签名,经过配置之后可以在github、gitea等网站上显示一把绿色的小锁。

既然能用于鉴别身份,那么GPG理论上也可以用作web应用的用户登录。但目前web应用的身份认证依然采用密码、2FA验证码等方式,因为GPG虽然有很多好处,但是也有很多难处导致了它难以推广。最大的难处在于,非对称加密无法人工介入、必须得借助软件运算和硬件储存,因此“如何保管自己的私钥”成为了非对称加密认证这个木桶上最短的那块板子,对绝大多数人来说,其实际运用体验和安全度甚至还不如密码+2FA。但是其思路依然值得借鉴,业内目前已经有了很多相关的探索,例如Web Authentication API

GPG的基本使用

工具链程序安装:

Linux发行版会随系统安装,在windows平台上推荐安装gpg4win

这里插一嘴,gpg4win 是一系列工具链,包括一个带GUI的程序Kleopatra,后者看似提供了图形化的界面以便于人们轻松使用gpg命令,但实际上它的界面设计得非常糟糕,尤其是堪比机翻的中文汉化让人一脸懵逼。因此我强烈建议不要使用这类客户端程序,直接使用命令行。在这个AI时代,或者准确说大语言模型AI得到广泛应用的时代,作为文本的命令行语句远远比用户图形界面的操作更容易掌握。

创建新的密钥对:

gpg --full-generate-key

一些选项:

  • 算法:默认ECC即可,比RSA先进一些
  • 有效期:默认不过期即可,也可以写个五年十年
  • Real Name: 填你的姓名、网名或昵称或任意你能认出你自己的代号
  • 邮箱:建议用真实有效的邮箱,因为邮箱往往被外界视为用户名

列出所有密钥:

gpg --list-keys --keyid-format LONG
gpg --list-secret-keys --keyid-format LONG

注意上述命令一个是列出公钥,一个是列出私钥,其输出可能看起来几乎完全一致。每一行开头会告诉你这一行是什么:

  • pub public 主公钥
  • sec secret 主私钥
  • uid 用户身份,包含名称和邮箱,是你创建密钥对时声明的

公钥的意思是“你信任哪些密钥”,私钥的意思是“你拥有哪些密钥”。当你创建或导入一个私钥后,会自动生成它对应的公钥,因此上述两条命令会分别输出同一套密钥的公钥和私钥。

导出公钥:

gpg --export -a > pub.asc

用于分享给Git/Github/Gitea或其他人。

导出私钥:

gpg --export-secret-keys -a > private.asc

务必记得直接给它加密。由于windows对于命令行输入密码的支持很差,难以实现一行命令完成导出+压缩,因此这里不提供加密压缩的命令语句,请自行利用7-zip等软件的GUI界面完成加密压缩。压缩完毕后记得删除刚刚导出的私钥文件!

导入公钥和私钥:

gpg --import pub.asc
gpg --import private.asc

签名和认证:

echo "签名内容"| gpg -a --detach-sig # 仅限Unix使用

但是!特别注意!在windows平台下,echo命令会自动在结尾添加换行符\r\n导致签名结果错误!

set /p data="签名内容" <nul | gpg -a --detach-sig  # windows cmd 使用

延长有效期:

gpg --list-keys # 列出所有密钥
gpg --edit-key <你的密钥ID或邮> # 从此进入会话模式
# gpg> key 0 # 默认操作主私钥
gpg> expire
# ... 跟随提示操作
gpg> save

上述操作对应的是主私钥sec,一般情况下主私钥默认承担了SC的职责,只改它就行了。如果需要修改子私钥ssb(默认承担E职责),则通过gpg> key 1命令进行切换。

Git提交签名:

gpg agent服务提供了对外接口,常见IDE(VSCode、Jetbrains)都可以很简单地设置。

至于git命令行操作,我不会也不想知道。

密钥管理策略

“如何保管私钥”是GPG安全的最大弱点。

参考ssh密钥,第一种策略是,一台设备一个私钥。但这样会与直觉或者说GPG签名的本来目——证明你是你——不符,因为这样在世界上就出现了很多个你,会给别人造成麻烦。

第二种策略,一个人一个私钥。私钥在跨设备传输、备份时,设置一个临时的口头密码,并尽量确保能窃取你的私钥压缩包的人(线上黑客)和可能知道你口头密码的人(线下亲人朋友)没有交集,这样的安全级别对于我们普通人的日常使用,特别是git提交签名来说,是足够安全的,也是最为可行的。

gitea配置

点击网页右上角头像-设置-SSH/GPG密钥,管理GPG密钥一栏点击增加密钥按钮。

首先需要输入公钥。

随后要进行认证(如果你的GPG密钥的uid所指定的邮箱,与你gitea账户设定的邮箱相同,似乎可以省略这一步)。此时在网页中会增加显示“令牌”一栏,其中的一串16进制字符串是gitea生成的随机字符串,但是注意这个令牌似乎是有时间限制的,操作gpg要尽快。

签名命令参考前文。