- 先阐述最简单和容易实现的操作——邮件加密和签名,着重以图形工具讲解。然后放在第二篇再讲解命令行工具,以及对文件进行加密和数字签名的方法。
是由 Phil Zimmermann (之所以提这个名字是因为这位仁兄背后有一段故事,有兴趣可以找找他的八卦)于 1991 开发的一个用于数据加密和数字签名的程序,由于被广泛应用,以至于后来形成一个开放的标准 OpenPGP,这个标准也是目前最为常用的邮件加密和签名的方式。而 GnuPG 则是实现了该标准的一个开源免费程序,本文将会简单介绍如何使用 GnuPG 管理钥匙、加密/解密文件和电子邮件、数字签名文件和电子邮件。篇幅有点长,一共分两章,不过内容是很简单的。@ivarptr
目录:
- 加密和数字签名的简单原理
- 下载并安装 GnuPG
- 使用(图形化)工具管理钥匙
- 邮件的加密和数字签名
- 使用命令行管理钥匙
- 使用命令行加密解密文件
- 使用命令行对文件进行数字签名
- GnuPG 的更多指南
一、加密和数字签名的简单原理
二、下载并安装 GnuPG
$ sudo pacman -S gnupg
三、使用(图形化)工具管理钥匙
四、邮件加密和数字签名
小练习:尝试用邮件客户端发送一封签名或者加密过的邮件给我:ivarptr@126.com。
from http://web.archive.org/web/20150327150738/http://archboy.org/2013/04/18/gnupg-pgp-encrypt-decrypt-message-and-email-and-digital-signing-easy-tutorial/
五、使用命令行管理钥匙
1、生成钥匙对
$ gpg --gen-key
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection?
What keysize do you want? (2048)
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)
Email address: ivarptr@126.com
Comment: ivarptr on Twitter
第2行输入你的email地址,比如我上面输入的是 ivarptr@126.com。
第3行输入一行备注,备注的作用是进一步标识自己的身份,比如你在姓名一行输入“小明”,为了让你的朋友更确切地知道是哪个小明,你可以输入“你隔壁家的小明”。
2、查看本机钥匙信息
$ gpg --list-keys
——————————–
pub 2048R/72E75B05 2013-04-17 [expires: 2015-04-17]
uid ivarptr (ivarptr on Twitter) <ivarptr@126.com>
sub 2048R/74F0F5F9 2013-04-17 [expires: 2015-04-17]
- 72E75B05 是这个公钥的id,这个id跟uid都是用于标识这个公钥的,因为uid是用户随便输入的所以会有重复的情况,因此在某些需要明确指定公钥的命令,需要用id而不能用uid表示这个公钥。另外在使用这个id表示一个钥匙时,记得在前面加上”0x”,是零和字母XYZ的X,比如”0x72E75B05″
- 2013-04-17 是生成这个公钥的时间,后面括号内的是有效期。
3、导出公钥
$ gpg -a --output key.public --export UID
- -a 表示输出文本文件格式。默认输出是二进制格式,因为二进制格式不太方便在网络(比如论坛或者博客)上展示,所以推荐文本格式。
- –output 指定输出文件的名字,你可以更改为其他名字。
- –export 表示执行输出公钥操作,后面的 UID 为你要输出的公钥的标识。
$ cat key.public
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.19 (GNU/Linux)
…………
…………
-----END PGP PUBLIC KEY BLOCK-----
4、把公钥发布到公钥服务器
$ gpg --keyserver keys.gnupg.net --send-key ID
- –keyserver 用于指定公钥服务器,没有特殊需求的话是可以省略这个参数的,不过有些 GnuPG 版本可能需要指定这个参数才能正常工作。
- –send-key 用于指定待发布的公钥的id。
六、使用命令行加密文件
1、在公钥服务器搜索作者的公钥并导入到本机
$ gpg --keyserver keys.gnupg.net --search-key ivarptr
(1) ivarptr (ivarptr on Twitter) <ivarptr@126.com>
2048 bit RSA key 72E75B05, created: 2013-04-17
Keys 1-1 of 1 for “ivarptr”. Enter number(s), N)ext, or Q)uit >
$ gpg --keyserver keys.gnupg.net --recv-key 0x72E75B05
$ gpg --import key.public
2、核对公钥的指纹值并签收公钥
$ gpg --fingerprint
Key fingerprint = 0D24 0A94 A86C 7B83 3F7C 200E 1CAF 0CB0 72E7 5B05
uid ivarptr (ivarptr on Twitter) <ivarptr@126.com>
sub 2048R/74F0F5F9 2013-04-17 [expires: 2015-04-17]
$ gpg --sign-key ivarptr
$ gpg --delete-keys ivarptr
3、加密一个文件
$ gpg -a --output message-ciper.txt -r ivarptr@126.com -e message.txt
- -a 表示输出文本文件格式。
- –output 指定输出(即加密后)的文件名。
- -r 指定信息的接收者(recipient)公钥的uid,可以是名字也可以是email地址。
- -e 表示这次要执行的是加密(encrypt)操作。
小练习:现在你可以用 email 把加密后的文件寄给我,或者把里面的内容复制然后粘贴到我博客的评论里,接下来我会解密然后回复你。如果你希望我也以加密的形式回复你,记得同时告诉我你的公钥 id。
4、解密一个文件
$ gpg --output message-plain.txt -d message-ciper.txt
- –output 指定输出(即解密后)的文件名。
- -d 表示这次要执行的是解密(decrypt)操作。
七、使用命令行对文件进行数字签名
1、数字签名一个文件的方法A
$ gpg -a -b message.txt
- -a 表示输出文本文件格式。
- -b 表示以生成独立的签名文件的方式进行签名。
$ 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) <ivarptr@126.com>”
2、数字签名一个文件的方法B
$ gpg -a --clearsign message.txt
-----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-----
$ gpg --verify abc.txt
$ gpg --output message-original.txt -d abc.txt
八、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
- Pretty Good Privacy http://en.wikipedia.org/wiki/Pretty_Good_Privacy
- Quick’n easy gpg cheatsheet http://irtfweb.ifa.hawaii.edu/~lockhart/gpg/
用GnuPG进行信息加密和解密
非对称加密采用的是另一种思想。它会给你产生两个密钥,一个称为“公钥”,另一个称为“私钥”。公钥是可以公开的,你尽管把它传给别人;私钥你一定 要保管好不让其他任何人知道。当某人得到你的公钥后,他就可以给你发送加密信息了。具体来说,他把他要发给你的信息用你的公钥加密后发给你,加密的信息只 能用你的私钥去解密。这样,因为世界上除了你以外没有别人知道你的私钥,所以即使别人看到发送给你的加密信息他也无法解密,甚至连发送者本人也不行。因为 他不知道你的私钥。简单说来,就是用公钥去加密;用对应的私钥去解密。想给谁发送加密信息,首先要得到他的公钥。
支持非对称加密的软件有多种,最著名的可能是美国的PGP了,不过它是个商业软件,价格不便宜。对于加密软件,我反对使用破解软件,因为如果信息需 要加密的话,肯定是非常重要的信息,破解软件无法保证加密的安全可靠。因此我建议使用免费开源的GnuPG软件进行信息的加密和解密。
首先去GnuPG的官方网站下载你的操作系统的软件包()。 然后按照安装向导进行安装。有一步是让你选择语言的,建议选择zh_CN – Chinese (simplified),这样会使GnuPG的输出信息为中文。默认的安装目录是C:Program FilesGNUGnuPG,建议把它加入到PATH环境变量中去。因为GnuPG是一个命令行的软件,将安装目录加入PATH后使用会方便得多。
接下来该使用GnuPG来生成你的公钥和私钥了。打开命令提示符,输入gpg –gen-key。GnuPG会提示你 选择密钥的种类,这里选择默认的第一项“DSA 和 ElGamal”,其他两个都只能用于签名而不能用来加密。按回车接受默认选择。接下来让你设置密钥的长度,数值在1024到4096位之间。长度越长, 安全程度越高,但相应的加密和解密时的计算量也就越大。其实即使是最小值1024位,估计用大型计算机去破解的话也得用好几个月的时间。默认长度是 2048位,足够安全了。然后设置你的密钥有效期,按照提示输入,0表示永不过期。后来确认无误后,输入y确定。
接着输入你的姓名、电子邮件和注释。这些信息将用来标识你的身份。然后按O确认。接着设置你的私钥密码。注意这个密码并不等同于你的私钥,它只是用 来保护私钥不会被其他人利用。私钥是一个很大的整数,你通常是不会去记住的。但当你需要用私钥去解密信息时,GnuPG会提示你输入密码,只有密码输对 了,GnuPG才会去读取你的私钥去解密信息。
输入完两次密码后,GnuPG会提示你动动鼠标键盘之类的,以便产生一个“足够随机”的随机数,最终生成一对公钥和私钥。
至此,一对儿密钥已经产生了。你需要把公钥告诉你的朋友。怎么样得到自己的公钥呢?用gpg的–export选项。下面这个命令会输出我的公钥(假定我在上面生成密钥时设定的姓名为“Wang Jinbo”):
gpg –export “Wang Jinbo”
你看到的应该是一大堆乱码,这其实就是公钥。如果希望公钥看起来整齐一些,可以使用-a选项设置输出为ASCII字符:
gpg –export -a “Wang Jinbo”
把上面的输出重定向到一个文件中去,例如wang.key:
gpg –export -a “Wang Jinbo” > wang.key
这样,wang.key这个文件就是我的公钥了,我可以把它放到我的网站上或者通过电子邮件发送给我的朋友们。
如果你得到了我的公钥,如何用它去加密呢?首先你需要导入我的公钥文件。
gpg –import wang.key
这会将我的公钥导入到你的“钥匙环”中。这样以后你就可以用我的公钥给我发送加密信息了。下面是具体的做法。
假设你给我发送的信息是hello.txt这个文件。现在用GnuPG来加密:
gpg -e -r “Wang Jinbo” hello.txt
这会在当前目录下生成hello.txt.gpg这个文件,这个就是就是hello.txt被加密后的结果。你可以用记事本打开看看,应该是一大堆无意义的乱码。然后你就可以把这个文件通过电子邮件发到我的邮箱中去。我收到后,用下面的方法去解密。
gpg -d hello.txt.gpg
GnuPG会提示我输入密码,也就是我在gpg –gen-key中设定的密码。密码输入完后,GnuPG会在屏幕上立刻显示出解密以后的内容。如果被加密的不是文本内容,比如是一个图片,则可以将输出重定向到一个文件中去:
gpg -d hello.png.gpg > hello.png
---------------------------------------
GnuPG 介绍
一、介绍
PGP(Pretty Good Privacy),是一个基于 RSA 公钥加密体系的邮件加密软件。它不但可以对用户的数据保密以防止非授权者阅读,还能对用户的邮件加上数字签名从而使收 信人确信邮件是由该用户发出。让人们可以安全地和从未见过的人们通信,而事先不需要任何保密的渠道用来传递密钥。PGP 采用了审慎的密钥管理,一种 RSA 和传统加密的杂合算法,用于数字签名的邮件文摘算法,加密前压缩等。它功能强大,速度很快。
GnuPG 是实现安全通信和数据存储的一系列工具集,可以做加密数据和做数字签名之用。在功能上,它和 PGP 是 一样的。由于 PGP 使用了 IDEA 专利算法,所以使用 PGP 会有许可证的麻烦。但是 GnuPG 并没有使用这个算法,所以对用户来说使用 GnuPG 没有任何 限制。GnuPG 使用非对称加密算法,安全程度比较高。GnuPG 主要有以下特点:
- 完全兼容 PGP
- 没有使用任何专利算法,没有专利问题
- 遵循 GNU 公共许可证
- 与 OpenPGP 兼容
- 使用广泛,安全性高于 PGP2,可以加密校验和 PGP5.x 格式的信息
- 支持多种加密算法
- 支持扩展模块
- 用户标识遵循标准结构
- 多语言支持
- 支持匿名信息接收
- 支持HKP密钥服务
一些基本概念:
密钥用途:
- [S]: 用于签名
- [E]: 用于加密
- [A]: 用于身份认证
- [C]: 主密钥特有,用于认证子密钥
密钥算法
- RSA
- ElGamal
- DSA
- ECDH
- ECDSA
- EdDSA
- …
ECC 算法,在版本 2.1.0 ,支持 ed25519 数字签名,在版本 2.1.7 ,支持 curve25519 加密,需要在操作时时添加参数 --expert
,顾名思义,专家模式
二、命令
创建主密钥对
$ gpg --full-gen-key # 生成密钥对,默认 RSA 算法
# or
$ gpg --default-new-key-algo rsa4096 --full-gen-key
$ gpg --gen-revoke KEY_ID # 为 ID 生成吊销密钥
$ gpg --send-keys KEY_ID # 发布公钥
创建子密钥
$ gpg --edit-key KEY_ID # 假设刚生成的密钥
......
gpg> addkey # 根据实际需求选择签名还是加密
一个主密钥对,可以绑定若干子密钥对,子密钥对具备加密或签名功能。任何时候,你应该在非主设备上只使用子密钥对,不应该分发主密钥,你的主密钥应该保存在安全的地方。
显示密钥 ID
$ gpg -K --keyid-form LONG # or
$ gpg -K --keyid-format LONG
$ git config --global user.signingkey KEY_ID # git 中添加签名密钥
公钥处理
$ gpg --armor --output filename.asc --export KEY_ID # ASCII 格式导出公钥
$ gpg --armor --output sub.asc --export SUBKEY_ID! # 导出 sub ID 子密钥公钥
$ gpg --list-public-keys|-k # 显示所有公钥,或
$ gpg --check-sig # 监测公钥环中公钥的签名信息
$ gpg --fingerprint KEY_ID # 查看公钥指纹信息
私钥处理
$ gpg --armor --output filename.asc --export-secret-keys KEY_ID # 导出 ID 的主私钥,不加用户标志,则导出所有主私钥
$ gpg --armor --output filename.asc --export-secret-subkeys SUBKEY_ID! # 导出 sub ID 的子密钥私钥
$ gpg --list-secret-keys|-K # 显示所有私钥
其他
$ gpg --import filename.asc # 导入私钥或公钥
$ gpg --delete-secret-and-public-key KEY_ID # 删除私钥和公钥
$ gpg --delete-secret-key KEY_ID # 删除私钥
$ gpg --delete-key KEY_ID # 删除公钥
$ gpg --edit-key KEY_ID # 编辑密钥,要帮助输入 help
gpg> help
quit 退出此菜单
save 保存并退出
help 显示此帮助
fpr 显示密钥指纹
grip 显示 keygrip
list 列出密钥和用户标识
uid 选择用户标识 N
key 选择子密钥 N
check 检查签名
sign 为所选用户标识添加签名 [* 参见下面的相关命令]
lsign 为所选用户标识添加本地签名
tsign 为所选用户标识添加信任签名
nrsign 为所选用户标识添加不可吊销签名
adduid 增加一个用户标识
addphoto 增加一个照片标识
deluid 删除选定的用户标识
addkey 增加一个子密钥
addcardkey 增加一个密钥到智能卡
keytocard 移动一个密钥到智能卡
bkuptocard 移动一个备份密钥到智能卡上
delkey 删除选定的子密钥
addrevoker 增加一个吊销用密钥
delsig 从所选用户标识上删除签名
expire 变更密钥或所选子密钥的使用期限
primary 标记所选的用户标识为主要
pref 列出偏好设置(专家模式)
showpref 列出偏好设置(详细模式)
setpref 为所选用户标识设定偏好设置列表
keyserver 为所选用户标识设定首选公钥服务器 URL
notation 为所选用户标识的设定注记
passwd 变更密码
trust 变更信任度
revsig 吊销所选用户标识上的签名
revuid 吊销选定的用户标识
revkey 吊销密钥或选定的子密钥
enable 启用密钥
disable 禁用密钥
showphoto 显示选定的照片标识
clean 压缩不可用的用户标识并从密钥上移除不可用的签名
minimize 压缩不可用的用户标识并从密钥上移除所有签名
* ‘sign’命令可以通过‘l’前缀(lsign)进行本地签名,‘t’前缀(tsign)进行
信任签名,‘nr’前缀(nrsign)进行不可吊销签名,
或者上述三种前缀的任意组合(ltsign、tnrsign 等)。
三、应用
加密与解密
$ gpg -r filename.asc -e filename # 使用公钥文件对 filename 加密,生成二进制 filename.pgp
$ gpg -r KEY_ID -o filename.asc -ea filename # 同上,不过以 ASCII 方式输入结果,并输出 asc 文件
$ gpg -o filename -d filename.pgp # 对 filename.pgp 解密,保存为 filename
打包方式进行签名与验证
$ gpg -s filename # 使用默认的用户对 filename 进行打包方式的签名
$ gpg -u KEY_ID -s filename # 使用指定的用户 KEY_ID 对 filename 进行签名
$ gpg --verify filename.gpg # 验证签名
$ gpg -o filename -d filename.gpg # 解包并验证签名
分离方式进行签名与验证
$ gpg -sb filename
$ gpg -u KEY_ID -sb filename
$ gpg --verify filename.sig filename
签名并加密
$ gpg -r KEY_ID -es filename # 使用指定的公钥进行加密并签名,生成的二进制文件是 filename.gpg
$ gpg -r KEY_ID -o filename.asc -esa filename # 同上,加上以 ASCII 编码
签名加密时常用参数
-s, --sign # 签名
-b, --detach-sign # 分离式签名,文件与签名分开
-e, --encrypt # 加密
-d, --decrypt # 解密
-a, --armor # ascii 编码输出,一般与 -o file 搭配
-o, --output FILE # 输出文件
-r, --recipient USER-ID # 以特定的 ID 去加密
-u, --local-user USER-ID # 以特定的 ID 去签名或解密
作为 ssh 公钥
如果想将 gpg 作为 ssh 公钥,则在创建子钥的时候,需要创建一个 [A] 用途的专用子钥。
编辑 ~/.gnupg/gpg-agent.conf,加入
enable-ssh-support
编辑你的 ~/.bashrc 或 ~/.zshrc,加入如下,并最后重新载入下 source ~/.bashrc 或 source ~/.zshrc,原本写入 ssh-agent 相关的内容,也可以注释掉了
[[ -f /usr/bin/gpg-agent ]] && export GPG_TTY=$(tty)
[[ -n "$SSH_CONNECTION" ]] && export PINENTRY_USER_DATA="USE_CURSES=1"
unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
fi
编辑 ~/.ssh/config,加入
Match host * exec "gpg-connect-agent updatestartuptty /bye > /dev/null"
获取子钥的 keygrip
$ gpg --with-keygrip --list-key KEY_ID
将对应子匙的 keygrip 插入到 ~/.gnupg/sshcontrol 中
$ echo xxxxxxyour-keygripxxxxxx >> ~/.gnupg/sshcontrol
重启下 gpg-agent
$ gpg-connect-agent reloadagent /bye
接下来就可以检查下,ssh 验证列表中,是否存在公钥了
$ ssh-add -l
最后将上面的公钥添加到你的远程服务器,或 github 的 gpg 列表中即可
针对 github
如果有多个项目处于 github 的不同账户中,你可能需要针对不同项目配置不同的密钥
gpg --export-ssh-key subkey! > .ssh/repo-1
git config --local core.sshCommand "ssh -i ~/.ssh/repo-1" # 项目文件夹内执行
mutt 中的使用
复制 mutt 示例配置文件至 mutt 配置目录
$ cp /usr/share/doc/mutt/examples/gpg.rc ~/.mutt/
并在其最后加入
set pgp_autosign=yes
set pgp_replysign=yes
set pgp_replyencrypt=yes
set pgp_sign_as=KEYID # 你自己的公钥标志 ID
set pgp_timeout=60
set pgp_verify_sig=yes
编辑 ~/.mutt/muttrc
,加入如下行
$ source ~/.mutt/gpg.rc
thunderbird 中只需安装 Enigmail 扩展即可,支持 gnupg,可视化的配置就不多说了。
参考: