javacryptographyrsasymmetric-key

3DES key exchange with RSA in Java


I'm implementing a WebService in Java in which the server needs to send a 3DES key to the client using the RSA algorithm. The symmetric is generated by the server. Both the server and the client have their own RSA key-pairs, that were previously exchanged.

In this code, the server sends the symmetric key to the client.

@WebMethod
public byte[] getSymmetricKey(){
    try{
        Cipher cipher = Cipher.getInstance("RSA");

        // First, encrypts the symmetric key with the client's public key
        cipher.init(Cipher.ENCRYPT_MODE, this.clientKey);
        byte[] partialCipher = cipher.doFinal(this.key.getBytes());

        // Finally, encrypts the previous result with the server's private key
        cipher.init(Cipher.ENCRYPT_MODE, this.privateKey);
        byte[] cipherData = cipher.doFinal(partialCipher);

        return cipherData;
    }catch (Exception ex){
        ex.printStackTrace();
    }

}

When I run the encryption with the server's private key, I get an error of IllegalBlockSizeException. Why do I get this exception if the padding is activated by default? I've also tried explicitly activate the padding with Cipher.getInstance("RSA/ECB/PKCS1Padding"). Finally, here's the exception output:

    SEVERE: javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes
javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:346)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:391)
    at javax.crypto.Cipher.doFinal(Cipher.java:2087)
    at server.FileTransfererImpl.getSymmetricKey(FileTransfererImpl.java:112)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.reflect.misc.Trampoline.invoke(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.sun.xml.internal.ws.api.server.MethodUtil.invoke(Unknown Source)
    at com.sun.xml.internal.ws.api.server.InstanceResolver$1.invoke(Unknown Source)
    at com.sun.xml.internal.ws.server.InvokerTube$2.invoke(Unknown Source)
    at com.sun.xml.internal.ws.server.sei.EndpointMethodHandler.invoke(Unknown Source)
    at com.sun.xml.internal.ws.server.sei.SEIInvokerTube.processRequest(Unknown Source)
    at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Unknown Source)
    at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Unknown Source)
    at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Unknown Source)
    at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Unknown Source)
    at com.sun.xml.internal.ws.server.WSEndpointImpl$2.process(Unknown Source)
    at com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit.handle(Unknown Source)
    at com.sun.xml.internal.ws.transport.http.HttpAdapter.handle(Unknown Source)
    at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handleExchange(Unknown Source)
    at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handle(Unknown Source)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.AuthFilter.doFilter(Unknown Source)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(Unknown Source)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.ServerImpl$Exchange.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Solution

  • I was researching soem stuff today and found this question. Since it has not been answered, I'll leave this here for future reference.

    According with PKCS #1, the RSAES-PKCS1-V1_5-ENCRYPT algorithm can encrypt up to k - 11 bytes where k is the "size" of the key in bytes. Those 11 bytes are used for "headers".

    If you are using a 2048 bits RSA key, that gives you k = 256 and you can encrypt up to 256 - 11 = 245 bytes of data.

    Check the actual size of this.key.