GPG 使用指南


加密與簽名

在傳輸信息時,會面臨兩個典型的問題:

  1. 如何保證發出的消息,只能被預期的接收人獲取?
  2. 如何保證收到的消息,確實由預期的發送人發出?

這兩個問題不難理解。例如發送的郵件可能會被監聽,詐騙分子可以冒充你老板。不一定是在網絡上,在任何非面對面交流的情況下,都可能存在這兩個問題。例如打仗時,情報可能被敵方監聽竊取,收到的命令可能是被敵人冒充的。

對於第一個問題,可以通過加密來解決。就像戰爭電影中,雙方會加密自己的情報和破解對方的情報。

那么如何進行加密呢?最容易想到的方法就是雙方約定一套規則(加密算法),發送方將原始信息(明文)按照這套規則轉換(加密)成別人看不懂的信息(密文)。其他人不知道這套規則,就無法獲取原始信息。而接收人按照約定好的規則,則可以還原(解密)出原始信息。最簡單的規則可以是將字母后移三位,例如將 hi 轉換成 kl。這種規則很容易被人猜到,而且人類的腦洞是有限的,或者說優秀密碼學家設計出的加密算法是有限的,很可能就英雄所見略同了。而且如果加密算法被想到,就只能再換一種加密算法,估計密碼學專家的頭發也不太夠用。所以一般常用的加密算法都是公開的,再提供一個額外的保密的信息(密鑰),解密的時候必須使用相同的密鑰才能成功。例如提供一本書,發送方將信息轉換為書中的頁碼,接收方找到每頁第一個字即可還原信息。這就是常說的對稱加密的基本思路,對稱的意思是加解密雙方需要具備相同的密鑰,解密的人同時也可以加密信息。常見的對稱加密算法有:AES、Twofish 等。

對稱加密解決了消息本身不能被其他人獲取的問題,但帶來了一個新問題:密鑰又該如何傳輸呢?為了讓后續的消息能被安全的加密,通信雙方需要以安全的方式(例如面對面)交換一個密鑰,然后就可以使用這個密鑰進行安全的通信了。這就給通信帶了困難,很多時候可能不方便這樣面對面的交流。更致命的是,如果需要與多個人通信,與每個人都要重復一遍這個過程,而且交換的密鑰都不能相同。這樣交換密鑰和管理密鑰的成本都很高,甚至是不可行的。

有對稱加密,自然就有非對稱加密,可以用來解決密鑰交換的問題。非對稱加密的密鑰不是一個,而是一對。其中一個可以發布給所有人,用來加密信息,這個叫公鑰。另一個只能自己持有,用來解密信息,這個叫私鑰。他們就像一對鑰匙和鎖頭,和生活中的鎖頭不一樣,這里鑰匙(私鑰)只有一把,而鎖頭(公鑰)到處都是。這些鎖頭可以發布給所有人,發送方把信息用鎖頭鎖上再發送,最終只有鑰匙的持有者可以解開這條消息。常用的非對稱加密算法有:RSA、橢圓曲線算法等。

非對稱加密看起來沒什么問題了,那是不是就不需要對稱加密了?因為非對稱加密算法的計算一般都很復雜,性能遠遠不如對稱加密,所以這兩個結合才是最佳的選擇:用非對稱加密算法去加密對稱加密算法的密鑰,然后再用這個密鑰使用對稱加密算法去加密原始信息。發送信息的過程變成了:

  1. 接收方有一對公鑰和私鑰,並將公鑰廣而告之所有人,例如掛在自己的個人網站上
  2. 發送方使用對稱加密算法加密原始信息
  3. 發送方使用接收方的公鑰加密上一步使用的密鑰
  4. 發送方將這兩個信息一起發送給接收方

接收方收到消息后:

  1. 使用自己的私鑰解密出對稱加密用到的密鑰
  2. 使用解密出來的密鑰解密原始信息

這樣就徹底保證了發出的信息只能被預期的接收人獲取。至於公鑰如何廣而告之的問題,我們在后面的 GPG 使用中討論。

非對稱加密也可以反過來,使用私鑰加密,同樣只有對應的公鑰才能解密。這樣做一般不是為了保密,因為公鑰已經廣而告之,所有人都能解開。但是有另一個意義:可以用來做數字簽名。發送方使用自己的私鑰將信息加密(簽名),接收方收到信息后,使用公鑰解密(驗證)得到原始信息。這樣其他人沒有發送方的私鑰,如果冒充或篡改原始信息,接收方使用公鑰驗證時將會失敗。實際使用時一般不會對消息全文進行簽名,因為效率太低,只需要對消息的摘要進行簽名,如果消息被篡改,摘要也會變化,驗證同樣會失敗。發送信息的過程如下:

  1. 發送方有一對公鑰和私鑰,並將公鑰廣而告之所有人
  2. 發送方計算原始信息的摘要
  3. 發送方使用自己的私鑰加密摘要
  4. 發送方將原始信息和加密后的摘要一起發送給接收方

接收方收到信息后:

  1. 計算原始信息的摘要
  2. 使用發送方的公鑰解密發送方加密后的摘要
  3. 驗證兩個摘要是否相同

至此我們已經介紹了加密和簽名的基本概念,有了這兩個概念配合使用,就能解決本文開通提到的兩個問題。下面將會介紹如何通過 GPG 工具來實現這些。

什么是 GPG

GPG 可以分成兩部分來看:

第一部分:GPG 是一個加密、解密、簽名、驗證工具。前面介紹了加解密的基本概念、相關的算法。但這些概念和算法並不能直接使用,而 GPG 就是一個使用這些算法,對信息進行加密、解密、簽名、驗證的工具。具體介紹見如何使用部分。

第二部分:GPG 還是一個密鑰管理工具,可以用於管理自己的私鑰,其他人的公鑰,以及提供了一套公鑰信任體系。前面加解密概念中提到,公鑰要廣而告之,GPG 可以幫助我們更加安全高效的交換公鑰。具體介紹見管理密鑰部分。

另外在使用 GPG 時,可能還會看到 PGP、OpenPGP 等名詞,他們是什么關系?PGP (Pretty Good Privacy) 是最早的於 1991 年發布的此類工具。PGP 很好用,但他是商業軟件。於是 GNU 計划在 1999 年發布了開源版本的 GNU Privacy Guard (GnuPG 或 GPG)。而 OpenPGP 是於 1997 年制定的一套標准,GPG、PGP 等工具都實現了這套標准。

如何使用

已經做了很多鋪墊,接下來先看一下 GPG 是如何使用的。

下面的每一條命令都涉及很多可選參數可以組合使用,這也是命令行工具的靈活之處。不過初次接觸可能會覺得很不友好,沒有關系,只要了解即可,需要時可以通過 man gpg 快速查詢。

這里涉及到的一些概念,將在基本概念中介紹。

生成密鑰

命令:

gpg --gen-key

將會交互式的要求輸入真實姓名、郵箱的信息。輸入完成后將會生成一對密鑰。

查看已有密鑰

命令:

gpg (-k | -K) [--with-fingerprint] [--with-subkey-fingerprints] [--with-sig-list] [--with-sig-check] [<key-id>]
gpg --fingerprint
gpg --list-sigs

參數說明:

  • -k/--list-public-keys:查看公鑰。
  • -K/--list-secret-keys:查看私鑰。
  • --with-xxx:根據字面意思,將會額外打印一些信息,具體信息可以通過 man gpg 查看。
  • --fingerprint:打印密鑰的指紋,等價於 gpg -k --with-fingerprint
  • --list-sigs:打印密鑰的簽名,等價於 gpg -k --with-sig-list
  • <key-id>:僅打印指定的密鑰。可選,否則打印所有密鑰。如何選擇一個密鑰請參考:選擇密鑰

打印出來信息的含義,將在基本概念中進一步說明。

示例:

gpg -k
gpg -K
gpg --fingerprint

加密

命令:

gpg -r <key-id> [-o <output-file>] [-a] -e [<input-file>]

參數說明:

  • -r/--recipient:指定接受者的公鑰 ID,消息將會使用這個公鑰進行加密,也就是只有擁有這個私鑰的人才能解密信息。可以指定多個,則多個接受者都能解密信息。
  • -o/--output:指定加密后的信息輸出到哪個文件。可選,如果不指定將會輸出到標准輸出。
  • -a/--armor:將加密后的信息轉為可打印的 ASCII 字符。可選,如果不指定將會輸出二進制信息。
  • -e/--encrypt:加密。相應的還有解密、簽名、驗證等參數,將在后面介紹。
  • <input-file>:要加密的文件。可選,如果不指定將會從標准輸入讀取。

注意:只有 -r 指定的私鑰才能解密信息,如果沒有指定自己,則自己也無法解密。也可以僅指定自己,用於加密隱私文件。可以通過配置,加密時默認將自己包含在內,后面將會介紹。

示例:

gpg -r someone -o myfile.gpg -e myfile
echo 'some message' | gpg -r someone -ae

解密

命令:

gpg [-o <output-file>] -d [<input-file>]

參數說明:

  • -o/--output:指定解密后的信息輸出到哪個文件。可選,如果不指定將輸出到標准輸出。
  • -d/--decrypt:解密。
  • <input-file>:待解密的文件。可選,如果不指定將嘗試從標准輸入讀入。

解密時沒有指定私鑰,因為一般加密信息中會包含使用的公鑰 ID,GPG 將會自動在本地尋找對應的私鑰,如果找不到將會解密失敗。

示例:

gpg -o myfile -d myfile.gpg
echo 'some message' | gpg -r someone -e | gpg -d

簽名

命令:

gpg [-u <key-id>] [-o <output-file>] [-a] (-s | -b | --clearsign) [<input-file>]

參數說明:

  • -u/--local-user:指定用來簽名的密鑰 ID,簽名后,只有對應的公鑰可以驗證成功。如果不指定將使用默認密鑰,如果沒有默認密鑰將使用第一個可用密鑰。默認密鑰參考:配置文件
  • -s/--sign:簽名。
  • --clearsign:簽名並保持原始信息。-s 簽名后,信息將會打包成 GPG 的格式。雖然沒有加密,但仍需 GPG 命令才能解析查看。--clearsign 簽名,會保持原始信息,額外附加一段簽名信息,這樣任何人都可以直接看到原始信息,需要驗證的再使用 GPG 驗證。
  • -b/--detach-sign:分離簽名。如果是文本信息不想修改原始信息,可以使用 --clearsign 保持原始信息。而對於二進制文件,則可以使用 -b 創建一個獨立的簽名文件。

這三種簽名方式,實際動手操作一下就知道他們的差別了。

示例:

echo 'some message' | gpg -u myself --clearsign
gpg -b file.zip

驗證

命令:

gpg (--verify | -d) [<file>...]

參數說明:

  • --verify:僅驗證簽名是否正確,不輸出原始信息。
  • -d/--detach-sign:驗證簽名是否正確,並輸出原始信息。
  • <file>...:對於 -s/--clearsign 的簽名,輸入為簽名文件。對於 -b 的簽名,第一個參數為簽名文件,第二個參數為被簽名的數據,如果不指定第二個參數,將會自動嘗試去掉后綴作為原始文件名。

驗證簽名同樣不用指定公鑰。GPG 將會在本地的公鑰中尋找,如果無法找到,將會驗證失敗。

示例:

echo 'some message' | gpg -u myself -s | gpg -d
gpg --verify file.zip.sig

組合

為了更清楚的說明每個功能的用法,上面將每個參數分開介紹的,這些參數可以組合使用。例如實際使用時,可能同時需要簽名和加密:

echo 'some message' | gpg -u myself -r someone -ase

基本概念

查看密鑰列表時,會有類似如下輸出,在介紹如何管理密鑰前,先了解一下這些輸出信息的含義。這個輸出在每個版本有可能會不同。

$ gpg -k --with-fingerprint --with-subkey-fingerprint --with-sig-list
pub   rsa4096 2021-11-22 [SC]
      B69B C896 53B7 D844 C67F  137C 3684 CA4A 7AF9 0D04
uid           [ultimate] Some One (Just an example.) <example@mail.com>
sig 3        3684CA4A7AF90D04 2021-11-22  Some One (Just an example.) <example@mail.com>
sub   rsa3072 2021-11-22 [S] [expires: 2021-11-23]
      FED2 E682 2A8A E366 3694  4D72 51AE 0444 47EA C691
sig          3684CA4A7AF90D04 2021-11-22  Some One (Just an example.) <example@mail.com>
sub   rsa3072 2021-11-22 [E] [expires: 2021-11-23]
      B471 1661 FE14 AE6A 3907  DD65 3E40 85A7 CDAF 19EF
sig          3684CA4A7AF90D04 2021-11-22  Some One (Just an example.) <example@mail.com>
$ gpg -K --with-fingerprint --with-subkey-fingerprint --with-sig-list
sec   rsa4096 2021-11-22 [SC]
      B69B C896 53B7 D844 C67F  137C 3684 CA4A 7AF9 0D04
uid           [ultimate] Some One (Just an example.) <example@mail.com>
sig 3        3684CA4A7AF90D04 2021-11-22  Some One (Just an example.) <example@mail.com>
ssb   rsa3072 2021-11-22 [S] [expires: 2021-11-23]
      FED2 E682 2A8A E366 3694  4D72 51AE 0444 47EA C691
sig          3684CA4A7AF90D04 2021-11-22  Some One (Just an example.) <example@mail.com>
ssb   rsa3072 2021-11-22 [E] [expires: 2021-11-23]
      B471 1661 FE14 AE6A 3907  DD65 3E40 85A7 CDAF 19EF
sig          3684CA4A7AF90D04 2021-11-22  Some One (Just an example.) <example@mail.com>

密鑰類型

每個密鑰開頭都會有這樣幾個字母:pub/sub/sec/ssb,表示這個密鑰的類型。

在非對稱加密算法中,密鑰都是成對出現的。pubsec 就分別表示這一對密鑰的公鑰和私鑰,而 subssb 則分別表示一對子密鑰的公鑰和私鑰。

為什么會存在子密鑰?理論上只需一對主密鑰,就可以完成所有加密和簽名的需要了。而 GPG 支持一對主密鑰和若干對子密鑰,主要是為了密鑰本身的安全考慮。例如需要在多台設備上進行簽名和加密操作,如果在每個機器上都使用主密鑰,一旦丟失,則所有設備上的信息都將可以被解密。而且除了撤銷整個主密鑰之外,沒有任何其他辦法來止損。而如果將主密鑰保存在安全的地方,僅在必要的時候使用,其余機器上都使用子密鑰。那么如果一台機器上的子密鑰丟失,只有這台機器上的信息可能被泄露。而且無需撤銷整個主密鑰,只需要使用主密鑰撤銷這個子密鑰,然后重新創建一個子密鑰即可。

另外每個子密鑰也可以選擇不同的加密算法,可以指定不同子密鑰來選擇不同的加密算法來進行加解密。

密鑰用途

每個密鑰旁邊都會有方括號包圍的一個或多個字母,可能取值有 E/S/C/A,表示這個密鑰的用途。每個值的含義如下:

  • Encryption:加密。
  • Signing:簽名。
  • Certification:認證其他子密鑰或 uid。
  • Authentication:身份認證,例如用於 SSH 登錄。

其中前三個較為常用。如果使用 gpg --gen-key 生成的密鑰,默認就會生成一對主密鑰 [SC] 和一對子密鑰 [E]。這樣將會使用主密鑰進行簽名,使用子密鑰進行解密。

我們也可以自行添加其他子密鑰或者修改已有子密鑰用途,具體操作方式將在編輯密鑰中介紹。

加密算法

pub 等標識后面緊跟着的是密鑰的加密算法,例如 rsa3072 表示密鑰長度為 3072 位的 RSA 算法。當前版本 (2.2.19) 使用 gpg --gen-key 生成的默認密鑰使用的就是 3072 位的 RSA 算法。支持的其他算法可以輸入 gpg --version 查看。注意這里指的是非對稱加密的算法,對稱加密使用的算法可以在每次加密時通過參數指定不同算法。

如果想要生成其他算法的主密鑰,可以使用 gpg --full-gen-key 命令。這里也體現了使用子密鑰的靈活性,例如我們可以使用 4096 位的主密鑰,更加安全。然后使用 3072 位的子密鑰用於加密和簽名,更加高效。如果未來 3072 位密鑰不夠安全時,只需要重新生成 4096 位的子密鑰,而不用重新生成主密鑰。

指紋

每個密鑰或子密鑰下面都有一行由 10 組 4 個字符組成的信息。這是使用 SHA-1 算法對整個密鑰計算出來的摘要,共 160 位,20 字節,一般表示為 40 個十六進制數,就是現在看到的。這個指紋可以用於唯一的標識一對密鑰。

User ID

每個主密鑰可以有一個或多個 uid,用於標識用戶身份。格式為 Real Name (Comment) <Email>

有效性

每個 uid 旁邊的方括號內,標識了這個 uid 的有效性。

如果新導入了一個公鑰,默認將會顯示 [unknown]。這是因為任何人都可以聲稱自己是任何人,所以在導入公鑰時,需要想辦法驗證他的有效性。

第一種驗證方式是直接當面交換公鑰,絕對安全。但很多時候這不可能。

另一種方式是驗證指紋,可以使用 gpg --fingerprint 命令將指紋打印出來,然后通過打電話或者其他可靠的方式確認指紋是否正確。因為指紋是通過安全散列算法對整個密鑰信息計算的摘要,很難構造出(碰撞)兩個摘要相同的密鑰,所以一旦確認指紋沒錯,就可以認為整個密鑰是有效的。

確認之后,需要將密鑰標識為有效的,標識的方式就是使用自己的密鑰對公鑰進行簽名,這樣 GPG 就認為這是個有效的密鑰了。

注意簽名和有效性都是針對 uid 的。例如一個人聲稱了兩個身份,第一個 uid 說他叫特朗普,第二個 uid 說他是前美國總統。你想盡一切辦法最終只驗證了他確實叫特朗普,但不知道是不是那個美國總統。那就可以僅對第一個 uid 簽名。

如何對 uid 簽名將會在編輯密鑰具體介紹。

信任網絡

事實上,幾乎很難直接驗證每個密鑰的有效性,這時可以利用 GPG 的信任網絡來間接驗證密鑰的有效性。

簡單來說就是如果我確認了某個密鑰的主人確實是美國總統,而我信任他不會亂認人(但願吧)。那么如果這個密鑰對某個叫做國務卿的密鑰進行了簽名,我就也認為這個國務卿確實是有效的,而不用親自去認證。

信任分為幾個不同的等級:

  • ultimate:終極信任。一般只應該對自己的密鑰進行終極信任,可以理解為所有信任鏈的根節點。
  • full:完全信任。對於這個人簽名的其他密鑰,我也認可。
  • marginal:信了,但沒完全信。這個人簽名過的密鑰,我不一定認可,但如果三個這樣的人都簽了,那我就信了。
  • never:不信任。這個人對其他密鑰的簽名,我一律視而不見。

需要注意信任和有效性不一定有關系。信任表示的是對這個密鑰簽名其他密鑰的信任程度,而有效性是對這個密鑰本身的驗證。例如我知道某個密鑰確實是特朗普的,他是有效的。但我覺得這個人滿嘴跑火車,他簽名的其他密鑰我一概不認。

有了信任網絡,一個密鑰有效的條件就變成了:被一個 full 簽名或三個 marginal 簽名,同時這個簽名傳遞的路徑距離我(ultimate)的長度不超過 5。這些值都可以修改,具體可以參考 man gpg。更具體的說明可以參考 The GNU Privacy Handbook

如何修改信任值將在編輯密鑰具體介紹。

自簽名和交叉簽名

除了通過驗證其他人對 uid 的簽名外,所有 uid 和子密鑰都還需要有自簽名。否則攻擊者就可以繞過公鑰的主人插入一個自己的子密鑰,來冒充別人。而如果要求所有的 uid 和子密鑰都經過主密鑰自簽名,則冒名頂替的 uid 和子密鑰因為沒有主密鑰的私鑰,將無法蒙混過關。

對於子密鑰,除了自簽名外,還需要和主密鑰進行交叉簽名。否則攻擊者將其他人的子密鑰插入到自己密鑰中,就可以聲稱某個簽名是自己發出的。而如果要求子密鑰和主密鑰進行交叉簽名,則攻擊者因為無法獲取子密鑰的私鑰對自己的主密鑰進行簽名,將無法蒙混過關。

撤銷

GPG 在更新密鑰的時候,對 uid 的簽名、uid、子密鑰等都會采用合並的方式處理。因此如果一個簽名、uid 或者子密鑰不再使用了,將其刪除是沒有意義的,因為導出給其他人或者密鑰服務器,合並后原來的簽名、uid 和子密鑰還是存在的。所以如果不再使用,我們需要撤銷它。

其實無論撤銷什么,本質都是在撤銷簽名。撤銷對 uid 的簽名,將會生成一條撤銷簽名的信息,標記原來的簽名無效。而如果撤銷的是 uid 或子密鑰,將會撤銷對 uid 或子密鑰的自簽名,使原來的 uid 或子密鑰失效。

撤銷的密鑰只是不能用於新的加密和簽名。但依然可以解密和驗證已有的信息,只是會提示已經被撤銷。

當然也可以撤銷整個主密鑰,這些都將在編輯密鑰中介紹。

有效期

如果有必要,可以分別對主密鑰和每對子密鑰設置有效期。有效期可以隨時修改,過期前重新設置有效期即可,無需重新生成新密鑰。

過期的密鑰只是不能用於新的加密和簽名。但依然可以解密和驗證已有的信息,只是會提示過期。

設置有效期的安全性,並不在於定期更換密鑰,實際上 GPG 官方文檔也沒有推薦更換密鑰,而是建議在到期前續期。也不在於擔心密鑰泄露,因為如果密鑰泄露,獲取私鑰的人也可以隨時修改有效期。有效期的意義是在於讓持有公鑰的人,記得及時更新公鑰信息。例如如果密鑰已經泄露了,但沒有設置有效期。其他人如果沒有想到要主動更新公鑰,可能永遠也發現不了密鑰已經泄露了。那么獲取了私鑰的人冒充你進行簽名,依然會被其他人認可。

如何設置有效期將在編輯密鑰介紹。

選擇密鑰

前面介紹的命令中,已經出現了很多次 <key-id> 的占位符。其實這里用 <key-id> 並不恰當,只是沒有更好的名稱來描述。實際使用中,可以有多種方式來選擇一個密鑰。常用的有:

  • 指紋:就是那 40 個十六進制數。這是 GPG 推薦的,最不容易重復的方式,缺點是太長。
  • Key ID:有兩種格式
    • 短 ID:指紋的后 8 位,這種已經不推薦了,因為有被碰撞的風險
    • 長 ID:指紋的后 16 位
  • 精確匹配的郵箱:<xxx@xxx>
  • 部分匹配的郵箱:@xxx
  • 部分匹配 uid:someone,不區分大小寫

所有需要選擇某個 key 的地方,都可以使用上面這些形式。注意除了指紋和 Key ID 外,其他都可能匹配到多個,將會選擇第一個使用。

除了這些基本的匹配外,對於 Key ID 和指紋,還有個特殊的用法:!

前面介紹過 GPG 支持一對主密鑰和若干對子密鑰。而如果主密鑰支持 [SC],某個子密鑰也支持 [S]。那么簽名時將會使用哪個呢?答案是使用子密鑰。在選擇密鑰時,GPG 會自動選擇一個支持對應能力的子密鑰,如果存在多個,則選擇較新的一個。那么如果就是要使用某個特定的主密鑰或子密鑰呢?這時就可以在 key ID 或指紋后面加上 !,強制使用這個密鑰,而不要自動推算。

這種用法還可以用在導出密鑰時,僅導出某個子密鑰或主密鑰。

管理密鑰

導出密鑰

命令:

gpg [-a] [-o <output-file>] [--export-options <option>[,<option>...]] (--export | --export-secret-keys | --export-secret-subkeys) [<key-id>]

參數說明:

  • --export:導出公鑰。
  • --export-secret-keys:導出私鑰。
  • --export-secret-subkeys:導出子密鑰。
  • --export-options:導出選項,逗號分割,常用的有:
    • backup:導出用於備份。會將信任值、本地簽名等一起導出。
    • export-clean/export-minimize:參考:清理簽名
  • <key-id>:如果不指定將會導出所有公鑰或私鑰,如果指定僅會導出指定的密鑰,使用 ! 可以僅導出主密鑰或子密鑰。

導入密鑰

命令:

gpg --import [--import-options <option>[,<option>...]] [<key-file>]

參數說明:

  • --import:導入密鑰。
  • --import-options:導出選項,逗號分割,常用的有:
    • restore:恢復,與導出選項的 backup 對應。
    • import-show:回顯導入的密鑰信息。

示例:

gpg --import someone.gpg

刪除密鑰

命令:

gpg (--delete-keys | --delete-secret-keys | --delete-secret-and-public-keys) <key-id>...

參數說明:

  • --delete-keys:刪除公鑰。
  • --delete-secret-keys:刪除私鑰。
  • --delete-secret-and-public-keys:同時刪除私鑰和公鑰。

示例:

gpg --delete-keys someone
gpg --delete-secret-and-public-keys someone

密鑰服務器

通過手動的導入、導出密鑰,當密鑰比較多時會比較麻煩。更關鍵的是不方便密鑰的更新。例如已經通過手動導出的方式將公鑰發布給了很多人,一旦公鑰發生變動(例如獲得了一個新簽名、撤銷了一個子密鑰等),就需要重新導出,然后找到每個持有公鑰的人,要求他更新一下。而 GPG 可以通過密鑰服務器幫助我們完成這些,使用起來和導入導出差不多,只不過導出到密鑰服務器、從密鑰服務器導入而已。

命令:

gpg [--keyserver <key-server>] [--keyserver-options <option>[,<option>...]] (--send-keys | --recv-keys | --refresh-keys | --search-keys) [<key-id>]

參數說明:

  • --send-keys:將密鑰發送到密鑰服務器。
  • --recv-keys:從密鑰服務器接收密鑰。
  • --refresh-keys:從密鑰服務器更新本地密鑰。
  • --search-keys:從密鑰服務器搜索密鑰。
  • --keyserver:指定一個密鑰服務器,大部分密鑰服務器之間都會同步密鑰。
  • --keyserver-options:導入或導出密鑰時的一些選項,支持所有 --import-options--export-options,另外還支持像 http-proxy 來指定代理等。

示例:

gpg --search-keys EB4C1BFD4F042F6DDDCCEC917721F63BD38B4796
gpg --recv-keys EB4C1BFD4F042F6DDDCCEC917721F63BD38B4796
gpg --send-keys B69BC89653B7D844C67F137C3684CA4A7AF90D04

編輯密鑰

使用 gpg --edit-key <key-id> 命令,可以交互式的編輯一個密鑰。輸入 help 可以查看幫助,輸入 save 可以保存並退出編輯,輸入 quit 可以不保存退出編輯。

下面是一些常用操作的介紹。

對 uid 簽名

使用 signlsign 可以對 uid 進行簽名。兩者的區別是,sign 的簽名可以被導出和上傳到密鑰服務器,而 lsign 的簽名僅可以在本地查看和生效。一般我們驗證了一個人的身份,如果沒有得到公鑰主人的允許,應該優先使用 lsign 進行簽名。

如果需要撤銷一個簽名,可以使用 revsig 命令。如果簽名還沒有發布(上傳到密鑰服務器或者導出給其他人),也可以使用 delsig 直接刪除。

這里的簽名將會使用默認的私鑰,如果沒有指定將會使用第一個可用的私鑰。或者也可以在 --edit-key 時通過 -u 參數指定一個私鑰。

如果不指定某個 uid,將會對所有 uid 簽名。也可以先通過 uid [n] 命令選擇某個或某些 uid,再進行簽名。uid 0 將取消選擇所有 uid

信任密鑰

使用 trust 命令可以設置對密鑰的信任值。關於信任值的解釋和每個信任值的含義參考:信任網絡

信任值是一個很主觀的事情,因此信任值僅會保存到本地的數據庫中,不會被導出或上傳到數據庫中。除非使用 --export-options backup 選項導出。

uid

使用 adduid 命令可以創建一個新的 uid。並可以使用 uid [n] 命令選擇一個 uid 后,使用 primary 命令指定一個主 uid。

如果某個 uid 不再使用,可以先使用 uid [n] 選中,再使用 revuid 命令撤銷。如果 uid 還沒有發布,也可以使用 deluid 直接刪除。

子密鑰

使用 addkey 命令可以創建一對子密鑰。創建過程中可以交互式的選擇使用的算法、用途等。

如果某個子密鑰不再使用,可以先使用 key [n] 選中,再使用 revkey 命令撤銷。如果子密鑰還沒有發布也沒有使用過,可以使用 delkey 直接刪除。但要注意,如果刪除,使用此子密鑰加密過的信息將永遠無法解密!

撤銷密鑰

密鑰服務器為了防止被篡改,被設計為只增不刪的形式。也就是說如果密鑰一旦上傳到服務器,將永遠不能刪除。那么如果主密鑰丟失或者泄露了,我們只能撤銷它。

不選擇任何子密鑰,執行 revkey 命令,將撤銷整個密鑰。撤銷之后,重新將密鑰發送到密鑰服務器,密鑰服務器上的密鑰也會被撤銷。其他人從密鑰服務器更新之后,將會知道密鑰已經被撤銷,以后就不會再使用此密鑰進行加密,也將不會信任此密鑰的簽名。

上面的操作必須在我們擁有私鑰的情況下進行,而如果私鑰丟失了,我們就永遠無法更新密鑰的狀態了。所以為了避免出現這種情況,一般建議生成一個撤銷證書,和私鑰分開保存。撤銷證書本質上就是一個撤銷密鑰的簽名。如果私鑰丟失,需要將撤銷證書導入,並發送到密鑰服務器,密鑰服務器上的公鑰也將被撤銷。

  • 生成撤銷證書:gpg [-a] [-o <output-file>] --gen-revoke <key-id>
  • 通過導入撤銷證書撤銷密鑰:gpg --import [<input-file>]
  • 發布撤銷密鑰:
    • 如果之前使用了密鑰服務器,則發布到密鑰服務器即可:gpg --send-keys <key-id>
    • 如果是手動導出的方式,則再次導出並發送給其他人導入即可:gpg --export-keys <key-id>

注意: 密鑰一旦撤銷將無法恢復。

其實在擁有私鑰的情況下,無需撤銷證書即可撤銷整個密鑰。撤銷證書單獨保存的意義在於,他可以保存在比私鑰稍低一個安全等級的地方。因為一旦私鑰泄露,以往的信息都將泄露。而如果安全證書泄露,只會使密鑰失效,不會泄露任何信息。最多是需要重新生成一對密鑰發布給其他人,比較麻煩而已。例如撤銷證書可以放在信任的人那里備份,而私鑰只能放在不會被任何人獲取的地方備份。

過期時間

使用 expire 命令可以設置密鑰的過期時間。默認會設置主密鑰的,使用 key [n] 選中子密鑰后,將設置選中密鑰的。

密碼

使用 passwd 命令可以修改密鑰的密碼。

清理簽名

如果 uid 上收集的很多簽名無效了,例如撤銷了的簽名,不會刪除原有的簽名,而是在生成一條撤銷的信息。可以使用 clean 命令,清除所有無效的簽名。

如果更進一步,不需要所有其他人的簽名,則可以使用 minimize 清除自簽名外的所有簽名。

配置文件

前面的介紹中可以看到,很多時候我們都需要通過 -u 參數指定使用哪個密鑰進行簽名。還有加密時如果不指定自己,以后將會無法解密自己發出的信息。我們希望將這些參數默認配置下來,不用每次都在命令行中輸入。

GPG 命令中的所有長參數 (--開頭的參數) 都可以配置在 ~/.gnupg/gpg.conf 中,這樣每次執行 GPG 命令時,都會默認帶上這些參數。

例如指定默認的用於簽名的密鑰,指定每次加密都默認也加密給自己等等。

示例:

default-key B69BC89653B7D844C67F137C3684CA4A7AF90D04
encrypt-to B69BC89653B7D844C67F137C3684CA4A7AF90D04

使用場景

GPG 主要用於信息傳輸過程中的加密。對於大多數人來說,既沒有什么恐怖襲擊計划需要討論,也沒有幾百億的生意要談,所以可能用到的機會不多。不過 GPG 也可以用於給自己的文件進行加密,例如將敏感文件加密后再通過網盤備份等。

GPG 的簽名功能在很多地方都會用到。例如大部分 Linux 發行版的包管理系統,都會使用 GPG 簽名來保證包在分發的過程沒有被篡改。所以各種 Linux 發行版一般都在世界各地存在大量的鏡像源,我們可以放心的享受這些鏡像源的便利,不是靠對鏡像源的信任來保證的,而是靠 GPG 簽名來保證的。此外還可以使用 GPG 對 Git 的提交和標簽進行簽名等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM