GnuPG(全称:Gnu Privacy Guard,简称:GPG)的前身是PGP,他们都是简单好用的加密软件,但因GPG是免费的所以得到更广泛的使用。具体的说,GPG是一个命令行工具,可以为数据和通信进行加密和签名,因为其良好的集成性,所以很多的应用都可以使用GPG作为加密工具。下面在介绍GPG用法前,先介绍其加密签名的原理。

密钥对加密

传统的双向加密只用一把密钥,在发送加密文件的同时也会发送密钥。最大的问题就在于,如果密钥被截取了,那么这次加密就白费了。

GPG加密 JAVA版 下载 gpg加密原理_GPG加密 JAVA版 下载

更加优秀的加密方法是一个密钥对由公钥和私钥组成。公钥是全世界独一无二且公开的,别人用我们的公钥加密,我们用自己的私钥解密。私钥只有自己持有不会以任何形式传输,理论上这种方法不会被破解。下图详细介绍了如何采用这种密钥对的方法加密,我们的机器上存放一个列表保存所有公钥,在传输文件的时候,用对应的公钥进行加密。那么这些公钥从那里来呢?在公网上由公钥服务器维护公钥信息,我们只需要传到一台服务器上,通过交换机制所有的公钥服务器都能保存我们的公钥。

GPG加密 JAVA版 下载 gpg加密原理_GPG加密 JAVA版 下载_02

数字签名

我们往往在一片文章的最后署上自己的签名表示这篇文章是自己写的。数字签名也是类似的功能,在传输信息的末尾附上一些标志信息表示信息是由本人发送的。与加密不同,加密是用接受者的公钥加密,让接受者自己解密;而签名是用发送者的公钥签名,接受者需要拥有发送者的公钥并使用发送者的公钥验证此签名。

数字签名的好处一个是能保证消息发送的来源,另一个是能够验证消息在传输过程中没有被改变。

安全隐患

这种密钥对的加密签名方法,最致命的问题在于,如果我们获取到的接受者的公钥是假的,那么一切操作都没用了。下图阐述了在C冒充B的公钥的情况下,是如何悄无声息的破解并读取A的文件的,C甚至可以修改A的文件,这样的做法使得加密完全失效。

GPG加密 JAVA版 下载 gpg加密原理_服务器_03

公钥指纹

那么GPG是如何解决公钥安全性问题的呢?

每个公钥都会生成一个独一无二的公钥指纹,我们获取到别人的公钥后公钥指纹是能够查看的,通过一些通信手段或打电话确认对方的指纹,查看获取到的公钥的指纹并对比,如果一样那么这个公钥是正确的可信度就很高了。

实际上这个方法也不能完全保证安全。思考这样一个问题:如果你获取公钥和获取指纹的两个过程,都被别人蒙蔽了呢?黑客提供给你一个完全错误的公钥和那个公钥的指纹,在你核对的时候发现两者都是正确的,实际上,你还是被欺骗了。这里陷入了一个悖论:如果有一个中间人永远能够阻隔你和接收方的验证,那么你永远都不能安全的传输文件,所以这说明了这种加密方法永远不能肯定安全性,只能说可信度很高。所以,获取公钥指纹且比对正确只能提高这个公钥的可信度,使用的时候仍需谨慎。

GPG使用手册

  • 安装
  • 下载源码或dmg安装包
# 下载源码的安装方式
./configure
make
make install
  • 使用其他安装工具安装
# Debian / Ubuntu 环境
sudo apt-get install gnupg

# Fedora 环境
yum install gnupg

# mac 环境
brew install gpg
  • 验证是否安装成功
# mac 环境 
# mac环境一切gpg开头的命令,都需要使用gpg2代替
gpg2 --help

# 其他环境
gpg --help
  • 生成密钥
# 开始生成密钥流程
gpg --gen-key
  • 此部分一切按照默认选项选择即可
  • 创建用户标识
  • 填写真实姓名
  • 填写电子邮箱
  • 上述两步结束之后,得到的姓名和电子邮箱的组合就是用户标识
  • 设定私钥密码
  • 系统会让我们设定一个私钥密码,这一步是为了防止其他人擅自使用私钥
  • 创建密钥
  • 系统生成密钥,密钥实际上是一对公钥和私钥,这个公钥是用户标识的Hash字符串,可以用来代表你的身份,默认情况下,秘钥都是一串长度为8的十六进制数字。我们平时使用公钥,将其上传到公共的公钥服务器,当确认身份时,在本地将其和私钥比对,达到加密或签名的作用
  • 生成撤销证书
gpg --gen-revoke 公钥
  • 生成了撤销证书后,以后秘钥作废,可以请求外部服务器撤销公钥
  • 显示秘钥列表
gpg --list-keys

#下面为秘钥信息

/home/gwon/.gnupg/pubring.gpg                 #文件位置
-------------------------------
pub 4096R/EDDD6D76 2013-07-11                 #公钥特性
uid Ruan YiFeng <yifeng.ruan@gmail.com>       #用户标识
sub 4096R/3FA69BE4 2013-07-11                 #私钥特征
  • 在创建秘钥中,GPG会创造一个我们给出的用户标识(即用户名+邮箱)的随机秘钥。用同样的方法,我们能创造很多个用户标识不同的不同秘钥,用上述的命令即可显示秘钥的列表
  • 删除秘钥
gpg --delete-key 公钥
  • 秘钥多了,有的时候我们想要删除某个秘钥,上述命令即可
  • 将秘钥打印出来
# --armor  可以将二进制转换成ASCII码
# --output 标识输出到哪个文件
# --export 表示要输出哪个公钥的秘钥
# --export-secret-keys 表示要输出哪个私钥的秘钥

gpg --armor --output public-key.txt --export 公钥

gpg --armor --output private-key.txt --export-secret-keys 私钥
  • 公钥是二进制文件,我们可以将其输出到我们指定的文件
  • 上传公钥
gpg --send-keys 公钥 --keyserver hkp://subkeys.pgp.net
  • 仅仅创建了密钥,我们也只是自娱自乐,如何让其他人知道我们创建了一对秘钥,并且进行运用呢?我们需要将公钥发布出去,发布到一台机器上后,通过交换机制,所有的机器都将知道我们的公钥。这就好比,秘钥是一对钥匙和锁,我们把公钥当作锁发给了所有的服务器,我们自己拿着钥匙也就是私钥
  • 生成公钥指纹
gpg --fingerprint 秘钥
  • 因为公钥上传是不需要额外的验证的,也就是说所有人都能用你的名义上传公钥。我们可以在网上发布一个公钥指纹,让其他人核对下载的公钥是否是真的
  • 输入秘钥
# 本地直接导入
gpg --import 密钥文件

# 服务器获取
gpg --keyserver hkp://subkeys.pgp.net --search-keys 公钥
  • 不仅仅是自己生成的秘钥,我们也可以将其他人的秘钥添加进我们的系统
  • 加密与解密
# 加密
# --recipient 表示文件接受者的公钥
# --output    加密后的文件的名称
# --encrypt   需要加密的文件的名称
gpg --recipient 公钥 --output demo.en.txt --encrypt demo.txt

# 解密
# --decrypt   表示需要解密的文件的名称
# --output    解密后生成的文件的名称  
gpg --decrypt demo.en.txt --output demo.de.txt
  • 我们用对方的公钥进行加密,加密后获得文件可以方向发送给对方,对方接收到文件后,通过自己的私钥解密即可
  • 签名与检验
# 签名
# 签名有很多种命令行做法,这里推荐一种最好的
# --armor         将签名后的文件以ASCII字符表示,可读性好
# --detach-sign   签名后的文件名,签名后的文件和源文件是两个文件,并不在原文件上签名
gpg --armor --detach-sign demo.txt

# 验证签名
# 验证签名的前提条件是发送签名的那个人的公钥在你的秘钥列表中
# 可以通过上面提到的两种方法添加对方的公钥到自己的列表中
# --verify 验证文件
gpg --verify demo.txt.asc demo.txt
  • 有的时候我们并不需要对文件加密,只需要表示文件的发送者确实是本人,也就是签名
  • 签名并加密
gpg --local-user 发送公钥 --recipient 接受公钥 --armor --sign --encrypt demo.txt
  • 有的时候我们签名和加密都需要,此时会先加密再签名,验证的时候先验证签名再解密