当前位置: 首页 > 面试题库 >

Java中的确定性RSA加密

祁博涛
2023-03-14
问题内容

这是我在此站点上提出的第一个问题,我对RSA仅具有基本的数学理解,请耐心等待!:)

我正在为大学的最后一个项目编写Java Web应用程序。它是基于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:数据必须以零开头

非常感谢您阅读本文!任何帮助将不胜感激。

编辑-抱歉,我最初的问题不是很清楚我想要做什么,所以这里有[尝试]的解释:

  • 明文是选举中的选民投票。
  • 选民投票的目的是在不牺牲选民的机密性(等)的情况下进行端到端的验证。投票后,将为选民提供一张收据,供他们用来验证自己的投票已正确记录,并且稍后将向他们显示其投票未被篡改。选民将其收据上的信息与网上发布的相同副本进行比较。
  • 但是,任何投票人都不可能证明自己的投票方式(这可能会导致胁迫),因此该信息不是明文,而是投票的加密副本。
  • 实际上,明文被加密了四次,使用了四个不同的非对称密钥-由两个不同的出纳员持有,每个出纳员持有两个密钥。因此,将一个投票(明文)提供给一个出纳员,该出纳员使用公钥#1对其进行加密,然后使用他的第二个公共密钥对THAT密文进行加密,将THAT密文交给第二个出纳员,第二个出纳员使用相同的两个密钥对其进行加密方式。生成的密文(四个顺序加密的结果)就是发布到网络上的内容(公开)。柜员是可信赖的。
  • 每个加密的投票都可以可视化为“洋葱”,其中的中心是投票,并且有多层加密。为了进行投票,必须依次除去每一层,这意味着必须以相反的顺序应用相应的私钥(由出纳员持有)。这是安全性的关键-所有出纳员必须协同工作才能解密票。
  • Web公告板可以显示为具有5列的表格-第一个(在左侧)保存完全加密的选票(也显示在每个选民的收据上),并且是在投票过程中唯一可见的栏。第二列包含相同的投票集,但除去了外层-出纳员2通过在计数阶段使用其私钥解密投票来填充此列和第3列。在计算阶段结束时,第5列包含可以被计算的完全解密的选票。
  • 每个投票人都会获得一张收据,将其链接到第1列中的加密投票。这没有显示他们的投票方式,但允许他们验证自己的投票未被篡改,因为在整个选举过程中,他们可以验证自己的加密投票仍然在第1列中保持不变。当然,这只是“端到端验证”的一半,因为选民无法验证解密是否正确完成,即,第2列中有一个条目是他们的投票减去加密的外层。每个投票人仅负责第1栏之前的验证。
  • 此后,审核员有责任检查第1列中的条目是否解密到第2列,依此类推。他们这样做的方法是依靠 确定性 加密,并且用于加密的公共密钥是公共的。
  • 由于公开密钥是公开的,因此您不希望人们简单地从第5列到第1列划界线,因为某人的投票经过反复加密后才参与投票-这样,将您与加密投票联系起来的收据实际上会将您与未加密的可读投票->强制!因此,只有第1、3和5列是公开的(这就是每个出纳员执行两次加密的原因),并且对于第3列中的每个条目,{2,4}中只有一个对应的条目会向审核员显示。这样可以防止任何人(甚至审计员)将加密的投票链接到未加密的投票。
  • 因此,审核员需要在第3列中获取一个条目,在第2列中获得相应的条目以及公共密钥,并执行相同的加密以验证他们确实在第2列中获得了该条目。
  • 放在一起,可以提供端到端的可验证性。

抱歉,这太长了-我希望它能说明我对确定性加密的需求。我错过了很多基本细节(我已经对该方案进行了重大修改),但希望所有的核心原则都在那里。非常感谢您的阅读-
非常感谢。


问题答案:

卸下衬垫会使系统不安全。如您所说,如果公用密钥确实是公用的,那么攻击者可以简单地转到第5列,获取纯文本,并以适当的顺序用4个公用密钥对其进行加密。然后,他们可以将接收到的密文与接收到的密文进行匹配,从而损害“无强制性”属性。

随机填充可以阻止这种情况,因为攻击者不知道要添加什么填充。

您将需要使用常规填充,但要将一部分私钥透露给审核员的一部分(在选举系统中通常称为“审查员”)。这意味着一名审查员可以确认第1列与第2列匹配,而另一名审查员可以确认第2列与第3列匹配,依此类推。监票员不能将选民与选票相提并论,只能合作。

收到“消息大于模数”错误的原因是,由于每个模数不同,因此一次加密的密文可能超出了下一次加密的允许范围。



 类似资料:
  • 问题内容: 我想用RSA加密对String进行加密。我的公钥/私钥已生成并存储在DB中。在android中,我使用以下代码: 出于调试目的,我尝试使用相同的参数调用此方法两次,并且String结果相似(符合预期)。 我想在Java中生成相同的加密字符串。但是,“ android.util.Base64”类在Java中不可用,因此我尝试使用默认的Base64类: 但是Android中生成的Strin

  • 问题内容: 我试图来回编码一个简单的String“ test”。 但是,尽管加密工作得很好(ALGORITHM是“ RSA”),但是当尝试解密刚刚从加密“ test”中获得的字符串时,出现以下异常: javax.crypto.IllegalBlockSizeException:数据不得超过256个字节 我是否应该将加密的字节分成256个块才能解密? 问题答案: 您无法可靠地将随机字节转换为。结果将

  • 问题内容: 我正在尝试使用RSA私钥加密某些内容。 我遵循以下示例:http : //www.junkheap.net/content/public_key_encryption_java, 但将其转换为使用私钥而不是公共密钥。遵循该示例,我认为我需要做的是: 读取DER格式的私钥 生成PCKS8EncodedKeySpec 从KeyFactory调用generatePrivate()获得一个私钥

  • 我正在尝试使用java对用户电子邮件id进行RSA加密,并尝试使用php进行解密。但我没有成功。以下是详细信息 java中的源代码: 私钥: RSA 加密输出: 和Bas64编码输出: php解密代码 php输出返回none。。。

  • 我正在检查一个用Python编写的代码,它用来生成一个RSA公钥对。 它会生成keypair,但是在代码的末尾,它会再次运行ssh-keygen。我不知道为什么这样做。因为,rsa.generate()本身将生成keypair,我们将其导出到两个单独的文件中。为什么需要再次运行ssh-keygen? 下面是代码中的几行: 文件pub将存储公钥,id_rsa将存储来自rsa.generate()函数

  • 我在python上做加密,在Java上尝试解密,但总是得到解密错误 我在Java有部分加密和解密信息代码,用RSA编码解密: 不幸的是,我无法在这段代码中进行更改,所以我所能做的就是在python部分中进行更改。这部分工作正常。为了检查,我使用以下代码进行加密: 当我使用来自Java代码的结果进行加密,并将这个结果用于解密Java文件--所有的工作都很好。我需要相同的加密部分,但编写与Python