能否使用私钥加密/公钥解密?

26

[免责声明:我知道,如果你对加密货币有所了解,你可能会告诉我为什么我做错了 - 我已经通过谷歌搜索了解到这似乎是典型的答复。]

假设以下情况:您有一个中央机构想要为给定域发行登录 cookie。在此域上,您不一定信任每个人,但您有一些关键的终端点应该能够读取 cookie。我说有几个,但实际上这些“受信任”的合作伙伴数量可能很大。cookie 并不包含太多信息 - 用户名、时间戳、到期时间、随机数。当然,在加密之后,它应该保持尽可能小以提高性能。现在,有两个安全问题:

1) 我们不相信此域上的每个 Web 服务器都具有用户数据。因此,只应将读取 cookie 的权限限制为这些受信任的合作伙伴。 2) 虽然我们信任这些合作伙伴保护我们用户的数据,但我们仍希望权威中心是不可伪造的(在合理范围内)。

现在,如果我们为权威机构生成一个私钥并将其保密,并仅向“受信任的合作伙伴”分发公钥,我们应该能够使用私钥进行加密,并使任何拥有公钥的人都可以读取。我不确定的是,是否仍然需要签署消息,或者解密行为是否证明它是由私钥生成的。这种方案与向所有相关方散布对称密钥并将其用于加密,同时仅使用私钥进行签名相比,有什么优缺点呢?当然,欢迎告诉我这是一个愚蠢的想法的所有方法,但请记住,实际的论据可能比重复 Alice 和 Bob 要更具说服力。

哦,如果涉及到任何“坑”,实现指针也会很有用,尽管您可以在 Google 上找到基础知识!

7个回答

20
Nate Lawson在这里这里解释了为什么不能将公钥用作保密的解密密钥(这是一个微妙的问题,许多人在你之前都犯过这个错误,所以不要感到难过!)。
只需使用您的公钥进行签名以确保真实性,使用单独的对称密钥进行保密。
我已经阅读了足够多有关公钥系统和RSA等加密算法的有趣攻击,因此我完全同意这个结论:

公钥加密系统和RSA特别脆弱。 不要将它们与设计不同的方式使用。

(这意味着:使用公钥进行加密,使用私钥进行签名,任何其他操作都是玩火。) 附录: 如果您想减小生成的cookie大小,您应该考虑使用ECDSA而不是RSA来生成签名-ECDSA签名比具有相同安全系数的RSA签名要小得多。

Nate Lawson提出的理由似乎是Thomas回答中提到的第一个问题:公钥的e值通常太小而无法保密。为了保持公钥的机密性,您需要使用非常大的随机数来生成其e值。 - Brilliand

6
在密码学中,你的身份由你所知道的信息决定。在你的情况下,有一个中央机构负责发放你的Cookie,并且你不希望其他实体也能做到这一点。因此,中央机构必须“知道”一些私有数据。同时,你希望“受信任的Web服务器”能够访问Cookie内容,而你不希望其他人看到Cookie。因此,“受信任的Web服务器”也必须拥有自己的私有数据。
一般来说,中央机构将在Cookie上应用数字签名,并使用受信任的Web服务器已知的密钥加密Cookie。而你考虑的方案是这样的:
- 有一个RSA模数n和两个典型的RSA指数d和e(使得ed≡1(mod p-1)和q-1,其中n=pq)。中央机构知道d,受信任的Web服务器知道e,模数n是公开的。 - 中央机构通过填充Cookie为模n的整数c,并计算s=c^d(mod n)来处理Cookie。 - 受信任的Web服务器通过计算c=s^e(mod n)来访问Cookie数据。
虽然这样的方案可能起作用,但我认为它存在以下问题:
  • 为了基本安全,e必须足够大。通常RSA描述中,e是公共指数,而且很小(例如e=3)。当它是公开的时,小指数没有问题,但是由于你不希望cookie内容被第三方访问,所以你必须使e足够大以抵御穷举搜索。同时,受信任的Web服务器不应知道pq,只知道n。这意味着受信任的Web服务器需要使用大模数和大指数进行计算,而不知道模数因子。这似乎是一个小问题,但它淘汰了许多RSA实现库。你将“独自一人”,使用大整数(以及所有已知的“侧信道泄漏”实现问题)。
  • RSA签名的抗性和RSA加密的抗性已经得到充分研究,但是没有同时研究过。碰巧填充是关键的,而且你不能为加密和签名使用相同的填充方案。在这里,你需要一个填充方案,既适合签名又适合加密。密码学家通常认为,在几年内有数百个训练有素的密码学家研究了该方案,并且没有发现明显的弱点(或者修复了发现的任何弱点)时,可以实现良好的安全性。自制的方案几乎总是无法实现安全。
  • 如果许多人知道一个秘密,那么它就不再是秘密了。在这里,如果所有Web服务器都知道e,那么你不能撤销受信任的Web服务器的权限,而不选择新的e并将新值通知给所有剩余的受信任的Web服务器。你在使用共享对称密钥时也会遇到这个问题。

目前正在研究如何在同一类型中确保机密性和可验证完整性的问题。你可以查阅signcryption。目前还没有建立统一的标准。

基本上,我认为你会更喜欢更经典的设计,仅使用数字签名进行签名,而(对称或非对称)加密用于保密部分。这将使你能够使用现有的库,尽可能少地使用自制代码。

对于签名部分,你可以使用DSA或ECDSA:它们产生更短的签名(相当于1024位RSA签名的安全性,DSA签名通常为320位)。从中央机构的角度来看,ECDSA也允许更好的性能:在我的PC上,使用单个核心,OpenSSL每秒可以产生超过6500个ECDSA签名(在P-192 NIST曲线上),而“仅”1145个RSA签名(使用1024位密钥)。ECDSA签名包含两个192位整数,即384位编码,而RSA签名长度为1024位。 P-192中的ECDSA被认为至少与RSA-1024一样强大,或者可能更强大。


5
你应该使用某种数字签名方案或其他旨在解决你场景中完整性问题的机制。
仅加密是不够的。你如何知道解密后的消息是正确的?如果用错误的密钥解密一个cookie,或者解密一些无意义的数据会发生什么?你可能会得到一个看起来有效的cookie!(时间戳在你认为有效的范围内,用户名是合法的,随机数是……嗯……一个数字等等)。
在我所知道的大多数非对称加密算法中,没有内置验证。这意味着用错误的密钥解密消息将不会“失败”——它只会给你一个错误的明文,你必须将其与有效的明文区分开来。这就是完整性的作用,最常见的方法是使用数字签名。
顺便说一下,RSA已经被广泛研究并且有几个需要注意的地方,因此如果你打算从头开始实现它,最好事先阅读如何避免创建“相对容易破解”的密钥。

啊,当然!那很有道理。我也不打算重新实现RSA,只是要使用openssl库。所以无论我是用对称密钥还是私钥加密,似乎都需要签名。那么问题就是,我应该忍受并分发另一个对称加密密钥,还是如果在这种情况下拥有公钥和对称密钥的人是相同的,我会失去什么,假设我用私钥加密? - agnoster

1

公钥是公开的,这是其定义。如果你使用私钥加密并使用公钥解密,那么这对于窥探者来说是不安全的。它只是说明:“这些数据来自持有私钥X的人X”,任何人都可以验证,因为密钥的另一半是公开的。

如果你不信任某个人将公钥X放在你不信任的服务器上,该怎么办?

如果你想要在两个服务器之间建立一个安全的通信线路,你需要让所有受信任的服务器都拥有自己的公钥/私钥对,我们称之为Y键对。

然后,服务器X可以使用私钥X和公钥Y加密消息。这意味着“服务器X发送了一条只有Y能够阅读的消息,并且Y可以验证它来自X。”

(而且这条消息应该包含一个短暂的对称密钥,因为公钥加密非常耗时。)

这就是SSL所做的事情。它使用公钥加密来建立会话密钥。

话虽如此,最好使用库。这些东西很容易搞砸。


1
关于您的问题“解密是否是生成私钥的证据”,答案是肯定的,如果接收方可以对数据进行简单的验证。比如你有“用户名:John,时间戳:<数字>,到期日:dd/mm/yyyy”。现在,如果使用错误的公钥进行解密,那么你得到“用户名:<一些字母>,时间戳:<仅数字>,到期日:??/??/????” 的概率为零。您可以使用正则表达式(regex)进行验证,例如“用户名:[a-zA-Z]+,时间戳:[0-9]+,到期日:....”,如果验证失败,则放弃它。您甚至可以检查日期是否在1到31之间,月份是否在1到12之间,但如果使用错误的公钥,则通常会在“用户名:”处失败。如果验证成功,您仍然需要检查时间戳,并确保您没有遭受重放攻击。

然而,请考虑以下内容:

  1. RSA 公钥加密并不适用于结构化数据的批量加密,因为它容易被攻击者利用。公钥加密通常有两种用途:1) 安全地传输对称密钥(即没有结构定义的密钥),该密钥将用于批量加密;这是通过使用公钥加密对称密钥来完成的;2) 数字签名一个文档,方法是使用私钥加密文档的哈希值(同样也是没有结构的东西)。在您的情况下,您正在加密具有明确定义的结构的 cookie。
  2. 您依赖于公钥不会落入错误人或实体手中。
  3. 公钥加密比对称密钥加密慢约 1000 倍。这在您的情况下可能并不是一个因素。

如果您仍然想使用此方法,并能将公钥 分发给“受信任的合作伙伴”,则应生成一个随机会话密钥(即对称密钥),使用私钥加密并发送给所有具有公钥的接收方。然后使用会话密钥加密 cookie。您可以定期更改会话密钥。更少地更改公钥:您可以生成新的公钥/私钥对,并使用会话密钥加密公钥并将其发送给所有收件人。


1
正如caf的回答所提到的,你不能用RSA保持公钥的机密性。它可以从传输的消息中单独检索出来。不要这样做。 - Paŭlo Ebermann
保罗,我没有说你可以用RSA保密公钥。 - Babu Srinivasan
你没有明确说出来,但是你的提议依赖于公钥仅为接收者所知。你甚至这样说:“你依赖于公钥不会落入错误的人或实体手中。”而这是行不通的。 - Paŭlo Ebermann

0
作为密钥分发方式的替代方案,根据你的应用情况而定,可以考虑使用 Kerberos,它使用对称密钥加密、单一高度保护的堡垒服务器来控制所有密钥材料,以及一组巧妙的协议(参见Needham-Schroder protocol)。

0
我猜你信任“可信合作伙伴”来解密和验证cookie,但不希望他们能够生成自己的cookie?如果这不是问题,你可以使用一个更简单的系统:向所有参与方分发一个秘密密钥,并使用它来加密cookie并为其生成HMAC。无需公钥加密,也无需多个密钥。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接