拥抱 GPG


#1

本人转载自我的博客: https://mantou.life/posts/embracing-gpg/ ,转载请注明出处

为什么?

最近越来越多的事情让我感觉到,第三方终究是不可信任的。例如近期 Apple 把中国用户的 iCloud 数据交给国内有政府背景的公司来运营,让大家十分的不满,纷纷把 Apple ID 转区到别的地方,让自己的数据不会被储存在国内的服务器里。

理想总是十分美好的,即使自己没有什么见不得人的地方,也希望自己的隐私能够受到很好的保护。但是在国家机器面前,它能通过制定法律让你的隐私荡然无存,而你也无可奈何。所以,第三方变得越来越不可信任,人们逐渐的开始寻找一种 端对端 的或者说 去中心化 的方式来保管自己的数据。

ZeroNetIPFS ,越来越多的去中心化数据存储方案被开发出来,并且活跃度越来越高。这就很明显的说明,全世界人民都面临着同样的问题,而不仅仅是我所在的国家。

GPG 是什么?

这里引用一下 WikipediaGPG 的定义

GNU Privacy Guard(GnuPG或GPG)是一种加密软件,它是PGP加密软件的满足GPL
的替代物。GnuPG依照由IETF订定的OpenPGP技术标准设计。GnuPG用于加密、数字签名及产生非对称匙对的软件。

说到 GPG 就不得不先解释一下什么是 公钥加密算法。以最为著名的 RSA 作为例子——在 RSA 里,有 公钥私钥 两个概念。你可以用你的私钥来导出你的公钥,但是当只有公钥时却不能知道你的私钥。如果使用一对密钥中的公钥来加密数据,只有这对密钥中的私钥才能解密出数据;如果是用这对密钥的私钥加密数据,只有这对密钥中的公钥才能解密出数据。

按照 GPG 的设计,用户之间的认证是通过用自己的私钥签名对方的公钥来实现的。可能这样说有点不太好懂,可以举个简单的例子——你和我是很好的朋友,你可以把你的公钥给我,或者我把我的公钥给你,然后我们互相给对方的公钥签名,然后通过公共的 Keyserver 广播给所有人。Keyserver 的作用仅仅只是用来交换公钥和签名,并没有其它的任何特权,不会对你的密钥对产生任何影响。

当你生成第一个密钥对时,GPG 就会在你的电脑上生成一个类似 通讯录 的东西来储存所有人的公钥,当然包括你的私钥。我的 “通讯录” 长这样:

$ gpg --list-keys zzy228961125@gmail.com
pub   rsa4096 2017-09-28 [SC] [有效至:2019-09-28]
      A388717C602AE2280874BF28E45BCB833E0E7935
uid           [ 绝对 ] Mason Zhang <zzy228961125@gmail.com>
uid           [ 绝对 ] Mason Zhang <228961125@qq.com>
uid           [ 绝对 ] Mason Zhang <masonz961125@gmail.com>
uid           [ 绝对 ] [jpeg image of size 6353]
sub   rsa4096 2017-09-28 [E] [有效至:2019-09-28]
sub   rsa4096 2017-10-01 [S] [有效至:2019-10-01]
sub   rsa4096 2017-10-01 [A] [有效至:2019-10-01]

rsa4096 代表我这个密钥对使用 4096 bit 的 RSA 算法,创建时间是 2017-09-28,有效期至 2019-09-28A388717C602AE2280874BF28E45BCB833E0E7935 是我的根公钥。一个 GPG 密钥对下可以有多个 uid ,可以用作签名你不同的邮件地址。再往下是我的三个不同用途的子密钥,[E] 代表该子密钥用来加密,[S] 代表该子密钥用来签名。

GPG 能干什么?

签名

这里的 签名 和现实中的签名,意义实际上完全一样。当一份文件或者合同,上面有你的签名就代表你认可这个文件或者合同的有效性,或者说,这个文件或合同就是来自于你的。在 GPG 里,我们可以这么干:

$ echo 'Hello GPG!' | gpg --clearsign -a
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hello GPG!
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCAAdFiEEbFwcYmz45QngKfz8wpI6gzSAKtkFAlpY6LYACgkQwpI6gzSA
Ktk0nA/+PlF5Z7DHQkn7cUCX6QVO8+AwBCA3XlXUwKxd4qaW6r6V17dpLLE/xtWl
VDPniMUAYiv3Da/0jEp2tPbJj9TZJQbrs3IevKF4T0dDHPH+DJuCNHzX/Yn/TSrZ
E6M+PCJ9wQxDShToWKWm2EcWjCefhquvtIIVEIJWvT+yZXWhtLY0HPW3rbX876VV
MlHA/FLqUqNptYi5E0Z/+XtcsfP6Pcq6TjicsiljRyIPTmyFZkku0hfs0yCdKtij
V4IczhU/EEU6Laz2wjiGJjTlTv5CJaQnEcLdJVpCTbOsX0jjaxNW0syYUdFHrHD4
+SazjWroWVb+ONA1rUWPopHwzs+77ckqLWF4QvGheSoFQhQwhGkPbY0VQznJ1qq8
q6/kCO/HxJrwZ8cx6La4dBP+9MZY2uiSmQlt0hvnCB5GuMhcezDnu3Cz256GaXCq
ReLnBVrLEcw6GXyjBTA5x1qLTM04Z6Q5DtgcxJLWjuUZGJO9fAUeX/ZVsZJd02ow
GSyPwden4qiHScndrEIcE2lSMgo+/lfSsaiA/1E6RTWL+eWUQ0YlfuuC5Xvyh9bC
aiHjXtcIOUHNZh8qGUvJOyCcWkueciaPF3BlAFIFLJCgqZzeMJhUlrhfr0fXBDga
fDm3TcVgra1iQia68T1aNFsiKQuNKlQ4mSZm7Pt5jc1LP4rKFKs=
=bCzv
-----END PGP SIGNATURE-----

GPG 输出的内容里,首先表明了摘要算法是 SHA1,接着是原始内容,最后是签名后的数据。如何更高级的使用 GPG 进行签名,可以自行 Google。

Git

给 Git 的 Commit 或者 Tag 签名,也是 GPG 的用途之一。好处有很多,比如可以保证 Commit 或 Tag 是不是由 Owner 提交或发布的。你可以在 GitHub 或者 GitLab 这样非常流行的 Git 托管网站上添加你的公钥,然后在本地 Git 配置里开启公钥签名,并且制定要用来加密的公钥。我本地的配置是这样的:

[user]
        name = Mason Zhang
        email = zzy228961125@gmail.com
        signingkey = C2923A8334802AD9
[core]
        excludesfile = ~/.gitignore
[alias]
        co = checkout
        br = branch
        ci = commit
        st = status
[commit]
        gpgSign = true

在提交 Commit 或 Tag 时,你可以通过 git commit -S -m "XXX"git tag -s vx.y.z 来签名。

加密消息/文件

和上面的签名一样,我们举个简单的例子:

$ echo 'Hello GPG!' | gpg --encrypt -a -r zzy228961125@gmail.com
-----BEGIN PGP MESSAGE-----

hQIMA2ai2q7HhSuuAQ/+MHFQq3OU7XEyRjcV3FphISncd4rBFeCsYXQ6tOm8KGHP
TzY/Iz23KURf7SiYEV7mNnVEaZnXGjiXk94AVb74QqgzMuA91wdxdkRNizokhACc
NSdi/0uHMK3iS8E/tUNB5NeCKu5mikI1nLvMSAhB3DE+D7ZD9IDVeapG9Vhp3ecu
mS+ZPJPLH6Xvf6eEtb3Dk9Xv1PcPmmrk+pXB0fgfK2LpNM9bMCJ6Ir5RidoDyD/F
dyJDReLUXxpXlRRGdaPJEUyNdc6jEnPJAclLjL96liq/TnzHHkPHCScidbG0442x
/C4RdUiSkNN70+q/Tpu/6+ewqzO/OqNwGhUcjDalHHFsC1aKsFxC2SNaga+Efg04
MOI80RTSvWSa5zBxTwKq2Unkh4gDprDAP+HEU5xw7U1Q5lQfwvNke8pQZfiWb+lI
sgUfHktkQs93ui4HomzG725LohCY/IZaARGKkepE30YUAoT6TBtMc9yyJxP6QOd6
xCCXikRsmofe/vuQErlaSmvSxOrvZFEp5SIqnrWAJsowdd08YgOYOp3Dlh/pjE7t
+7qrXB1EVbdDMBAvuPhSu4PyBNdMFDJPqJFJ7RVw4BKp4gfque5gaHEwRC0wFhjH
s2CEtq9NP9C9siaTgRq9c0ieyjZnoIqOrE3J0b+Ir/oS8QTSOElJuOoF+c0pfYfS
RgGJXVvrHOyy4UeBWuIF/d2jyln8cvHMA2OQ8xcJIvODrep/nMjz3TtCVV+x3fPM
UTDMIpPsBuF8FfxWXWAKZ3xOYPI/CRs=
=jzxl
-----END PGP MESSAGE-----

这里指定了我作为消息的接受者,所以在 gpg 命令后面有我的 ID。GPG 默认是输出二进制的加密后数据,-a 选项指明输出以字符表示的二进制内容。

当你收到别人发给你的 GPG 加密过的消息时,你可以这样来解密出消息/文件:

$ gpg --decrypt gpg-message
gpg: 由 4096 位的 RSA 密钥加密,钥匙号为 66A2DAAEC7852BAE、生成于 2017-09-28
      “Mason Zhang <zzy228961125@gmail.com>”
Hello GPG!

加密的密码

目前市场的密码管理器已经不胜枚举,以 1Password 为例,用户需要订阅他们的服务,或者自行设置要存放密码的云储存,例如 Google Drive 或 Dropbox 以及 iCloud。但是 1Password 加密并储存密码的具体方式我们并不知道,而且对于那些购买了订阅服务的用户来说,安全问题更加堪忧,例如之前爆出的 1Password 在向服务器发送用户密码数据时是明文的,而并非加密后的,真的让人很是惊讶。

这里我要介绍一个用 GPG 来加密并储存密码的工具,pass-storepass-store 的开发者认为:密码的管理应该是简单并且遵从 Unix 哲学的。所以 pass-store 用 GPG 加密你的密码,并以文件的形式储存在硬盘里。

pass-store 的储存结构是可以自定义的,它看起来长这样:

zx2c4@laptop ~ $ pass
Password Store
├── Business
│   ├── some-silly-business-site.com
│   └── another-business-site.net
├── Email
│   ├── donenfeld.com
│   └── zx2c4.com
└── France
    ├── bank
    ├── freebox
    └── mobilephone

当你需要某一个账户的密码时,你可以这样获得密码:

zx2c4@laptop ~ $ pass Email/zx2c4.com
sup3rh4x3rizmynam3

或者直接让 pass-store 直接给你复制到剪贴板里:

zx2c4@laptop ~ $ pass -c Email/zx2c4.com
Copied Email/jason@zx2c4.com to clipboard. Will clear in 45 seconds.

期初我也是从朋友那里得知还有 pass-store 这种东西,那时我只是把它作为一个后备工具使用,毕竟当初我的所有账户基本都是使用同一个密码。但是近期我发现我的 Steam 账户频繁的被人登录,但是由于我绑定了手机认证器,所以他登录不上去;然后我又莫名其妙的收到了我其中一个邮箱注册 Medium 的邮件,这让我觉得事情有些不对,所以我就又拿起了 pass-store ,接着把我的所有账户的密码都换成随机字符串,并且存在 pass-store 里。

如果你觉得把 pass-store 的数据放在硬盘里不是特别的安全,可能有一天你的硬盘花掉了,你的密码就没了。没关系,有一个上面提过的网站叫 GitHub,你可以大大方方的把你的密码放在上面,并且 pass-store 也是支持很多 git 操作的,你的每一次密码改动他都会生成 commit,然后你可以手动的把这些改动 push 到 remote。

pass-store 还有移动端的实现,比如 passforios 是 iOS 平台的实现,Android-Password-Store 是 Android 平台的实现。他们都具有和电脑端相同的功能。

参考文章

GPG 与端到端加密:论什么才是可以信任的 —— 王子亭的博客

pass - the standard unix password manager