GnuPG
According to the official website
- GnuPG is a complete and free implementation of the OpenPGP standard as defined by RFC 4880 (also known as PGP). GnuPG allows you to encrypt and sign your data and communications; it features a versatile key management system, along with access modules for all kinds of public key directories. GnuPG, also known as GPG, is a command line tool with features for easy integration with other applications. A wealth of frontend applications and libraries are available. GnuPG also provides support for S/MIME and Secure Shell (ssh).
安装
gnupg should already be installed on your system as it is a dependency of pacman.
This will also install pinentry, a collection of simple PIN or passphrase entry dialogs which GnuPG uses for passphrase entry. The shell script /usr/bin/pinentry determines which pinentry dialog is used, in the order described at #pinentry.
If you want to use a graphical frontend or program that integrates with GnuPG, see List of applications/Security#Encryption, signing, steganography.
配置
Home directory
The GnuPG home directory is where the GnuPG suite stores its keyrings and private keys, and reads configurations from. By default, the path used is ~/.gnupg. There are two ways to override this
- Set the
$GNUPGHOMEenvironment variable. - Use the
--homedirargument, e.g.$ gpg --homedir path/to/dir[1].
By default, the home directory has its permissions set to 700 and the files it contains have their permissions set to 600. Only the owner of the directory has permission to read, write, and access the files. This is for security purposes and should not be changed. In case this directory or any file inside it does not follow this security measure, you will get warnings about unsafe file and home directory permissions.
配置文件
All of GnuPG's behavior is configurable via command line arguments. For arguments you would like to be the default, you can add them to the respective configuration file
- gpg checks
gnupg_home/gpg.conf(user) and/etc/gnupg/gpg.conf(global) [2]. Since gpg is the main entrypoint for GnuPG, most configuration of interest will be here. See GPG Options for possible options. - dirmngr checks
gnupg_home/dirmngr.confand/etc/gnupg/dirmngr.conf. dirmngr is a program internally invoked bygpgto access PGP keyservers [3]. See Dirmngr Options for possible options.
These two configuration files cover the common usecases, but there are more auxiliary programs in the GnuPG suite with their own options. See the GnuPG manual for a comprehensive list.
Create the desired file(s), and set their permissions to 600 as discussed in #Home directory.
Add to these files any long options you want. Do not write the two dashes, but simply the name of the option and required arguments. For example, to make GnuPG always use a keyring at a specific path, as if it was invoked as gpg --no-default-keyring --keyring keyring-path ...
gnupg_home/gpg.conf (or /etc/gnupg/gpg.conf)
no-default-keyring keyring keyring-path
Other examples are found in #See also.
Additionally, pacman uses a different set of configuration files for package signature verification. See Pacman/Package signing for details.
Default options for new users
If you want to setup some default options for new users, put configuration files in /etc/skel/.gnupg/. When the new user is added in system, files from here will be copied to its GnuPG home directory. There is also a simple script called addgnupghome which you can use to create new GnuPG home directories for existing users
# addgnupghome user1 user2
This will add the respective /home/user1/.gnupg/ and /home/user2/.gnupg/ and copy the files from the skeleton directory to it. Users with existing GnuPG home directory are simply skipped.
用法
- Whenever a
user-idis required in a command, it can be specified with your key ID, fingerprint, a part of your name or email address, etc. GnuPG is flexible on this. - Whenever a
key-idis needed, it can be found adding the--keyid-format=longflag to the command. To show the master secret key for example, rungpg --list-secret-keys --keyid-format=long user-id, the key-id is the hexadecimal hash provided on the same line as sec.
Create a key pair
Generate a key pair by typing in a terminal
$ gpg --full-gen-key
--full-gen-key the generated key will advertise an AEAD mechanism, which is not understood by other OpenPGP implementations. To disable this after key creation see #Disable unsupported AEAD mechanism.Also add the --expert option to the command line to access more ciphers and in particular some newer elliptic curves like Curve448.
The command will prompt for answers to several questions. For general use most people will want
- The default ECC (sign and encrypt) for signing and encryption keys.
- The default Curve 25519 to use Curve25519 and Ed25519.
- An expiration date: a period of one year is good enough for the average user. This way even if access is lost to the keyring, it will allow others to know that it is no longer valid. At a later stage, if necessary, the expiration date can be extended without having to re-issue a new key.
- Your name and email address. You can add multiple identities to the same key later (e.g., if you have multiple email addresses you want to associate with this key).
- no optional comment. Since the semantics of the comment field are not well-defined, it has limited value for identification.
- A secure passphrase, find some guidelines in Security#Choosing secure passwords.
--gen-key option uses default parameters for the key cipher, size and expiry and only asks for real name and email address.List keys
To list keys in your public key ring
$ gpg --list-keys
To list keys in your secret key ring
$ gpg --list-secret-keys
Export your public key
GnuPG's main usage is to ensure confidentiality of exchanged messages via public-key cryptography. With it each user distributes the public key of their keyring, which can be used by others to encrypt messages to the user. The private key must always be kept private, otherwise confidentiality is broken. See Wikipedia:Public-key cryptography for examples about the message exchange.
So, in order for others to send encrypted messages to you, they need your public key.
To generate an ASCII version of a user's public key to file public-key.asc (e.g. to distribute it by e-mail)
$ gpg --export --armor --output public-key.asc user-id
Alternatively, or in addition, you can use a keyserver to share your key.
- Add
--no-emit-versionto avoid printing the version number, or add the corresponding setting to yourgpg.conf. - You can omit the
user-idto export all public keys within your keyring. This is useful if you want to share multiple identities at once, or for importing in another application, e.g. Thunderbird.
Import a public key
In order to encrypt messages to others, as well as verify their signatures, you need their public key. To import a public key with file name public-key.asc to your public key ring
$ gpg --import public-key.asc
Alternatively, try retrieving their public key via WKD (in case the domain of their email address supports it) or using a keyserver.
If you wish to import a key ID to install a specific Arch Linux package, see pacman/Package signing#Managing the keyring and Makepkg#Signature checking.
Use a keyserver
Sending keys
You can register your key with a public PGP key server, so that others can retrieve it without having to contact you directly
$ gpg --send-keys key-id
Searching and receiving keys
To find out details of a key on the keyserver, without importing it, do
$ gpg --search-keys user-id
To import a key from a key server
$ gpg --receive-keys key-id
To refresh/update the keychain with the latest version from a key server
$ gpg --refresh-keys
- You should verify the authenticity of the retrieved public key by comparing its fingerprint with one that the owner published on an independent source(s) (e.g., contacting the person directly). See Wikipedia:Public key fingerprint for more information.
- It is recommended to use the long key ID or the full fingerprint when receiving a key. Using a short ID may encounter collisions. All keys will be imported that have the short ID, see fake keys found in the wild for such example.
auto-key-retrieve to the GPG configuration file will automatically fetch keys from the key server as needed. This is not a compromise on security, but it can be considered a privacy violation; see "web bug" in gpg(1) § auto-key-retrieve.Key servers
See OpenPGP#Keyserver for a general overview of OpenPGP keyservers and their features.
An alternative key server can be specified with the keyserver option in one of the configuration files, for instance
~/.gnupg/dirmngr.conf
keyserver hkp://keyserver.ubuntu.com
A temporary use of another server is handy when the regular one does not work as it should. It can be achieved by, for example,
$ gpg --keyserver hkps://keys.openpgp.org/ --search-keys user-id
- If you are experiencing keyserver failures, you may want to check your DNS and your resolver configurations or its logs beforehand (e.g systemd-resolved).
- If receiving fails with the message
gpg: keyserver receive failed: Connection refused, try using a different DNS server. - If connecting to a keyserver fails with
gpg: keyserver receive failed: Server indicated a failure, you may need to configure gpg to use an alternate port. For example, to use port 80 on Ubuntu's keyserver, usekeyserver hkp://keyserver.ubuntu.com:80. - You can connect to the keyserver over Tor with Tor#Torsocks. Or using the
--use-torcommand line option. See [4] for more information. - You can connect to a keyserver using a proxy by setting the
http_proxyenvironment variable and settinghonor-http-proxyindirmngr.conf. Alternatively, sethttp-proxy host[:port]in the configuration file to override the environment variable of the same name. Restart thedirmngr.serviceuser service for the changes to take effect.
Web Key Directory
See OpenPGP#Web Key Directory for a general overview.
Lookup certificates using WKD
When encrypting to an email address (e.g. user@example.org), if it is not already in the local keyring, GnuPG, by default, will retrieve the public OpenPGP key using the Web Key Directory protocol (i.e. GnuPG will download the key via HTTPS from the example.org web server). For example
$ gpg --recipient user@example.org --encrypt doc
To retrieve a public key and import it into your keyring, use the --locate-keys or --locate-external-keys options. The former will not do anything if the key already exists in the local keyring, while the later will always refresh the key. For example
$ gpg --locate-external-keys user@example.org
--auto-key-locate option which defaults to local,wkd; see its description in gpg(1). In case you have set auto-key-locate to a value without wkd in the GPG configuration file, you can use the --auto-key-locate clear,wkd command line option to override it.Create a WKD
If you control the domain of your email address yourself and have a web server that provides HTTPS with a trusted TLS certificate, you can follow this guide to enable WKD for your domain.
Encrypt and decrypt
Asymmetric
You need to import a public key of a user before encrypting (option -e/--encrypt) a file or message to that recipient (option -r/--recipient). Additionally you need to create a key pair if you have not already done so.
To encrypt a file with the name doc, use
$ gpg --recipient user-id --encrypt doc
To decrypt (option -d/--decrypt) a file with the name doc.gpg encrypted with your public key, use
$ gpg --output doc --decrypt doc.gpg
gpg will prompt you for your passphrase and then decrypt and write the data from doc.gpg to doc. If you omit the -o/--output option, gpg will write the decrypted data to stdout.
- Add
--armorto encrypt a file using ASCII armor, suitable for copying and pasting a message in text format. - Use
-R user-idor--hidden-recipient user-idinstead of-rto not put the recipient key IDs in the encrypted message. This helps to hide the receivers of the message and is a limited countermeasure against traffic analysis. - Add
--no-emit-versionto avoid printing the version number, or add the corresponding setting to your configuration file. - You can use GnuPG to encrypt your sensitive documents by using your own user-id as recipient or by using the
--default-recipient-selfflag; however, you can only do this one file at a time, although you can always tarball various files and then encrypt the tarball. See also Data-at-rest encryption#Available methods if you want to encrypt directories or a whole file-system.
Symmetric
Symmetric encryption does not require the generation of a key pair and can be used to simply encrypt data with a passphrase. Simply use -c/--symmetric to perform symmetric encryption
$ gpg -c doc
The following example
- Encrypts
docwith a symmetric cipher using a passphrase - Uses the AES-256 cipher algorithm to encrypt the data
- Uses the SHA-512 digest algorithm to mangle the passphrase and generate the encryption key
- Mangles the passphrase for 65536 iterations
$ gpg -c --s2k-cipher-algo AES256 --s2k-digest-algo SHA512 --s2k-count 65536 doc
To decrypt a symmetrically encrypted doc.gpg using a passphrase and output decrypted contents into the same directory as doc do
$ gpg --output doc --decrypt doc.gpg
Directory
Encrypting/decrypting a directory can be done with gpgtar(1).
Encrypt
$ gpgtar -c -o dir.gpg dir
Decrypt
$ gpgtar -d dir.gpg
Key maintenance
Backup your private key
To backup your private key do the following
$ gpg --export-secret-keys --armor --output private-key.asc user-id
If the private key is protected by a passphrase, the exported key file will be protected by the same one.
GnuPG may ask you to enter the passphrase for the key. This is required, because the internal protection method of the secret key is different from the one specified by the OpenPGP protocol.[5]
- The passphrase is usually the weakest link in protecting your secret key. Place the private key in a safe place on a different system/device, such as a locked container or encrypted drive. It is the only safety you have to regain control to your keyring in case of, for example, a drive failure, theft or worse.
- This method of backing up key has some security limitations. See the Moving GPG Keys Privately post on VHSblog for a potentially more secure way to back up and import keys using gpg.
To import the backup of your private key
$ gpg --import private-key.asc
Backup your revocation certificate
Revocation certificates are automatically generated for newly generated keys. These are by default located in ~/.gnupg/openpgp-revocs.d/. The filename of the certificate is the fingerprint of the key it will revoke. The revocation certificates can also be generated manually by the user later using
$ gpg --gen-revoke --armor --output revcert.asc user-id
This certificate can be used to revoke a key if it is ever lost or compromised. The backup will be useful if you have no longer access to the secret key and are therefore not able to generate a new revocation certificate with the above command. It is short enough to be printed out and typed in by hand if necessary.
Edit your key
Running the gpg --edit-key user-id command will present a menu which enables you to do most of your key management related tasks.
Type help in the edit key sub menu to show the complete list of commands. Some useful ones
> 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 command. You can then set your favourite one as primary.Exporting subkey
If you plan to use the same key across multiple devices, you may want to strip out your master key and only keep the bare minimum encryption subkey on less secure systems.
First, find out which subkey you want to export.
$ gpg --list-secret-keys --with-subkey-fingerprint
Select only that subkey to export.
$ mktemp -d
/tmp/tmp.XXXXXXXXXX
$ gpg --armor --export-secret-subkeys --output /tmp/tmp.XXXXXXXXXX/subkey.asc subkey-id!
!), all of your subkeys will be exported.At this point you could stop, but it is most likely a good idea to change the passphrase as well. Import the key into a temporary folder.
$ gpg --homedir /tmp/tmp.XXXXXXXXXX --import /tmp/tmp.XXXXXXXXXX/subkey.asc $ gpg --homedir /tmp/tmp.XXXXXXXXXX --edit-key user-id > passwd > save $ gpg --homedir /tmp/tmp.XXXXXXXXXX --armor --output /tmp/tmp.XXXXXXXXXX/subkey.altpass.asc --export-secret-subkeys subkey-id!
At this point, you can now use /tmp/tmp.XXXXXXXXXX/subkey.altpass.asc on your other devices.
Extending expiration date
It is good practice to set an expiration date on your subkeys, so that if you lose access to the key (e.g. you forget the passphrase) the key will not continue to be used indefinitely by others. When the key expires, it is relatively straight-forward to extend the expiration date
$ gpg --edit-key user-id > expire
You will be prompted for a new expiration date, as well as the passphrase for your secret key, which is used to sign the new expiration date.
YYYY-MM-DD formatted date or YYYYMMDDThhmmss formatted timestamp as the expiration value.Repeat this for any further subkeys that have expired
> key 1 > expire
Finally, save the changes and quit
> save
Update it to a keyserver.
$ gpg --keyserver keyserver.ubuntu.com --send-keys key-id
Alternatively, if you use this key on multiple computers, you can export the public key (with new signed expiration dates) and import it on those machines
$ gpg --export --output pubkey.gpg user-id $ gpg --import pubkey.gpg
There is no need to re-export your secret key or update your backups: the master secret key itself never expires, and the signature of the expiration date left on the public key and subkeys is all that is needed.
Rotating subkeys
Alternatively, if you prefer to stop using subkeys entirely once they have expired, you can create new ones. Do this a few weeks in advance to allow others to update their keyring.
Create new subkey (repeat for both signing and encrypting key)
$ gpg --edit-key user-id > addkey
And answer the following questions it asks (see #Create a key pair for suggested settings).
Save changes
> save
Update it to a keyserver.
$ gpg --keyserver pgp.mit.edu --send-keys user-id
You will also need to export a fresh copy of your secret keys for backup purposes. See #Backup your private key for details on how to do this.
Revoke a key
Key revocation should be performed if the key is compromised, superseded, no longer used, or you forget your passphrase. This is done by merging the key with the revocation certificate of the key.
If you have no longer access to your keypair, first import a public key to import your own key.
Then, to revoke the key, import the file saved in #Backup your revocation certificate
$ gpg --import revcert.asc
Now the revocation needs to be made public. Use a keyserver to send the revoked key to a public PGP server if you used one in the past, otherwise, export the revoked key to a file and distribute it to your communication partners.
Signatures
Signatures certify and timestamp documents. If the document is modified, verification of the signature will fail. Unlike encryption which uses the recipient public key to encrypt a document, signatures are created with the sender's private key. The recipient of a signed document then verifies the signature using the sender's public key.
Create a signature
Sign a file
To sign a file use the -s/--sign flag
$ gpg --output doc.sig --sign doc
doc.sig contains both the compressed content of the original file doc and the signature in a binary format, but the file is not encrypted. However, you can combine signing with encrypting.
Clearsign a file or message
To sign a file without compressing it into binary format use
$ gpg --output doc.sig --clearsign doc
Here both the content of the original file doc and the signature are stored in human-readable form in doc.sig.
Make a detached signature
To create a separate signature file to be distributed separately from the document or file itself, use the --detach-sig flag
$ gpg --output doc.sig --detach-sig doc
Here the signature is stored in doc.sig, but the contents of doc are not stored in it. This method is often used in distributing software projects to allow users to verify that the program has not been modified by a third party.
Verify a signature
To verify a signature use the --verify flag
$ gpg --verify doc.sig
where doc.sig is the signed file containing the signature you wish to verify.
If you are verifying a detached signature, both the signed data file and the signature file must be present when verifying. For example, to verify Arch Linux's latest iso you would do
$ gpg --verify archlinux-version.iso.sig
where archlinux-version.iso must be located in the same directory.
You can also specify the signed data file with a second argument
$ gpg --verify archlinux-version.iso.sig /path/to/archlinux-version.iso
If a file has been encrypted in addition to being signed, simply decrypt the file and its signature will also be verified.
gpg-agent
gpg-agent is mostly used as daemon to request and cache the password for the keychain. This is useful if GnuPG is used from an external program like a mail client. gnupg comes with systemd user sockets which are enabled by default. These sockets are gpg-agent.socket, gpg-agent-extra.socket, gpg-agent-browser.socket, gpg-agent-ssh.socket, and 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-dir 保持一致。套接字名称使用非默认 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 是 keygrip。您可以通过运行 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
gpg-agent 可以通过 pinentry-program 语句进行配置,以便在提示用户输入密码时使用特定的 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,这允许通过兼容的管理器(如 GNOME Keyring、KeePassXC 或 KDE Wallet)记住密码。 /usr/bin/pinentry-kwallet是KDE Wallet的替代方案,它需要安装 kwalletcliAUR 包。
PINENTRY_KDE_USE_WALLET 设置为非空值,以重新启用 Secret Service API 集成。如果您从元软件包或软件包组安装了 KDE,那么您应该已经安装了 kwallet-pam,在这种情况下,您的 KDE Wallet 很可能已经使用 Blowfish 加密针对您的账户密码创建,因此使用此 环境变量 是安全的。记住在更改配置后 重新加载代理。
缓存密码
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,这可能会破坏使用 --passphrase-fd 0 命令行选项从 STDIN 管道传入密码的向后兼容性。为了获得与旧版本相同的功能,必须执行两件事:
首先,编辑 gpg-agent 配置以允许 loopback pinentry 模式:
~/.gnupg/gpg-agent.conf
allow-loopback-pinentry
如果代理正在运行,请 重新加载代理 以使更改生效。
其次,应用程序需要更新以包含一个命令行参数来使用 loopback 模式,如下所示:
$ 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"
- 如果您使用脚本来管理变量,您也可以通过
unset SSH_AGENT_PID来取消设置SSH_AGENT_PID,而不是将其设置为空字符串。 - 如果您手动设置
SSH_AUTH_SOCK,请注意,如果您使用的是自定义GNUPGHOME,您的套接字位置可能会不同。您可以使用以下 bash 示例,或者将SSH_AUTH_SOCK更改为gpgconf --list-dir 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 并刷新 TTY,以防用户切换到 X 会话,如 gpg-agent(1) 中所述。例如:
~/.bashrc
export GPG_TTY=$(tty) gpg-connect-agent updatestartuptty /bye >/dev/null
如果您同时使用多个终端,并希望 gpg-agent 通过 pinentry-curses 在运行 ssh 命令的同一终端中询问密码,请将以下内容添加到 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 对话框。有关密码缓存,请参阅 #Cache passwords。
使用 PGP 密钥进行 SSH 身份验证
您还可以将 PGP 密钥用作 SSH 密钥。这需要一个具有 Authentication 功能的密钥(参见 #Custom capabilities)。使用 PGP 密钥进行 SSH 身份验证有多种好处,包括:
- 减少密钥维护,因为您将不再需要维护 SSH 密钥。
- 能够将身份验证密钥存储在智能卡上。GnuPG 将在卡可用时自动检测密钥,并将其添加到代理(通过
ssh-add -l或ssh-add -L检查)。密钥的注释应为:openpgp:key-id或cardno:card-id。
要检索 GPG/SSH 密钥的公钥部分,请运行 gpg --export-ssh-key gpg-key。如果您的密钥具有身份验证功能但此命令仍以“不可用的公钥”失败,请添加一个 ! 后缀([12])。
除非您的 GPG 密钥在密钥卡上,否则您需要将密钥添加到 $GNUPGHOME/sshcontrol 才能被识别为 SSH 密钥。如果您的密钥在密钥卡上,其 keygrip 会被隐式添加到 sshcontrol。如果不是,请按此方式获取密钥的 keygrip:
$ gpg --list-keys --with-keygrip
sub rsa4096 2018-07-25 [A]
Keygrip = 1531C8084D16DC4C36911F1585AF0ACE7AAFD7E7
然后像这样编辑 sshcontrol。添加 keygrip 是一次性操作;除非您添加其他密钥,否则您将不再需要编辑该文件。
$GNUPGHOME/sshcontrol
1531C8084D16DC4C36911F1585AF0ACE7AAFD7E7
将 gpg-agent 和 ssh-agent 转发到远程
可以通过将 gpg 套接字转发到远程机器来将 gpg-agent 转发到远程机器,如 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 agent 中所述)。因此,使用默认路径,将是:
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 作为与智能卡读取器的接口,请参考 man page 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)。
与 pcscd 共享访问
GnuPG scdaemon 是唯一一个在使用 PCSC_SHARE_EXCLUSIVE 标志连接到 pcscd 的流行 pcscd 客户端。其他客户端,如浏览器和 电子身份识别 中列出的程序使用的 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";。如果没有这样的条目,请使用 opensc 提供的 opensc-tool --atr。搜索 Answer to Reset 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)。
然而,从 2.4.0 版本(2022 年 12 月)开始,GnuPG 选择在 IETF 流程之外推出格式的更改和扩展(请参阅 draft-koch-librepgp)。
大多数 GnuPG 专有格式(与 OpenPGP 标准不同)带有“版本 5”(此版本未在 IETF OpenPGP 标准中使用)并引入了不兼容性:
- GnuPG“版本 5”密钥使用不同的指纹(更长,因为使用了 SHA-256)。
- 添加了一个新的对称加密数据包格式(OCB 加密数据包)。对该格式的支持通过一个“功能标志”发出信号,该标志默认情况下被积极启用。请参阅 #Disable unsupported AEAD mechanism。
- 一个新的 后量子密码学格式,同样偏离了 IETF 流程(请参阅 draft-ietf-openpgp-pqc)。
外部审查认为 GnuPG 的格式扩展的稳健性存在问题(请参阅 LibrePGP 中已知安全问题的摘要)。
请参阅 对“对 OpenPGP 更新的批判”的批判 以更深入地讨论与 GnuPG 特定的格式更改有关的问题,以及 “RFC 9580 与 LibrePGP 的比较” 以进行详细的技术比较。
Arch Linux 的立场是优先与 OpenPGP 标准兼容。为此,对 gnupg 包应用了诸如 默认恢复 RFC4880bis 的补丁。这确保了与其他 OpenPGP 实现的长期兼容性,并默认避免了厂商锁定。
禁用不支持的 AEAD 机制
使用 gnupg 2.4 时,gpg 会生成广告支持 GnuPG 特定的 AEAD 加密机制(基于 OCB)的密钥。然而,这种 AEAD 风格并不被其他 OpenPGP 实现支持!
尽管许多下游通过 修补 GnuPG 源代码 试图移除此新默认值,但在使用 --full-gen-key 时,OCB 基础的自定义 AEAD 加密机制仍会为新密钥设置。
您可以使用 gpg 本身来检查密钥是否设置了 GnuPG 的自定义 AEAD:
$ gpg --list-secret-keys --list-options=show-pref-verbose FINGERPRINT
...
uid [ultimate] Archie <archie@archlinux.example>
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 --expert --edit-key FINGERPRINT
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,这两者对大多数人来说都足够安全。但是,如果您使用的是早于 2.1 的 GnuPG 版本,或者您想要更高的安全性,那么您应该遵循上述步骤。
加密密码
加密密码可能很有用,这样它就不会以明文形式写在配置文件中。一个很好的例子是您的电子邮件密码。
首先创建一个包含您的密码的文件。您需要在密码后留一个空行,否则 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 使用 信任网络。密钥签名派对允许用户在物理地点聚集以验证密钥。 Zimmermann-Sassaman 密钥签名协议是一种使这些活动非常有效的方法。 此处 可以找到一篇操作指南。
为了在密钥签名派对后更轻松地签名密钥并将签名发送给所有者,您可以使用 caff 工具。可以从 AUR 通过包 caff-gitAUR 进行安装。
要将签名发送给所有者,您需要一个可用的 MTA。如果您还没有,请安装 msmtp。
始终显示长 ID 和指纹
要始终显示长密钥 ID,请在您的配置文件中添加 keyid-format 0xlong。要始终显示密钥的完整指纹,请在您的配置文件中添加 with-fingerprint。
自定义功能
为了进一步自定义,还可以为您的密钥指定自定义功能。以下功能可用:
- 认证(仅限主密钥)- 允许密钥创建证明用户 ID 在其他密钥上是正确的认证。
- 签名 - 允许密钥对数据进行加密签名,他人可以用公钥进行验证。
- 加密 - 允许任何人使用公钥加密数据,只有私钥才能解密。
- 身份验证 - 允许密钥与各种非 GnuPG 程序进行身份验证。该密钥可用作例如 SSH 密钥。
可以通过运行以下命令来指定主密钥的功能:
$ gpg --full-generate-key --expert
并选择一个允许您设置自己能力的选项。
相比之下,要为子密钥指定自定义能力,请向 gpg --edit-key 添加 --expert 标志,有关更多信息,请参阅 #编辑您的密钥。
故障排除
su
在使用 pinentry 时,您必须拥有正在使用的终端设备(例如 /dev/tty1)的正确权限。但是,使用 su(或 sudo)时,所有权仍归原始用户,而不是新用户。这意味着即使作为 root,pinentry 也会因 Permission denied 错误而失败。如果在使用 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 报告。
GNOME on Wayland 覆盖 SSH 代理套接字
对于 Wayland 会话,gnome-session 将 SSH_AUTH_SOCK 设置为标准的 gnome-keyring 套接字 $XDG_RUNTIME_DIR/keyring/ssh。这将覆盖 elsewhere 设置的任何值。
有关如何禁用此行为,请参阅 GNOME/Keyring#禁用。
mutt
Mutt 可能无法正确使用 gpg-agent,您需要在运行 mutt 时设置一个 环境变量 GPG_AGENT_INFO(内容不重要)。还要确保正确启用密码缓存,请参阅 #缓存密码。
请参阅 此论坛帖子。
“丢失”的密钥,升级到 gnupg 版本 2.1
当 gpg --list-keys 无法显示以前存在的密钥,并且应用程序抱怨缺少或无效密钥时,某些密钥可能未迁移到新格式。
请阅读 GnuPG 无效数据包的解决方法。基本上,它说旧的 pubring.gpg 和 secring.gpg 文件中的密钥存在一个 bug,现在已被新的 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。如果 gtk2AUR 不可用,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)
Keyblock 资源不存在
如果您在尝试导入密钥时遇到此类错误
gpg: keyblock resource 'gnupg_home/pubring.kbx': No such file or directory
这是因为 GnuPG 不会在其主目录尚不存在时创建它。只需手动创建它:
$ mkdir -m 700 gnupg_home
子密钥以受限能力创建
在某些情况下,使用自定义能力集创建子密钥会导致子密钥被标记为“受限”。当在交互式提示中切换能力时,这会在 addkey 命令中使用选项 7 或 8(“设置您自己的能力”)时发生。一种解决方法是在提示选择能力时,直接以字符串形式输入所需的能力集,而不是切换单个能力。例如,输入“=A”以仅创建具有身份验证能力的子密钥。
参见
- GNU Privacy Guard 主页
- Alan Eliasen 的 GPG 教程
- RFC 4880 — “OpenPGP 消息格式”
- gpg.conf 建议和最佳实践
- Fedora:创建 GPG 密钥
- Debian:子密钥
- 使用 PGP 保护代码完整性
- 更全面的 gpg 教程
- /r/GPGpractice — 一个用于练习使用 GnuPG 的 subreddit。
- LibrePGP 中已知安全问题的摘要,发布于 blog.pgpkeys.eu