javaencryptioncryptographyrsapublic-key-encryption

Java rsa decrypt_mode behavior


I was just experimenting with the following code but I don't understand why the code behaves the way it does:

public class Test
{

    public static void main(String args[]) throws Exception
    {
        CertificateFactory certificateFactory1 = CertificateFactory.getInstance("X.509");
        X509Certificate certificate1 = (X509Certificate)certificateFactory1.generateCertificate(Test.class.getResourceAsStream("pub.cer");      //Loading ssl certificate 
        PublicKey pk1 = certificate1.getPublicKey();
        Cipher cipher1 = Cipher.getInstance("RSA/ECB/NOPADDING");
        cipher1.init(Cipher.ENCRYPT_MODE, pk1);
        bytes[] encrypted = cipher1.doFinal("dummy".getBytes("UTF-8");

        CertificateFactory certificateFactory2 = CertificateFactory.getInstance("X.509");
        X509Certificate certificate2 = (X509Certificate)certificateFactory2.generateCertificate(Test.class.getResourceAsStream("pub.cer");     //Loading ssl certificate
        PublicKey pk2 = certificate2.getPublicKey();
        Cipher cipher2 = Cipher.getInstance("RSA/ECB/NOPADDING");
        cipher2.init(Cipher.DECRYPT_MODE, pk2);
        bytes[] decrypted = cipher2.doFinal(encrypted);
    }
}

Why in byte[] decrypted I'm getting output by doFinal? I'm using jdk1.8.0_192.

Because I'm using public key for decryption and in asymmetric public key cryptography we can encrypt with public key and decrypt with private key.

Can somebody explain that and hopefully back it up with documentation?


Solution

  • If you specify NoPadding then you basically get modular exponentiation. Of course, before that there is a step to convert the binary input to a number, and afterwards the encoding from a number to binary again. Funny enough that's true for both encryption and decryption, as those operations are rather symmetric for RSA.

    The only difference is that you do first use the public key for encryption and the private key for decryption. However, sometimes you have to create your own verification scheme. In that case a raw modular exponentiation with the public key will nicely give you the (commonly padded) result. So then decryption with the public key makes some sense, even if it technically shouldn't be called decryption.

    All in all, if your input is about the right size than just the decoding the input to a number, modular encryption (or decryption) and finally encoding the result will never fail. So you just get an output with the same size as the modulus, i.e. the key size in bytes. It is the unpadding for RSA that may fail. But your code would just run because you don't do any unpadding.

    Of course, if you use the wrong modulus and exponent, the result of the decryption will not make any sense; it will look like a random number between 0 and the modulus used for the last operation.