使用GnuPG(PGP)加密信息及數(shù)字簽名教程
PGP (Pretty Good Privacy) 是由 Phil Zimmermann 于 1991 開發(fā)的一個用于數(shù)據(jù)加密和數(shù)字簽名的程序,由于被廣泛應(yīng)用以至于后來形成一個開放的標準 OpenPGP,而 GnuPG 則是實現(xiàn)了該標準的一個開源免費程序,本文將會簡單介紹如何使用GnuPG管理鑰匙、加密解密文件和電子郵件、數(shù)字簽名文件和電子郵件等內(nèi)容。篇幅有點長,不過內(nèi)容是很簡單的,可以一步一步跟著來。
一、加密和數(shù)字簽名的簡單原理
首先每個人使用程序生成地球上惟一的一對鑰匙,分別稱為公鑰和私鑰。公鑰用于加密,私鑰用于解密。使用公鑰加密過的信息只能由配對的私鑰解開。
加密的過程是:如果A君要發(fā)送信息給B君,首先B君得把自己的公鑰扔出來,A君得獲取B君的公鑰后加密信息并發(fā)送過去,B君收到(加過密的)信息使用自己的私鑰解密就可以還原信息了。
而數(shù)字簽名的過程稍微不同,信息是通過普通未加密方式發(fā)送信息給對方的,只是在每條信息后面都會附加一坨字符(名曰:簽名),這個簽名是由程序根據(jù)發(fā)送者的私鑰以及信息內(nèi)容計算得出,接收者使用發(fā)送者的公鑰就可以核對信息有無被篡改。
二、獲取并安裝GnuPG
GnuPG是一個集鑰匙管理、加密解密、數(shù)字簽名于一身的工具,對于Linux 系統(tǒng),一般可以在系統(tǒng)本身的軟件源找到GnuPG,比如對于ArchLinux可以使用如下命令安裝:
$ sudo pacman -S gnupg
對于 Windows 系統(tǒng)可以下載免費開源程序包 GPG4Win,建議下載完全版,里面既包含了 GnuPG 命令行工具,又有圖形鑰匙管理工具 Kleopatra 和支持 GnuPG 的郵件客戶端程序 Claws Mail。#p#
三、生成鑰匙對并發(fā)布公鑰到網(wǎng)上
下面的講解是基于命令行的,如果你比較喜歡圖形工具,仍然建議先閱讀完本章,因為圖形工具的操作基本上跟下面的命令一一對應(yīng),而使用命令行講解比較方便和容易理解。
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
Key is valid for? (0)
默認是永遠有效的,如果你打算過一段時間就換一把新鑰匙,可以在此輸入期限,比如輸入30表示有效期為30天,數(shù)字后面可以加上單位,比如30m表示30個月,30y表示30年。如果你不知道這步有什么作用,則直接回車。然后詢問你確定嗎?果斷輸入y并回車。
接下來是填寫一些個人信息:
Real name: ivarptr
Email address: ivarptr@126.com
Comment: ivarptr on Twitter
第1行輸入你的名字或者平常喜歡用的網(wǎng)名,比如我的是ivarptr。
第2行輸入你的email地址,比如我上面輸入的是 ivarptr@126.com。
第3行輸入一行備注,備注的作用是進一步標識自己的身份,比如你在姓名一行輸入“小明”,為了讓你的朋友更確切地知道是哪個小明,你可以輸入“你隔壁家的小明”。
這三行信息用于產(chǎn)生一個標識(uid),用來標識這個鑰匙對,在下面的命令行里,就可以用名字或者email地址來指定這個鑰匙對。
雖然理論上這些信息是可以隨意輸入,而且也不會有人阻止你這么做,不過當別人拿到你的公鑰時可能會搞不清誰對應(yīng)誰,所以盡量使用別人分辨得清的名字和email地址。信息輸入完之后再輸入o并回車確定。
因為 GnuPG 的鑰匙(包括公鑰和私鑰)是保存在本機上的,如果有人或者黑客進入你的計算機把你的私鑰盜走了,那么你的身份就有可能被冒充的危險。所以接下來你需要輸入一個密碼用于保護你的私鑰。這個密碼最好選擇一個稍微復(fù)雜一些的。
接下來就是等待程序生成鑰匙對了,這個過程根可能需要幾秒到幾分鐘時間,期間你可以去忙其他的事情。
2、查看本機鑰匙信息
上一步完成后,可以使用如下命令查看本機上的公鑰:
$ gpg --list-keys
輸出的結(jié)果跟下面的類似:
/home/ivarptr/.gnupg/pubring.gpg
——————————–
pub 2048R/72E75B05 2013-04-17 [expires: 2015-04-17]
uid ivarptr (ivarptr on Twitter)
sub 2048R/74F0F5F9 2013-04-17 [expires: 2015-04-17]
從中我們可以看到剛才生成的鑰匙對的公鑰部分,其中:
72E75B05 是這個公鑰的id,這個id跟uid都是用于標識這個公鑰的,因為uid是用戶隨便輸入的所以會有重復(fù)的情況,因此在某些需要明確指定公鑰的命令,需要用id而不能用uid表示這個公鑰。
2013-04-17 是生成這個公鑰的時間,后面括號內(nèi)的是有效期。
在實際應(yīng)用中,因為要發(fā)送加密信息給你的朋友就需要對方的公鑰,所以在本機上可能會有多個朋友的公鑰,但私鑰往往只有一個,也就是自己的私鑰。使用下面命令可以查看本機上的私鑰。
$ gpg –list-secret-keys
3、導(dǎo)出公鑰
為了將自己的公鑰扔給他人,你需要把公鑰導(dǎo)出成為一個文件:
$ gpg -a --output key.public --export UID
注:你要把其中的 UID 替換成你的名字或者email地址。
其中參數(shù)
-a 表示輸出文本文件格式。默認輸出是二進制格式,因為二進制格式不太方便在網(wǎng)絡(luò)(比如論壇或者博客)上展示,所以推薦文本格式。
–output 指定輸出文件的名字,你可以更改為其他名字。
–export 表示執(zhí)行輸出公鑰操作,后面的 UID 為你要輸出的公鑰的標識。
運行之后會在當前文件夾得到一個 key.public 文件,你可以使用文本編輯器或者 cat 命令查看里面的內(nèi)容,大致如下:
$ cat key.public
—–BEGIN PGP PUBLIC KEY BLOCK—–
Version: GnuPG v2.0.19 (GNU/Linux)
…………
…………
—–END PGP PUBLIC KEY BLOCK—–
公鑰導(dǎo)出之后,你可以通過各種方式把它發(fā)送給你的朋友,比如email或者聊天工具。而比較方便的是把公鑰發(fā)布到公鑰服務(wù)器。
4、把公鑰發(fā)布到公鑰服務(wù)器
公鑰服務(wù)器用于儲存和發(fā)布用戶的公鑰以便相互交流,這些服務(wù)都是免費的,GnuPG 默認的公鑰服務(wù)器是 keys.gnupg.net,你可以在這里找到更多的服務(wù)器。你也可以使用瀏覽器打開它們的網(wǎng)站,然后把你的公鑰復(fù)制粘貼上去。當然最直接的是通過命令行:
$ gpg --keyserver keys.gnupg.net --send-key ID
注:你要把其中的 ID 替換成你公鑰的id。
其中參數(shù):
–keyserver 用于指定公鑰服務(wù)器,沒有特殊需求的話是可以省略這個參數(shù)的,不過有些 GnuPG 版本可能需要指定這個參數(shù)才能正常工作。
–send-key 用于指定待發(fā)布的公鑰的id。
好了,至此你已經(jīng)學(xué)會生成鑰匙對以及發(fā)布公鑰了。#p#
四、導(dǎo)入他人的公鑰,加密一個文件
下面我們來做個試驗,嘗試導(dǎo)入作者的公鑰,然后使用該公鑰加密一個文件。通過這個試驗就可以學(xué)會怎樣獲取他人的公鑰并用之加密信息。
1、在公鑰服務(wù)器搜索作者的公鑰并導(dǎo)入到本機
使用如下的命令可以搜索到我的公鑰:
$ gpg --keyserver keys.gnupg.net --search-key ivarptr
參數(shù) –search-key 用于指定搜索關(guān)鍵字,可以是uid的名字或者email地址部分。結(jié)果大致如下:
gpg: searching for “ivarptr” from hkp server keys.gnupg.net
(1) ivarptr (ivarptr on Twitter)
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并回車把搜索結(jié)果瀏覽個遍。當你看到id和uid都跟你要找的那個吻合時,輸入搜索結(jié)果前面顯示的數(shù)字就可以把相應(yīng)的公鑰下載到本機。如上面的搜索結(jié)果,按數(shù)字1并回車就可以把我的公鑰導(dǎo)入到本機。輸入q并回車可退出搜索。
注:服務(wù) keys.gnupg.net 背后是一組服務(wù)器,它們之間的信息同步需要一定的時間,如果你剛剛提交了自己的公鑰,可能不會立即搜索就有結(jié)果,只要過一段時間(大概1小時)就好了。如果你用的是普通公鑰服務(wù)器,比如 pgp.mit.edu 則不會有這個問題。
如果你確切知道要導(dǎo)入的公鑰的id,也可以跳過搜索這步而直接使用如下的命令導(dǎo)入:
$ gpg --keyserver keys.gnupg.net --recv-key 72E75B05
其中 72E75B05 是我公鑰的id,如果把它替換成你朋友的公鑰id則為導(dǎo)入你朋友的公鑰。
導(dǎo)入公鑰還有另一種方法:如果我把公鑰文件直接發(fā)送了給你,你也可以跳過公鑰服務(wù)器。下面假設(shè)我的公鑰文件 key.public 已發(fā)送給你,你運行如下命令就可以導(dǎo)入我的公鑰了:
$ gpg --import key.public
2、核對公鑰的指紋值并簽收公鑰
把對方的公鑰導(dǎo)入到本機后,就已經(jīng)可以用它來加密信息或者用于校驗我的數(shù)字簽名。不過這樣每次操作時都會提示公鑰不可信,因為雖然你導(dǎo)入了我的公鑰,但存在導(dǎo)入冒充者的公鑰的可能性。所以你需要進一步跟我核對公鑰是否正確,然后簽收(sign key)它。
因為公鑰有可能出現(xiàn)冒牌貨,所以每個公鑰里都加入了指紋值,使用下面命令可以查看指紋值:
$ gpg --fingerprint
列出的結(jié)果應(yīng)該有一組如下所示:
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)
sub 2048R/74F0F5F9 2013-04-17 [expires: 2015-04-17]
其中 “0D24 0A94 A86C 7B83 3F7C 200E 1CAF 0CB0 72E7 5B05” 就是這個公鑰的指紋值。你應(yīng)該通過打電話或者聊天工具等方式詢問對方并核對指紋值是否一致,如果吻合的話就說明你取得的是真貨了。
注:因為我不可能公布我的電話,所以如果你看到取回來的公鑰指紋值跟我博客這篇文章的一致,就可以當作是真貨了。當然如果是實際的朋友,一定要親口核對的。
確定取得的公鑰是真貨之后,使用如下命令對這個公鑰進行簽收(sign key):
$ gpg --sign-key ivarptr
運行上面的命令之后它提示你再確認一次指紋值,輸入y并按回車確定。
提示,如果發(fā)現(xiàn)獲取回來的是冒牌貨,可以使用如下的命令刪除它:
$ gpg --delete-keys ivarptr
3、加密一個文件
使用文本編輯器(比如記事本或者 vim、echo)創(chuàng)建一個名為 message.txt 的文件,里面寫上任意一行文字,然后使用如下的命令加密它:
$ gpg -a --output message-ciper.txt -r ivarptr@126.com -e message.txt
其中參數(shù):
-a 表示輸出文本文件格式。
–output 指定輸出(即加密后)的文件名。
-r 指定信息的接收者(recipient)公鑰的uid,可以是名字也可以是email地址。
-e 表示這次要執(zhí)行的是加密(encrypt)操作。
執(zhí)行完畢之后會在當前文件夾產(chǎn)生文件 message-ciper.txt,這個就是被加密之后的文件。
注:如果你要加密的是一個二進制文件,則可以省略 -a 參數(shù),這樣產(chǎn)生的加密文件的體積會小一些。
小練習(xí):現(xiàn)在你可以用 email 把加密后的文件寄給我,或者把里面的內(nèi)容復(fù)制然后粘貼到我博客的評論里,接下來我會解密然后回復(fù)你。如果你希望我也以加密的形式回復(fù)你,記得同時告訴我你的公鑰 id(以及公鑰服務(wù)器地址,假如不是用默認服務(wù)器的話)。
4、解密一個文件
現(xiàn)在假設(shè)我已經(jīng)收到你寄過來的加密文件 message-ciper.txt,使用如下的命令解密:
$ gpg --output message-plain.txt -d message-ciper.txt
其中參數(shù):
–output 指定輸出(即解密后)的文件名。
-d 表示這次要執(zhí)行的是解密(decrypt)操作。
GnuPG 程序會自動使用我的私鑰來解密信息,最后得到一個跟原始內(nèi)容一樣的文本文件 message-plain.txt。
至此,你已經(jīng)學(xué)會使用 GnuPG 加密解密文件了。
提示1:導(dǎo)入公鑰、核對公鑰的指紋值、簽名公鑰這些操作你只需做一次,以后就可以重復(fù)多次使用該公鑰加密信息并發(fā)送給對方。
提示2:如果你想自己體會整個加密和解密過程,可以用自己的公鑰加密信息,然后用自己的私鑰解密,只需把上面第3步的命令當中的接收者uid(ivarptr@126.com)更改為自己的uid即可。#p#
五、數(shù)字簽名一個文件
下面我會簽名一個文件,你可以嘗試檢驗一下這個簽名。
1、數(shù)字簽名一個文件的方法A
現(xiàn)在我有一個文本文件 message.txt,使用如下命令即可對它進行數(shù)字簽名:
$ gpg -a -b message.txt
其中參數(shù)
-a 表示輸出文本文件格式。
-b 表示以生成獨立的簽名文件的方式進行簽名。
命令執(zhí)行完畢之后,會在當前文件夾里產(chǎn)生一個 message.txt.asc 的文件,這個文件即簽名。現(xiàn)在我應(yīng)該把原信息文件 message.txt 連同簽名文件 message.txt.asc 一起寄給你,然后你使用如下命令檢驗:
$ gpg --verify message.txt.asc
如無意外,應(yīng)該會看到如下兩行:
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) ”
其中最重要的是 “Good signature” 字樣,表示通過檢驗,否則表示沒通過檢驗(即意味著原信息的內(nèi)容被篡改或者原信息不是我發(fā)出的)。
提示:如果你有多個私鑰,在簽名時需要加上參數(shù) -u 指定私鑰的 uid。
2、數(shù)字簽名一個文件的方法B
如果不想生成一個獨立的簽名文件,則還可以用如下的命令進行簽名:
$ gpg -a --clearsign message.txt
跟方法A不同的地方是用參數(shù) –clearsign 替代了參數(shù) -b。參數(shù) clearsign 表示將簽名和原信息合并在一起,并生成一個新文件。
命令運行后同樣會生成一個文件 message.txt.asc,內(nèi)容如下:
—–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—–
你可以復(fù)制這段文字然后保存到一個文件里,如 abc.txt,然后使用如下命令進行檢驗:
$ gpg --verify abc.txt
使用如下命令可以把原始信息提取出來:
$ gpg --output message-original.txt -d abc.txt
#p#
六、郵件加密和數(shù)字簽名
如果你只是希望 GnuPG 用于郵件加密和數(shù)字簽名,上面的命令是可以完全不用的,因為鑰匙的管理工作(如生成鑰匙對、導(dǎo)出導(dǎo)入、鑰匙簽名等)都可以使用圖形工具完成,比如 KDE 的 Kleopatra 和 Gnome 下的 seahorse。至于郵件內(nèi)容的加密解密和數(shù)字簽名以及校驗,一般比較完善的郵件客戶端工具都內(nèi)置集成 GnuPG 的功能,比如 Evolution、KMail、Mozilla Thunderbird,谷歌告訴我 Windows 下的 Outlook 和 Live Mail 也支持但我沒有試驗過,如果不行那么使用 GPG4Win 附帶的 Claws Mail 就可以了。下面我以 Evolution 為例簡單介紹如何設(shè)置。
其實關(guān)鍵的設(shè)置只有一步,就是關(guān)聯(lián)你的 email 帳號和私鑰的id/uid。在 Evolution 的帳號屬性里,轉(zhuǎn)到 Security 頁,在 OpenPGP Key Id 里輸入你的私鑰id或者uid即可。如下圖:

[圖1]
然后在寫email時點擊菜單的 Options 勾選 OpenPGP 簽名或者加密,然后再發(fā)送即可。如下圖:

[圖2]
對方收到郵件時,Evolution 會自動檢驗簽名或者自動解密郵件內(nèi)容。
小練習(xí):嘗試用郵件客戶端發(fā)送一封簽名或者加密過的郵件給我。
提示1:在簽名或者解密時,有可能會彈出一個窗口要求你輸入一個密碼,這個密碼是指保護私鑰所設(shè)置的密碼,也就是生成鑰匙對時設(shè)置的密碼。
提示2:用網(wǎng)易郵箱收取簽過名的郵件時可能會顯示檢驗失敗,這是因為網(wǎng)易郵箱會在郵件末尾添加附件的下載地址,相當于更改了郵件的原始內(nèi)容,所以簽名檢驗失敗是肯定的。
七、GnuPG 更多的使用方法
請盡量閱讀 GnuPG 官方的文檔:
迷你Howto教程:http://www.dewinter.com/gnupg_howto/english/GPGMiniHowto.html
迷你Howto教程(中文版): http://www.gnupg.org/howtos/zh/index.html
The GNU Privacy Handbook http://www.gnupg.org/gph/en/manual.html
還有一些本文未提到但會用得上的命令:
Quick’n easy gpg cheatsheet http://irtfweb.ifa.hawaii.edu/~lockhart/gpg/
文本完,如有問題可以@ivarptr 。謝謝!
原文地址:http://archboy.org/2013/04/18/gnupg-pgp-encrypt-decrypt-message-and-email-and-digital-signing-easy-tutorial/