GnuPG
根據 官方網站:
- GnuPG 是完整實現了 RFC4880(即PGP)所定義的 OpenPGP 標準的自由軟件。GnuPG 可以加密和簽名你的數據和通訊信息,包含一個通用的密鑰管理系統以及用於各種公鑰目錄的訪問模塊。GnuPG,簡稱 GPG,是一個易於與其它程序整合的命令行工具,擁有很多前端程序和函數庫。GnuPG 還支持 S/MIME 和 Secure Shell (ssh)。
安裝[編輯 | 編輯原始碼]
軟件包 pinentry包 也會被同時安裝,它是一些簡單的 PIN 或 passphrase 輸入對話框的合集,GnuPG 需要用這些對話框來輸入密碼。至於用哪個 pinentry 對話框,則是由 shell 腳本 /usr/bin/pinentry
來確定,先後順序參考 #pinentry。
如果要使用圖形界面或集成了 GnuPG 的程序,請查看加密、簽名與信息隱藏軟件[損壞的鏈接:無效的章節]。
配置[編輯 | 編輯原始碼]
主目錄[編輯 | 編輯原始碼]
GnuPG 套件將密鑰環和私鑰存儲在 GnuPG 主目錄,並從中讀取配置。默認路徑為 ~/.gnupg
。有兩種方法可以改變主目錄的路徑:
默認情況下,主目錄的 權限 設置為 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 的密鑰都將被導入,參見 在野外發現的偽密鑰作為示例。
公鑰服務器[編輯 | 編輯原始碼]
常見的公鑰服務器:
- 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
備份你的吊銷證書[編輯 | 編輯原始碼]
生成新密鑰對的時候會同時生成吊銷證書,默認存放在 ~/.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 的連接。
gpgconf --list-dirs
的值。 套接字名稱使用非默認 GnuPG 主目錄的哈希 [4],您可以硬編碼它不用擔心它的改變。
配置[編輯 | 編輯原始碼]
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 -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
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_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[編輯 | 編輯原始碼]
GnuPG uses scdaemon as an interface to your smartcard reader, please refer to the man page scdaemon(1) for details.
GnuPG only setups[編輯 | 編輯原始碼]
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.
[編輯 | 編輯原始碼]
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.
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/
.
tty
is not enough.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