gpg加密命令 linux_加密方案 GNUPG & Yubikey

随着时间流逝,我生活中出现的设备越来越多,密码也越来越多,因为记忆成本很多密码强度都不够高,不安全,所以迫切需要一款密码学加密工具来真正解放主动记忆密码,能够将密码存储在一个文件中并且保证这个文件绝对安全。

基本概念

生成密钥对命令 gpg --full-generate-key 按照提示即可,这里注意过程中是要输入一个口令来保护你的私钥,这个口令和加解密没关系,而且后期也可以改,只是用来防止有人操作你电脑进行解密, 所以这个口令可以为空。

生成好密钥对之后gpg会默认生成一对主密钥对和一个子密钥对,在使用时我们通常并不会纠结主,子关系,gpg也弱化了这一个概念,通常我们发布的公钥指的是包含主公钥和所有子公钥的文件,这个文件是可变的,我们可以撤销某个子公钥,也可以添加某个子公钥,然后重新发布公钥文件。

同理如没有特殊说明我们说的私钥文件,指的是包含主私钥和所有子私钥的文件,这个私钥和公钥一样也是可变的。

a9098d9666f4bc07bb6e592327206e17.png

生成好的主密钥对只提供认证(Sign)和签发子证书(Cert),自身没有加密功能,主要作用是用来管理子证书: 生成和吊销。

5edc1d86d5737d0e649a204d9895500a.png

子证书用来加密

d93efee1261c59ef5445d40f5d25e2e6.png

使用 gpg --list-keys 列出本地证书可以看到对应的作用

~ $ gpg --list-keys
/home/quanwei/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072 2020-10-26 [SC] [expires: 2022-10-26]
      A5E7F2FE9590FE9B66BBC25B9D940B6C1ED930EF
uid           [ultimate] Alice <Alice@126.com>
sub   rsa3072 2020-10-26 [E] [expires: 2022-10-26]

所有flag对应含义如下

  1. S: PUBKEY_USAGE_SIG 签名
  2. C: PUBKEY_USAGE_CERT 签发子证书
  3. E: PUBKEY_USAGE_ENC 加密
  4. A: PUBKEY_USAGE_AUTH 认证

另外证书会设定一个过期时间,主要用来告知对方这个证书已经不再用了,请不要用这个证书加密。过期时间是可以修改的,同一个证书随意设定过期时间,即便证书超过了这个时间依然不影响实际的加解密工作,仅作为一种约定。

我们执行 gpg -o pub.sec --armor --export userID是导出了所有公钥信息。

我们从另外一台计算机导入导入这个公钥:

6c9c12ec6d4ee72a0ba79d149b1e5877.png

此时另外一台电脑上显示了我们导出的公钥,而没有私钥信息。

我总结GNUPG主要有下面几种场景:

邮件加密, 发送给某人/群发

这种场景是邮件时代端到端加密常见的一种,也是网上资料介绍最多的场景. 例如Alice想要发送邮件给Bob,那么需要做的事情如下

  1. 导入Bob的公钥,通过其它方式确认后, 信任这个公钥 (例如线下交换,或者Bob在个人网站上放了自己公钥的指纹).
  2. 将信息使用Bob的公钥进行加密(这个公钥文件必须包含一个或多个用来加密的子公钥)

gpg -r Bob -o message.txt.gpg -e message.txt

  1. -r recipient 信息接收者,也就是用谁的公钥加密, 如果需要群发,gpg接受多个接收者加密,例如 gpg -r Bob -r Alice -e
  2. -o 输出文件,一般追加.gpg作为新文件标识
  3. -e 执行加密动作

这时候输出的gpg文件是一个二进制文件,只能作为附件发送,而不能通过普通的邮件文本imessage或者其他IM工具发送,为了能够在普通的文本方式发送,可以输出为文本格式

gpg -r Bob -o message.txt.gpg --armor -e message.txt

  1. --armor 使用ascii格式输出

发送给某人之后,引出了另一个问题,就是如何证明这段文本是某一方发送的? 比如说Bob发送一个 "借我500" 的信息给Alice, Alice收到之后如何知道这段信息是Bob发送的呢?此时需要Bob对这段信息进行签名.

Bob执行(Sign + Encrypt)

echo 借我500 | gpg --sign -r Alice -o message.txt.gpg -e

  1. --sign 进行签名操作(使用默认证书进行签名)
  2. --clear-sign 和sign一样,只不过生成格式为ascii形式, 如果加密时用的armor, 则签名时替换成clear-sign
  3. --local-user <uid> 指定本地进行sign和encrypt的用户id

生成message.txt.gpg,此时Alice进行解密

gpg -d message.txt.gpg

输出如下,此时就可以确认这个信息来自Bob

~ $ gpg -d message.txt.gpg 
give me 500
gpg: Signature made Mon 26 Oct 2020 05:39:29 PM CST
gpg:                using RSA key CCBD7B73A6DCE6016699ABC479B0637CDD9A8C52
gpg:                issuer "bob@126.com"
gpg: Good signature from "Bobob <Bob@126.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: CCBD 7B73 A6DC E601 6699  ABC4 79B0 637C DD9A 8C52
/c/Users/quanw/Desktop/gpg/linux $ 

这时候都是对消息进行加解密和签名,如果需要对文件进行加解密和签名往往需要不同的操作。

附件加密,附件签名,附件认证

附件加密和消息一样,这里的附件等同于文件,但是不同的是这个文件的接收方往往不是自己,是给别人加密的文件,或者验证来自别人的文件,给自己加密下面另说。

加密附件

gpg -r Bob -o data.zip.gpg -e data.zip

签名附件和签名消息不同,消息签名时我将消息体和签名文件放到了一起,并且同时执行 sign 和 encrypt 的操作。对附件则不需要这么复杂,因为我们往往已经有了一个文件想直接让对方使用, 只需要生成一个文件指纹验证文件完整性即可。

gpg --detach-sign --armor data.zip

  1. detach-sign 只生成签名而不包含原始信息

此时会生成同名的data.zip.sig文件包含了具体的指纹,生成形式如下

-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEpXstWE238KYG4MS0ibIomUOvH+sFAl+WnPwACgkQibIomUOv
H+u+QQ/+LBQVaDMLshRroPpPA/tKaDdhnNCxJiOwlwdhxWTy+ImwBy8wyJGgGEuo
4PstATnEK8RLQT8PqLq5svZKwcE6kCXOrF2/bSBpv99eix3hRdn9U7cayYG9ti0E
GJ9lOXBC1s7lzkGdv4qEJBWcygYjsAa43d2GHCz8jOj5omdZ5Q2QwAWMgpDMXQ98
cv27xi/BViLRuLnLm9IUKxqy/DTU+lQwFS3AjBI0pi+ELrKSSsgikTLmobiHVl90
ZWYPtAI/C+ZQPFKQpu8wduhMiWS//Di2mkTG+TwYhAClo6yDf3IR4zrA/hxkLPWC
p2IKAqNHCWijp625r+RztXVcfbwluBEQqepnpJlN4X0cboXsecG/fPLA8L3zhbWc
b/GW/aewAxHeLsDQHGWcoodMZMWBdsQOPd/1/HDrjZA0faKeH147IbQ8lFb5HTu+
LafnuEa8Vgh4FY/rgCQDlkWuADDqkMw2eOXg/3dma2XkNjG2husvA8xLMq2zxyBM
S6LW7QWNPj4toDihuVSj5Lj2MvGVrQDDs/Zs6Em34fqMSuCTuDUPOCfB+pja7ZxK
ZEIDro9FAd4xg6nViEhLNQ/HbZRAAbBVNFIYJa9BlCYeTVnet9Lg4ijN57n4kRkk
zm5hOAvccOCJMagdLdFqxXzQmTn0Hw3DWjajxKPrVuZYq2RMOig=
=c7Oh
-----END PGP SIGNATURE-----

此时接受方收到文件签名和文件指纹之后只需要

gpg --verify data.zip.sig data.zip

即可验证文件是否合法。

私人文件加解密

最终到了这里,最贴合我生活方式的一种,因为很少找到另外一个使用gpg的人,而且也没有发布文件的场景,上面介绍的加解密都是两人或多人之间进行的动作。同样GNUPG也能做私人文件加密方案,例如使用pass命令管理本地密码,或者私人文档需要存网盘,为了不让他人触碰这些信息,需要加密。

对自己的文件进行加密有一个要求,因为我们可能需要在不同设备上进行解密,所以如何保证自己的私钥安全是显而易见的问题。

Alice对自己的文件加密

gpg -r Alice -o data.doc.gpg -e data.doc

接收方是自己

解密时直接解密

gpg -d data.doc

这就是常用的操作,但是因为我们要跨设备使用,例如公司电脑上传了一个文件,在家里需要能够进行解密,所以私钥免不了要来回拷贝或者备份,这样就增加了私钥泄漏的风险,设备越多, 风险越大。这里有个常识是我们加密解密都是用的subkey,所以如果想解密文件只需要携带这个subkey的私钥即可。然后为了安全这个subkey可以一段时间更换一次,这样如果私钥泄漏也不至于所有文件都能被解密。

gpg -o alice-pub.key --export

这句导出了alice的公钥文件alice-pub.key,里面包含了公钥证书。公钥文件是可变的,这句只是导出了目前所有的公钥。

gpg -o alice-secret.key --export-secret-key

这里导出全部私钥文件,包含master私钥和subkey的私钥,严格保存。

gpg -o alice-subkeys.key --export-secret-subkeys

这里导出了所有subkey的私钥.

  1. alice-pub.key 公钥文件,可以放在一个公共位置,或者发布到keyserver
  2. alice-secret.key 私钥文件,严格保存,使用它来签发新证书或撤销已经发布的subkey
  3. alice-subkeys.key 只包含subkey的私钥文件, 严格保存,用来解密文件,切换设备时拷贝这个文件进行解密.
  4. 如果subkey私钥遭遇泄漏,或者subkey已经不再安全,此时用主私钥生成一个撤销文件撤销keyserver上已发布公钥,然后使用主私钥生成一个新的subkey用来加密,将包含新subkey的公钥证书重新发布到keyserver上,在不同设备上更新公钥文件,使用新的subkey加密。解密时使用新的alice-subkeys.key进行解密。

也就是除了公钥其他的私钥都要严格保密,在不同设备切换时只拷贝subkey的私钥。一旦私钥泄漏我们唯一能做的就是让未来加密的文件不被解密,已经加密的文件除非重新加密否则还是不安全的。

由此可得出主私钥在其中扮演的角色是非常重要的,所以对于主私钥的备份gpg也有一种方法,就是 gpg -o alice-secret.key --armor --export-secret-key使用ascii的形式导出私钥,然后将私钥打印到一张纸上进行备份。

另外一点我们提到经常需要携带的私钥是subkey, 为了保护subkey,设计者们提出了smartcard的概念,smartcard是一个usb物理设备,这个设备提供一些特殊硬件设计保护私钥不被外界读取,同时又能用来解密文件。这样的设备目前商业化的做的最好的就是yubikey产品系列了,用一个硬件设备保存私钥即便携又安全,个人比较推荐。

2f2d5705ceee7546f10ced84da925405.png
yubico.com

将私钥保存在yubikey很简单.

插入yubikey之后, 使用gpg --card-status查看状态

ed988c9fde27c40a6c7c5229196148e6.png

如果看到上面的信息说明yubikey已经成功被识别了, 下面将 Alice 的相关私钥导入到yubikey中

> gpg --edit-key Alice
> keytocard
Really move the primary key? (y/N) y
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

...

> key

sec  rsa2048/3C37786437E36A07
     created: 2020-10-26  expires: 2022-10-26  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa2048/FF7B5E819CE6C789
     created: 2020-10-26  expires: 2022-10-26  usage: E
[ultimate] (1). Alice <Alice@126.com>

> key 1

sec  rsa2048/3C37786437E36A07
     created: 2020-10-26  expires: 2022-10-26  usage: SC
     trust: ultimate      validity: ultimate
ssb* rsa2048/FF7B5E819CE6C789
     created: 2020-10-26  expires: 2022-10-26  usage: E
[ultimate] (1). Alice <Alice@126.com>

> keytocard

Please select where to store the key:
   (2) Encryption key
Your selection? 2

...

> q

这里我们成功将签名用的私钥和解密用的私钥导入进去. 注意使用的命令是keytocard, 这个命令执行之后对应的私钥文件会移动到智能卡中,此时主机上的私钥信息就不存在了,而是被一个智能卡的占位符取代,gpg知道此时这个私钥存储在智能卡上,下次解密时就会提示你插入智能卡。

导入成功之后退出,此时 gpg --card-status可以看到已经导入的key.

使用 pass 管理密码

初始化好gpg之后,就可以用来管理密码了, 以 debian 为例

安装pass

> sudo apt install pass -y

使用gpg角色初始化 store

> pass init Alice
mkdir: created directory '/home/quanwei/.password-store/'
Password store initialized for Alice

新增密码

> pass insert emacs-china
Enter password for emacs-china:
Retype password for emacs-china:

显示密码

> pass show emacs-china
github

此时我们就可以将密码文件夹 ~/.password-store 安全地使用网盘或者github进行同步,只有我们能够解密,或者借助yubikey随时随地解密。


结语

总而言之,只有密码学意义上的加密才是真正的安全,虽然 GNUPG 用到的 RSA 安全性已经受到质疑,但在现在的时间点依然是保护个人安全最好用的工具之一。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值