来自RSAPrivateKeySpec的Java RSA密钥javax.crypto.BadPaddingException:解密错误

时间:2018-04-20 19:16:08

标签: java encryption rsa

我有一个没有Java Crypto Library的RSA Code类。 它有效。

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;
    }
}

但是当我从RSAPrivateKeySpec创建一个Java Library PrivateKey时,来自该类的RSAPrivateKey使用Modulus和Exponent,并使用类加密的BigInteger加密java加密库a,它会抛出javax.crypto.BadPaddingException: Decryption error。 这里:

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())));

为什么?

抱歉我的英文不好

1 个答案:

答案 0 :(得分:1)

Cipher.getInstance()的输入可以有两种形式:

  
      
  • “algorithm / mode / padding”或
  •   
  • “算法”
  •   

如果仅指定Cipher.getInstance("RSA");,则会获得默认填充,并且由于加密不包含填充,因此在尝试删除预期填充时解密将失败。

尝试这样的方法来获得没有填充的RSA密码:

Cipher cip = Cipher.getInstance("rsa/ecb/nopadding");