|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.rsa; |
|
|
|
import java.math.BigInteger; |
|
|
|
import java.security.*; |
|
import java.security.spec.AlgorithmParameterSpec; |
|
import java.security.spec.RSAKeyGenParameterSpec; |
|
|
|
import sun.security.jca.JCAUtil; |
|
import static sun.security.util.SecurityProviderConstants.DEF_RSA_KEY_SIZE; |
|
import static sun.security.util.SecurityProviderConstants.DEF_RSASSA_PSS_KEY_SIZE; |
|
import sun.security.x509.AlgorithmId; |
|
import static sun.security.rsa.RSAUtil.KeyType; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi { |
|
|
|
|
|
private BigInteger publicExponent; |
|
|
|
|
|
private int keySize; |
|
|
|
private final KeyType type; |
|
private AlgorithmId rsaId; |
|
|
|
|
|
private SecureRandom random; |
|
|
|
RSAKeyPairGenerator(KeyType type, int defKeySize) { |
|
this.type = type; |
|
|
|
initialize(defKeySize, null); |
|
} |
|
|
|
|
|
public void initialize(int keySize, SecureRandom random) { |
|
try { |
|
initialize(new RSAKeyGenParameterSpec(keySize, |
|
RSAKeyGenParameterSpec.F4), null); |
|
} catch (InvalidAlgorithmParameterException iape) { |
|
throw new InvalidParameterException(iape.getMessage()); |
|
} |
|
} |
|
|
|
|
|
public void initialize(AlgorithmParameterSpec params, SecureRandom random) |
|
throws InvalidAlgorithmParameterException { |
|
if (params instanceof RSAKeyGenParameterSpec == false) { |
|
throw new InvalidAlgorithmParameterException |
|
("Params must be instance of RSAKeyGenParameterSpec"); |
|
} |
|
|
|
RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params; |
|
int tmpKeySize = rsaSpec.getKeysize(); |
|
BigInteger tmpPublicExponent = rsaSpec.getPublicExponent(); |
|
AlgorithmParameterSpec tmpParams = rsaSpec.getKeyParams(); |
|
|
|
if (tmpPublicExponent == null) { |
|
tmpPublicExponent = RSAKeyGenParameterSpec.F4; |
|
} else { |
|
if (tmpPublicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) { |
|
throw new InvalidAlgorithmParameterException |
|
("Public exponent must be 3 or larger"); |
|
} |
|
if (tmpPublicExponent.bitLength() > tmpKeySize) { |
|
throw new InvalidAlgorithmParameterException |
|
("Public exponent must be smaller than key size"); |
|
} |
|
} |
|
|
|
|
|
try { |
|
RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPublicExponent, |
|
512, 64 * 1024); |
|
} catch (InvalidKeyException e) { |
|
throw new InvalidAlgorithmParameterException( |
|
"Invalid key sizes", e); |
|
} |
|
|
|
try { |
|
this.rsaId = RSAUtil.createAlgorithmId(type, tmpParams); |
|
} catch (ProviderException e) { |
|
throw new InvalidAlgorithmParameterException( |
|
"Invalid key parameters", e); |
|
} |
|
|
|
this.keySize = tmpKeySize; |
|
this.publicExponent = tmpPublicExponent; |
|
this.random = random; |
|
} |
|
|
|
|
|
public KeyPair generateKeyPair() { |
|
|
|
int lp = (keySize + 1) >> 1; |
|
int lq = keySize - lp; |
|
if (random == null) { |
|
random = JCAUtil.getSecureRandom(); |
|
} |
|
BigInteger e = publicExponent; |
|
while (true) { |
|
|
|
BigInteger p = BigInteger.probablePrime(lp, random); |
|
BigInteger q, n; |
|
do { |
|
q = BigInteger.probablePrime(lq, random); |
|
|
|
if (p.compareTo(q) < 0) { |
|
BigInteger tmp = p; |
|
p = q; |
|
q = tmp; |
|
} |
|
|
|
n = p.multiply(q); |
|
// even with correctly sized p and q, there is a chance that |
|
// n will be one bit short. re-generate the smaller prime if so |
|
} while (n.bitLength() < keySize); |
|
|
|
// phi = (p - 1) * (q - 1) must be relative prime to e |
|
|
|
BigInteger p1 = p.subtract(BigInteger.ONE); |
|
BigInteger q1 = q.subtract(BigInteger.ONE); |
|
BigInteger phi = p1.multiply(q1); |
|
// generate new p and q until they work. typically |
|
|
|
if (e.gcd(phi).equals(BigInteger.ONE) == false) { |
|
continue; |
|
} |
|
|
|
|
|
BigInteger d = e.modInverse(phi); |
|
|
|
|
|
BigInteger pe = d.mod(p1); |
|
|
|
BigInteger qe = d.mod(q1); |
|
|
|
|
|
BigInteger coeff = q.modInverse(p); |
|
|
|
try { |
|
PublicKey publicKey = new RSAPublicKeyImpl(rsaId, n, e); |
|
PrivateKey privateKey = new RSAPrivateCrtKeyImpl( |
|
rsaId, n, e, d, p, q, pe, qe, coeff); |
|
return new KeyPair(publicKey, privateKey); |
|
} catch (InvalidKeyException exc) { |
|
// invalid key exception only thrown for keys < 512 bit, |
|
|
|
throw new RuntimeException(exc); |
|
} |
|
} |
|
} |
|
|
|
public static final class Legacy extends RSAKeyPairGenerator { |
|
public Legacy() { |
|
super(KeyType.RSA, DEF_RSA_KEY_SIZE); |
|
} |
|
} |
|
|
|
public static final class PSS extends RSAKeyPairGenerator { |
|
public PSS() { |
|
super(KeyType.PSS, DEF_RSASSA_PSS_KEY_SIZE); |
|
} |
|
} |
|
} |