GnuPG - Arch Linux 中文维基

跳至內容

# GnuPG

出自 Arch Linux 中文维基

本文或本節內容已經過時。

原因： 小部分翻譯已經過期，且部分段落內容缺乏翻譯，請閱讀英文頁面中的內容。 (在Talk:GnuPG討論)
翻譯狀態：

- 本文（或部分內容）譯自 GnuPG，最近一次同步於 2023-07-30，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

相關文章

- pacman/Package signing
- Data-at-rest encryption
- List of applications/Security#Encryption, signing, steganography

根據官方網站：

  GnuPG 是完整實現了 RFC4880（即PGP）所定義的 OpenPGP 標準的自由軟體。GnuPG 可以加密和簽名你的數據和通訊信息，包含一個通用的密鑰管理系統以及用於各種公鑰目錄的訪問模塊。GnuPG，簡稱 GPG，是一個易於與其它程序整合的命令行工具，擁有很多前端程序和函數庫。GnuPG 還支持 S/MIME 和 Secure Shell (ssh)。

## 安裝

提示：一般情況下，GnuPG 已作為 pacman包 等軟體包的依賴而被安裝。

安裝軟體包 gnupg包。

軟體包 pinentry包 也會被同時安裝，它是一些簡單的 PIN 或 passphrase 輸入對話框的合集，GnuPG 需要用這些對話框來輸入密碼。至於用哪個 pinentry 對話框，則是由 shell 腳本 `/usr/bin/pinentry` 來確定，先後順序參考 #pinentry。

如果要使用圖形界面或集成了 GnuPG 的程序，請查看加密、簽名與信息隱藏軟體。

## 配置

### 主目錄

GnuPG 套件將密鑰環和私鑰存儲在 GnuPG 主目錄，並從中讀取配置。默認路徑為 `~/.gnupg`。有兩種方法可以改變主目錄的路徑：

- 設置 `$GNUPGHOME` 環境變量。
- 使用 `--homedir` 參數，如 `$ gpg --homedir /path/to/dir` [1]。

默認情況下，主目錄的權限設置為 `700`，其包含的文件的權限設置為 `600`。只有目錄的所有者有權讀取、寫入和訪問文件。這是出於安全目的，不應更改。如果此目錄或其中的任何文件不遵循此安全措施，您將收到有關不安全文件和主目錄權限的警告。

### 配置文件

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`。

在這些文件中添加任何你想要的長選項。不要寫兩個破折號，只需寫選項的名稱和所需的參數。例如，要始終使GnuPG在特定路徑上使用密鑰環，就像使用`gpg --no-default-keyring --keyring keyring-path ...`調用它一樣：

    gnupg_home/gpg.conf (或 /etc/gnupg/gpg.conf)

    no-default-keyring
    keyring keyring-path

其他示例可以在#參閱中找到。

另外，pacman 在包簽名驗證方面使用了一組不同的配置文件。有關詳細信息，請參閱Pacman/Package signing。

### 新用戶的默認選項

要給新建用戶設定一些默認選項，把配置文件放到 `/etc/skel/.gnupg/`。系統創建新用戶時，就會把文件複製到 GnuPG 目錄。還有一個 addgnupghome 命令可以為已有用戶創建新 GnuPG 主目錄：

    # addgnupghome user1 user2

此命令會檢查 `/home/user1/.gnupg/` 和 `/home/user2/.gnupg/`，並從 skeleton 目錄複製文件過去。具有已存在的 GnuPG 主目錄的用戶只需跳過即可。

## 用法

注意：

- 如果需要一個 `user-id`，可以使用 key ID、指紋、用戶名或電郵地址的部分等替代，GnuPG 對此的處理很靈活。
- 如果需要一個 `key-id`，可以給命令加上 `--keyid-format=long` 選項來查詢。例如，如果想要查看主密匙，可以使用`gpg --list-secret-keys --keyid-format=long user-id`命令，key-id 是和 sec 同一行的十六進制散列值。

### 創建密鑰對

用下面命令創建一個密鑰對：

    $ gpg --full-gen-key

使用 `--expert` 選項可以選擇其它的加密算法，尤其是較新的ECC（橢圓曲線加密）。

命令執行後會需要用戶回答一些問題，大部分用戶應該需要的是：

- 默認的「RSA 和 RSA」用於加密和解密。
- 默認的密鑰長度，即 3072。增大長度到 4096「成本極高，但獲益很少」。這個帖子說明了為何 GPG 不默認使用 RSA-4096。
- 過期日期。大部分用戶可以選擇一年。這樣即使無法訪問密鑰環，用戶也知道密鑰已經過期。如果有需要，可以不重新簽發密鑰就延長過期時間。
- 用戶名和電子郵件。可以給同樣的密鑰不同的身份，比如給同一個密鑰關聯多個電子郵件。
- 不填寫可選注釋。注釋欄位並沒有被很好地定義，作用有限。
- 一個安全的密鑰口令。可參考如何選擇安全的密碼。

注意：任何導入密鑰的人都可以看到這裡的用戶名和電子郵件地址。
提示：較簡單的 `--gen-key` 選項對密鑰類型、密鑰長度、過期時間均使用默認值，僅詢問姓名和電郵地址。

### 查看密鑰

查看公鑰：

    $ gpg --list-keys

查看私鑰:

    $ gpg --list-secret-keys

### 導出公鑰

GPG 的主要用途是通過公鑰加密信息以確保其私密性。你可以分發自己的公鑰，而其他人通過該公鑰加密發給你的信息。而你的私鑰必須始終保密，否則將會威脅信息的私密性。相關內容，請參見公開密鑰加密。

所以其他人需要有你的公鑰才能給你發加密信息。

以下命令可生成公鑰的 ASCII 版本（`--armor` 參數）（例如用於以電子郵件發布）：

    $ gpg --export --armor --output public-key.asc user-id

此外，還可以通過密鑰伺服器分發公鑰。

提示：

- 使用 `--no-emit-version` 可以避免列印版本號，通過配置文件也可以進行此設置。
- 可以省略 `user-id` 以導出密鑰環內所有的公鑰。這可以用來分享多個身份，或是將其導入到另一個程序，比如 Thunderbird。

### 導入公共密鑰

要給其他人發送加密信息，或者驗證他們的簽名，就需要他們的公鑰。通過文件 `public.key` 導入公鑰到密鑰環：

    $ gpg --import public.key.asc

此外，還可以通過#密鑰伺服器導入公鑰。

如想導入某個 key ID 以安裝某個 Arch Linux 軟體包，可參見 pacman 的相關說明和 makepkg 的相關說明。

### 使用公鑰伺服器

#### 發布公鑰

你可以將你的公鑰註冊到一個公共的密鑰伺服器，這樣其他人不用聯繫你就能獲取到你的公鑰：

    $ gpg --send-keys key-id

警告：一旦一個公鑰被發送到密鑰伺服器，它就無法從伺服器上刪除。這個網頁解釋了原因。
注意：與公鑰相關聯的電郵地址一旦公開，可能會被垃圾郵件發送者盯上。請做好相應的防護措施。

#### 搜索和接收公鑰

要查詢公鑰的詳細信息而不是導入，執行：

    $ gpg --search-keys user-id

要導入一個公鑰：

    $ gpg --receive-keys key-id

要使用密鑰伺服器中的最新版本刷新/更新鑰匙串：

    $ gpg --refresh-keys

警告：

- 您應該通過將其指紋與所有者在獨立來源（例如直接聯繫該人）上發布的指紋進行比較，以驗證檢索到的公鑰的真實性。請參閱 Wikipedia:Public key fingerprint 獲取更多信息。
- 接收密鑰時，建議使用長密鑰 ID 或完整指紋。使用短密鑰 ID 可能會導致衝突。所有具有短密鑰 ID 的密鑰都將被導入，參見 在野外發現的偽密鑰作為示例。

提示：將 `auto-key-retrieve` 添加到 GPG 配置文件中，將在需要時自動從密鑰伺服器獲取密鑰。這不會對安全性造成妥協，但可以被視為侵犯隱私；請參閱gpg(1)中的"web bug"。

#### 公鑰伺服器

常見的公鑰伺服器：

- Ubuntu Keyserver：聯盟式（federated）、沒有驗證、公鑰不可刪除。
- Mailvelope Keyserver：中心式、驗證電郵 ID、公鑰可刪除。
- keys.openpgp.org：中心式、驗證電郵 ID、公鑰可刪除、沒有第三方簽名（即不支持信任網絡）。

維基百科（英文）上有更多的伺服器。

備選公鑰伺服器可以在#配置文件中的 `keyserver` 選項中註明，例如：

    ~/.gnupg/dirmngr.conf

    keyserver hkp://keyserver.ubuntu.com

當常規伺服器無法正常工作時，臨時使用另一台伺服器很方便。例如，可以通過以下方法實現：

    $ gpg --keyserver hkps://keys.openpgp.org/ --search-keys user-id

提示：

- 若遇到錯誤信息 `gpg: keyserver receive failed: General error`，且你使用了默認的 HKPS 公鑰伺服器池，請在 `dirmngr.conf` 中設置 HKPS 池證書： `hkp-cacert /usr/share/gnupg/sks-keyservers.netCA.pem` 然後殺掉舊的 `dirmngr` 進程。
- 若遇到錯誤信息 `gpg: keyserver receive failed: Connection refused`，可嘗試更換 DNS 伺服器。
- 你可以通過 `--use-tor` 選項或 Torsocks 來使用 Tor 連接密鑰伺服器。詳見這個網頁。
- 你可以通過設置環境變量 `http_proxy` 並在 `dirmngr.conf` 中寫入 `honor-http-proxy` 以使用代理訪問密鑰伺服器。或者，你也可以通過在 `dirmngr.conf` 中寫入 `http-proxy host[:port]` 以直接覆蓋環境變量`http_proxy`來使用代理。重啟 `dirmngr.service` 用戶服務以使改動生效。
- 如果連接到密鑰伺服器失敗並顯示 `gpg: keyserver receive failed: Server indicated a failure`，您可能需要將 gpg 配置為使用備用埠。例如，要在 Ubuntu 的密鑰伺服器上使用埠 80，請使用 `keyserver hkp://keyserver.ubuntu.com:80`。

### 網絡公鑰目錄

網絡公鑰服務（Web Key Service，WKS）協議是公鑰分發的新標準。電子郵件域將提供其自己的公鑰伺服器，稱為網絡公鑰目錄（Web Key Directory，WKD）。在高於 2.1.16 版本的 GPG 中，在依電子郵件地址（如`user@example.com`）加密時，如果該公鑰不在本地密鑰環中，GPG 將以 HTTPS 向電子郵件的域（`example.com`）查詢 OpenPGP 公鑰。選項 `auto-key-locate` 將在本地密鑰環內無該電郵地址的公鑰時，按 WKD 協議查找公鑰。

    $ gpg --recipient user@example.org --auto-key-locate --encrypt doc

GnuPG Wiki 舉出了一些支持 WKD 的電子郵件服務商。若電郵地址域由你控制，可遵循這份指南在你的域上啟用 WKD。可用這個地址檢查你的公鑰是否能在 WKD 中找到。

### 加密與解密

#### 非對稱加解密

在加密（參數`--encrypt`或`-e`）一個文件或一條信息給另外一個人（參數`--recipient`或`-r`）之前，你需要先#導入他的公鑰。如果你還沒有#創建自己的密鑰對，請先創建。

要加密一個名為 doc 的文件：

    $ gpg --recipient user-id --encrypt doc

要解密（參數 `--decrypt` 或 `-d`）一個用你的公鑰加密的、名為 doc.gpg 的文件：

    $ gpg --output doc --decrypt doc.gpg

gpg 會提示你輸入密鑰口令，並將 doc.gpg 中的數據解密到 doc。如果你忽略了參數 `-o`（`--output`），gpg 將會直接輸出解密的信息。

提示：

- 使用參數 `--armor` 以 ASCII 編碼的形式加密文件（適用於複製與粘貼文本文件格式的消息）。
- 使用 `-R <user-id>` 或 `--hidden-recipient user-id` 代替 `-r` 可以不將收件人的指紋 ID 放入加密的消息中。這有助於隱藏收件人的信息，是針對流量分析的一個有限對策。
- 使用 `--no-emit-version` 以避免列印版本號。也可將相應配置添加到你的配置文件中。
- 你可以使用 GPG 將自己作為收件人來加密敏感文件，但是每次只能壓縮一個文件——儘管你可以將多個文件壓縮後再進行加密。如果需要加密一個目錄或一整個文件系統，請參見 Data-at-rest encryption#Available methods。

#### 對稱加解密

對稱加密不需要生成密鑰對，可用來簡單地給文件加上密碼。使用 `-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

請注意，上述命令將要求您輸入密鑰的密碼。這是因為，否則任何獲得上述導出文件訪問權限的人都可以像您一樣對文檔進行加密和簽名，而無需知道您的密碼。

警告：

- 口令通常是密鑰安全方面最薄弱的環節。最好把導出的文件放在另一個系統或者設備裡，比如物理保險柜或者加密驅動器中。這是當你遇到設備被盜、磁碟故障等情況時恢復對密鑰控制權的唯一安全措施。
- 這種備份方式有一些安全局限性，這篇文章 https://web.archive.org/web/20210803213236/https://habd.as/post/moving-gpg-keys-privately/ 中有關於用 gpg 備份和導入密鑰的更加安全的辦法。

用如下命令導入你的私鑰備份

    $ gpg --import private-key.asc

提示： 你可以用 Paperkey 來把私鑰導出為明文文本或條形碼，並列印出來存檔。

### 備份你的吊銷證書

生成新密鑰對的時候會同時生成吊銷證書，默認存放在 `~/.gnupg/openpgp-revocs.d/` 下，證書的文件名是對應的密鑰的指紋。 你也可以用以下命令手動生成吊銷證書：

    $ gpg --gen-revoke --armor --output revcert.asc user-id

如果密鑰丟失或洩露，此證書可用於 #吊銷密鑰。如果你無法訪問密鑰，則無法使用上述命令生成新的吊銷證書，那麼備份將非常有用。吊銷證書很短，你可以把他列印出來然後在需要使用的時候手動輸入到電腦裡。

警告：任何能接觸到吊銷證書的人都可以吊銷你的密鑰對，而且無法撤消。所以請像保護私鑰一樣保護你的吊銷證書。

### 編輯你的密鑰

運行 `gpg --edit-key user-id` 命令將會出現一個菜單，該菜單使你能夠執行大部分密鑰管理相關的任務。

在編輯密鑰子菜單中輸入 `help` 命令可以顯示完整的命令列表。以下是一些有用的命令：

    > passwd       # 修改密码短语
    > clean        # 压缩任何不再可用的用户ID（例如已撤销或已过期）
    > revkey       # 撤销密钥
    > addkey       # 向该密钥添加子密钥
    > expire       # 更改密钥过期时间
    > adduid       # 添加附加的名称、注释和电子邮件地址
    > addphoto     # 向密钥添加照片（必须是JPG格式，推荐大小为240x288，当提示时输入完整路径）

提示：如果你有多個電子郵件帳戶，你可以使用 `adduid` 命令將每個帳戶都添加為一個身份。然後你可以將你最喜歡的帳戶設置為 `primary`。

### 導出子密鑰

如果您計劃在多個設備上使用相同的密鑰，您可能希望去除主密鑰，只保留在較不安全的系統上的最低限度的加密子密鑰。

首先，找出您想要導出的子密鑰。

    $ gpg --list-secret-keys --with-subkey-fingerprint

僅選擇要導出的子密鑰。

    $ gpg -a --export-secret-subkeys [子密钥id]! > /tmp/subkey.gpg

警告：如果您忘記添加「!」，所有子密鑰都將被導出。

到此為止，您可以停止了，但最好同時更改密碼。將密鑰導入臨時文件夾。

    $ gpg --homedir /tmp/gpg --import /tmp/subkey.gpg
    $ gpg --homedir /tmp/gpg --edit-key 用户id
    > passwd
    > save
    $ gpg --homedir /tmp/gpg -a --export-secret-subkeys [子密钥id]! > /tmp/subkey.altpass.gpg

注意：您會收到一個警告，說明主密鑰不可用且密碼未更改，但可以安全地忽略，因為子密鑰的密碼已經更改。

此時，您現在可以在其他設備上使用 `/tmp/subkey.altpass.gpg`。

### 延長過期日期

警告：永遠不要刪除已過期或已吊銷的子密鑰，除非你有充分的理由。這樣做將導致你無法解密使用舊子密鑰加密的文件。請僅從其他用戶那裡刪除已過期或已吊銷的密鑰以清理你的密鑰環。

在你的子密鑰上設置一個過期日期是一個好的做法，這樣如果你失去了對密鑰的訪問（例如，你忘記了密碼短語），密鑰將不會繼續被他人無限期地使用。當密鑰過期時，延長過期日期相對簡單：

    $ gpg --edit-key 用户ID
    > expire

你將被要求輸入一個新的過期日期，以及用於簽署新過期日期的你的密鑰密碼短語。

對於任何其他已過期的子密鑰，重複此步驟：

    > 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 使用 `gpg-agent.socket` 連接到 gpg-agent 守護進程。
- `gpg-agent-extra.socket` 的作用是在本地建立一個轉發自遠程系統的 Unix 域套接字。這樣就可以在遠程系統上使用 gpg，而無需向遠程系統公開私鑰。有關詳細信息，請參閱 gpg-agent(1)。
- `gpg-agent-browser.socket` 允許 Web 瀏覽器訪問 gpg-agent 守護進程。
- SSH 使用 `gpg-agent-ssh.socket` 緩存 ssh-add 程序添加的 SSH keys。有關必要的配置，請參閱 #SSH agent。
- `dirmngr.socket` 啟動一個 GnuPG 守護進程來處理與 keyserver 的連接。

注意：如果您沒有使用默認的 GnuPG #目錄位置, 您需要編輯所有套接字文件讓其使用 `gpgconf --list-dirs` 的值。 套接字名稱使用非默認 GnuPG 主目錄的哈希 [4]，您可以硬編碼它不用擔心它的改變。

### 配置

gpg-agent 用 `~/.gnupg/gpg-agent.conf` 文件配置。配置選項列在 gpg-agent(1) 中。例如，您可以更改默認密鑰的緩存 ttl：

    ~/.gnupg/gpg-agent.conf

    default-cache-ttl 3600

提示：要緩存整個會話的密碼(passphrase)，請運行以下命令：

    $ /usr/lib/gnupg/gpg-preset-passphrase --preset XXXXX

其中 XXXXX 是 keygrip。您可以在運行 `gpg --with-keygrip -K` 時獲取它的值。密碼(passphrase)將一直保存到 `gpg-agent` 重新啟動為止。如果設置了 `default-cache-ttl` 值，會優先採用它。

在 Linux 中，為了允許預設的密碼短語，需要通過使用 `--allow-preset-passphrase` 啟動 gpg-agent，或在 `~/.gnupg/gpg-agent.conf` 中設置`allow-preset-passphrase`。

### 重新加載 gpg-agent

在修改完配置之後，用 gpg-connect-agent 重新加載 gpg-agent：

    $ gpg-connect-agent reloadagent /bye

該命令應該輸出 `OK`。

但是在某些情況下，只是重新啟動可能不夠，比如當 `keep-screen` 被添加到 gpg-agent 配置中時。在這種情況下，您首先需要終止正在進行的 gpg-agent 進程，然後按上述方法重新啟動它。

### pinentry

`gpg-agent` 可以在 `pinentry-program` 中設定，以便使用特定的 pinentry包 用戶界面來提示用戶輸入(passphrase)。例如：

    ~/.gnupg/gpg-agent.conf

    pinentry-program /usr/bin/pinentry-curses

還有其他 pinentry 程序可選，參考 `pacman -Ql pinentry | grep /usr/bin/` 的輸出結果。

提示：

- 為了使用 `/usr/bin/pinentry-kwallet` 您需要安裝軟體包 kwalletcliAUR。
- 所有的默認 pinentry 程序（除了 `/usr/bin/pinentry-emacs`）都支持 DBus Secret Service API ，它允許通過一個兼容的管理器(如 GNOME Keyring 或 KeePassXC)記住密碼。

記得在修改完配置後要#重新加載 gpg-agent。

### 緩存密碼

`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

### Unattended passphrase

從 GnuPG 2.1.0 開始，需要使用 gpg-agent 和 pinentry，這可能會破壞使用 `--passphrase-fd 0` 命令行選項從 STDIN 傳入的密碼短語的向後兼容性。為了擁有與舊版本相同類型的功能，必須做兩件事：

首先，編輯 gpg-agent 配置允許 loopback pinentry 模式 :

    ~/.gnupg/gpg-agent.conf

    allow-loopback-pinentry

如果 gpg-agent 正在運行，重新加載它使配置生效。

其次，要麼應用程式需要更新，以包括一個命令行參數來使用迴環模式，例如：

    $ gpg --pinentry-mode loopback ...

如果不可能這樣做，則可以將選項添加到配置中：

    ~/.gnupg/gpg.conf

    pinentry-mode loopback

注意：上游作者指出，在 `gpg.conf` 中設置 `pinentry-mode loopback` 可能會破壞其他用法，如果可能，最好使用命令行選項。[5]

### SSH 代理

gpg-agent 具有 OpenSSH 代理仿真功能。如果您正在使用 GnuPG 套件，可以考慮使用 gpg-agent 來緩存 SSH 密鑰。此外，一些用戶可能更喜歡 GnuPG 代理提供的 PIN 輸入對話框作為其密碼(passphrase)管理的一部分。

#### 設置 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` 而不是將 `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 是否以 `gpg-agent --daemon /bin/sh` 的方式啟動, 在這種情況下，shell 從父進程繼承 `SSH_AUTH_SOCK` 變量, gpg-agent [6].

#### 配置 pinentry 使用正確的 TTY

如果用戶切換了 X 會話，還需要設置 GPG_TTY 並刷新 TTY，如 gpg-agent(1) 中所述。例如：

    ~/.bashrc

    export GPG_TTY=$(tty)
    gpg-connect-agent updatestartuptty /bye >/dev/null

在同時使用多個終端時，如果想要 gpg-agent 通過 pinentry-curses 在運行 ssh 的終端上請求密碼(passphrase)，添加以下內容到 SSH 配置文件。這將使得每次運行 ssh 命令時都會刷新 TTY [7]：

    ~/.ssh/config

    Match host * exec "gpg-connect-agent UPDATESTARTUPTTY /bye"

請注意，必須設置 `GPG_TTY` 環境變量才能正常工作。

#### 添加 SSH 密鑰

gpg-agent 運行後，和 ssh-agent 一樣您可以通過 ssh-add 添加准許的密鑰。 准許的密鑰列表儲存在 `~/.gnupg/sshcontrol`。

一旦您的密鑰被批准，每次需要密碼(passphrase)時，都會有 pinentry 對話框。要緩存密碼，參見 #緩存密碼。

#### 使用 PGP 密鑰進行 SSH 身份驗證

您還可以使用 PGP 密鑰作為 SSH 密鑰。這需要一個具有`驗證`功能的密鑰（請參閱 #Custom ability）。使用 PGP 密鑰進行 SSH 身份驗證有各種好處，包括:

- 您不再需要維護 SSH 密鑰，減少了密鑰維護量。
- 可以在智慧卡上儲存驗證密鑰。GnuPG 將在卡可用時自動檢測密鑰，並將其添加到代理中（使用 `ssh-add -l` 或 `ssh-add -L` 檢查）。密鑰的備註應該會是 `openpgp:key-id` 或 `cardno:card-id`。

運行 `gpg --export-ssh-key gpg-key`獲取 GPG/SSH 公鑰。如果您的密鑰具有身份驗證功能，但此命令仍然失敗，並顯示 「Unusable public key」, 給 gpg-key 添加 `!` 後綴 ([8])。

除非您的 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 到遠程主機

提示：設置`ForwardAgent yes`，如此處所示，怎麼樣？

通過將 gpg 套接字轉發到遠程機器，可以將 gpg-agent 轉發到遠程計算機，如 GnuPG wiki 所述。

首先，將以下行添加到遠程計算機上的 `/etc/ssh/sshd_config`，以便在連接時自動刪除舊的套接字。如果不這樣做，則需要手動刪除遠程計算機上的套接字，然後才能連接啟用了轉發的代理，以便代理轉發正常工作：

    /etc/ssh/sshd_config

    ...
    StreamLocalBindUnlink yes
    ...

注意：必須在遠程計算機上運行 `systemctl reload sshd`，使 sshd 加載新配置。

在客戶端上，用 `RemoteForward` SSH 指令來將發往遠程埠的通信轉發到本地埠。如 ssh_config(5) § RemoteForward 中所述，該指令參數的第一項是遠程主機上監聽套接字的路徑，第二項是本地主機上目標套接字的路徑。配置應該如下所示：

    $HOME/.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 轉發:

- local_agent_ssh_socket 是在遠程機器上 `gpgconf --list-dir agent-ssh-socket` 的輸出。
- remote_agent_ssh_socket 是在本地機器上 `gpgconf --list-dir agent-ssh-socket` 的輸出。

注意：如果要使用 ssh-agent 轉發，需要在遠程機器上將 `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 myremote` 會自動將 gpg-agent 轉發到遠程，並允許使用 gpg 密鑰解密/簽名（如果包含第二行 `RemoteForward`，則會允許 gpg 和 ssh-agent 一起工作）。

## Smartcards

本文或本節需要翻譯。要貢獻翻譯，請訪問簡體中文翻譯團隊。

附註： 以下內容缺少中文翻譯（在 Talk:GnuPG# 中討論）

GnuPG uses scdaemon as an interface to your smartcard reader, please refer to the man page scdaemon(1) for details.

### GnuPG only setups

注意： To allow scdaemon direct access to USB smartcard readers the optional dependency libusb-compat包 must be installed

If you do not plan to use other cards but those based on GnuPG, you should check the `reader-port` parameter in `~/.gnupg/scdaemon.conf`. The value '0' refers to the first available serial port reader and a value of '32768' (default) refers to the first USB reader.

### GnuPG with pcscd (PCSC Lite)

pcscd(8) is a daemon which handles access to smartcard (SCard API). If GnuPG's scdaemon fails to connect the smartcard directly (e.g. by using its integrated CCID support), it will fallback and try to find a smartcard using the PCSC Lite driver.

To use pscsd install pcsclite包 and ccid包. Then start and/or enable `pcscd.service`. Alternatively start and/or enable `pcscd.socket` to activate the daemon when needed.

#### Always use pcscd

If you are using any smartcard with an opensc driver (e.g.: ID cards from some countries) you should pay some attention to GnuPG configuration. Out of the box you might receive a message like this when using `gpg --card-status`

    gpg: selecting openpgp failed: ec=6.108

By default, scdaemon will try to connect directly to the device. This connection will fail if the reader is being used by another process. For example: the pcscd daemon used by OpenSC. To cope with this situation we should use the same underlying driver as opensc so they can work well together. In order to point scdaemon to use pcscd you should remove `reader-port` from `~/.gnupg/scdaemon.conf`, specify the location to `libpcsclite.so` library and disable ccid so we make sure that we use pcscd:

    ~/.gnupg/scdaemon.conf

    pcsc-driver /usr/lib/libpcsclite.so
    card-timeout 5
    disable-ccid

Please check scdaemon(1) if you do not use OpenSC.

#### Shared access with pcscd

GnuPG `scdaemon` is the only popular `pcscd` client that uses `PCSC_SHARE_EXCLUSIVE` flag when connecting to `pcscd`. Other clients like OpenSC PKCS#11 that are used by browsers and programs listed in Electronic identification are using `PCSC_SHARE_SHARED` that allows simultaneous access to single smartcard. `pcscd` will not give exclusive access to smartcard while there are other clients connected. This means that to use GnuPG smartcard features you must before have to close all your open browser windows or do some other inconvenient operations. Starting from version 2.2.28 LTS and 2.3.0 you can enable shared access by modifying your `scdaemon.conf` file and adding `pcsc-shared` line end of it.

##### Multi applet smart cards

When using YubiKeys or other multi applet USB dongles with OpenSC PKCS#11 may run into problems where OpenSC switches your Yubikey from OpenPGP to PIV applet, breaking the `scdaemon`.

You can hack around the problem by forcing OpenSC to also use the OpenPGP applet. Open `/etc/opensc.conf` file, search for Yubikey and change the `driver = "PIV-II";` line to `driver = "openpgp";`. If there is no such entry, use `pcsc_scan`. Search for the Answer to Reset `ATR: 12 34 56 78 90 AB CD ...`. Then create a new entry.

    /etc/opensc.conf

    ...
    card_atr 12:23:34:45:67:89:ab:cd:... {
        name = "YubiKey Neo";
        driver = "openpgp"
    }
    ...

After that you can test with `pkcs11-tool -O --login` that the OpenPGP applet is selected by default. Other PKCS#11 clients like browsers may need to be restarted for that change to be applied.

##### Using a smart card on a remote client via SSH

If you log into a machine via SSH and try to use an attached device via pcscd, you will notice errors such as:

    gpg: selecting card failed: No such device
    gpg: OpenPGP card not available: No such device

This is due to Polkit restricting access to local clients. To fix this, you can add a rule to allow certain users in all cases. The below rule allows all users in the `wheel` group to access devices via `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;
        }
    });

After creating the file, make sure to restart `polkit.service`.

## Tips and tricks

### Different algorithm

You may want to use stronger algorithms:

    ~/.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

In the latest version of GnuPG, the default algorithms used are SHA256 and AES, both of which are secure enough for most people. However, if you are using a version of GnuPG older than 2.1, or if you want an even higher level of security, then you should follow the above step.

### Encrypt a password

It can be useful to encrypt some password, so it will not be written in clear on a configuration file. A good example is your email password.

First create a file with your password. You need to leave one empty line after the password, otherwise gpg will return an error message when evaluating the file.

Then run:

    $ gpg -e -a -r user-id your_password_file

`-e` is for encrypt, `-a` for armor (ASCII output), `-r` for recipient user ID.

You will be left with a new `your_password_file.asc` file.

提示：pass automates this process.

### Change trust model

By default GnuPG uses the Web of Trust as the trust model. You can change this to Trust on first use by adding `--trust-model=tofu` when adding a key or adding this option to your GnuPG configuration file. More details are in this email to the GnuPG list.

### Hide all recipient id's

By default the recipient's key ID is in the encrypted message. This can be removed at encryption time for a recipient by using `hidden-recipient user-id`. To remove it for all recipients add `throw-keyids` to your configuration file. This helps to hide the receivers of the message and is a limited countermeasure against traffic analysis (i.e. using a little social engineering, anyone who is able to decrypt the message can check whether one of the other recipients is the one they suspect). On the receiving side, it may slow down the decryption process because all available secret keys must be tried (e.g. with `--try-secret-key user-id`).

### Using caff for keysigning parties

To allow users to validate keys on the keyservers and in their keyrings (i.e. make sure they are from whom they claim to be), PGP/GPG uses the Web of Trust. Keysigning parties allow users to get together at a physical location to validate keys. The Zimmermann-Sassaman key-signing protocol is a way of making these very effective. Here you will find a how-to article.

For an easier process of signing keys and sending signatures to the owners after a keysigning party, you can use the tool caff. It can be installed from the AUR with the package caff-gitAUR.

To send the signatures to their owners you need a working MTA. If you do not have already one, install msmtp.

### Always show long ID's and fingerprints

To always show long key ID's add `keyid-format 0xlong` to your configuration file. To always show full fingerprints of keys, add `with-fingerprint` to your configuration file.

### Custom capabilities

For further customization also possible to set custom capabilities to your keys. The following capabilities are available:

- Certify (only for master keys) - allows the key to create subkeys, mandatory for master keys.
- Sign - allows the key to create cryptographic signatures that others can verify with the public key.
- Encrypt - allows anyone to encrypt data with the public key, that only the private key can decrypt.
- Authenticate - allows the key to authenticate with various non-GnuPG programs. The key can be used as e.g. an SSH key.

It is possible to specify the capabilities of the master key, by running:

    $ gpg --full-generate-key --expert

And select an option that allows you to set your own capabilities.

Comparably, to specify custom capabilities for subkeys, add the `--expert` flag to `gpg --edit-key`, see #Edit your key for more information.

## Troubleshooting

### su

When using `pinentry`, you must have the proper permissions of the terminal device (e.g. `/dev/tty1`) in use. However, with su (or sudo), the ownership stays with the original user, not the new one. This means that pinentry will fail with a `Permission denied` error, even as root. If this happens when attempting to use ssh, an error like `sign_and_send_pubkey: signing failed: agent refused operation` will be returned. The fix is to change the permissions of the device at some point before the use of pinentry (i.e. using gpg with an agent). If doing gpg as root, simply change the ownership to root right before using gpg:

    # chown root /dev/ttyN  # where N is the current tty

and then change it back after using gpg the first time. The equivalent is true with `/dev/pts/`.

注意：The owner of tty must match with the user for which pinentry is running. Being part of the group `tty` is not enough.
提示：If you run gpg with `script` it will use a new tty with the correct ownership:

    # script -q -c "gpg --gen-key" /dev/null

### Agent complains end of file

If the pinentry program is `/usr/bin/pinentry-gnome3`, it needs a DBus session bus to run properly. See General troubleshooting#Session permissions for details.

Alternatively, you can use a variety of different options described in #pinentry.

### KGpg configuration permissions

There have been issues with kgpg包 being able to access the `~/.gnupg/` options. One issue might be a result of a deprecated options file, see the bug report.

### GNOME on Wayland overrides SSH agent socket

For Wayland sessions, `gnome-session` sets `SSH_AUTH_SOCK` to the standard gnome-keyring socket, `$XDG_RUNTIME_DIR/keyring/ssh`. This overrides any value set elsewhere.

See GNOME/Keyring#Disabling on how to disable this behavior.

### mutt

Mutt might not use gpg-agent correctly, you need to set an environment variable `GPG_AGENT_INFO` (the content does not matter) when running mutt. Be also sure to enable password caching correctly, see #Cache passwords.

See this forum thread.

### "Lost" keys, upgrading to gnupg version 2.1

When `gpg --list-keys` fails to show keys that used to be there, and applications complain about missing or invalid keys, some keys may not have been migrated to the new format.

Please read GnuPG invalid packet workaround. Basically, it says that there is a bug with keys in the old `pubring.gpg` and `secring.gpg` files, which have now been superseded by the new `pubring.kbx` file and the `private-keys-v1.d/` subdirectory and files. Your missing keys can be recovered with the following commands:

    $ cd
    $ cp -r .gnupg gnupgOLD
    $ gpg --export-ownertrust > otrust.txt
    $ gpg --import .gnupg/pubring.gpg
    $ gpg --import-ownertrust otrust.txt
    $ gpg --list-keys

### gpg hanged for all keyservers (when trying to receive keys)

If gpg hanged with a certain keyserver when trying to receive keys, you might need to kill dirmngr in order to get access to other keyservers which are actually working, otherwise it might keeping hanging for all of them.

### Smartcard not detected

Your user might not have the permission to access the smartcard which results in a `card error` to be thrown, even though the card is correctly set up and inserted.

One possible solution is to add a new group `scard` including the users who need access to the smartcard.

Then use udev rules, similar to the following:

    /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"

One needs to adapt VENDOR and MODEL according to the `lsusb` output, the above example is for a YubikeyNEO.

### server 'gpg-agent' is older than us (x < y)

This warning appears if `gnupg` is upgraded and the old gpg-agent is still running. Restart the user's `gpg-agent.socket` (i.e., use the `--user` flag when restarting).

### IPC connect call failed

Make sure `gpg-agent` and `dirmngr` are not running with `killall gpg-agent dirmngr` and the `$GNUPGHOME/crls.d/` folder has permission set to `700`.

By default, the gnupg包 package uses the directory `/run/user/$UID/gnupg/` for sockets. GnuPG documentation states this is the preferred directory (not all file systems are supported for sockets). Validate that your `agent-socket` configuration specifies a path that has an appropriate file system. You can find the your path settings for `agent-socket` by running `gpgconf --list-dirs agent-socket`.

Test that `gpg-agent` starts successfully with `gpg-agent --daemon`.

### Mitigating Poisoned PGP Certificates

In June 2019, an unknown attacker spammed several high-profile PGP certificates with tens of thousands (or hundreds of thousands) of signatures (CVE-2019-13050) and uploaded these signatures to the SKS keyservers. The existence of these poisoned certificates in a keyring causes gpg to hang with the following message:

    gpg: removing stale lockfile (created by 7055)

Possible mitigation involves removing the poisoned certificate as per this blog post.

### Invalid IPC response and Inappropriate ioctl for device

The default pinentry program is `/usr/bin/pinentry-gtk-2`. If gtk2包 is unavailable, pinentry falls back to `/usr/bin/pinentry-curses` and causes signing to fail:

    gpg: signing failed: Inappropriate ioctl for device
    gpg: [stdin]: clear-sign failed: Inappropriate ioctl for device

You need to set the `GPG_TTY` environment variable for the pinentry programs `/usr/bin/pinentry-tty` and `/usr/bin/pinentry-curses`.

    $ export GPG_TTY=$(tty)

### Keyblock resource does not exist

If you get an error like this when trying to import keys

    gpg: keyblock resource 'gnupg_home/pubring.kbx': No such file or directory

it is because GnuPG will not create its home directory if it does not yet exist. Simply create it manually

    $ mkdir -m 700 gnupg_home

## 參見

- GNU Privacy Guard Homepage
- 掃盲文件完整性校驗——關於散列值和數字簽名 @ 編程隨想的博客
- Alan Eliasen's GPG Tutorial
- RFC 4880 — "OpenPGP Message Format"
- gpg.conf recommendations and best practices
- Fedora:Creating GPG Keys
- Debian:Subkeys
- Protecting code integrity with PGP
- A more comprehensive gpg Tutorial
- /r/GPGpractice - a subreddit to practice using GnuPG.

分類：​

- 加密
- 郵件
- GNU
- OpenPGP
- 使用「模板:過時」標記的頁面或章節

隱藏分類：​

- 使用「模板:Translateme」標記的頁面或章節

GnuPG
新增話題