Decrypting “long” message encrypted with RSA java
Asked Answered
W

2

6

Hi this is the same question, that was asked two years ago: Java/JCE: Decrypting “long” message encrypted with 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. 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.

Wayfarer answered 16/4, 2010 at 14:19 Comment(0)
S
15

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; with a 1024-bit RSA key, and RSA as the standard describes it, the maximum size is 117 bytes, no more. There is no way to encrypt a larger message with RSA alone, and that's a definite, mathematical certainty.

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, e.g. 128 bits (that's 16 bytes). Let's call it K.
  2. You encrypt K with the RSA public key; this yields E.
  3. You encrypt the message with K using a symmetric encryption algorithm ("AES/CBC/PKCS5Padding"). Since this is a one-shot key, you can use an all-zeros IV. This yields a bunch of bytes, let's call it F.
  4. The encrypted message is then the concatenation of E and F.

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. The key K is never stored anywhere, and a new key K is generated every time (even if you encrypt the same message twice). 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". 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. A library which supports both and has good reputation is Bouncy Castle.

Selfacting answered 16/4, 2010 at 15:54 Comment(7)
Good answer. Nothing more to add.Intangible
Its a pity, that I can't change the specification.Wayfarer
It might just be a matter of how you interpret the specification. If it just says "The data should be encrypted using a 1024 bit RSA key", then Thomas' answer is the standard way to do this, so I would argue that it is completely in agreement with the spec.Rileyrilievo
-1. It is well known that this encryption mode is not secure. It is susceptible to a chosen ciphertext attack. Either use OAEP padding rather than the old PKCS#1 padding or better use some authentication.Floorage
Also Bouncy Castle isn't that great either. It still has significant unpatched flaws in it implementation of RSA.Floorage
If it is "well known" that PKCS#1 v1.5 padding is "insecure" and "susceptible to a chosen ciphertext attack", then maybe you could provide a reference supporting that assertion ?Selfacting
The very same paragraph in which PKCS#1 (2.0) talks about the Bleichenbacher attack on the v1.5 padding also states that there are a few countermeasures which are very effective in thwarting the attack, without changing a single bit in the padding or encryption process (and that's what any decent SSL implementation does, by the way). The v1.5 padding is not insecure; what is insecure is non-binary error reporting on failed operation. The same kind of attack actually applies to OAEP, see: citeseerx.ist.psu.edu/viewdoc/…Selfacting
H
3

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.

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();
Heterozygous answered 18/5, 2014 at 15:15 Comment(2)
One should never do such a chunked RSA encryption/decryption. It is error prone, insecure and horribly slow for longer messages.Cloudless
A lot of messages here say what not to do. It would be nice to at least mention what to look for. Right now I look for some information how to do things. What I know now is RSA is for encrypting key of symetric algorithm, AES for example.Brianabriand

© 2022 - 2024 — McMap. All rights reserved.