Java中的确定性RSA加密 [英] Deterministic RSA encryption in Java

查看:284
本文介绍了Java中的确定性RSA加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我在这个网站上的第一个问题,我只有一个基本的数学理解的RSA,所以请忍受我! :)



我正在为大学的最后一年项目编写一个Java Web应用程序。这是一个基于网络的实施Pret-a-electer,一个安全的投票系统,对于那些听说过它们的人来说。



本质上我的问题是我想能够授予执行审核员角色的人:




  • a 字节数组(明文到加密)

  • 一个RSA公钥文件

  • 一个目标字节数组,这是我的结果自己计算密文给出明文和公钥



然后我想让审核员能够使用前两个进行加密项目,并认为第三是结果。因此,我需要加密为确定性,即每次重复使用相同的明文和公钥加密时生成相同的密码。



注意 - 我在这个项目中使用非常小的数据块 - 完全没有对称加密...我知道这是一个有趣的使用RSA!)



无论如何,我发现在Java中,使用

  cipher = Cipher.getInstance(RSA); 

使用默认的随机填充方案,费用为11个字节(所以使用2048位密钥对,可以加密2048 / 8-11 = 245字节)。相同明文的重复加密产生不同的密文,这显然不是我想要的ECB模式。



我的问题是 - 我应该使用以下吗? / strong>

  cipher = Cipher.getInstance(RSA / ECB / NoPadding); 

我在很多地方读过RSA是不安全的,没有填充。这是因为攻击者可以构建一个明文/密文的字典吗?这是确定性加密的一个副作用,以便允许审核员验证我的加密,在我的方案中,审核员是信任,这样就可以了。



我的问题的第二部分是更多的与java相关的。如果我使用如上所述的RSA / ECB / NoPadding,我相信我能够提供(例如)长度为128(对于1024位RSA密钥对)的源字节数组,并对以获得长度为128的另一个字节数组。如果我再次使用不同的1024长度公钥加密 ,那么我得到


javax.crypto.BadPaddingException:消息大于模块


有没有人知道为什么?



编辑 - 使用NoPadding进行加密并不总是产生这种异常 - 它是气质。然而,即使加密不会产生这种异常,解密也会产生这种情况:


javax.crypto.BadPaddingException:数据必须以零开始。 p>

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



编辑 - 对不起,我原来的问题不是很清楚我想做什么,所以这里是一个]说明:




  • 明文是选举中的选民投票。

  • Pret-a-选民的目标是端对端可验证,而不牺牲选民保密(等)。投票后,向选民提供一张可以用来核实其投票已经正确记录的收据,稍后会向他们表明投票没有被篡改。投票人对收到的信息进行比较,并在网路上张贴相同的副本。

  • 然而,任何投票人都不可能证明他/她投票的方式(如这可能导致强制),所以信息不是明文,而是一个加密的投票副本。

  • 事实上,明文被加密了四次,四个不同的非对称键被持有由两个不同的柜员,每个拿着两个钥匙。所以,向一个出纳员提供一个投票(明文),他们使用公钥#1加密它,然后用他的第二个公钥加密THAT密文,给第二个出纳员加密他的两个密钥的第二个柜员办法。得到的密文(四个连续加密的结果)是发布到网络(公开)的内容。柜员是值得信赖的。

  • 每个加密的投票都可以被视为一个洋葱,中心是投票,有几层加密。为了获得投票权,必须依次删除每一层,这意味着必须以相反的顺序应用相应的私钥(由计票员持有)。这是安全的关键 - 所有柜员必须合作开展工作,以解密投票。

  • 网络公告板可以被视为具有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匹配,依此类推。一个个人的监票员不能将投票人与投票相匹配,只能合作。






由于每个模数不同,所以重新得到消息大于模数的错误,所以来自一个加密的密文可能超出下一次加密的允许范围。


This is my first question on this site, and I only have a basic mathematical understanding of RSA, so please bear with me! :)

I'm writing a Java web application for my final year project at university. It's a web-based implementation of "Pret-a-voter", a secure voting system, for those who have heard of it.

Essentially my problem is that I want to be able to give someone performing the role of an auditor:

  • a source byte array (the plaintext to be encrypted)
  • an RSA public key file
  • a "destination" byte array, which is the result of my own computation of the cipherdata given the plaintext and the public key

I then want the auditor to be able to perform encryption using the first two items, and be satisfied that the third is the result. I therefore need the encryption to be deterministic, i.e. generate the same cipherdata each time encryption with the same plaintext and public key are repeated.

(Note - I'm working with very small blocks of data in this project - there is no symmetric encryption involved at all... I'm aware this is an "interesting" use of RSA!)

Anyway I found that in Java, using

cipher = Cipher.getInstance("RSA");

uses the default random padding scheme, at a cost of 11 bytes (so with a 2048-bit key pair, it's possible to encrypt 2048/8-11 = 245 bytes). Repeated encryptions of the same plaintext generate different ciphertexts, which is obviously not the ECB mode that I want.

My question is - should I use the following?

cipher = Cipher.getInstance("RSA/ECB/NoPadding");

I've read in lots of places that RSA is insecure without padding. Is that simply because an attacker can build a dictionary of plaintexts/ciphertexts? This is a side-effect of the deterministic encryption I require in order to allow auditors to verify my encryption, and in my scheme auditors are trusted, so that would be OK.

Part two of my question is more java-related. If I do use RSA/ECB/NoPadding as above, I believe I'm able to provide a source byte array of (say) length 128 (for a 1024-bit RSA key pair) and encrypt that to get another byte array of length 128. If I then try to encrypt that again, with a different 1024-length public key, I get

javax.crypto.BadPaddingException: Message is larger than modulus

Does anyone know why?

EDIT - encryption with NoPadding doesn't always generate this exception - it's temperamental. However, even when encryption does not generate this exception, decryption generates this:

javax.crypto.BadPaddingException: Data must start with zero

Many thanks for reading through this! Any help would be greatly appreciated.

EDIT - sorry, my original question wasn't very clear about what it is I want to do, so here's an [attempt at an] explanation:

  • The plaintext is a voter's vote in an election.
  • Pret-a-voter aims to be end-to-end verifiable without sacrificing voter confidentiality (etc). After voting, the voter is provided with a receipt that they can use to verify that their vote has been recorded correctly, and which will later show them that their vote has not been tampered with. The voter performs a comparison of the information on their receipt with an identical copy posted on the web.
  • However, it should not be possible for any voter to prove how he/she voted (as that could lead to coercion) so the information is not the plaintext, but an encrypted copy of the vote.
  • In fact, the plaintext is encrypted four times, with four different asymmetric keys - held by two different tellers, each holding two of the keys. So, a vote (plaintext) is provided to one teller, who encrypts it using public key #1, and then encrypts THAT ciphertext with his second public key, gives THAT ciphertext to the second teller who encrypts it with his two keys in the same way. The resulting ciphertext (result of four sequential encryptions) is what is posted to the web (made public). The tellers are trusted.
  • Each encrypted vote can be visualised as an "onion" where the centre is the vote and there are several layers of encryption. In order to get to the vote, each layer must be removed in turn, meaning the corresponding private keys (held by the tellers) must be applied in the reverse sequence. This is key to the security - all tellers must work cooperatively in order to decrypt the votes.
  • The web bulletin board can be visualised as a table with 5 columns - the first (on the left) holds the fully-encrypted votes (also shown on each voter's receipt), and is the only visible column during the vote-casting stage. The second column contains the same set of votes, but with the outer layer removed - teller 2 populates this column and column 3 by decrypting the votes using its private keys during the tallying stage. At the end of the tallying stage, column 5 contains the fully-decrypted votes that can then be tallied.
  • Each voter gets a receipt that links them to an encrypted vote in column 1. This doesn't show how they voted, but allows them to verify that their vote has not been tampered with as throughout the election process they can verify that their encrypted vote is still there in column 1, untouched. This is only half of the "end-to-end verification", of course, since voters are unable to verify that the decryptions have been done correctly, i.e. that there's an entry in column 2 which is their vote minus the outer layer of encryption. Each voter is responsible only for the verification UP TO the point of column 1.
  • Thereafter, it is the auditors' responsibility to check that the entries in column 1 decrypt to column 2, and so on. The way they do this is by relying on deterministic encryption and the public keys used for the encryption being public.
  • Since public keys are public, you don't want people to simply draw lines from column 5 to column 1, joining up someone's vote as it becomes repeatedly encrypted - that way, a receipt that ties you to an encrypted vote actually ties you to an unencrypted, readable vote --> coercion! So, only columns 1, 3 and 5 are public (this is why each teller performs TWO encryptions), and for each entry in column 3, only ONE of the corresponding entries in {2,4} are revealed to auditors. This prevents anyone (even auditors) from linking an encrypted vote to an unencrypted vote.
  • Auditors therefore need to take an entry in column 3, be given the corresponding entry in column 2 and the public key, and perform the same encryption to verify that they do indeed get the entry in column 2.
  • Put together, this offers end-to-end verifiability.

Sorry that was so lengthy - I hope it describes my need for deterministic encryptions. I've missed out a lot of fundamental details (I've modified this scheme heavily) but hopefully the core principles are all there. Thank you so much for reading - I really appreciate it.

解决方案

Removing the padding makes the system insecure. If the public keys are indeed public, as you say, then an attacker can simply go to column 5, take the plaintexts, and encrypt them with the 4 public keys in the proper sequence. They can then match up the resulting ciphertexts with that from the reciepts, compromising the "no coercion" property.

Random padding stops this, because the attacker doesn't know what padding to add.

You will need to use normal padding, but reveal a subset of the private keys to a subset of the auditors (usually called "scrutineers" in electoral systems). This means that one scrutineer can confirm that column 1 matches column 2, another can confirm that column 2 matches column 3, and so on. An individual scrutineer can't match a voter to a ballot, only co-operating ones.


The reason that you're getting the "Message is larger than modulus" error is because each modulus is different, so the ciphertext from one encryption may be outside the allowable range for the next encryption.

这篇关于Java中的确定性RSA加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆