这是我在这个网站上的第一个问题,我对RSA只有基本的数学了解,所以请多多包涵!:)
我正在为我在大学的最后一年项目编写一个 Java Web 应用程序。这是一个基于网络的“Pret-a-voter”实现,一个安全的投票系统,对于那些听说过它的人来说。
本质上,我的问题是我希望能够让某人担任审计员的角色:
- 源字节数组(要加密的明文)
- 一个 RSA 公钥文件
- 一个“目标”字节数组,这是我自己计算给定明文和公钥的密码数据的结果
然后,我希望审核员能够使用前两项执行加密,并对第三项是结果感到满意。因此,我需要确定性的加密,即每次重复使用相同的明文和公钥进行加密时生成相同的密码数据。
(注意 - 我在这个项目中使用非常小的数据块 - 根本不涉及对称加密......我知道这是 RSA 的“有趣”使用!)
无论如何我发现在Java中,使用
cipher = Cipher.getInstance("RSA");
使用默认的随机填充方案,成本为 11 个字节(因此使用 2048 位密钥对,可以加密 2048/8-11 = 245 个字节)。相同明文的重复加密会产生不同的密文,这显然不是我想要的ECB模式。
我的问题是 -我应该使用以下内容吗?
cipher = Cipher.getInstance("RSA/ECB/NoPadding");
我在很多地方读到 RSA 在没有填充的情况下是不安全的。这仅仅是因为攻击者可以构建明文/密文字典吗?这是我需要的确定性加密的副作用,以允许审核员验证我的加密,并且在我的方案中,审核员是受信任的,所以可以。
我的问题的第二部分与 java 相关。如果我确实如上所述使用 RSA/ECB/NoPadding,我相信我能够提供(比如说)长度为 128 的源字节数组(对于 1024 位 RSA 密钥对)并对其进行加密以获得另一个长度的字节数组128. 如果我然后尝试使用不同的 1024 长度的公钥再次加密它,我得到
javax.crypto.BadPaddingException:消息大于模数
有谁知道为什么?
编辑 - 使用 NoPadding 加密并不总是产生这个异常 - 它是喜怒无常的。然而,即使加密没有产生这个异常,解密也会产生这个:
javax.crypto.BadPaddingException:数据必须从零开始
非常感谢您阅读本文!任何帮助将不胜感激。
编辑 - 抱歉,我最初的问题不是很清楚我想要做什么,所以这里有一个 [attempt at an] 解释:
- 明文是选民在选举中的投票。
- Pret-a-voter 旨在在不牺牲选民机密性(等)的情况下进行端到端的验证。投票后,选民将获得一张收据,他们可以使用该收据来验证他们的投票是否被正确记录,并且稍后会向他们表明他们的投票没有被篡改。选民将其收据上的信息与发布在网络上的相同副本进行比较。
- 但是,任何选民都不可能证明他/她是如何投票的(因为这可能会导致强制),因此信息不是明文,而是投票的加密副本。
- 事实上,明文被加密了四次,使用四个不同的非对称密钥——由两个不同的柜员持有,每个柜员持有两个密钥。因此,向一个出纳员提供投票(明文),该出纳员使用公钥#1对其进行加密,然后用他的第二个公钥加密该密文,将该密文提供给第二个出纳员,该出纳员使用他的两个密钥对其进行加密方式。生成的密文(四次连续加密的结果)是发布到网络(公开)的内容。出纳员是值得信赖的。
- 每个加密投票都可以可视化为一个“洋葱”,其中中心是投票,并且有几层加密。为了进行投票,必须依次删除每一层,这意味着必须以相反的顺序应用相应的私钥(由出纳员持有)。这是安全的关键——所有出纳员必须合作才能解密选票。
- 网络公告板可以可视化为一个有 5 列的表格 - 第一列(左侧)保存完全加密的选票(也显示在每个选民的收据上),并且是投票阶段唯一可见的列。第二列包含相同的选票集,但移除了外层 - 出纳员 2 通过在计票阶段使用其私钥解密选票来填充此列和第 3 列。在计票阶段结束时,第 5 列包含可以计票的完全解密的选票。
- 每个选民都会收到一张收据,将他们链接到第 1 列中的加密投票。这不会显示他们的投票方式,但允许他们验证他们的投票没有被篡改,因为在整个选举过程中,他们可以验证他们的加密投票仍然存在于第 1 列中,未触及。当然,这只是“端到端验证”的一半,因为选民无法验证解密是否正确完成,即第 2 列中有一个条目,即他们的投票减去外层加密. 每个选民只负责验证直到第 1 列的点。
- 此后,审核员有责任检查第 1 列中的条目是否解密到第 2 列,依此类推。他们这样做的方式是依靠确定性加密和公开的用于加密的公钥。
- 由于公钥是公开的,您不希望人们简单地从第 5 列到第 1 列画线,在重复加密时加入某人的投票 - 这样,将您与加密投票联系起来的收据实际上将您与未加密、可读的投票 --> 强制!因此,只有第 1、3 和 5 列是公开的(这就是每个出纳员执行两次加密的原因),并且对于第 3 列中的每个条目,只有 {2,4} 中的一个对应条目向审计员显示。这可以防止任何人(甚至审计员)将加密投票与未加密投票联系起来。
- 因此,审计员需要在第 3 列中输入一个条目,在第 2 列中给出相应的条目和公钥,并执行相同的加密以验证他们确实获得了第 2 列中的条目。
- 总之,这提供了端到端的可验证性。
抱歉,太长了——我希望它描述了我对确定性加密的需求。我错过了很多基本细节(我已经对这个方案进行了大量修改),但希望核心原则都在那里。非常感谢您阅读 - 我真的很感激。