什么是数字签名
- 验证发送者:消息/文件的发送者确定就是他/她
- 完整性:消息在传送过程中没有被篡改
- 不可抵赖:发送者无法否认某某消息是她/他发的
OpenPGP 数字签名最佳实践
密钥创建和数字签名
- 使用一个强劲的密钥用于数字签名。
4096位
(或至少2048位
)的私钥。Mailfence 默认生成 4096 位的RSA密钥。- 使用子密钥(sub-key)用于签名GnuPG
工具创建子密钥。然后你可以把子密钥导入到 Mailfence 密钥仓库里并无缝地在你所有设备上使用。GPG
密钥验证变得有点麻烦,因为每次对别人的密钥做验证时都需要把主密钥导入到本地环境。此外,如果给子密钥设置了过期日期(推荐如此)的话,那子密钥必须在过期日前续期,要么就重新签发子密钥。还有,使用了你的公钥的人(比如,要验证一些你签名了的东西)会收到关于你的密钥已经过期的报错,如果他们不经常从公共密钥服务器上更新他们的GPG
密钥串的话。- 叫你的朋友和同事对你的公钥签名
- 转发带数字签名的消息时要特别留心
- “尝试”预先获得发件人的密钥指纹!
- 一定要总是确认消息发件人的密钥对的指纹!
- 确保签名密钥没有被撤回或过期!
- 导出消息到本地时带上它的数字签名!
- 数字签名的法律价值
注:反过来说如果你在某些很反常的场景中不想出现令自己“不可抵赖”的可能性,那么就得去用基于「可否认的验证」技术了!
注:如果你当前使用的邮箱帐号本身并不安全,那么以上的 OpenPGP 数字签名最佳实践是帮不到你的。(译者补充:这通常是对于直接使用邮件服务页面里的密钥签名功能的人来说的,因为任何人只要能登录你的邮箱界面就能直接使用你的私钥,进行签名等等操作。所以前提还是要保护你的邮箱帐号密码。若你使用密钥的方式跟邮箱本身是脱离的就还比较安全,如Enigmail
或Mailvelope
。)
---------------------------------
OpenPGP 最佳实践 - 密钥服务器
配置一个密钥服务器并让你的计算机同步密钥
如果你不经常地刷新你手中的 PGP 公钥,你就没法及时地了解到十分需要关注的 PGP 公钥的过期或者撤销情况。关于密钥接受有两个步骤,许多用户会把自己的公钥上传到密钥服务器上,为了保证你能接受到这些同步,你需要先正确地配置密钥服务器。
安全地连接一个 sks 密钥服务器池而不是某台具体的服务器
很多 OpenPGP 客户端被配置了一个固定的密钥服务器,这样当服务器出现问题的时候你就有可能没法接受到重要的密钥同步,除了这种单点故障之外,这也会是一个泄漏 OpenPGP 用户之间关联信息的一个主要方式,从而成为一个被攻击的目标。
因此我们推荐使用 sks 密钥服务器池,这个池中的机器会被定期地检查运行状态,如果出现故障就会被移出这个池。
你也需要保证你是在使用 hkps 加密地与这个服务器池通讯,为了使用 hkps,你需要先安装 gnupg-curl
sudo apt-get install gnupg-curl
然后,要使用这个密钥池,你需要下载 sks-keyservers.net 的 CA 证书 并把它保存在你机器上的某处,然后你需要 验证这个 CA 的 PGP 指纹,现在你需要在 ~/.gnupg/gpg.conf
中添加两行。
keyserver hkps://hkps.pool.sks-keyservers.net
keyserver-options ca-cert-file=/path/to/CA/sks-keyservers.netCA.pem # 注意,这个证书地址就是之前下载的那个 CA 的位置
现在你与证书服务器之前的通讯就会通过 hkps,这个可以在有人嗅探你的流量的时候保护的你的社交关系。如果你使用的不是 hkps 而是 hkp 的话,当你在某个密钥服务器上 gpg --refresh-keys
的时候,嗅探你流量的人就可以看到你同步 key 的信息,有了这些信息就事情就会变得十分有趣了。
Note: hkps://keys.indymedia.org, hkps://keys.mayfirst.org and hkps://keys.riseup.net 都提供 hpks 密钥服务器(当然我们还是建议你使用一个密钥服务器池)
保证所有的密钥都是通过你选择的密钥服务器同步
当创建一个密钥对的时候,我们可以指定某一台服务器来拉取他们的 Key,我们建议你使用以下配置信息来忽略对服务器指定:
keyserver-options no-honor-keyserver-url
这样做有如下好处:
- 可以防止有人通过指定的服务器通过不安全的方式拉取密钥
- 如果指定的服务器使用了 hkps,如果对方没有下载 CA 证书的话密钥就可能永远没法被同步
需要注意的是攻击者也可以指定一个密钥服务器并且监控你是从哪儿同步了他们的密钥(注:类似 BT 种子钓鱼,可以钓出对方的 IP 地址)
慢慢同步你的密钥并且一次同步一个
现在已经配置好了一个不错的服务器池,你现在需要做的就是定期地同步你的密钥,对于 Debian 和 Ubuntu 用户来说最好的方式就是使用 parcimonie:
sudo apt-get install parcimonie
parcimonie 是一个走 Tor 的缓慢的密钥同步守护进程。它使用随机化休眠机制,并且所有同步密钥的流量都是通过 Tor. 这样会让攻击者难以通过你的手中公钥来关联到你。
你不应该使用 gpg --refresh-keys
或者邮件客户端上的刷新按钮来刷新密钥,因为这样的话密钥服务器管理员,监听者都可以知道你在刷新的密钥了。
不要盲目地相信来自密钥服务器的密钥
所有人都可以把自己的密钥上传到密钥服务器上所有你不应该仅仅是下载下密钥就盲目地认为就是你需要的那个。你用该通过线下或者电话的方式向对方确认其密钥的指纹信息。当你确定了对方的指纹后,你就可以通过如下指令下载对方的公钥:
gpg --recv-key '<fingerprint>'
下一步就是确认你下载你的密钥就是你需要的那个,密钥服务器可能会给了一个其他密钥的给你。如果你的 GnuPG 版本小于 2.1,那你就需要手动确认你下载到的 Key,如果你的 GnuPG 版本大于 2.1 的话它会自动拒绝来自密钥服务器的不正确的密钥。
你可以用两种方式来确认密钥指纹:
- 直接检查密钥指纹
gpg --fingerprint '<fingerprint>'
- 尝试在本地用那个指纹给一个密钥签名
gpg --lsign-key '<fingerprint>'
如果你确定你拿到了那个人的正确的密钥,比较建议的是在本地给那个密钥签名,如果你希望公开的表明你和那个人的联系的话,你可以公开 --sign-key
.
注意上面命令中密钥指纹只需要被单引号或者双引号包含。
不要依靠 Key ID
短的 OpenPGP ID,比如 0×2861A790,只有 32 位长,他们已经 被证明 一个其他的 Key 可以有先同的 Key ID. 长的 OpenPGP ID,比如 0xA1E6148633874A3D 有 64 位长,也是可以 被碰撞 的,所以 也是一个严重的问题
如果你需要一个强密码学保证的验证方法,你应该使用全指纹,你永远不应该以来或短或长的 Key ID.
你至少应该在 GPG 配置文件中写上 keyid-format 0xlong
和 with-fingerprint
来保证所有密钥都是显示 64 位长的 ID 且显示指纹。
在导入前检查
如果你在一个地方(比如网站上面)下载了一个密钥,你应该在导入前验证密钥指纹。
gpg --with-fingerprint <keyfile>
---------
OpenPGP 最佳实践 - 密钥配置
你应该已经可以从一个密钥服务器上同步其他人的密钥了,现在你需要保证你的 OpenPGP 密钥已经被正确的配置。
使用一个强壮的主密钥
(注:此段有许多内容较为过时,我将选择性翻译) 在 2011 年美国 NIST放弃了 DSA-1024 加密算法。
现在推荐使用 sha512 生成的 4096 位的 RSA 密钥,并且使用双密钥签名的 密钥转移声明,并且让其他人知道你的密钥,有一份 不错的文档 写清楚了这么做的所有步骤。
转变会比较艰难,但是这样是值得的,且这也是一个最好的使用工具实践的方法。
密钥过期时间不要超过 2 年
很多人不希望他们的密钥过期,但是你真的这么认为么?密钥的过期时间可以在任意时刻(哪怕已经过期)修改。所以过期时间更像是一个自动的定时开关,如果你在没有及时重置开关则密钥可以自动失效,这样可以让其他人知道你一直对密钥有所有和管理能力。
当然,如果设置一个过期时间的话就意味着你以后在某个时间需要延长一次,这个是一个你需要记住的微小的工作。
你可能会认为这样很烦人并且不想处理它,但是这个是一个基础的让你保持对 OpenPGP 工具熟悉的方法,它表明了你的密钥仍然在被使用着。此外,有些人不会对一个没有过期日期的密钥签名。
假设你已经生成了一个没有过期时间的密钥,你可以通过以下指令来添加过期时间:
gpg --edit-key <密钥指纹>
现在选择一个你想设置过期时间的子密钥,并且输入 expire
指令:
gpg> key 1
gpg> expire
然后设置一个合理的过期时间并且退出(比如两年):
Key is valid for? (0) 2y
gpg> save
然后你需要把你的公钥推到密钥服务器上来宣布这次改动:
gpg --send-key <密钥指纹>
在日历上提醒你延长过期时间
你肯定记不住密钥过期时间的,所以在过期前的一两个月设置一个提示告诉你该更新过期时间了。
生成一个吊销证书
如果你忘记了你的密码或者你的私钥已经被他人获取,你唯一的希望就是等到的密钥过期(当然,这样并不是一个好的解决方法),或者把你的吊销证书推到密钥服务器上,这样可以通知到其他人你的密钥已经被吊销不再使用了。
一个被吊销的密钥仍然可以用来验证证书或者解密信息(如果你还能解开私钥的话),但是已经不能被其他人用来加密消息发送给你,使用以下指令创建一个称为 revoke.asc
的销毁证书:
gpg --output revoke.asc --gen-revoke '<fingerprint>'
你可能会希望把这个文件打印出来并且隐藏起来。如果有人得到了这个,他们就可以吊销你的密钥,这样就会很不方便,但如果他们得到了你的私钥,那么吊销的密钥就十分必要了。
需要注意这个在 GnuPG 2.1 及以上会默认进行。
主密钥只用来认证(或者签名),使用一个子密钥用来加密
这个在 GnuPG 1.4.18 及以上是默认进行的。
用一个单独的子密钥来签名
默认 GnuPG 使用同一个子密钥来签名消息和给其他密钥签名。如果使用单独的子密钥来操作的话会十分有用,因为签名消息远远比签名其他的密钥重要。
在这个情况下你的主密钥仅仅用来认证,且很少被使用。
可以使用 edit-key
来编辑,使用 addkey
来生成子密钥。
把主密钥完全放在线下
这个保护你的主密钥的方法很有技巧性。如果你的主密钥被盗,攻击者就可以用它来创建的新的身份并且吊销你的证书,将主密钥完全放在线下可以很好的防止这类攻击。
确保你使用了单独的签名密钥,你没法使用已经被下线的主密钥给邮件签名。
# 导出你的主密钥
gpg -a --export-secret-key john.doe@example.com > secret_key
# 导出所有子密钥
gpg -a --export-secret-subkeys john.doe@example.com > secret_subkeys.gpg
# 删除 keyring 上的所有私钥,这样就只有子密钥的
$ gpg --delete-secret-keys john.doe@example.com
Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y
# 重新导入你的子密钥
$ gpg --import secret_subkeys.gpg
# 确认已经导入完成
$ gpg --list-secret-keys
# 在磁盘上把子密钥删除
$ rm secret_subkeys.gpg
然后你需要保护好 secret_key
内容,比如放在一个 U 盘中,或者使用智能卡(注:比如 Yubikey)来储存密钥,设备的安全性决定了你密钥的安全性。
请确保你有吊销证书。
你可以通过 --list-secrect-keys
参数,通过判断私钥部分显示的是 sec#
而不是 sec
来确认私钥部分已经被移除。
提示:在上述操作中私钥在你的磁盘上时使用明文储存的,所以一个单独的 rm
并不能彻底删除掉,考虑使用 wipe 工具,当然,如果你使用的是 SSD 的话,操作前请确保已经上了 FDE(全盘加密),否则没法彻底删除。
No comments:
Post a Comment