使用GnuPG(PGP)加密信息及數字簽名教程

PGP (Pretty Good Privacy) 是由 Phil Zimmermann 於 1991 開發的一個用於數據加密和數字簽名的程序,由於被廣泛應用以至於後來形成一個開放的標準 OpenPGP,而 GnuPG 則是實現了該標準的一個開源免費程序,本文將會簡單介紹如何使用 GnuPG 管理鑰匙、加密解密文件和電子郵件、數字簽名文件和電子郵件等內容。篇幅有點長,不過內容是很簡單的,可以一步一步跟着來。@ivarptr

  一、加密和數字簽名的簡單原理

  首先每個人使用程序生成地球上惟一的一對鑰匙,分別稱爲公鑰和私鑰。公鑰用於加密,私鑰用於解密。使用公鑰加密過的信息只能由配對的私鑰解開。

  加密的過程是:如果A君要發送信息給B君,首先B君得把自己的公鑰扔出來,A君得獲取B君的公鑰後加密信息併發送過去,B君收到(加過密的)信息使用自己的私鑰解密就可以還原信息了。

  而數字簽名的過程稍微不同,信息是通過普通未加密方式發送信息給對方的,只是在每條信息後面都會附加一坨字符(名曰:簽名),這個簽名是由程序根據發送者的私鑰以及信息內容計算得出,接收者使用發送者的公鑰就可以覈對信息有無被篡改。

  二、獲取並安裝 GnuPG

  GnuPG 是一個集鑰匙管理、加密解密、數字簽名於一身的工具,對於 Linux 系統,一般可以在系統本身的軟件源找到 GnuPG,比如對於 ArchLinux 可以使用如下命令安裝:

$ sudo pacman -S gnupg

  對於 Windows 系統可以下載免費開源程序包 GPG4Win,建議下載完全版,裏面既包含了 GnuPG 命令行工具,又有圖形鑰匙管理工具 Kleopatra 和支持 GnuPG 的郵件客戶端程序 Claws Mail。

  三、生成鑰匙對併發布公鑰到網上

  下面的講解是基於命令行的,如果你比較喜歡圖形工具,仍然建議先閱讀完本章,因爲圖形工具的操作基本上跟下面的命令一一對應,而使用命令行講解比較方便和容易理解。

  1、生成鑰匙對

$ gpg --gen-key

  使用上面的命令可以生成地球上惟一的一對鑰匙對(注:命令行前的錢幣符號是提示符,不用輸入),運行後會詢問你幾個問題,首選是選擇鑰匙對的算法:

Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection?

  默認選擇 RSA 就可以了,輸入1並回車。然後選擇鑰匙的長度:

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)

  默認是 2048 位,直接回車。然後選擇鑰匙的有效期限:

Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)

  默認是永遠有效的,如果你打算過一段時間就換一把新鑰匙,可以在此輸入期限,比如輸入30表示有效期爲30天,數字後面可以加上單位,比如30m表示30個月,30y表示30年。如果你不知道這步有什麼作用,則直接回車。然後詢問你確定嗎?果斷輸入y並回車。

  接下來是填寫一些個人信息:

Real name: ivarptr
Email address: [email protected]
Comment: ivarptr on Twitter

  第1行輸入你的名字或者平常喜歡用的網名,比如我的是 ivarptr。
第2行輸入你的email地址,比如我上面輸入的是 [email protected]
第3行輸入一行備註,備註的作用是進一步標識自己的身份,比如你在姓名一行輸入“小明”,爲了讓你的朋友更確切地知道是哪個小明,你可以輸入“你隔壁家的小明”。

  這三行信息用於產生一個標識(uid),用來標識這個鑰匙對,在下面的命令行裏,就可以用名字或者email地址來指定這個鑰匙對。

  雖然理論上這些信息是可以隨意輸入,而且也不會有人阻止你這麼做,不過當別人拿到你的公鑰時可能會搞不清誰對應誰,所以儘量使用別人分辨得清的名字和email地址。信息輸入完之後再輸入o並回車確定。

  因爲 GnuPG 的鑰匙(包括公鑰和私鑰)是保存在本機上的,如果有人或者***進入你的計算機把你的私鑰盜走了,那麼你的身份就有可能被冒充的危險。所以接下來你需要輸入一個密碼用於保護你的私鑰。這個密碼最好選擇一個稍微複雜一些的。

  接下來就是等待程序生成鑰匙對了,這個過程根可能需要幾秒到幾分鐘時間,期間你可以去忙其他的事情。

  2、查看本機鑰匙信息

  上一步完成後,可以使用如下命令查看本機上的公鑰:

$ gpg --list-keys

  輸出的結果跟下面的類似:

/home/ivarptr/.gnupg/pubring.gpg
——————————–
pub 2048R/72E75B05 2013-04-17 [expires: 2015-04-17]
uid ivarptr (ivarptr on Twitter) <[email protected]>
sub 2048R/74F0F5F9 2013-04-17 [expires: 2015-04-17]

  從中我們可以看到剛纔生成的鑰匙對的公鑰部分,其中:

  • 72E75B05 是這個公鑰的id,這個id跟uid都是用於標識這個公鑰的,因爲uid是用戶隨便輸入的所以會有重複的情況,因此在某些需要明確指定公鑰的命令,需要用id而不能用uid表示這個公鑰。

  • 2013-04-17 是生成這個公鑰的時間,後面括號內的是有效期。

  在實際應用中,因爲要發送加密信息給你的朋友就需要對方的公鑰,所以在本機上可能會有多個朋友的公鑰,但私鑰往往只有一個,也就是自己的私鑰。使用下面命令可以查看本機上的私鑰。

  $ gpg –list-secret-keys

  3、導出公鑰

  爲了將自己的公鑰扔給他人,你需要把公鑰導出成爲一個文件:

$ gpg -a--output key.public --export UID

  注:你要把其中的 UID 替換成你的名字或者email地址。

  其中參數

  • -a 表示輸出文本文件格式。默認輸出是二進制格式,因爲二進制格式不太方便在網絡(比如論壇或者博客)上展示,所以推薦文本格式。

  • –output 指定輸出文件的名字,你可以更改爲其他名字。

  • –export 表示執行輸出公鑰操作,後面的 UID 爲你要輸出的公鑰的標識。

  運行之後會在當前文件夾得到一個 key.public 文件,你可以使用文本編輯器或者 cat 命令查看裏面的內容,大致如下:

$ cat key.public

—–BEGIN PGP PUBLIC KEY BLOCK—–
Version: GnuPG v2.0.19 (GNU/Linux)

…………
…………
—–END PGP PUBLIC KEY BLOCK—–

  公鑰導出之後,你可以通過各種方式把它發送給你的朋友,比如email或者聊天工具。而比較方便的是把公鑰發佈到公鑰服務器。

  4、把公鑰發佈到公鑰服務器

  公鑰服務器用於儲存和發佈用戶的公鑰以便相互交流,這些服務都是免費的,GnuPG 默認的公鑰服務器是 keys.gnupg.net,你可以在這裏找到更多的服務器。你也可以使用瀏覽器打開它們的網站,然後把你的公鑰複製粘貼上去。當然最直接的是通過命令行:

$ gpg --keyserver keys.gnupg.net --send-key ID

  注:你要把其中的 ID 替換成你公鑰的id。

  其中參數:

  • –keyserver 用於指定公鑰服務器,沒有特殊需求的話是可以省略這個參數的,不過有些 GnuPG 版本可能需要指定這個參數才能正常工作。

  • –send-key 用於指定待發布的公鑰的id。

  好了,至此你已經學會生成鑰匙對以及發佈公鑰了。

  四、導入他人的公鑰,加密一個文件

  下面我們來做個試驗,嘗試導入作者的公鑰,然後使用該公鑰加密一個文件。通過這個試驗就可以學會怎樣獲取他人的公鑰並用之加密信息。

  1、在公鑰服務器搜索作者的公鑰並導入到本機

  使用如下的命令可以搜索到我的公鑰:

$ gpg --keyserver keys.gnupg.net --search-key ivarptr

  參數 –search-key 用於指定搜索關鍵字,可以是uid的名字或者email地址部分。結果大致如下:

gpg: searching for “ivarptr” from hkp server keys.gnupg.net
(1) ivarptr (ivarptr on Twitter) <[email protected]>
2048 bit RSA key 72E75B05, created: 2013-04-17
Keys 1-1 of 1 for “ivarptr”. Enter number(s), N)ext, or Q)uit >

  如果有重名的情況,這裏會列出多條記錄。你可以輸入n並回車把搜索結果瀏覽個遍。當你看到id和uid都跟你要找的那個吻合時,輸入搜索結果前面顯示的數字就可以把相應的公鑰下載到本機。如上面的搜索結果,按數字1並回車就可以把我的公鑰導入到本機。輸入q並回車可退出搜索。

  注:服務 keys.gnupg.net 背後是一組服務器,它們之間的信息同步需要一定的時間,如果你剛剛提交了自己的公鑰,可能不會立即搜索就有結果,只要過一段時間(大概1小時)就好了。如果你用的是普通公鑰服務器,比如 pgp.mit.edu 則不會有這個問題。

  如果你確切知道要導入的公鑰的id,也可以跳過搜索這步而直接使用如下的命令導入:

$ gpg --keyserver keys.gnupg.net --recv-key 72E75B05

  其中 72E75B05 是我公鑰的id,如果把它替換成你朋友的公鑰id則爲導入你朋友的公鑰。

  導入公鑰還有另一種方法:如果我把公鑰文件直接發送了給你,你也可以跳過公鑰服務器。下面假設我的公鑰文件 key.public 已發送給你,你運行如下命令就可以導入我的公鑰了:

$ gpg --import key.public

  2、覈對公鑰的指紋值並簽收公鑰

  把對方的公鑰導入到本機後,就已經可以用它來加密信息或者用於校驗我的數字簽名。不過這樣每次操作時都會提示公鑰不可信,因爲雖然你導入了我的公鑰,但存在導入冒充者的公鑰的可能性。所以你需要進一步跟我覈對公鑰是否正確,然後簽收(sign key)它。

  因爲公鑰有可能出現冒牌貨,所以每個公鑰裏都加入了指紋值,使用下面命令可以查看指紋值:

$ gpg --fingerprint

  列出的結果應該有一組如下所示:

pub 2048R/72E75B05 2013-04-17 [expires: 2015-04-17]
Key fingerprint = 0D24 0A94 A86C 7B83 3F7C 200E 1CAF 0CB0 72E7 5B05
uid ivarptr (ivarptr on Twitter) <[email protected]>
sub 2048R/74F0F5F9 2013-04-17 [expires: 2015-04-17]

  其中 “0D24 0A94 A86C 7B83 3F7C 200E 1CAF 0CB0 72E7 5B05” 就是這個公鑰的指紋值。你應該通過打電話或者聊天工具等方式詢問對方並覈對指紋值是否一致,如果吻合的話就說明你取得的是真貨了。

  注:因爲我不可能公佈我的電話 :D 所以如果你看到取回來的公鑰指紋值跟我博客這篇文章的一致,就可以當作是真貨了。當然如果是實際的朋友,一定要親口覈對的。

  確定取得的公鑰是真貨之後,使用如下命令對這個公鑰進行簽收(sign key):

$ gpg --sign-key ivarptr

  運行上面的命令之後它提示你再確認一次指紋值,輸入y並按回車確定。

  提示,如果發現獲取回來的是冒牌貨,可以使用如下的命令刪除它:

$ gpg --delete-keys ivarptr

  3、加密一個文件

  使用文本編輯器(比如記事本或者 vim、echo)創建一個名爲 message.txt 的文件,裏面寫上任意一行文字,然後使用如下的命令加密它:

$ gpg -a--output message-ciper.txt -r ivarptr@126.com -e message.txt

  其中參數:

  • -a 表示輸出文本文件格式。

  • –output 指定輸出(即加密後)的文件名。

  • -r 指定信息的接收者(recipient)公鑰的uid,可以是名字也可以是email地址。

  • -e 表示這次要執行的是加密(encrypt)操作。

  執行完畢之後會在當前文件夾產生文件 message-ciper.txt,這個就是被加密之後的文件。

  注:如果你要加密的是一個二進制文件,則可以省略 -a 參數,這樣產生的加密文件的體積會小一些。

小練習:現在你可以用 email 把加密後的文件寄給我,或者把裏面的內容複製然後粘貼到我博客的評論裏,接下來我會解密然後回覆你。如果你希望我也以加密的形式回覆你,記得同時告訴我你的公鑰 id(以及公鑰服務器地址,假如不是用默認服務器的話)。

  4、解密一個文件

  現在假設我已經收到你寄過來的加密文件 message-ciper.txt,使用如下的命令解密:

$ gpg --output message-plain.txt -d message-ciper.txt

  其中參數:

  • –output 指定輸出(即解密後)的文件名。

  • -d 表示這次要執行的是解密(decrypt)操作。

  GnuPG 程序會自動使用我的私鑰來解密信息,最後得到一個跟原始內容一樣的文本文件 message-plain.txt。

  至此,你已經學會使用 GnuPG 加密解密文件了。

  提示1:導入公鑰、覈對公鑰的指紋值、簽名公鑰這些操作你只需做一次,以後就可以重複多次使用該公鑰加密信息併發送給對方。
提示2:如果你想自己體會整個加密和解密過程,可以用自己的公鑰加密信息,然後用自己的私鑰解密,只需把上面第3步的命令當中的接收者uid([email protected])更改爲自己的uid即可。

  五、數字簽名一個文件

  下面我會簽名一個文件,你可以嘗試檢驗一下這個簽名。

  1、數字簽名一個文件的方法A

  現在我有一個文本文件 message.txt,使用如下命令即可對它進行數字簽名:

$ gpg -a-b message.txt

  其中參數

  • -a 表示輸出文本文件格式。

  • -b 表示以生成獨立的簽名文件的方式進行簽名。

  命令執行完畢之後,會在當前文件夾裏產生一個 message.txt.asc 的文件,這個文件即簽名。現在我應該把原信息文件 message.txt 連同簽名文件 message.txt.asc 一起寄給你,然後你使用如下命令檢驗:

$ gpg --verify message.txt.asc

  如無意外,應該會看到如下兩行:
gpg: Signature made Thu 18 Apr 2013 12:35:00 AM CST using RSA key ID 72E75B05
gpg: Good signature from “ivarptr (ivarptr on Twitter) <[email protected]>”

  其中最重要的是 “Good signature” 字樣,表示通過檢驗,否則表示沒通過檢驗(即意味着原信息的內容被篡改或者原信息不是我發出的)。

  提示:如果你有多個私鑰,在簽名時需要加上參數 -u 指定私鑰的 uid。

  2、數字簽名一個文件的方法B

  如果不想生成一個獨立的簽名文件,則還可以用如下的命令進行簽名:

$ gpg -a--clearsign message.txt

  跟方法A不同的地方是用參數 –clearsign 替代了參數 -b。參數 clearsign 表示將簽名和原信息合併在一起,並生成一個新文件。

  命令運行後同樣會生成一個文件 message.txt.asc,內容如下:

—–BEGIN PGP SIGNED MESSAGE—–
Hash: SHA1

hello world, my key id is 72E75B05, finger is 0D24 0A94……5B05, check it
out.
—–BEGIN PGP SIGNATURE—–
Version: GnuPG v2.0.19 (GNU/Linux)

iQEcBAEBAgAGBQJRbuXuAAoJEByvDLBy51sFaY8IAKKnXX2JGI51mzYSakqvhNnr
iV2JLvokMkvyDuJQGeNDMim5W7P0/df+G4oO45B9b0iFx6DSQwZGeBjEGCXvCURa
uU2fdEqjaSarlrs0d4R1ihol8rCxkZwBYBBPjcvDkVwoVJJYS0zc3OYzMvWhb8mk
Q72wQ0obX5LedUVrauG9OLkvq9aBKONr6Xlkldd133v3gb/Wzjf71CLYcRoJDpze
2XBSkrGS0UxRp3WixJJK8xyfDfI9VHBaXEndCkgQ+Mpfq9nV5XAm3MKcPjlENq4g
xGywHRpnwpW8N22VE6ZFEUFlXrh5C8hZfGaG/EcT21PeAbZYH8RcnYTbJ+s2nZ4=
=lhd6
—–END PGP SIGNATURE—–

  你可以複製這段文字然後保存到一個文件裏,如 abc.txt,然後使用如下命令進行檢驗:

$ gpg --verify abc.txt

  使用如下命令可以把原始信息提取出來:

$ gpg --output message-original.txt -d abc.txt

  六、郵件加密和數字簽名

  如果你只是希望 GnuPG 用於郵件加密和數字簽名,上面的命令是可以完全不用的,因爲鑰匙的管理工作(如生成鑰匙對、導出導入、鑰匙簽名等)都可以使用圖形工具完成,比如 KDE 的 Kleopatra 和 Gnome 下的 seahorse。至於郵件內容的加密解密和數字簽名以及校驗,一般比較完善的郵件客戶端工具都內置集成 GnuPG 的功能,比如 Evolution、KMail、Mozilla Thunderbird,谷歌告訴我 Windows 下的 Outlook 和 Live Mail 也支持但我沒有試驗過,如果不行那麼使用 GPG4Win 附帶的 Claws Mail 就可以了。下面我以 Evolution 爲例簡單介紹如何設置。

  其實關鍵的設置只有一步,就是關聯你的 email 帳號和私鑰的id/uid。在 Evolution 的帳號屬性裏,轉到 Security 頁,在 OpenPGP Key Id 裏輸入你的私鑰id或者uid即可。如下圖:

evolution-pgp-setting

  [圖1]

  然後在寫email時點擊菜單的 Options 勾選 OpenPGP 簽名或者加密,然後再發送即可。如下圖:

evolution-pgp-write
[圖2]

  對方收到郵件時,Evolution 會自動檢驗簽名或者自動解密郵件內容。

小練習:嘗試用郵件客戶端發送一封簽名或者加密過的郵件給我。

  提示1:在簽名或者解密時,有可能會彈出一個窗口要求你輸入一個密碼,這個密碼是指保護私鑰所設置的密碼,也就是生成鑰匙對時設置的密碼。

  提示2:用網易郵箱收取簽過名的郵件時可能會顯示檢驗失敗,這是因爲網易郵箱會在郵件末尾添加附件的下載地址,相當於更改了郵件的原始內容,所以簽名檢驗失敗是肯定的。

  七、GnuPG 更多的使用方法

  請儘量閱讀 GnuPG 官方的文檔:

  還有一些本文未提到但會用得上的命令:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章