用 PGP 保護代碼完整性(五):將子密鑰移到一個硬體設備中
在本系列教程中,我們將提供一個使用 PGP 的實用指南。如果你沒有看過前面的文章,你可以通過下面的鏈接去查看。在這篇文章中,我們將繼續討論如何保護你的密鑰,談一談將你的子密鑰移到一個專門的硬體設備中的一些技巧。
清單
- 取得一個 GnuPG 兼容的硬體設備(必要)
- 配置 GnuPG 在設備上工作(必要)
- 設置用戶和管理員的 PIN(必要)
- 移動子密鑰到設備中(必要)
考慮事項
雖然現在主密鑰已經不用擔心泄露或失竊了,但子密鑰仍然在你的家目錄中。任何得到它的人都能夠解密你的通訊或假冒你的簽名(如果他們知道密鑰的密碼)。並且,每次執行一個 GnuPG 操作都要將密鑰載入到操作系統內存中,這將使一些更高級的惡意軟體有機會得到你的密鑰(想想 Meltdown 和 Spectre)。
完全保護密鑰的最好方式就是,將它移到一個專門的硬體設備中,這種硬體設備是一個可操作的智能卡。
智能卡的好處
一個智能卡包含一個加密晶元,它能夠存儲私鑰,並且直接在智能卡內部執行秘密操作。因為密鑰內容從來沒有離開過智能卡,計算機操作系統並不能檢索你插入的智能卡上的私鑰。這與前面用於備份目的的加密 USB 存儲是不同的 —— 雖然 USB 設備也是插入並解密的,但操作系統是能夠去訪問私鑰內容的。使用外置的加密 USB 介質並不能代替智能卡設備的功能。
智能卡的一些其它好處:
- 它們很便宜且易於獲得
- 它們小巧且易於攜帶
- 它們可以用於多種設備上
- 它們中的很多都具有防篡改功能(取決於製造商)
可用的智能卡設備
智能卡最初是嵌入到真實錢包大小的卡中,故而得名智能卡。你肯定可以買到並使用 GnuPG 功能的智能卡,並且它們是你能得到的最便宜的可用設備之一。但是,事實上智能卡有一個很重要的缺點:它們需要一個智能卡讀卡器,只有極小數的筆記本電腦上有這種讀卡器。
由於這個原因,製造商開始推出小型 USB 設備,它的大小和 U 盤類似,內置有微型智能卡,並且在晶元上簡單地實現了智能卡協議特性。下面推薦幾個這樣的設備:
- Nitrokey Start:開源硬體和自由軟體,可用於 GnuPG 的最便宜的選擇之一,但是額外的安全特性很少。
- Nitrokey Pro:類似於 Nitrokey Start,它提供防篡改及更多的安全特性(但沒有 U2F,具體查看指南的 U2F 節)。
- Yubikey 4:專利硬體和軟體,但比 Nitrokey Pro 便宜,並且可以用在最新的筆記本電腦上的 USB-C 介面;也提供像 U2F 這樣的額外的安全特性。
我們推薦選一個同時具備智能卡功能和 U2F 的設備,在寫這篇文章時,只能選擇 Yubikey 4。
配置智能卡設備
你的智能卡設備插入任何一台現代的 Linux 或 Mac 工作站上都應該能正常工作。你可以通過運行如下的命令去驗證它:
$ gpg --card-status
如果你沒有收到錯誤,有一個完整的卡列表,就表示一切正常。不幸的是,排除為什麼設備不能正常工作的所有可能原因,已經超出了本指南的範圍。如果你的智能卡使用 GnuPG 時有問題,請通過你的操作系統的常見支持通道尋求支持。
PIN 不一定是數字
注意,儘管名為 「PIN」(暗示你它必須是一個「數字」),不論是用戶 PIN 還是管理員 PIN 都不必非要是數字。
當你收到一個新設備時,它可能設置有一個默認的用戶和管理員 PIN,對於 Yubikey,它分別是 123456
和 12345678
。如果它們的 PIN 不是默認的,請查看設備附帶的說明書。
快速設置
為配置你的智能卡,你需要使用 GnuPG 菜單系統,因此這裡並沒有更方便的命令行開關:
$ gpg --card-edit
[...omitted...]
gpg/card> admin
Admin commands are allowed
gpg/card> passwd
你應該去設置用戶 PIN (1)、管理員 PIN (3)、和重置碼 (4)。請確保把它們記錄並保存到一個安全的地方 —— 尤其是管理員 PIN 和重置碼(它允許你去擦除整個智能卡內容)。你很少使用到管理員 PIN,因此如果你不記錄下來,很可能會忘掉它。
返回到智能卡主菜單,你也可以設置其它值(比如名字、性別、登入日期、等等),但是這些都不是必需的,一旦你的智能卡丟失了,將導致額外的信息泄露。
將子密鑰移到你的智能卡中
退出卡菜單(使用 q
命令)保存所有更改。接下來,我們將你的子密鑰移到智能卡中。將需要用到你的 PGP 密鑰的密碼,在大多數的智能卡操作中都將用到管理員 PIN。記住,那個 [fpr]
表示你的密鑰的完整的 40 個字元的指紋。
$ gpg --edit-key [fpr]
Secret subkeys are available.
pub rsa4096/AAAABBBBCCCCDDDD
created: 2017-12-07 expires: 2019-12-07 usage: C
trust: ultimate validity: ultimate
ssb rsa2048/1111222233334444
created: 2017-12-07 expires: never usage: E
ssb rsa2048/5555666677778888
created: 2017-12-07 expires: never usage: S
[ultimate] (1). Alice Engineer <alice@example.org>
[ultimate] (2) Alice Engineer <allie@example.net>
gpg>
使用 --edit-key
再次進入到菜單模式,你將注意到那個密鑰清單有一點小差別。從現在開始,所有的命令都是在這個菜單模式下運行,它用 gpg>
提示符來表示。
首先,我們來選擇移到智能卡中的密鑰 —— 你可以通過鍵入 key 1
(它表示選擇清單中的第一個密鑰)來實現:
gpg> key 1
這個輸出會有一點細微的差別:
pub rsa4096/AAAABBBBCCCCDDDD
created: 2017-12-07 expires: 2019-12-07 usage: C
trust: ultimate validity: ultimate
ssb* rsa2048/1111222233334444
created: 2017-12-07 expires: never usage: E
ssb rsa2048/5555666677778888
created: 2017-12-07 expires: never usage: S
[ultimate] (1). Alice Engineer <alice@example.org>
[ultimate] (2) Alice Engineer <allie@example.net>
注意與密鑰對應的 ssb
行旁邊的 *
—— 它表示這是當前選定的密鑰。它是可切換的,意味著如果你再次輸入 key 1
,這個 *
將消失,這個密鑰將不再被選中。
現在,我們來將密鑰移到智能卡中:
gpg> keytocard
Please select where to store the key:
(2) Encryption key
Your selection? 2
由於它是我們的 [E] 密鑰,把它移到加密區中是有很有意義的。當你提交了你的選擇之後,將會被提示輸入你的 PGP 密鑰的保護密碼,接下來輸入智能卡的管理員 PIN。如果命令沒有返回錯誤,表示你的密鑰已經被移到智能卡中了。
重要: 現在再次輸入 key 1
去取消選中第一個密鑰,並輸入 key 2
去選擇 [S] 密鑰:
gpg> key 1
gpg> key 2
gpg> keytocard
Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection? 1
你可以使用 [S] 密鑰同時做簽名和驗證,但是我們希望確保它在簽名區,因此,我們選擇 (1
)。完成後,如果你的命令沒有返回錯誤,表示操作已成功。
最後,如果你創建了一個 A 密鑰,你也可以將它移到智能卡中,但是你需要先取消選中 key 2
。完成後,選擇 q
:
gpg> q
Save changes? (y/N) y
保存變更將把你的子密鑰移到智能卡後,把你的家目錄中的相應子密鑰刪除(沒有關係,因為我們的備份中還有,如果更換了智能卡,你需要再做一遍)。
驗證移動後的密鑰
現在,如果你執行一個--list-secret-keys
操作,你將看到一個稍有不同的輸出:
$ gpg --list-secret-keys
sec# rsa4096 2017-12-06 [C] [expires: 2019-12-06]
111122223333444455556666AAAABBBBCCCCDDDD
uid [ultimate] Alice Engineer <alice@example.org>
uid [ultimate] Alice Engineer <allie@example.net>
ssb> rsa2048 2017-12-06 [E]
ssb> rsa2048 2017-12-06 [S]
在 ssb>
的輸出中的 >
表示子密鑰僅在智能卡上有效。如果你進入到你的密鑰目錄中,查看目錄的內容,你將會看到那個 .key
文件已經被存根替換:
$ cd ~/.gnupg/private-keys-v1.d
$ strings *.key
這個輸出將包含一個影子私鑰,它表示那個文件僅是個存根,真正的內容在智能卡中。
驗證智能卡的功能
驗證智能卡能否如期正常運行,你可以通過創建一個簽名來驗證:
$ echo "Hello world" | gpg --clearsign > /tmp/test.asc
$ gpg --verify /tmp/test.asc
首次運行這個命令時將詢問你智能卡的 PIN,在你運行 gpg —verify
之後,它將顯示 「Good signature」。
祝賀你,你已經成功將竊取你的開發者數字身份變得更加困難了!
其它常見 GnuPG 操作
下面是使用你的 PGP 密鑰需要做的一些常見操作的快速指南。
在下面的所有命令中,[fpr]
表示你的密鑰指紋。
掛載主密鑰離線存儲
下面的一些操作將需要你的主密鑰,因此首先需要去掛載你的主密鑰離線存儲,並告訴 GnuPG 去使用它。首先,找出介質掛載路徑,可以通過查看 mount
命令的輸出找到它。接著,設置你的 GnuPG 目錄為你的介質上備份的目錄,並告訴 GnuPG 將那個目錄做為它的家目錄:
$ export GNUPGHOME=/media/disk/name/gnupg-backup
$ gpg --list-secret-keys
確保你在輸出中看到的是 sec
而不是 sec#
(這個 #
表示密鑰不可用,仍然使用的是慣常的那個 Home 目錄)。
更新你慣常使用的那個 GnuPG 工作目錄
在你的離線存儲上做了任何更改之後,你應該將這些更改同步應用到你慣常使用的工作目錄中:
$ gpg --export | gpg --homedir ~/.gnupg --import
$ unset GNUPGHOME
延長密鑰過期日期
我們創建的主密鑰的默認過期日期是自創建之日起兩年後。這樣做都是為安全考慮,這樣將使淘汰密鑰最終從密鑰伺服器上消失。
延長你的密鑰過期日期,從當前日期延長一年,只需要運行如下命令:
$ gpg --quick-set-expire [fpr] 1y
如果為了好記住,你也可以使用一個特定日期(比如,你的生日、1 月 1 日、或加拿大國慶日):
$ gpg --quick-set-expire [fpr] 2020-07-01
記得將更新後的密鑰發送到密鑰伺服器:
$ gpg --send-key [fpr]
吊銷身份
如果你需要吊銷一個身份(比如,你換了僱主並且舊的郵件地址不再有效了),你可以使用一行命令搞定:
$ gpg --quick-revoke-uid [fpr] 'Alice Engineer <aengineer@example.net>'
你也可以通過使用 gpg --edit-key [fpr]
在菜單模式下完成同樣的事情。
完成後,記得將更新後的密鑰發送到密鑰伺服器上:
$ gpg --send-key [fpr]
下一篇文章中,我們將談談 Git 如何支持 PGP 的多級別集成。
通過來自 Linux 基金會和 edX 的免費課程 「Linux 入門」學習更多 Linux 知識。
作者:KONSTANTIN RYABITSEV 譯者:qhwdw 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive