解密用RSA java加密的“长”消息

嗨这是同一个问题,两年前被问过: Java / JCE:解密用RSA加密的“长”消息

我有一个大字节数组和rsa密钥对,由值1024启动。使用rsa加密和密钥的指定大小是强烈要求,我无法更改它。 所以我不能使用非对称加密对称密钥进行对称加密。 我不能使用任何其他键。 我有一个字节数组,需要返回加密的字节数组。 我想知道是否有任何现成的工具可以解决这个问题?

抱歉这样一个业余的问题,但我真的需要帮助。

如上所述,您的问题只有一个答案,那就是“不”。 RSA加密是一种算法,它对给定大小的消息进行加密,这取决于密钥大小; 使用1024位RSA密钥,RSA作为标准描述它,最大大小为117字节,不再多。 单独使用RSA无法加密更大的消息,这是一个明确的数学确定性。

如果您确实需要处理更长的消息,那么您必须添加其他内容。 在这种情况下,拜托, 不要尝试用你自己设计的任何东西来做一些非常聪明的数据分割成小块等等。 那条道路导致厄运。 你可能会产生一些似乎可以编译和运行的东西,但是在某些方面它总是很弱,就像几乎所有其他自制的密码学变体一样。 那是因为无法测试安全性:它不是“工作”或“不工作”的情况。

因此,非对称加密的良好路径如下:

  1. 您可以选择一些适当长度的随机字节序列,例如128位(即16字节)。 我们称之为K.
  2. 您使用RSA公钥加密K ; 这产生E.
  3. 您使用对称加密算法( "AES/CBC/PKCS5Padding" )使用K对消息进行加密。 由于这是一次性密钥,因此您可以使用全零IV。 这会产生一堆字节,我们称之为F.
  4. 然后,加密的消息是EF的串联。

解密以相反的顺序进行:RSA私钥用于从E恢复K ,然后K用于将F解密为原始消息。 密钥K永远不会存储在任何地方,每次都会生成一个新密钥K (即使您将相同的消息加密两次)。 这很重要,除非你明白自己在做什么,否则不要改变它(如果你这样做,那么你就已经知道了)。

鉴于你对你的问题的陈述,你必须做的不仅仅是“只是RSA”。 我上面描述的程序是关于你可以提出的最好的“其他东西”,安全方面。

将一些加密元素组装到这样的协议中是一个充满陷阱的过程,因此您可以使用已定义的格式和支持库获得更好的运气。 非对称加密的两种常见格式是CMS和OpenPGP 。 Bouncy Castle是一个既支持又享有良好声誉的图书馆。

如果您确实需要使用RSA加密/解密长字符串,那么您可以将字节分解为更小的“块”,并一次一个地通过密码处理每个字节块,同时将结果存储在ByteBuffer中。

加密:

 byte[] encData = null; try { // create public key X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(key); KeyFactory kf = KeyFactory.getInstance("RSA"); PublicKey pk = kf.generatePublic(publicKeySpec); Cipher pkCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); pkCipher.init(Cipher.ENCRYPT_MODE, pk); int chunkSize = 117; // 1024 / 8 - 11(padding) = 117 int encSize = (int) (Math.ceil(data.length/117.0)*128); int idx = 0; ByteBuffer buf = ByteBuffer.allocate(encSize); while (idx < data.length) { int len = Math.min(data.length-idx, chunkSize); byte[] encChunk = pkCipher.doFinal(data, idx, len); buf.put(encChunk); idx += len; } // fully encrypted data encData = buf.array(); } catch (Exception e) { e.printStackTrace(); 

解密

 Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); rsaCipher.init(Cipher.DECRYPT_MODE, rsaPk); int chunkSize = 128; int idx = 0; ByteBuffer buf = ByteBuffer.allocate(data.length); while(idx < data.length) { int len = Math.min(data.length-idx, chunkSize); byte[] chunk = rsaCipher.doFinal(data, idx, len); buf.put(chunk); idx += len; } // fully decrypted data byte[] decryptedData = buf.array();