背景:
- 一些现有的程序,例如git 附件(git-annex 加密) 和经过,委托加密通用石油气”一个完整且免费的实施开放PGP标准”。更具体地说,这些程序依赖于GPG 密钥 ID作为与 GPG 交互的方式:
GPG 用于创建和管理 GPG 公钥/私钥对。
该程序被指示通过其密钥 ID 使用特定的 GPG 公钥/私钥对。
虽然依赖 GPG 是好的并且值得称赞,但是实现这一点的具体方式(通过 GPG 密钥 id-s)导致了在后台不必要地使用公钥加密。
公钥/非对称加密解决了一些特定用例,广义上讲,这些用例涉及一个受信任方和多个不受信任方之间的信息安全传输。如果有人决定使用将
pass
自己的密码存储在公共 git 存储库中,则此方案中没有不受信任的一方来证明使用非对称加密的合理性。传统/对称加密可能比非对称加密更安全。例如,存在可以破解非对称加密的量子算法,但目前还没有量子计算机来运行它们。虽然不能保证一定会有这样的发展,但对称加密没有类似的(潜在)弱点。
非对称加密得益于两个不同的安全性层面:
(a)私钥使用密码进行对称加密
(b)将(加密的)私钥保存在安全的地方
因此,例如,只要 (b) 成立,(a) 就不会增加非对称加密的安全性。使用空密码短语进行非对称加密是完全有效的(尽管不建议)。
普通的对称加密使用单个私钥,仅提供 (a) 类安全性。如果要用对称加密取代非对称加密,最好同时保留 (a) 和 (b) 两个安全级别。一种方法是使用 2 个对称级别:
生成私人随机字符串
使用密码对称加密私有随机字符串,并进行私密存储
使用私有随机字符串对称加密消息,并公开存储
- 下面描述了当某个程序通过 GPG 密钥 ID 使用 GPG 时,底层发生的情况
pass
。(假设公钥加密是 RSA,对称加密是 AES。)首先,GPG 用于:
(i)创建 RSA 公钥/私钥对
(二)RSA公钥未加密,私下存储(硬盘)或公开存储(密钥服务器)
(三)使用 AES 加密 RSA 私钥和密码,并私下存储
接下来,OpenPGP 加密,加密的工作原理如下:
(iv)生成随机会话密钥
(v)使用会话密钥对消息进行 AES 加密,并公开存储
(vi)使用 RSA 公钥对会话密钥进行 RSA 加密,并公开存储
观察消息是否被破解任何一个(五)或者(六)
不必要的潜在漏洞:
假设未来量子计算机被开发出来,RSA 被破解了。(对于偏执狂来说,假设 RSA 已经被破解了。)虽然这将改变我们在网上银行等业务上的做法,但它也将带来完全没有必要对数据安全造成负面影响pass
。git-annex
这有多糟糕取决于上面 (ii) 中的 RSA 公钥是公开存储还是私下存储。如果是公开存储,则数据已被泄露:攻击者可以解密 (vi) 获取会话密钥,然后使用会话密钥解密 (v) 以获取消息。如果 (ii) 中的 RSA 公钥实际上是私下存储的,则数据的安全性将降低到 (b),即持有 RSA 公钥的介质的安全性,这相当于在没有密码的情况下进行非对称加密。
无论是否牵强,此漏洞都是完全没有必要的,因为它是由于在现有程序(如pass
/git-annex
和 GPG(通过 GPG 密钥 id-s))之间接口中不必要地使用了固有的公钥加密所致。
问题:
有没有一种“相对简单”的方法来:
当通过 GPG 密钥 id-s 在后台使用 GPG 时,删除非对称加密的使用
继续像以前一样使用 GPG 管理密钥
维持 4 中 (a) 和 (b) 所述的 2 级安全性
我想要的完整示意图是:
(i') 生成私人随机字符串
(ii')使用密码对私人随机字符串进行 AES 加密,并私密存储
(iii')使用私人随机字符串对消息进行 AES 加密,并公开存储
我知道如何分别执行每个步骤,但我要问的是,在程序可能通过 GPG 密钥 ID 使用 GPG 的方式中插入此类“修复”的最佳方法。具体来说,我希望此类程序发出形式为gpg --encrypt --recipient <keyid>
和的外部调用gpg --decrypt
。
结论:似乎没有灵丹妙药,使用gpg
包装器脚本拦截这些调用是唯一的方法。也许 GPG 将来应该考虑这个问题。
答案1
OpenPGP 中的对称加密
看了你的问题,我觉得你混淆了一些密码学术语和原理。没有使用私钥进行对称加密这样的东西。对称加密依赖于会话密钥(也称为密码块),而公钥/私钥(非对称)加密依赖于密钥对进行加密(公钥)和解密(私钥)操作。
OpenPGP 通常使用混合加密方法:使用对称加密和随机唯一会话密钥对消息(数据、文件等)进行加密。会话密钥通过公钥/私钥加密进行加密。这结合了对称加密和公钥/私钥加密的优点:对称加密非常快,但需要共享密钥;而公钥/私钥加密可以实现强大的密钥管理,并将公钥和私钥分开,但对于大量数据来说速度非常慢。
OpenPGP 的对称加密也一样,但它是从密码短语中派生出会话密钥。根据配置,在此过程中会添加一些盐(GnuPG 在此处有合理的默认值)。不涉及公钥或私钥(就像 RSA 那样)。在 GnuPG 中,通过应用选项可以实现这一点--symmetric
。
有没有办法让 gpg 执行纯对称加密,这样密码只用于保护私钥,就像非对称加密一样?当然,密码和私钥都是解密所必需的。
如果您想要“我是否可以单独存储会话密钥,使用密码加密,而不是依赖 OpenPGP 的字符串到密钥函数,然后使用密码加密此会话密钥”之类的问题,答案是否定的,这在 OpenPGP 协议中是不可能的。但是,您可以通过将公钥/私钥对存储在一个地方,仍然使用密码加密,来模拟此类操作。每次使用私钥时,密码都会用于解密私钥。
(顺便说一句,我相信通过存储在 LUKS 标头中的 MK salt 可以实现类似的效果:丢失它,仅靠密码就无法解密容器。)
不,盐会一起存储在消息的加密标头中(如果是 LUKS,则存储在加密容器中)。您无法将其与密钥进行比较,而且它也不是秘密。盐用于在计算会话密钥之前将其与密码短语结合起来,以防止彩虹表攻击。
覆盖会话密钥
在您的更新中,您细化了您的目标。
我想要的完整示意图是:
(i') 生成私人随机字符串
(ii')使用密码对私人随机字符串进行 AES 加密,并私密存储
(iii')使用私人随机字符串对消息进行 AES 加密,并公开存储
您无法准确实现这一点,但 GnuPG 知道一种(非标准化)方法来提取和定义要使用的会话密钥。来自man gpg
:
--show-session-key
显示一条消息使用的会话密钥。请参阅
--override-session-key
此选项的对应部分。我们认为密钥托管是一件坏事;但是用户应该有自由决定是否入狱或泄露一条特定消息的内容,而不会泄露所有用一个密钥加密的消息。除非你真的被迫这样做,否则不要使用它。
--override-session-key string
不要使用公钥,而是使用会话密钥字符串。此字符串的格式与 打印的格式相同
--show-session-key
。此选项通常不使用,但如果有人强迫您透露加密消息的内容,它会派上用场;使用此选项,您可以在不泄露密钥的情况下做到这一点。
您可以使用这些选项提取会话密钥,使用密码单独加密,并将其存储在某处。要使用它,您必须使用密码再次加密,然后将其传递给 GnuPG。当然,这可以通过一些包装器脚本或类似方法实现。这是您可以通过 GnuPG 获得的最接近的方法(这超出了 OpenPGP 的规定,这些选项是 GnuPG 特定的)。开发人员实际上并不认为这些选项可用于日常工作。
我不会滥用 GnuPG 和 OpenPGP 进行此类操作。您可以轻松使用 OpenSSL 甚至 GnuTLS 进行此类操作,而无需使用深奥的非标准化操作模式和包装器脚本。