3

I'm trying to generate a pair of keys from modulus,public exponent and private exponent to cipher a string and then decipher it, but the deciphered output is different from the input.

public class EncryptDecrypt {
public void encryptDecriptKey(){
    String text = new String("Hello");
    byte[] cipherData = null;
    byte[] cipherData2 = null;
    BigInteger modulus = new BigInteger("E265721199CB82C4080E6E4B87368D01701A1171704629C66BA67DFF1127BB287F9494C8FE80D95D591FEE57D90D96359309AC650E7D0DF39FAAE366C5D5D89F58B4C21FDA80A2792700196FF5AF2635D89DAAF5E622FB84059DE0A4F23DC5F2895917879FC72AA7AF587361D7D3E8578B17BAA92E26D8637D9F8F7556B8FAC1E7A72AB6462EE192CC2ABE81A1E50FEAF9D2967F4DB92DDCA617272ED21A685B8896A9A2D34B24E723693865022B7776D134A041FA7ADFB1BB7B53C7AD891BB3A28E1AE7B399AB3CAC10E55432159A513FB24847129926A344C92DC984F002A97895373B353186E30A9CB33CA3DC7617A4FCBC0BAA1CCBF1E22286F1A9A09D89", 16);
    BigInteger pubExp = new BigInteger("65537", 16);
    BigInteger privateExp = new BigInteger("6274C5AFBBD7926DD8271676483E44022D135924A1341234D55A198F549197C61BFDACDAE03B7ECC26D7491AF12D04771613EDE220F3E79E5C80BFD6511117DCEC81E7AE5CA2F685839D7A728341017807554225204974624CE304F016DD2079C29B792D2522437D9B36F72EC4E2C637542924A73087FA31024FE2DE9FB1607323B8F98020FF0EEFE386DFEB77931C0146B60F757A30397955CF554D86654DD5E9AD600E7982FD59B052DB1014BC186ABE0E0D7250EBDD6BB789DC29DEA9ADCFD12D5713CFAC53FB28035C7F436EEE3519C13DC6516AAA549B07E190F6D4754ED4CF4953EE1773E6E091E93D3C34668FFFC6AA2230A8367DEA9BC348F335B925", 16);

    KeyFactory keyFactory = null;
    RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(modulus, pubExp);
    RSAPublicKey key = null;
    Cipher cipher = null;
    try {
        keyFactory = KeyFactory.getInstance("RSA");
        key = (RSAPublicKey) keyFactory.generatePublic(pubKeySpec);
        cipher = Cipher.getInstance("RSA/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        cipherData = cipher.doFinal(text.getBytes());
    } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeySpecException e) {
        e.printStackTrace();
    }



    KeyFactory keyFactory2 = null;
    RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(modulus, privateExp);
    RSAPrivateKey privatekey = null;
    Cipher cipher2 = null;
    try {
        keyFactory2 = KeyFactory.getInstance("RSA");
        privatekey = (RSAPrivateKey) keyFactory1.generatePrivate(privateKeySpec);
        cipher2 = Cipher.getInstance("RSA/ECB/NoPadding");
        cipher2.init(Cipher.DECRYPT_MODE, privatekey);
        cipherData2 = cipher2.doFinal(cipherData);
    } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeySpecException e) {
        e.printStackTrace();
    }

        System.out.println(Arrays.toString(text.getBytes()));
        System.out.println(Arrays.toString(cipherData2));
        //the two outputs should be equals
}

}

4
  • Raw RSA - indicated by "NoPadding" is insecure. Note that raw RSA uses modular exponentiation. That means that anything larger than the modulus first gets reduced to a value in the range [0, N) where N is the modulus. This could well look as garbage when converted into a string. Commented May 3, 2017 at 23:15
  • Without input, output and (test) key values we cannot debug. Try and create an MCVE. Commented May 3, 2017 at 23:16
  • @MaartenBodewes now it is an MCVE Commented May 3, 2017 at 23:32
  • Related: Restore RSA private key by modulus, public and private exponents using Java Security Commented Sep 25, 2019 at 17:15

1 Answer 1

5

It's because you're reading the exponent as base 16 when it is base 10

BigInteger pubExp = new BigInteger("65537", 16);

This should be:

BigInteger pubExp = new BigInteger("65537", 10);

or

BigInteger pubExp = BigInteger.valueOf(65537);

Furthermore, after this fix, the result is usually left-padded with zero bytes. These need to be removed before comparing the strings.

The reason for that is that RSA operates on numbers. Because no padding method was used this padding cannot be be removed: your original plaintext may also have started with zero valued bytes. So you get back your plaintext padded up to the modulus in size (i.e. the key size).

To fix this last part use a secure padding, e.g. OAEP padding: "RSA/ECB/OAEPWithSHA1AndMGF1Padding" for encryption and decryption.

Sign up to request clarification or add additional context in comments.

5 Comments

I copy pasted forgetting to change the exponent thanks!
Good catch Devon; alexius, I cannot tell from your comment if this solved your issue or not.
Devon, I had another issue to add, I hope you don't mind if I added it to your answer; both are issues and together they will fix the problem.
@MaartenBodewes Thanks, I was actually wondering what the best solution was for that after your comment
@alexsius If this solved your problem, you may accept the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.