0

I have a RSA Code class without the Java Crypto Library. It works.

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;

public class RSA {

    public static RSAKeyPair generateKeyPair(int keysize) {
        Random rnd = new SecureRandom();
        BigInteger p = new BigInteger(keysize / 2, 100, rnd);
        BigInteger q = new BigInteger(keysize / 2, 100, rnd);
        BigInteger n = p.multiply(q);
        BigInteger phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
        BigInteger e;
        do {
            e = new BigInteger(phi.bitLength(), rnd);
        } while (e.compareTo(BigInteger.ONE) <= 0 || e.compareTo(phi) >= 0 || !e.gcd(phi).equals(BigInteger.ONE));
        BigInteger d = e.modInverse(phi);
        return new RSAKeyPair(new RSAPublicKey(e, n), new RSAPrivateKey(d, n), n);
    }

    public static BigInteger encrypt(BigInteger m, RSAPublicKey key) {
        return m.modPow(key.getPublicExponent(), key.getModulus());
    }

    public static BigInteger decrypt(BigInteger c, RSAPrivateKey key) {
        return c.modPow(key.getPrivateExponent(), key.getModulus());
    }

}

class RSAPublicKey {
    private BigInteger e;
    private BigInteger n;

    public RSAPublicKey(BigInteger e, BigInteger n) {
        this.e = e;
        this.n = n;
    }

    public BigInteger getPublicExponent() {
        return e;
    }

    public BigInteger getModulus() {
        return n;
    }
}

class RSAPrivateKey {
    private BigInteger d;
    private BigInteger n;

    public RSAPrivateKey(BigInteger d, BigInteger n) {
        this.d = d;
        this.n = n;
    }

    public BigInteger getPrivateExponent() {
        return d;
    }

    public BigInteger getModulus() {
        return n;
    }
}

class RSAKeyPair {
    private RSAPublicKey pub;
    private RSAPrivateKey priv;
    private BigInteger modulus;

    public RSAKeyPair(RSAPublicKey pub, RSAPrivateKey priv, BigInteger modulus) {
        this.pub = pub;
        this.priv = priv;
        this.modulus = modulus;
    }

    public RSAPublicKey getPublicKey() {
        return pub;
    }

    public RSAPrivateKey getPrivateKey() {
        return priv;
    }

    public BigInteger getModulus() {
        return modulus;
    }
}

But when i create a Java Library PrivateKey from RSAPrivateKeySpec with a Modulus and Exponent from a RSAPrivateKey from the class and encrypt with the java crypto library a with the class encrypted BigInteger it throws a javax.crypto.BadPaddingException: Decryption error. here:

RSAKeyPair pair = generateKeyPair(1024);
        BigInteger encrypted = encrypt(new BigInteger("123456789"), pair.getPublicKey());
        KeyFactory factory = KeyFactory.getInstance("RSA");
        RSAPrivateKeySpec privSpec = new RSAPrivateKeySpec(pair.getPrivateKey().getModulus(), pair.getPrivateKey().getPrivateExponent());
        PrivateKey priv = factory.generatePrivate(privSpec);
        Cipher cip = Cipher.getInstance("RSA");
        cip.init(Cipher.DECRYPT_MODE, priv);
        System.out.println(new BigInteger(cip.doFinal(encrypted.toByteArray())));

Why?

sorry for my bad english

1 Answer 1

1

Input to Cipher.getInstance() can have two forms:

  • "algorithm/mode/padding" or
  • "algorithm"

When you only specify Cipher.getInstance("RSA"); you get a default padding, and as you encryption did not include a padding, the decrypt fails when trying to remove an expected padding.

Try something like this to get a RSA cipher without padding:

Cipher cip = Cipher.getInstance("rsa/ecb/nopadding");
Sign up to request clarification or add additional context in comments.

1 Comment

And the reason (PKCS1-v1_5 fka type 02) padding is the default is that in most actual uses unpadded RSA is insecure and easily broken -- in addition the OP's method being much slower than necessary. But those aren't programming issues and belong on another Stack.

Your Answer

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