GnuPG
根据 官方网站
- GnuPG 是 OpenPGP 标准的完整且免费的实现,该标准由 RFC 4880(也称为 PGP)定义。 GnuPG 允许您加密和签名您的数据和通信;它具有通用的密钥管理系统,以及用于各种公钥目录的访问模块。 GnuPG,也称为 GPG,是一个命令行工具,具有易于与其他应用程序集成的功能。 提供了大量的前端应用程序和库。 GnuPG 还提供对 S/MIME 和 Secure Shell (ssh) 的支持。
安装
这也将安装 pinentry,这是一组简单的 PIN 码或密码输入对话框,GnuPG 用于密码输入。 shell 脚本 /usr/bin/pinentry
确定使用哪个 pinentry 对话框,顺序如 #pinentry 中所述。
如果您想使用图形前端或与 GnuPG 集成的程序,请参阅 应用程序列表/安全#加密、签名、隐写术。
配置
Home 目录
GnuPG home 目录是 GnuPG 套件存储其密钥环和私钥,并从中读取配置的位置。 默认情况下,使用的路径是 ~/.gnupg
。 有两种方法可以覆盖它
默认情况下,home 目录的 权限 设置为 700
,并且它包含的文件权限设置为 600
。 只有目录的所有者才有权读取、写入和访问文件。 这是为了安全目的,不应更改。 如果此目录或其中的任何文件不遵循此安全措施,您将收到有关不安全文件和 home 目录权限的警告。
配置文件
GnuPG 的所有行为都可以通过命令行参数配置。 对于您希望作为默认值的参数,您可以将它们添加到相应的配置文件中
- gpg 检查
gnupg_home/gpg.conf
(用户)和/etc/gnupg/gpg.conf
(全局) [2]。 由于 gpg 是 GnuPG 的主要入口点,因此大多数感兴趣的配置都将在此处。 有关可能的选项,请参阅 GPG 选项。 - dirmngr 检查
gnupg_home/dirmngr.conf
和/etc/gnupg/dirmngr.conf
。 dirmngr 是一个程序,由gpg
内部调用以访问 PGP 密钥服务器 [3]。 有关可能的选项,请参阅 Dirmngr 选项。
这两个配置文件涵盖了常见的用例,但 GnuPG 套件中还有更多辅助程序,它们有自己的选项。 有关完整列表,请参阅 GnuPG 手册。
创建所需的文件,并将它们的权限设置为 600
,如 #Home 目录 中所述。
将您想要的任何长选项添加到这些文件中。 不要写两个破折号,而只需写选项的名称和所需的参数。 例如,要使 GnuPG 始终使用特定路径的密钥环,就像它是以 gpg --no-default-keyring --keyring keyring-path ...
方式调用一样
gnupg_home/gpg.conf (or /etc/gnupg/gpg.conf)
no-default-keyring keyring keyring-path
其他示例可以在 #参见 中找到。
此外,pacman 使用一组不同的配置文件进行软件包签名验证。 有关详细信息,请参阅 Pacman/软件包签名。
新用户的默认选项
如果您想为新用户设置一些默认选项,请将配置文件放在 /etc/skel/.gnupg/
中。 当新用户添加到系统时,此处的文件将被复制到其 GnuPG home 目录。 还有一个名为 addgnupghome 的简单脚本,您可以使用它为现有用户创建新的 GnuPG home 目录
# addgnupghome user1 user2
这将添加相应的 /home/user1/.gnupg/
和 /home/user2/.gnupg/
,并将文件从骨架目录复制到其中。 具有现有 GnuPG home 目录的用户将被跳过。
用法
- 每当命令中需要
user-id
时,可以使用您的密钥 ID、指纹、您的姓名或电子邮件地址的一部分等来指定。 GnuPG 在这方面很灵活。 - 每当需要
key-id
时,可以通过向命令添加--keyid-format=long
标志来找到它。 例如,要显示主密钥,请运行gpg --list-secret-keys --keyid-format=long user-id
,key-id 是与 sec 在同一行上提供的十六进制哈希。
创建密钥对
通过在终端中键入以下内容来生成密钥对
$ gpg --full-gen-key
还要向命令行添加 --expert
选项以访问更多密码,特别是像 Curve448 这样的较新的 椭圆曲线。
该命令将提示您回答几个问题。 对于一般用途,大多数人会想要
- 签名和加密密钥的默认ECC(签名和加密)。
- 默认的 Curve 25519 使用 Curve25519 和 Ed25519。
- 过期日期:一年期限对于普通用户来说已经足够了。 这样,即使密钥环的访问权限丢失,它也会让其他人知道它不再有效。 在稍后阶段,如有必要,可以延长过期日期,而无需重新颁发新密钥。
- 您的姓名和电子邮件地址。 您可以稍后向同一密钥添加多个身份(例如,如果您有多个要与此密钥关联的电子邮件地址)。
- 否 可选注释。 由于注释字段的语义 定义不明确,因此其识别价值有限。
- 安全密码,在 安全#选择安全密码 中找到一些指南。
--gen-key
选项使用密钥密码、大小和过期的默认参数,并且仅询问真实姓名和电子邮件地址。列出密钥
要列出您的公钥环中的密钥
$ gpg --list-keys
要列出您的私钥环中的密钥
$ gpg --list-secret-keys
导出您的公钥
GnuPG 的主要用途是通过公钥密码术确保交换消息的机密性。 使用它,每个用户分发其密钥环的公钥,其他人可以使用该公钥来加密给用户的消息。 私钥始终必须保密,否则机密性将被破坏。 有关消息交换的示例,请参阅 Wikipedia:公钥密码术。
因此,为了让其他人向您发送加密消息,他们需要您的公钥。
要生成用户公钥的 ASCII 版本到文件 public-key.asc
(例如,通过电子邮件分发它)
$ gpg --export --armor --output public-key.asc user-id
或者,或者另外,您可以 使用密钥服务器 来共享您的密钥。
- 添加
--no-emit-version
以避免打印版本号,或将相应的设置添加到您的gpg.conf
。 - 您可以省略
user-id
以导出密钥环中的所有公钥。 如果您想一次共享多个身份,或者导入到另一个应用程序(例如 Thunderbird)中,这将非常有用。
导入公钥
为了加密发送给其他人的消息以及验证他们的签名,您需要他们的公钥。 要将文件名为 public-key.asc
的公钥导入到您的公钥环
$ gpg --import public-key.asc
或者,使用密钥服务器 查找公钥。
如果您希望导入密钥 ID 以安装特定的 Arch Linux 软件包,请参阅 pacman/软件包签名#管理密钥环 和 Makepkg#签名检查。
使用密钥服务器
发送密钥
您可以向公共 PGP 密钥服务器注册您的密钥,以便其他人可以检索它,而无需直接与您联系
$ gpg --send-keys key-id
搜索和接收密钥
要在密钥服务器上查找密钥的详细信息,而无需导入它,请执行
$ gpg --search-keys user-id
要从密钥服务器导入密钥
$ gpg --receive-keys key-id
要使用密钥服务器刷新/更新密钥链到最新版本
$ gpg --refresh-keys
- 您应该通过将其指纹与所有者在独立来源(例如,直接联系该人)上发布的指纹进行比较来验证检索到的公钥的真实性。 有关更多信息,请参阅 Wikipedia:公钥指纹。
- 建议在接收密钥时使用长密钥 ID 或完整指纹。 使用短 ID 可能会遇到冲突。 所有具有短 ID 的密钥都将被导入,有关此类示例,请参阅 在野外发现的假密钥。
auto-key-retrieve
添加到 GPG 配置文件 将在需要时自动从密钥服务器获取密钥。 这不是对安全性的妥协,但可以被认为是侵犯隐私; 请参阅 gpg(1) § auto-key-retrieve 中的“web bug”。密钥服务器
有关 OpenPGP 密钥服务器及其功能的概述,请参阅 OpenPGP#密钥服务器。
可以使用 配置文件 之一中的 keyserver
选项指定备用密钥服务器,例如
~/.gnupg/dirmngr.conf
keyserver hkp://keyserver.ubuntu.com
当常规服务器无法正常工作时,临时使用另一个服务器很方便。 例如,可以通过以下方式实现
$ gpg --keyserver hkps://keys.openpgp.org/ --search-keys user-id
- 如果您遇到密钥服务器故障,您可能需要事先检查您的 DNS 和您的解析器配置或其日志(例如 systemd-resolved)。
- 如果接收失败并显示消息
gpg: keyserver receive failed: Connection refused
,请尝试使用其他 DNS 服务器。 - 如果连接到密钥服务器失败并显示
gpg: keyserver receive failed: Server indicated a failure
,您可能需要配置 gpg 以使用备用端口。 例如,要在 Ubuntu 的密钥服务器上使用端口 80,请使用keyserver hkp://keyserver.ubuntu.com:80
。 - 您可以使用 Tor 和 Tor#Torsocks 连接到密钥服务器。 或者使用
--use-tor
命令行选项。 有关更多信息,请参阅 [4]。 - 您可以通过设置
http_proxy
环境变量 并在dirmngr.conf
中设置honor-http-proxy
来使用代理连接到密钥服务器。 或者,在配置文件中设置http-proxy host[:port]
以覆盖同名的环境变量。 重启dirmngr.service
用户服务 以使更改生效。
Web 密钥目录
有关概述,请参阅 OpenPGP#Web 密钥目录。
使用 WKD 查找证书
当加密到电子邮件地址(例如 user@example.org
)时,如果本地密钥环中尚不存在公钥,则 GnuPG (>=2.1.16) 将通过 HTTPS 查询域 (example.com
) 以获取公共 OpenPGP 密钥。 如果本地密钥环中没有此电子邮件地址的密钥,则 --auto-key-locate
选项将默认使用 WKD 协议来定位密钥
$ gpg --recipient user@example.org --auto-key-locate --encrypt doc
创建 WKD
如果您自己控制电子邮件地址的域,您可以按照 本指南 为您的域启用 WKD。
加密和解密
非对称加密
您需要在加密(选项 -e
/--encrypt
)文件或消息给该接收者(选项 -r
/--recipient
)之前 导入用户的公钥。 此外,如果您尚未这样做,则需要 创建密钥对。
要加密名为 doc 的文件,请使用
$ gpg --recipient user-id --encrypt doc
要解密(选项 -d
/--decrypt
)使用您的公钥加密的名为 doc.gpg 的文件,请使用
$ gpg --output doc --decrypt doc.gpg
gpg 将提示您输入密码,然后解密并将数据从 doc.gpg 写入 doc。 如果您省略 -o
/--output
选项,gpg 将把解密的数据写入 stdout。
- 添加
--armor
以使用 ASCII 编码加密文件,适用于复制和粘贴文本格式的消息。 - 使用
-R user-id
或--hidden-recipient user-id
代替-r
以不将接收者密钥 ID 放入加密消息中。 这有助于隐藏消息的接收者,并且是针对流量分析的有限对策。 - 添加
--no-emit-version
以避免打印版本号,或将相应的设置添加到您的配置文件。 - 您可以使用 GnuPG 通过使用您自己的用户 ID 作为接收者或使用
--default-recipient-self
标志来加密您的敏感文档; 但是,您一次只能执行一个文件,尽管您始终可以将各种文件打包成 tarball,然后加密该 tarball。 如果您要加密目录或整个文件系统,另请参阅 静态数据加密#可用方法。
对称加密
对称加密不需要生成密钥对,可以用于简单地用密码加密数据。 只需使用 -c
/--symmetric
执行对称加密
$ gpg -c doc
以下示例
- 使用密码使用对称密码加密
doc
- 使用 AES-256 密码算法加密数据
- 使用 SHA-512 摘要算法来处理密码并生成加密密钥
- 将密码迭代 65536 次
$ gpg -c --s2k-cipher-algo AES256 --s2k-digest-algo SHA512 --s2k-count 65536 doc
要使用密码解密对称加密的 doc.gpg
并将解密的内容输出到与 doc
相同的目录中,请执行
$ gpg --output doc --decrypt doc.gpg
目录
可以使用 gpgtar(1) 完成目录的加密/解密。
加密
$ gpgtar -c -o dir.gpg dir
解密
$ gpgtar -d dir.gpg
密钥维护
备份您的私钥
要备份您的私钥,请执行以下操作
$ gpg --export-secret-keys --armor --output private-key.asc user-id
如果私钥受密码保护,则导出的密钥文件将受到同一密码的保护。
GnuPG 可能会要求您输入密钥的密码。 这是必需的,因为私钥的内部保护方法与 OpenPGP 协议指定的保护方法不同。[5]
- 密码通常是保护您的私钥的最薄弱环节。 将私钥放在不同系统/设备上的安全位置,例如锁定的容器或加密驱动器。 这是您在发生驱动器故障、盗窃或更糟情况时重新获得对密钥环控制权的唯一安全保障。
- 这种备份密钥的方法有一些安全限制。 有关使用 gpg 备份和导入密钥的可能更安全的方法,请参阅 VHSblog 上的 私下移动 GPG 密钥 帖子。
要导入私钥的备份
$ gpg --import private-key.asc
备份您的吊销证书
吊销证书是为新生成的密钥自动生成的。 默认情况下,这些证书位于 ~/.gnupg/openpgp-revocs.d/
中。 证书的文件名是它将吊销的密钥的指纹。 吊销证书也可以由用户稍后手动生成,方法是使用
$ gpg --gen-revoke --armor --output revcert.asc user-id
如果密钥丢失或泄露,则可以使用此证书 吊销密钥。 如果您不再有权访问私钥,因此无法使用上述命令生成新的吊销证书,则备份将非常有用。 它足够短,可以打印出来并在必要时手动输入。
编辑您的密钥
运行 gpg --edit-key user-id
命令将显示一个菜单,您可以通过该菜单执行大多数与密钥管理相关的任务。
在编辑密钥子菜单中键入 help
以显示完整命令列表。 一些有用的命令
> passwd # change the passphrase > clean # compact any user ID that is no longer usable (e.g revoked or expired) > revkey # revoke a key > addkey # add a subkey to this key > expire # change the key expiration time > adduid # add additional names, comments, and email addresses > addphoto # add photo to key (must be JPG, 240x288 recommended, enter full path to image when prompted)
adduid
命令将每个帐户添加为身份。 然后,您可以将您喜欢的帐户设置为 primary
。导出子密钥
如果您计划在多个设备上使用同一密钥,您可能需要剥离您的主密钥,并且只在不太安全的系统上保留最少的加密子密钥。
首先,找出您要导出的子密钥。
$ gpg --list-secret-keys --with-subkey-fingerprint
仅选择要导出的子密钥。
$ gpg --armor --export-secret-subkeys subkey-id! > /tmp/subkey.asc
此时您可以停止,但更改密码也是一个好主意。 将密钥导入到临时文件夹中。
$ gpg --homedir /tmp/gpg --import /tmp/subkey.asc $ gpg --homedir /tmp/gpg --edit-key user-id > passwd > save $ gpg --homedir /tmp/gpg --armor --export-secret-subkeys subkey-id! > /tmp/subkey.altpass.asc
此时,您现在可以在您的其他设备上使用 /tmp/subkey.altpass.asc
。
延长过期日期
最好在您的子密钥上设置过期日期,这样,如果您丢失了对密钥的访问权限(例如,您忘记了密码),密钥将不会无限期地被其他人使用。 当密钥过期时,延长过期日期相对简单
$ gpg --edit-key user-id > expire
系统将提示您输入新的过期日期,以及用于签署新过期日期的私钥密码。
YYYY-MM-DD
格式的日期或 YYYYMMDDThhmmss
格式的时间戳作为过期值来指定确切的过期日期和时间。对任何其他已过期的子密钥重复此操作
> key 1 > expire
最后,保存更改并退出
> save
将其更新到密钥服务器。
$ gpg --keyserver keyserver.ubuntu.com --send-keys key-id
或者,如果您在多台计算机上使用此密钥,您可以导出公钥(带有新签名的过期日期)并将其导入到这些机器上
$ gpg --export --output pubkey.gpg user-id $ gpg --import pubkey.gpg
无需重新导出您的私钥或更新您的备份:主密钥本身永远不会过期,并且留在公钥和子密钥上的过期日期签名是所有需要的。
轮换子密钥
或者,如果您更喜欢在子密钥过期后完全停止使用它们,您可以创建新的子密钥。 提前几周执行此操作,以便其他人可以更新他们的密钥环。
创建新的子密钥(对签名密钥和加密密钥重复此操作)
$ gpg --edit-key user-id > addkey
并回答它提出的以下问题(有关建议的设置,请参阅 #创建密钥对)。
保存更改
> save
将其更新到密钥服务器。
$ gpg --keyserver pgp.mit.edu --send-keys user-id
您还需要导出私钥的新副本以进行备份。 有关如何执行此操作的详细信息,请参阅 #备份您的私钥。
吊销密钥
密钥撤销应在密钥泄露、被取代、不再使用或您忘记了密码短语时执行。这通过将密钥与密钥的撤销证书合并来完成。
如果您无法再访问您的密钥对,首先导入公钥以导入您自己的密钥。
然后,要撤销密钥,导入保存在#备份您的撤销证书中的文件
$ gpg --import revcert.asc
现在需要公开撤销。如果您过去使用过公钥服务器,请使用密钥服务器将撤销的密钥发送到公共 PGP 服务器;否则,将撤销的密钥导出到文件并分发给您的通信伙伴。
签名
签名用于认证文档并添加时间戳。如果文档被修改,签名验证将失败。与使用接收者公钥加密文档的加密不同,签名是使用发送者的私钥创建的。签名文档的接收者随后使用发送者的公钥验证签名。
创建签名
签署文件
要签署文件,请使用 -s
/--sign
标志
$ gpg --output doc.sig --sign doc
doc.sig
文件包含原始文件 doc
的压缩内容和二进制格式的签名,但该文件未加密。但是,您可以将签名与加密结合使用。
明文签署文件或消息
要签署文件而不将其压缩为二进制格式,请使用
$ gpg --output doc.sig --clearsign doc
这里,原始文件 doc
的内容和签名都以人类可读的形式存储在 doc.sig
中。
制作分离式签名
要创建一个与文档或文件本身分开分发的单独签名文件,请使用 --detach-sig
标志
$ gpg --output doc.sig --detach-sig doc
这里,签名存储在 doc.sig
中,但 doc
的内容未存储在其中。此方法常用于分发软件项目,以允许用户验证程序是否未被第三方修改。
验证签名
要验证签名,请使用 --verify
标志
$ gpg --verify doc.sig
其中 doc.sig
是包含您要验证的签名的已签名文件。
如果您正在验证分离式签名,则在验证时,已签名的数据文件和签名文件都必须存在。例如,要验证 Arch Linux 的最新 iso,您将执行以下操作
$ gpg --verify archlinux-version.iso.sig
其中 archlinux-version.iso
必须位于同一目录中。
您还可以使用第二个参数指定已签名的数据文件
$ gpg --verify archlinux-version.iso.sig /path/to/archlinux-version.iso
如果文件除了被签名外还被加密,只需解密该文件,其签名也将被验证。
gpg-agent
gpg-agent 主要用作守护程序,以请求和缓存密钥链的密码。如果从外部程序(如邮件客户端)使用 GnuPG,这将非常有用。gnupg 带有默认启用的 systemd 用户套接字。这些套接字是 gpg-agent.socket
、gpg-agent-extra.socket
、gpg-agent-browser.socket
、gpg-agent-ssh.socket
和 dirmngr.socket
。
- 主
gpg-agent.socket
由 gpg 用于连接到 gpg-agent 守护程序。 - 本地系统上
gpg-agent-extra.socket
的预期用途是设置从远程系统转发的 Unix 域套接字。这使得可以在远程系统上使用 gpg,而无需将私钥暴露给远程系统。有关详细信息,请参阅 gpg-agent(1)。 gpg-agent-browser.socket
允许 Web 浏览器访问 gpg-agent 守护程序。gpg-agent-ssh.socket
可以被 SSH 用来缓存由 ssh-add 程序添加的 SSH 密钥。有关必要的配置,请参阅 #SSH 代理。dirmngr.socket
启动一个 GnuPG 守护程序,处理与密钥服务器的连接。
ListenStream
(参见 systemd.socket(5) § options),使其与 gpgconf --list-dirs
一致。套接字名称使用非默认 GnuPG 主目录的哈希值 [7],因此您可以硬编码它,而不必担心它会更改。配置
gpg-agent 可以通过 ~/.gnupg/gpg-agent.conf
文件进行配置。配置选项在 gpg-agent(1) 中列出。例如,您可以更改未使用密钥的缓存 ttl
~/.gnupg/gpg-agent.conf
default-cache-ttl 3600
$ /usr/lib/gnupg/gpg-preset-passphrase --preset XXXXX
其中 XXXXX 是密钥指纹。您可以在运行 gpg --with-keygrip --list-secret-keys
时获取其值。密码短语将存储到 gpg-agent
重新启动为止。如果您设置了 default-cache-ttl
值,它将优先。
--allow-preset-passphrase
启动 gpg-agent 或在 ~/.gnupg/gpg-agent.conf
中设置 allow-preset-passphrase
来允许此密码短语预设。重新加载代理
更改配置后,使用 gpg-connect-agent 重新加载代理
$ gpg-connect-agent reloadagent /bye
该命令应打印 OK
。
但是,在某些情况下,仅重新启动可能不足够,例如当 keep-screen
已添加到代理配置中时。在这种情况下,您首先需要杀死正在进行的 gpg-agent 进程,然后您可以按照上述说明重新启动它。
pinentry
可以通过 pinentry-program
节配置 gpg-agent
,以便在提示用户输入密码短语时使用特定的 pinentry 用户界面。例如
~/.gnupg/gpg-agent.conf
pinentry-program /usr/bin/pinentry-curses
还有其他 pinentry 程序可供您选择 - 请参阅 pacman -Ql pinentry | grep /usr/bin/
。您可能需要为您选择的 pinentry 程序安装相关的可选依赖项。
- pinentry 程序
/usr/bin/pinentry-gnome3
(GNOME)、/usr/bin/pinentry-qt
、/usr/bin/pinentry-qt5
和/usr/bin/pinentry-gtk
(通用) [8] 支持 DBus Secret Service API,该 API 允许通过兼容的管理器(如 GNOME Keyring、KeePassXC 或 KDE Wallet)记住密码。 - KDE Wallet 的替代方案是
/usr/bin/pinentry-kwallet
,它需要安装 kwalletcliAUR 软件包。
PINENTRY_KDE_USE_WALLET
设置为非空值来重新启用 Secret Service API 集成。记住在更改配置后重新加载代理。
缓存密码
max-cache-ttl
和 default-cache-ttl
定义 gpg-agent 应缓存密码多少秒。要在一个会话中输入一次密码,请将它们设置为非常高的值,例如
gpg-agent.conf
max-cache-ttl 60480000 default-cache-ttl 60480000
对于 SSH 模拟模式下的密码缓存,请设置 default-cache-ttl-ssh
和 max-cache-ttl-ssh
,例如
gpg-agent.conf
default-cache-ttl-ssh 60480000 max-cache-ttl-ssh 60480000
无人值守密码短语
从 GnuPG 2.1.0 开始,需要使用 gpg-agent 和 pinentry,这可能会破坏从 STDIN 使用 --passphrase-fd 0
命令行选项管道输入密码短语的向后兼容性。为了具有与旧版本相同类型的功能,必须完成两件事
首先,编辑 gpg-agent 配置以允许环回 pinentry 模式
~/.gnupg/gpg-agent.conf
allow-loopback-pinentry
如果代理正在运行,重新加载代理以使更改生效。
其次,应用程序需要更新以包含使用环回模式的命令行参数,如下所示
$ gpg --pinentry-mode loopback ...
...或者,如果不可能这样做,请将该选项添加到配置中
~/.gnupg/gpg.conf
pinentry-mode loopback
SSH 代理
gpg-agent 具有 OpenSSH 代理模拟。如果您已经使用 GnuPG 套件,您不妨考虑使用其代理来缓存您的 SSH 密钥。此外,某些用户可能更喜欢 GnuPG 代理提供的 PIN 输入对话框,作为其密码短语管理的一部分。
设置 SSH_AUTH_SOCK
设置以下变量以与 gpg-agent 而不是默认的 ssh-agent 通信。
SSH_AGENT_PID="" SSH_AUTH_SOCK="${XDG_RUNTIME_DIR}/gnupg/S.gpg-agent.ssh"
- 如果您正在使用脚本来管理您的变量,您也可以取消设置
SSH_AGENT_PID
,而不是将其设置为""
,通过unset SSH_AGENT_PID
。 - 如果您手动设置
SSH_AUTH_SOCK
,请记住,如果您使用自定义的GNUPGHOME
,您的套接字位置可能会有所不同。您可以使用以下 bash 示例,或将SSH_AUTH_SOCK
更改为gpgconf --list-dirs agent-ssh-socket
的值。 - 如果安装了 GNOME Keyring,则必须禁用其 ssh 组件。否则,它将覆盖
SSH_AUTH_SOCK
。
或者,依赖于 Bash。这也适用于非标准套接字位置
~/.bashrc
unset SSH_AGENT_PID if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)" fi
gnupg_SSH_AUTH_SOCK_by
变量的测试是针对代理以 gpg-agent --daemon /bin/sh
启动的情况,在这种情况下,shell 从父进程继承 SSH_AUTH_SOCK
变量,gpg-agent [10]。配置 pinentry 以使用正确的 TTY
还要设置 GPG_TTY 并在用户切换到 X 会话时刷新 TTY,如 gpg-agent(1) 中所述。例如
~/.bashrc
export GPG_TTY=$(tty) gpg-connect-agent updatestartuptty /bye >/dev/null
如果您同时使用多个终端,并且希望 gpg-agent 从运行 ssh 命令的同一终端通过 pinentry-curses 请求密码短语,请将以下内容添加到 SSH 配置文件中。这将使每次运行 ssh 命令时都刷新 TTY [11]
~/.ssh/config
Match host * exec "gpg-connect-agent UPDATESTARTUPTTY /bye"
请注意,必须设置 GPG_TTY 环境变量才能使其工作。
添加 SSH 密钥
一旦 gpg-agent 运行,您可以使用 ssh-add 来批准密钥,遵循与 ssh-agent 相同的步骤。批准的密钥列表存储在 ~/.gnupg/sshcontrol
文件中。
一旦您的密钥被批准,每次需要您的密码短语时,您都会收到一个 pinentry 对话框。有关密码缓存,请参阅 #缓存密码。
使用 PGP 密钥进行 SSH 身份验证
您还可以使用您的 PGP 密钥作为 SSH 密钥。这需要具有 Authentication
功能的密钥(请参阅 #自定义功能)。使用 PGP 密钥进行 SSH 身份验证有多种好处,包括
- 减少密钥维护,因为您不再需要维护 SSH 密钥。
- 能够将身份验证密钥存储在智能卡上。当卡可用时,GnuPG 将自动检测到密钥,并将其添加到代理(使用
ssh-add -l
或ssh-add -L
检查)。密钥的注释应类似于:openpgp:key-id
或cardno:card-id
。
要检索您的 GPG/SSH 密钥的公钥部分,请运行 gpg --export-ssh-key gpg-key
。如果您的密钥具有身份验证功能,但此命令仍然失败并显示“Unusable public key”,请添加 !
后缀 ([12])。
除非您的 GPG 密钥在密钥卡上,否则您需要将您的密钥添加到 $GNUPGHOME/sshcontrol
才能被识别为 SSH 密钥。如果您的密钥在密钥卡上,则其密钥指纹将隐式添加到 sshcontrol
。否则,请通过以下方式获取您的密钥的密钥指纹
$ gpg --list-keys --with-keygrip
sub rsa4096 2018-07-25 [A] Keygrip = 1531C8084D16DC4C36911F1585AF0ACE7AAFD7E7
然后像这样编辑 sshcontrol
。添加密钥指纹是一次性操作;除非您要添加其他密钥,否则您无需再次编辑该文件。
$GNUPGHOME/sshcontrol
1531C8084D16DC4C36911F1585AF0ACE7AAFD7E7
将 gpg-agent 和 ssh-agent 转发到远程
可以将一个人的 gpg-agent 转发到远程计算机,方法是将 gpg 套接字转发到远程计算机,如 GnuPG wiki 所述。
首先,将以下行添加到远程计算机上的 /etc/ssh/sshd_config
中,以启用在连接时自动删除过时的套接字。如果没有此项,则在启用代理转发以使其工作之前,需要手动删除远程计算机上的套接字。
/etc/ssh/sshd_config
... StreamLocalBindUnlink yes ...
sshd.service
,以使新配置被 sshd 加载。在客户端上,使用 RemoteForward
SSH 指令将目标为远程端口的流量转发到本地主机上的端口。如 ssh_config(5) § RemoteForward 中所述,此指令的参数是远程计算机上的侦听套接字路径,然后是本地主机上的目标套接字路径。您的配置应如下所示
~/.ssh/config
Host remote_name ... RemoteForward remote_agent_socket local_agent_extra_socket RemoteForward remote_agent_ssh_socket local_agent_ssh_socket
第一行配置 gpg-agent 转发
- remote_agent_socket 是远程主机上
gpgconf --list-dir agent-socket
的输出。 - local_agent_extra_socket 是本地主机上
gpgconf --list-dir agent-extra-socket
的输出。
第二行是可选的。它配置 ssh-agent 转发
- remote_agent_ssh_socket 是远程主机上
gpgconf --list-dir agent-ssh-socket
的输出。 - local_agent_ssh_socket 是本地主机上
gpgconf --list-dir agent-ssh-socket
的输出。
SSH_AUTH_SOCK
设置为 gpgconf --list-dir agent-ssh-socket
的输出,如 #SSH 代理 中所述)。因此,使用默认路径,它将是
RemoteForward /run/user/1000/gnupg/S.gpg-agent /run/user/1000/gnupg/S.gpg-agent.extra RemoteForward /run/user/1000/gnupg/S.gpg-agent.ssh /run/user/1000/gnupg/S.gpg-agent.ssh
完成此配置后,调用 ssh remote_name
应会自动将 gpg-agent 转发到远程计算机,并允许使用您的 gpg 密钥进行解密/签名(如果包含第二行 RemoteForward
行,则允许将 ssh-agent 与 gpg 一起使用)。
智能卡
GnuPG 使用 scdaemon 作为智能卡读卡器的接口,请参阅 手册页 scdaemon(1) 以了解详细信息。
GnuPG 的 gpg-card 工具可用于配置 scdaemon,并充当智能卡配置的前端,请参阅 gpg-card(1) 以了解详细信息。
gpg --edit-card
命令将密钥移动到智能卡,则可能保留了明文私钥备份。[13] 有关信息和使用 gpg-card checkkeys
进行补救,请参阅 GnuPG 咨询。仅限 GnuPG 设置
如果您不打算使用其他卡,而只使用基于 GnuPG 的卡,则应检查 ~/.gnupg/scdaemon.conf
中的 reader-port
参数。值 '0' 指的是第一个可用的串行端口读卡器,值 '32768'(默认值)指的是第一个 USB 读卡器。
GnuPG 与 pcscd (PCSC Lite)
pcscd(8) 是一个守护程序,用于处理对智能卡(SCard API)的访问。在早期版本中,如果 GnuPG 的 scdaemon 无法直接连接到智能卡(例如,通过使用其集成的 CCID 支持),它会回退并尝试使用 PCSC Lite 驱动程序查找智能卡。自 2.4 版本起,但是,您将必须在 ~/.gnupg/scdaemon.conf
中添加 disable-ccid
选项,才能使用 pcscd。
要使用 pscsd,安装 pcsclite 和 ccid。然后启动和/或启用 pcscd.service
。或者启动和/或启用 pcscd.socket
以在需要时激活守护程序。
始终使用 pcscd
如果您正在使用任何带有 opensc 驱动程序的智能卡(例如:来自某些国家的身份证),您应该注意 GnuPG 配置。开箱即用,当使用 gpg --card-status
时,您可能会收到如下消息
gpg: selecting openpgp failed: ec=6.108
默认情况下,scdaemon 将尝试直接连接到设备。如果读卡器正在被另一个进程使用,则此连接将失败。例如:OpenSC 使用的 pcscd 守护程序。为了应对这种情况,我们应该使用与 opensc 相同的底层驱动程序,以便它们可以很好地协同工作。为了指示 scdaemon 使用 pcscd,您应该从 ~/.gnupg/scdaemon.conf
中删除 reader-port
,指定 libpcsclite.so
库的位置并禁用 ccid,以确保我们使用 pcscd
~/.gnupg/scdaemon.conf
pcsc-driver /usr/lib/libpcsclite.so card-timeout 5 disable-ccid
如果您不使用 OpenSC,请检查 scdaemon(1)。
GnuPG scdaemon
是唯一流行的 pcscd
客户端,它在连接到 pcscd
时使用 PCSC_SHARE_EXCLUSIVE
标志。其他客户端(如浏览器和 电子身份识别 中列出的程序使用的 OpenSC PKCS#11)正在使用 PCSC_SHARE_SHARED
,它允许同时访问单个智能卡。当有其他客户端连接时,pcscd
不会授予对智能卡的独占访问权。这意味着要使用 GnuPG 智能卡功能,您必须事先关闭所有打开的浏览器窗口或执行其他不方便的操作。
从 2.2.28 LTS 和 2.3.0 版本开始,您可以通过修改 scdaemon.conf
文件并在其末尾添加行 pcsc-shared
来启用共享访问。请记住,scdaemon(1) § --pcsc-shared 将此标志描述为“有点危险的选项”,因为“某些信息是从卡中缓存的”。
多应用小程序智能卡
当使用 YubiKeys 或其他多应用小程序 USB 加密狗时,OpenSC PKCS#11 可能会遇到问题,其中 OpenSC 将您的 Yubikey 从 OpenPGP 切换到 PIV 应用小程序,从而破坏 scdaemon
。
您可以通过强制 OpenSC 也使用 OpenPGP 应用小程序来解决此问题。打开 /etc/opensc.conf
文件,搜索 Yubikey 并将 driver = "PIV-II";
行更改为 driver = "openpgp";
。如果没有此类条目,请使用 pcsc_scan
。搜索应答复位 ATR: 12 34 56 78 90 AB CD ...
。然后在 app
块中创建一个新的 card_atr
块,引用您的设备 ATR。
/etc/opensc.conf
app default { ... card_atr 12:23:34:45:67:89:ab:cd:... { name = "YubiKey Neo"; driver = "openpgp" } } ...
之后,您可以使用 pkcs11-tool -O --login
测试 OpenPGP 应用小程序是否默认被选中。其他 PKCS#11 客户端(如浏览器)可能需要重新启动才能应用该更改。
在远程客户端上使用智能卡
例如,如果您通过 SSH 登录到计算机或通过 usbipd-win 将智能卡共享到 WSL,并尝试通过 pcscd 使用连接的设备,您会注意到如下错误
gpg: selecting card failed: No such device gpg: OpenPGP card not available: No such device
这是由于 Polkit 限制对本地客户端的访问。要解决此问题,您可以添加一条规则以允许某些用户在所有情况下都访问。以下规则允许 wheel
组中的所有用户通过 pcscd
访问设备
/etc/polkit-1/rules.d/99-pcscd.rules
polkit.addRule(function(action, subject) { if (action.id == "org.debian.pcsc-lite.access_card" && subject.isInGroup("wheel")) { return polkit.Result.YES; } }); polkit.addRule(function(action, subject) { if (action.id == "org.debian.pcsc-lite.access_pcsc" && subject.isInGroup("wheel")) { return polkit.Result.YES; } });
创建文件后,请确保重新启动 polkit.service
。
OpenPGP 兼容性
GnuPG 最初是 OpenPGP 格式的实现。目前,该项目基于 RFC 4880,并且不支持 RFC 9580(它取代了 RFC 4880)。
但是,从 2022 年 12 月的版本 2.4.0 开始,GnuPG 已选择在 IETF 流程之外推出对格式的更改和扩展(请参阅 draft-koch-librepgp)。
大多数 GnuPG 专有格式(与 OpenPGP 标准 不同)都带有“版本 5”(此版本未在 IETF OpenPGP 标准中使用)并引入不兼容性
- GnuPG “版本 5”密钥使用不同的指纹(更长,因为使用了 SHA-256)。
- 添加了新的对称加密数据包格式(OCB 加密数据包)。对这种格式的支持通过“功能标志”发出信号,该标志默认情况下被积极启用。请参阅 #禁用不受支持的 AEAD 机制。
- 一种新的 后量子密码学格式,再次偏离 IETF 流程(请参阅 draft-ietf-openpgp-pqc)。
外部评论对 GnuPG 格式扩展的合理性提出了担忧(请参阅 LibrePGP 中已知安全问题的摘要)。
有关 GnuPG 特定格式更改的更深入讨论,请参阅 对“对 OpenPGP 更新的评论的评论”的评论。
Arch Linux 的立场是优先考虑与 OpenPGP 标准的兼容性。为此,诸如 默认情况下恢复 RFC4880bis 的补丁之类的补丁已应用于 gnupg 软件包。这确保了与其他 OpenPGP 实现的长期兼容性,并默认避免了供应商锁定。
禁用不受支持的 AEAD 机制
使用 gnupg 2.4,gpg
生成密钥,这些密钥声明支持 GnuPG 特定的 AEAD 加密机制(基于 OCB)。但是,其他 OpenPGP 实现不支持此 AEAD 风格!
尽管许多下游尝试通过 修补 GnuPG 源代码来删除此新默认值,但在使用 --full-gen-key
时,基于 OCB 的自定义 AEAD 加密机制仍然为新密钥设置。
是否为密钥设置了 GnuPG 的自定义 AEAD 可以借助 gpg
本身进行检查
$ gpg --expert --edit-key <FINGERPRINT> gpg> showpref [ultimate] (1). Foobar McFooface (test) <foobar@mcfooface.com> Cipher: AES256, AES192, AES, 3DES AEAD: OCB Digest: SHA512, SHA384, SHA256, SHA224, SHA1 Compression: ZLIB, BZIP2, ZIP, Uncompressed Features: MDC, AEAD, Keyserver no-modify
可以禁用此机制
gpg> setpref AES256 AES192 AES SHA512 SHA384 SHA256 SHA224 ZLIB BZIP2 ZIP Set preference list to: Cipher: AES256, AES192, AES, 3DES AEAD: Digest: SHA512, SHA384, SHA256, SHA224, SHA1 Compression: ZLIB, BZIP2, ZIP, Uncompressed Features: MDC, Keyserver no-modify Really update the preferences? (y/N) y
技巧和窍门
不同的算法
您可能想要使用更强大的算法
~/.gnupg/gpg.conf
... personal-digest-preferences SHA512 cert-digest-algo SHA512 default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed personal-cipher-preferences TWOFISH CAMELLIA256 AES 3DES
在最新版本的 GnuPG 中,使用的默认算法是 SHA256 和 AES,这两种算法对于大多数人来说都足够安全。但是,如果您使用的 GnuPG 版本早于 2.1,或者如果您想要更高的安全级别,则应遵循上述步骤。
加密密码
加密某些密码可能很有用,这样它就不会以明文形式写入配置文件中。一个很好的例子是您的电子邮件密码。
首先创建一个包含您的密码的文件。您需要在密码后保留一个空行,否则 gpg 在评估文件时将返回错误消息。
然后运行
$ gpg -e -a -r user-id your_password_file
-e
用于加密,-a
用于 armor(ASCII 输出),-r
用于接收者用户 ID。
您将得到一个新的 your_password_file.asc
文件。
更改信任模型
默认情况下,GnuPG 使用 信任网络作为信任模型。您可以通过在添加密钥时添加 --trust-model=tofu
或将此选项添加到您的 GnuPG 配置文件来将其更改为 首次使用时信任。更多详细信息请参见 发送到 GnuPG 列表的这封电子邮件。
隐藏所有接收者 ID
默认情况下,接收者的密钥 ID 包含在加密消息中。可以通过在加密时为接收者使用 hidden-recipient user-id
来移除它。要为所有接收者移除它,请在您的配置文件中添加 throw-keyids
。这有助于隐藏消息的接收者,并且是针对流量分析的有限对策(即,通过一点社会工程学,任何能够解密消息的人都可以检查其他接收者中是否有人是他们怀疑的对象)。在接收端,这可能会减慢解密过程,因为必须尝试所有可用的密钥(例如,使用 --try-secret-key user-id
)。
使用 caff 进行密钥签名聚会
为了允许用户验证密钥服务器和他们密钥环中的密钥(即,确保它们来自他们声称的身份),PGP/GPG 使用了 信任网络。密钥签名聚会允许用户在物理位置聚集在一起以验证密钥。齐默尔曼-萨萨曼密钥签名协议是一种使这些聚会非常有效的方法。这里 您将找到一篇操作指南文章。
为了简化密钥签名和在密钥签名聚会后将签名发送给所有者的过程,您可以使用工具 caff。它可以从 AUR 安装,软件包为 caff-gitAUR。
要将签名发送给其所有者,您需要一个工作的 邮件传输代理 (MTA)。如果您还没有,请安装 msmtp。
始终显示长 ID 和指纹
要始终显示长密钥 ID,请将 keyid-format 0xlong
添加到您的配置文件中。要始终显示密钥的完整指纹,请将 with-fingerprint
添加到您的配置文件中。
自定义功能
为了进一步自定义,还可以为您的密钥设置自定义功能。以下功能可用:
- 认证(仅适用于主密钥)- 允许密钥创建认证,证明其他密钥上的用户 ID 是正确的。
- 签名 - 允许密钥创建对数据的加密签名,其他人可以使用公钥进行验证。
- 加密 - 允许任何人使用公钥加密数据,只有私钥才能解密。
- 认证 - 允许密钥使用各种非 GnuPG 程序进行身份验证。密钥可以用作例如 SSH 密钥。
可以通过运行以下命令来指定主密钥的功能:
$ gpg --full-generate-key --expert
--full-generate-key
时,生成的密钥将声明 AEAD 机制,这不被其他 OpenPGP 实现所理解。要在密钥创建后禁用此功能,请参阅 #禁用不支持的 AEAD 机制。并选择允许您设置自己的功能的选项。
类似地,要为子密钥指定自定义功能,请将 --expert
标志添加到 gpg --edit-key
,有关更多信息,请参阅 #编辑您的密钥。
故障排除
su
当使用 pinentry
时,您必须拥有正在使用的终端设备(例如 /dev/tty1
)的正确权限。但是,使用 su(或 sudo),所有权仍然属于原始用户,而不是新用户。这意味着 pinentry 将会失败,并出现 Permission denied
错误,即使是以 root 身份。如果在尝试使用 ssh 时发生这种情况,将返回类似 sign_and_send_pubkey: signing failed: agent refused operation
的错误。解决方法是在使用 pinentry 之前(即使用带有代理的 gpg)的某个时间点更改设备的权限。如果以 root 身份执行 gpg,只需在 使用 gpg 之前将所有权更改为 root
# chown root $(tty)
然后在 su(或 sudo)终止后将其改回。
tty
组的一部分 是不 够的。script
运行 gpg,它将使用具有正确所有权的新 tty# script -q -c "gpg --gen-key" /dev/null
Agent 抱怨文件结尾
如果 pinentry 程序是 /usr/bin/pinentry-gnome3
,它需要一个 DBus 会话总线才能正常运行。有关详细信息,请参阅 通用故障排除#会话权限。
或者,您可以使用 #pinentry 中描述的各种不同的选项。
KGpg 配置权限
在 kgpg 访问 ~/.gnupg/
选项时存在问题。一个问题可能是由于已弃用的 options 文件导致的,请参阅 bug 报告。
Wayland 上的 GNOME 覆盖 SSH 代理套接字
对于 Wayland 会话,gnome-session
将 SSH_AUTH_SOCK
设置为标准的 gnome-keyring 套接字 $XDG_RUNTIME_DIR/keyring/ssh
。这会覆盖在其他地方设置的任何值。
有关如何禁用此行为,请参阅 GNOME/Keyring#禁用。
mutt
Mutt 可能无法正确使用 gpg-agent,您需要在运行 mutt 时设置一个 环境变量 GPG_AGENT_INFO
(内容无关紧要)。还要确保正确启用密码缓存,请参阅 #缓存密码。
请参阅 此论坛帖子。
“丢失”的密钥,升级到 gnupg 版本 2.1
当 gpg --list-keys
未能显示曾经存在的密钥,并且应用程序抱怨密钥丢失或无效时,某些密钥可能尚未迁移到新格式。
请阅读 GnuPG 无效数据包解决方法。基本上,它说明旧的 pubring.gpg
和 secring.gpg
文件中的密钥存在错误,这些文件现在已被新的 pubring.kbx
文件和 private-keys-v1.d/
子目录和文件取代。您可以使用以下命令恢复丢失的密钥:
$ cd $ cp -r .gnupg gnupgOLD $ gpg --export-ownertrust > otrust.txt $ gpg --import .gnupg/pubring.gpg $ gpg --import-ownertrust otrust.txt $ gpg --list-keys
gpg 在所有密钥服务器上挂起(尝试接收密钥时)
如果 gpg 在尝试接收密钥时在某个密钥服务器上挂起,您可能需要杀死 dirmngr 以访问实际上正在工作的其他密钥服务器,否则它可能会一直挂起所有密钥服务器。
未检测到智能卡
您的用户可能没有访问智能卡的权限,这会导致抛出 card error
,即使卡已正确设置并插入。
一个可能的解决方案是添加一个新的组 scard
,其中包括需要访问智能卡的用户。
然后使用 udev 规则,类似于以下内容:
/etc/udev/rules.d/71-gnupg-ccid.rules
ACTION=="add", SUBSYSTEM=="usb", ENV{ID_VENDOR_ID}=="1050", ENV{ID_MODEL_ID}=="0116|0111", MODE="660", GROUP="scard"
需要根据 lsusb
输出调整 VENDOR 和 MODEL,以上示例适用于 YubikeyNEO。
服务器 'gpg-agent' 比我们旧 (x < y)
如果 gnupg
已升级,但旧的 gpg-agent 仍在运行,则会出现此警告。重启 用户 的 gpg-agent.socket
(即,重启时使用 --user
标志)。
IPC 连接调用失败
确保 gpg-agent
和 dirmngr
没有运行,可以使用 killall gpg-agent dirmngr
杀死它们,并且 $GNUPGHOME/crls.d/
文件夹的权限设置为 700
。
默认情况下,gnupg 软件包使用目录 /run/user/$UID/gnupg/
作为套接字。GnuPG 文档 指出这是首选目录(并非所有文件系统都支持套接字)。验证您的 agent-socket
配置是否指定了具有适当文件系统的路径。您可以通过运行 gpgconf --list-dirs agent-socket
找到您的 agent-socket
路径设置。
使用 gpg-agent --daemon
测试 gpg-agent
是否成功启动。
缓解中毒的 PGP 证书
在 2019 年 6 月,一位不明攻击者用数万(或数十万)个签名垃圾邮件攻击了几个高知名度的 PGP 证书 (CVE-2019-13050),并将这些签名上传到密钥服务器。密钥环中存在这些中毒的证书会导致 gpg 挂起,并显示以下消息:
gpg: removing stale lockfile (created by 7055)
可能的缓解措施是按照这篇 博客文章 中的说明删除中毒的证书。
无效的 IPC 响应和设备的不适当 ioctl
默认的 pinentry 程序是 /usr/bin/pinentry-gtk-2
。如果 gtk2 不可用,pinentry 将回退到 /usr/bin/pinentry-curses
,并导致签名失败
gpg: signing failed: Inappropriate ioctl for device gpg: [stdin]: clear-sign failed: Inappropriate ioctl for device
您需要为 pinentry 程序 /usr/bin/pinentry-tty
和 /usr/bin/pinentry-curses
设置 GPG_TTY
环境变量。
$ export GPG_TTY=$(tty)
密钥块资源不存在
如果您在尝试导入密钥时收到类似这样的错误:
gpg: keyblock resource 'gnupg_home/pubring.kbx': No such file or directory
这是因为如果 GnuPG 的主目录尚不存在,则它不会创建它。只需手动创建它即可:
$ mkdir -m 700 gnupg_home
子密钥创建时具有受限功能
在某些情况下,使用自定义功能集创建子密钥会导致子密钥被标记为“受限”。当在交互式提示中切换功能时,在选项 7 或 8(“设置您自己的功能”)的 addkey
命令中会发生这种情况。一种解决方法是在提示选择功能时,直接输入所需的功能集作为字符串,而不是切换单个功能。例如,输入 "=A" 以创建仅具有身份验证功能的子密钥。