简体   繁体   English

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

[英]Decrypting “long” message encrypted with RSA java

Hi this is the same question, that was asked two years ago: Java/JCE: Decrypting “long” message encrypted with RSA 嗨这是同一个问题,两年前被问过: Java / JCE:解密用RSA加密的“长”消息

I had a large byte array and rsa keypair, initiated by value 1024. Using rsa encryption and the specified size of the key is strong requirement, I can't change it. 我有一个大字节数组和rsa密钥对,由值1024启动。使用rsa加密和密钥的指定大小是强烈要求,我无法更改它。 So I can't use symmetric encryption with asymetric encryption symmetric key. 所以我不能使用非对称加密对称密钥进行对称加密。 I can't use any other keys. 我不能使用任何其他键。 I had a byte array and need ciphered byte array to be returned. 我有一个字节数组,需要返回加密的字节数组。 I wonder if there is any ready tool, that can manage with this problem? 我想知道是否有任何现成的工具,可以解决这个问题?

Sorry for such an amateurish question, but I really need a help. 对不起这样一个业余的问题,但我真的需要帮助。

As stated, your question has a single answer, and that's "no". 如上所述,您的问题只有一个答案,那就是“不”。 RSA encryption is an algorithm which encrypts messages up to a given size, which depends on the key size; RSA加密是一种算法,它对给定大小的消息进行加密,这取决于密钥大小; with a 1024-bit RSA key, and RSA as the standard describes it, the maximum size is 117 bytes, no more. 使用1024位RSA密钥,RSA作为标准描述它,最大大小为117字节,不再多。 There is no way to encrypt a larger message with RSA alone, and that's a definite, mathematical certainty. 单独使用RSA无法加密更大的消息,这是一个明确的数学确定性。

If you really need to process longer messages, then you necessarily have to add something else. 如果您确实需要处理更长的消息,那么您必须添加其他内容。 In that case, please, please , do not try to do anything fancy of your own devising with some oh-so-clever splitting of data into small blocks and the like. 在那种情况下,拜托, 不要尝试用你自己设计的任何东西来做一些非常聪明的数据分成小块等。 That path leads to doom. 那条道路导致厄运。 You might produce something which appears to compile and run, but which will be invariably weak in some way, like almost every other home-made variation on cryptography. 你可能会产生似乎可以编译和运行的东西,但在某种程度上它总是很弱,就像几乎所有其他自制的密码学变体一样。 That's because security cannot be tested: it is not a case of "works" or "does not work". 那是因为无法测试安全性:它不是“工作”或“不工作”的情况。

The well-trodden path of asymmetric encryption goes thus: 因此,非对称加密的良好路径如下:

  1. You select a random sequence of bytes of some appropriate length, eg 128 bits (that's 16 bytes). 您可以选择一些适当长度的随机字节序列,例如128位(即16字节)。 Let's call it K . 我们称之为K.
  2. You encrypt K with the RSA public key; 您使用RSA公钥加密K ; this yields E . 这产生E.
  3. You encrypt the message with K using a symmetric encryption algorithm ( "AES/CBC/PKCS5Padding" ). 您使用对称加密算法( "AES/CBC/PKCS5Padding" )使用K对消息进行加密。 Since this is a one-shot key, you can use an all-zeros IV. 由于这是一次性密钥,因此您可以使用全零IV。 This yields a bunch of bytes, let's call it F . 这会产生一堆字节,我们称之为F.
  4. The encrypted message is then the concatenation of E and F . 然后,加密的消息是EF的串联。

Decryption proceeds in the reverse order: the RSA private key is used to recover K from E , then K is used to decrypt F into the original message. 解密以相反的顺序进行:RSA私钥用于从E恢复K ,然后K用于将F解密为原始消息。 The key K is never stored anywhere, and a new key K is generated every time (even if you encrypt the same message twice). 密钥K永远不会存储在任何地方,每次都会生成一个新密钥K (即使您对同一消息加密两次)。 That's important, do not change that unless you understand what you are doing (and if you do, then you already know that). 这很重要,除非你明白自己在做什么,否则不要改变它(如果你这样做,那么你就已经知道了)。

Given what you state about your problem, you have to do something else than "just RSA". 鉴于你对你的问题的陈述,你必须做的不仅仅是“只是RSA”。 The procedure I describe above is about the best "something else" that you could come up with, security-wise. 我上面描述的程序是关于你可以提出的最好的“其他东西”,安全方面。

Assembling some cryptographic elements into such a protocol is a process fraught with pitfalls so you may have better luck using an already defined format and support library. 将一些加密元素组装到这样的协议中是一个充满陷阱的过程,因此使用已定义的格式和支持库可能会有更好的运气。 Two common formats for asymmetric encryption are CMS and OpenPGP . 非对称加密的两种常见格式是CMSOpenPGP A library which supports both and has good reputation is Bouncy Castle . Bouncy Castle是一个既支持又享有良好声誉的图书馆。

If you do need to encrypt/decrypt long strings using RSA, then you can break the bytes up in to smaller "chunks" and process each chunk of bytes through the cipher one at a time while storing the results in a ByteBuffer. 如果您确实需要使用RSA加密/解密长字符串,那么您可以将字节分解为较小的“块”,并一次一个地通过密码处理每个字节块,同时将结果存储在ByteBuffer中。

Encryption: 加密:

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();

Decryption 解密

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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM