简介
OpenPGP
OpenPGP 是一个由 IETF 制定的一个标准,定义了用于加密、解密、签名和密钥管理的规范。截至 24/12/26,它的最新标准的标准号为 RFC9580
GnuPG
GnuPG 是 RFC4880 定义的 OpenPGP 标准的完整、自由、免费实现。GnuPG 允许你对数据和通信进行加密核签名;它拥有一个多功能密钥管理系统,以及各种公共密钥目录的访问模块
GnuPG 简称 GPG,是一种命令行工具,具有与其他应用程序轻松集成的功能。有大量的前端应用程序和库可供使用。
注意
参考
本文部分技术核心取自以下文章,感谢这些文章的作者
如果可能,请尽量阅读上方的原文来学习
下文注释
在下文代码块中,左上角写着#
的为需要超级用户身份执行的权限;左上角写着$
的只需要普通用户既可执行
以下代码只使用#
和$
来表示权限等级,不再明文写sudo
私钥的保密
所有的私钥、私钥备份一般只有个人或企业拥有,一切向你所有私钥的人都是诈骗
你应该确保私钥只有全天下只有你拥有
如果私钥有已被泄露的可能性,请及时吊销密钥
私钥的重要性
续签、吊销密钥都必须拥有私钥才能生成相应证书,所以请你妥善保管好私钥
私钥应该及时备份,并加密保存或离线保存
如果你失去私钥,你将永远无法续签、吊销以及未来进行签名
有效期
生成私钥时,建议将有效期设置短一些,因为它是可以续签的,为避免夜长梦多,建议将有效期设置短一些,以免遭遇不测
可信与抵赖
虽然数字签名的签名时间可以由签名者伪造,内容也可以随意写。所以签名内容并不一定可信,但是一旦签名者将内容发布出去,他将永远无法抵赖他曾经签名过这段内容
这也就是为什么数字签名可以具有与纸质签名同等法律效力的原因,它更安全,在需要更高可信度的情况下
命令行
在任何时候,你都不应该把口令、密钥等敏感信息直接输入在命令上,包括 echo
类似这样
$ bash
|
|
为什么?
- 你在 bash 上执行的内容,会被记录,可以在
history
命令中查看,也可以在~/.bash_history
上查看 - 你执行的命令语句在运行中可以在
ps
、htop
等进程查看器中看到
怎么办
应该尽可能从文件读取,或使用标准输入流输入
例如,执行单独一条 gpg --import
或 gpg -c
等命令后,gpg 就会持续等待你将内容输入在控制台(作为标准输入流)上,期间可以换行,直到读取到 EOF 信号为止
等待你粘贴或输入完信息后,向标准输入流发送一个 EOF 信号即可结束,在 Linux 的 Shell 中,它是 Ctrl+D 快捷键
安装 GnuPG
正常情况下,GnuPG 会默认安装在 GNU/Linux 操作系统上,因为它们的软件包管理器通常都会校验签名,没有 GnuPG 作为接口的话,是无法工作的。如果没有安装,可以尝试使用包管理器安装,例如 apt install gnupg
在 Windows 下,也有类似 Gpg4win 的支持,Gpg4win 会同时安装一个图形页面程序,可以让你方便地管理和操作各种内容(例如密钥创建、删除、吊销、加密、解密、签名、验证等)
密码算法
以下是 GnuPG 截至 2.2.40 支持的密码算法
非对称密码
算法 | 加密 | 数字签名 | 密钥交换 | 基于 | 问题 |
---|---|---|---|---|---|
RSA | √ | √ | √ | 大整数的因数分解 | 效率低。应至少使用 2048 位确保安全 |
ELG | √ | √ | √ | 离散对数 | 效率低 |
DSA | √ | 离散对数 | 不安全、效率低 | ||
ECDH | √ | 椭圆曲线离散对数 | |||
ECDSA | √ | 椭圆曲线离散对数 | |||
EDDSA | √ | 爱德华曲线离散对数 |
对称密码
算法 | 基于 | 问题 |
---|---|---|
IDEA | 线性代数 | 效率低 |
3DES | 3 次 DES 运算 | 效率低 |
CAST5 | Feistel网络 | 效率适中 |
BLOWFISH | Feistel网络 | 不安全 |
AES | 有限域上的代数运算 | |
AES192 | ||
AES256 | ||
TWOFISH | Feistel网络 | |
CAMELLIA128 | Feistel网络 | |
CAMELLIA192 | ||
CAMELLIA256 |
散列
帮助文档
使用 --help
标记,可以列出 gpg 常用选项帮助文档
- 可以简写为
-h
查看版本
使用 --version
标记,可以查看当前 gpg 版本
列出所有选项
使用 --dump-options
标记,可以列出 gpg 所有可用的选项
列出所有公钥
使用 --list-public-keys
标记,可以列出当前存储的所有公钥
- 可以简写为
-k
/--list-keys
列出所有私钥
使用 --list-secret-keys
标记,可以列出当前存储的所有私钥
- 可以简写为
-K
生成新的非对称密钥对
使用 --generate-key
标记,可以通过当前参数随机生成一个新的非对称密钥对
- 可以简写为
--gen-key
- 参数位于
openpgp-revocs.d
目录下
生成新的非对称密钥对:向导模式
使用 --full-generate-key
标记,可以随机生成一个新的非对称密钥对,并使用向导模式
- 可以简写为
--full-gen-key
导出公钥
使用 --export
标记,可以导出公钥
- 可以在后面指定多个密钥名,若不指定密钥名,默认会导出所有的公钥
备份私钥
使用 --export-secret-subkeys
标记,可以备份私钥
- 可以简写为
--export-secret-keys
- 可以在后面指定多个密钥名,若不指定密钥名,默认会导出所有的私钥
导入密钥
使用 --import
标记,可以导入密钥,或更新密钥的状态(例如续签、吊销等)
- 可以写为
--fast-import
删除公钥
使用 --delete-keys
标记,可以删除公钥
- 可以在后面指定多个密钥名
- 注意:该操作不会吊销密钥,如果你已经把公钥公布出去,此举不会吊销你的密钥,它仍然在互联网、密钥服务器和保存过你公钥的计算机上存在
- 如果想要吊销密钥,请参阅 生成吊销密钥证书
删除私钥
使用 --delete-secret-keys
标记,可以删除公钥
- 可以在后面指定多个密钥名
- 注意:该操作不会吊销密钥,如果你已经把公钥公布出去,此举不会吊销你的密钥,它仍然在互联网、密钥服务器和保存过你公钥的计算机上存在
- 如果想要吊销密钥,请参阅 生成吊销密钥证书
- 注意:该操作不可撤销,请确认你已经完全不需要该密钥,或已经做好备份的情况下再继续。如果它已被公布,你在失去私钥后永远也无法吊销它
生成吊销密钥证书
使用 --gen-revoke
标记,可以生成吊销密钥证书
- 注意:该操作不会吊销密钥,如果你已经把公钥公布出去,此举不会吊销你的密钥,它仍然在互联网、密钥服务器和保存过你公钥的计算机上存在
- 如果想要吊销密钥,请将生成出来的证书公布到互联网、密钥服务器和保存过你公钥的计算机那里,让他们使用 导入密钥 来更新该公钥
- 可以配合 额外标记/输出文件,以将输出写到文件。但该标记必须写在语句的前方。若不使用,默认会打印在标准输出流上
对称加密
使用 --symmetric
标记,可以使用口令对称加密数据
当你运行命令后,软件会向你询问口令
- 可以简写为
-c
- 可以在后面指定一个文件,若不指定文件,默认从标准输入流中读取
- 可以配合 额外标记/装甲 创建 ASCII 字符封装的输出。但该标记必须写在语句的前方。若不使用,默认会输出二进制数据
- 可以配合 额外标记/输出文件,以将输出写到文件。但该标记必须写在语句的前方。若不使用,默认会在相同位置生成一个
.gpg
文件(或在同时签名时生成.sig
文件,或在使用 armor 标记时生成asc
文件) - 可以配合
--cipher-algo
后面加一个算法,以指定加密算法。若不使用,默认使用 AES256 - 可以配合 非对称加密
- 可以配合 签名
- 可以配合 分离式签名,以生成一个加密的签名
- 默认情况下,gpg 会缓存对称加密的口令,因此解密操作可能不需要用户输入口令。可以配合
--no-symkey-cache
禁用这一功能。
你知道吗
非对称加密
使用 --encrypt
标记,可以使用公钥加密数据
- 可以简写为
-e
- 可以在后面指定一个文件,若不指定文件,默认从标准输入流中读取
- 可以使用
--recipient
/-r
指定收件人。。但该标记必须写在语句的前方。若不使用,程序会向你询问收件人 - 可以配合 额外标记/装甲 创建 ASCII 字符封装的输出。但该标记必须写在语句的前方。若不使用,默认会输出二进制数据
- 可以配合 额外标记/输出文件,以将输出写到文件。但该标记必须写在语句的前方。若不使用,默认会在相同位置生成一个
.gpg
文件(或在同时签名时生成.sig
文件,或在使用 armor 标记时生成asc
文件) - 可以配合 对称加密
- 可以配合 签名
- 可以配合 分离式签名,以生成一个加密的签名
你知道吗
椭圆曲线密码只能用于签名与密钥交换,为什么我能为一个椭圆曲线公钥加密文件?
要明白这一点,你需要知道迪菲-赫尔曼密钥交换(简称 DH)是怎样工作的,请自行了解
当你为一个椭圆曲线公钥加密文件时,gpg 会随机生成一个椭圆曲线迪菲-赫尔曼密钥交换(简称 ECDH)算法的密钥对(称为临时密钥对),它是椭圆曲线版的 DH 密钥交换算法,具有更高效、安全的算法和更短的密钥
gpg 此时拥有临时密钥对和收件人的公钥
也就是说,gpg 可以使用临时私钥和收件人的公钥合成共享密钥
这个共享密钥就是一个对称密钥,用于接下来的加密
gpg 会将临时公钥明文地放在消息头部,并将加密的数据和一些其他数据放在后面
当收件人收到数据后,它会结合临时公钥和自己的私钥合成一个相同共享密钥,并解密剩下的内容
由于合成共享安全密钥必须拥有一方的公钥和另一方的私钥,而非发送者既不知道临时私钥,也不知道收件人的私钥,所以无法解密信息
这也就是为什么每次非对称加密的结果都不相同,甚至天翻地覆的原因,因为每次加密都会完全随机地生成临时密钥对
也许这就是密钥交换的魅力所在吧
但是请注意,虽然它是密钥交换的结果,但它不像 TLS、SSH 那样,它并不向前保密,因为 TLS 与 SSH 双方都使用临时密钥对,而 gpg 加密数据只有一方使用临时密钥对,所以一旦接收者的密钥泄露,以前被保存下来的内容都能被轻松解密
与对称加密相同,非对称加密时 gpg 同样会将加密前文件的文件名、加密时间、收件人的邮箱及名称写在头部或尾部,但请放心,它们是加密存储的,没有口令无法查看。若是从标准输入流读取的,则文件名会是一个空字符串。不过注意,它们都是可以伪造的
签名
使用 --sign
标记,可以对数据进行签名
- 可以简写为
-s
- 此种签名方式包含整个文件,也就是说它会生成一个新的文件,包含原文件和签名信息。这个文件是 gpg 的格式,所以无法直接运行,必须先 删除签名 后才能使用
- 可以在后面指定一个文件,若不指定文件,默认从标准输入流中读取
- 可以配合 额外标记/装甲 创建 ASCII 字符封装的输出。但该标记必须写在语句的前方。若不使用,默认会输出二进制数据
- 可以配合 额外标记/输出文件,以将输出写到文件。但该标记必须写在语句的前方。若不使用,默认会在相同位置生成一个
.gpg
文件(或在使用 armor 标记时生成asc
文件) - 可以配合 对称加密
- 可以配合 非对称加密
分离式签名
使用 --detach-sign
标记,可以对数据进行分离式签名
- 可以简写为
-b
- 与 签名 不同,分离式签名会产生一个额外的文件,这个文件不包含原文件,只包含签名信息。通常将其和原文件一起发布,这使原文件可以直接运行而不是必须 删除签名 后才能使用
- 可以在后面指定一个文件,若不指定文件,默认从标准输入流中读取
- 可以配合 额外标记/装甲 创建 ASCII 字符封装的输出。但该标记必须写在语句的前方。若不使用,默认会输出二进制数据
- 可以配合 额外标记/输出文件,以将输出写到文件。但该标记必须写在语句的前方。若不使用,默认会在相同位置生成一个
.sig
文件(或在使用 armor 标记时生成asc
文件) - 可以配合 对称加密,以生成一个加密的签名文件
- 可以配合 非对称加密,以生成一个加密的签名
验证签名
使用 --verify
标记,可以对签名进行验证
- 可以在后面指定 0~2 个文件。
- 如果该签名是一个含文件信息的签名,则后面只能指定 0~1 个文件。若不指定文件,默认从标准输入流中读取
- 如果该签名是一个分离式的签名,则后面只能指定 1~2 个文件。第 1 个参数必须是签名文件,第二个参数必须是源文件。如果只指定第 1 个参数,则 gpg 会在当前目录下寻找与签名文件同名的源文件(去掉
.sig
或.asc
),如果没有找到,程序会以错误的方式退出
解密
使用 --decrypt
标记,可以解密数据,或是删除文件上的签名使其恢复成原文件
- 可以简写为
-d
- 后面可以加一个文件,若不加文件,则默认从标准输入流中读取
- 可以配合 额外标记/输出文件,以将输出写到文件。但该标记必须写在语句的前方。若不使用,默认会输出到标准输出流
列出所有数据
使用 --list-packets
标记,可以列出 gpg 格式文件中的所有元数据(例如加密/签名时间、原文件名、密钥 ID、接收者等等)
额外标记
详细输出
使用 --verbose
标记,可以输出详细信息,以方便在出现问题时分析
- 可以简写为
-v
输出文件
使用 --output
标记,后面跟一个文件,可以将输出重定向到此文件
- 可以简写为
-o
装甲
使用 --armor
标记,可以创建 ASCII 字符封装的输出,以方便在无法使用不可打印字符时
- 可以简写为
-a
你知道吗
它使用头部 + Base64 + 尾部组成
日常使用
去中心化使用
如果你只是想与小伙伴建立加密通信,你可以与小伙伴们互相交换公钥,这样你就可以加密只有小伙伴的私钥才能解密的消息(包括你自己也无法解密它)。为了防止消息被篡改或防止抵赖,你可以为消息生成签名信息,全天下只有你能够生成这段签名信息
OpenPGP 为电子邮件而生,所以部分邮箱客户端拥有 OpenPGP 加密和签名功能,例如 Thunderbird,用好它们,即使是邮箱服务器管理员也无法解密或伪造消息
商业化使用
更多时候,OpenPGP 是用于签名软件的。软件开发者(特别是自由软件开发者)通常会在分发软件时附上一份分离式签名文件,以供用户验证软件未被篡改,也供用户审查软件内容,一旦签名,签名者就无法抵赖自己签名过这些内容
如果你是软件用户,在遇到可验证签名的软件时,你可以先导入该开发者的公钥(通常位于他们的主页上),然后通过 GnuPG 来验证它,以确保它未被篡改
如果你是开发者,想要签名自己的软件,可以把你的公钥放在你的主页上,然后每次发布软件时带上你的签名