8242897: KeyFactory.generatePublic( x509Spec ) failed with java.security.InvalidKeyException

Changed SunRsaSign provider to accept RSA signature oid in RSA key encoding for backward compatibility

Reviewed-by: weijun
This commit is contained in:
Valerie Peng 2020-06-03 04:29:04 +00:00
parent 563ce12127
commit 56b7960496
9 changed files with 283 additions and 168 deletions

View file

@ -32,8 +32,7 @@ import java.security.interfaces.*;
import java.security.spec.*; import java.security.spec.*;
import sun.security.action.GetPropertyAction; import sun.security.action.GetPropertyAction;
import sun.security.x509.AlgorithmId; import sun.security.rsa.RSAUtil.KeyType;
import static sun.security.rsa.RSAUtil.KeyType;
/** /**
* KeyFactory for RSA keys, e.g. "RSA", "RSASSA-PSS". * KeyFactory for RSA keys, e.g. "RSA", "RSASSA-PSS".
@ -211,7 +210,7 @@ public class RSAKeyFactory extends KeyFactorySpi {
throw new InvalidKeyException("Key must not be null"); throw new InvalidKeyException("Key must not be null");
} }
// ensure the key algorithm matches the current KeyFactory instance // ensure the key algorithm matches the current KeyFactory instance
checkKeyAlgo(key, type.keyAlgo()); checkKeyAlgo(key, type.keyAlgo);
// no translation needed if the key is already our own impl // no translation needed if the key is already our own impl
if ((key instanceof RSAPrivateKeyImpl) || if ((key instanceof RSAPrivateKeyImpl) ||
@ -259,7 +258,7 @@ public class RSAKeyFactory extends KeyFactorySpi {
RSAPublicKey rsaKey = (RSAPublicKey)key; RSAPublicKey rsaKey = (RSAPublicKey)key;
try { try {
return new RSAPublicKeyImpl( return new RSAPublicKeyImpl(
RSAUtil.createAlgorithmId(type, rsaKey.getParams()), type, rsaKey.getParams(),
rsaKey.getModulus(), rsaKey.getModulus(),
rsaKey.getPublicExponent()); rsaKey.getPublicExponent());
} catch (ProviderException e) { } catch (ProviderException e) {
@ -269,7 +268,7 @@ public class RSAKeyFactory extends KeyFactorySpi {
} else if ("X.509".equals(key.getFormat())) { } else if ("X.509".equals(key.getFormat())) {
RSAPublicKey translated = new RSAPublicKeyImpl(key.getEncoded()); RSAPublicKey translated = new RSAPublicKeyImpl(key.getEncoded());
// ensure the key algorithm matches the current KeyFactory instance // ensure the key algorithm matches the current KeyFactory instance
checkKeyAlgo(translated, type.keyAlgo()); checkKeyAlgo(translated, type.keyAlgo);
return translated; return translated;
} else { } else {
throw new InvalidKeyException("Public keys must be instance " throw new InvalidKeyException("Public keys must be instance "
@ -284,7 +283,7 @@ public class RSAKeyFactory extends KeyFactorySpi {
RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key; RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key;
try { try {
return new RSAPrivateCrtKeyImpl( return new RSAPrivateCrtKeyImpl(
RSAUtil.createAlgorithmId(type, rsaKey.getParams()), type, rsaKey.getParams(),
rsaKey.getModulus(), rsaKey.getModulus(),
rsaKey.getPublicExponent(), rsaKey.getPublicExponent(),
rsaKey.getPrivateExponent(), rsaKey.getPrivateExponent(),
@ -302,7 +301,7 @@ public class RSAKeyFactory extends KeyFactorySpi {
RSAPrivateKey rsaKey = (RSAPrivateKey)key; RSAPrivateKey rsaKey = (RSAPrivateKey)key;
try { try {
return new RSAPrivateKeyImpl( return new RSAPrivateKeyImpl(
RSAUtil.createAlgorithmId(type, rsaKey.getParams()), type, rsaKey.getParams(),
rsaKey.getModulus(), rsaKey.getModulus(),
rsaKey.getPrivateExponent() rsaKey.getPrivateExponent()
); );
@ -314,7 +313,7 @@ public class RSAKeyFactory extends KeyFactorySpi {
RSAPrivateKey translated = RSAPrivateKey translated =
RSAPrivateCrtKeyImpl.newKey(key.getEncoded()); RSAPrivateCrtKeyImpl.newKey(key.getEncoded());
// ensure the key algorithm matches the current KeyFactory instance // ensure the key algorithm matches the current KeyFactory instance
checkKeyAlgo(translated, type.keyAlgo()); checkKeyAlgo(translated, type.keyAlgo);
return translated; return translated;
} else { } else {
throw new InvalidKeyException("Private keys must be instance " throw new InvalidKeyException("Private keys must be instance "
@ -329,13 +328,13 @@ public class RSAKeyFactory extends KeyFactorySpi {
X509EncodedKeySpec x509Spec = (X509EncodedKeySpec)keySpec; X509EncodedKeySpec x509Spec = (X509EncodedKeySpec)keySpec;
RSAPublicKey generated = new RSAPublicKeyImpl(x509Spec.getEncoded()); RSAPublicKey generated = new RSAPublicKeyImpl(x509Spec.getEncoded());
// ensure the key algorithm matches the current KeyFactory instance // ensure the key algorithm matches the current KeyFactory instance
checkKeyAlgo(generated, type.keyAlgo()); checkKeyAlgo(generated, type.keyAlgo);
return generated; return generated;
} else if (keySpec instanceof RSAPublicKeySpec) { } else if (keySpec instanceof RSAPublicKeySpec) {
RSAPublicKeySpec rsaSpec = (RSAPublicKeySpec)keySpec; RSAPublicKeySpec rsaSpec = (RSAPublicKeySpec)keySpec;
try { try {
return new RSAPublicKeyImpl( return new RSAPublicKeyImpl(
RSAUtil.createAlgorithmId(type, rsaSpec.getParams()), type, rsaSpec.getParams(),
rsaSpec.getModulus(), rsaSpec.getModulus(),
rsaSpec.getPublicExponent() rsaSpec.getPublicExponent()
); );
@ -355,13 +354,13 @@ public class RSAKeyFactory extends KeyFactorySpi {
PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec)keySpec; PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec)keySpec;
RSAPrivateKey generated = RSAPrivateCrtKeyImpl.newKey(pkcsSpec.getEncoded()); RSAPrivateKey generated = RSAPrivateCrtKeyImpl.newKey(pkcsSpec.getEncoded());
// ensure the key algorithm matches the current KeyFactory instance // ensure the key algorithm matches the current KeyFactory instance
checkKeyAlgo(generated, type.keyAlgo()); checkKeyAlgo(generated, type.keyAlgo);
return generated; return generated;
} else if (keySpec instanceof RSAPrivateCrtKeySpec) { } else if (keySpec instanceof RSAPrivateCrtKeySpec) {
RSAPrivateCrtKeySpec rsaSpec = (RSAPrivateCrtKeySpec)keySpec; RSAPrivateCrtKeySpec rsaSpec = (RSAPrivateCrtKeySpec)keySpec;
try { try {
return new RSAPrivateCrtKeyImpl( return new RSAPrivateCrtKeyImpl(
RSAUtil.createAlgorithmId(type, rsaSpec.getParams()), type, rsaSpec.getParams(),
rsaSpec.getModulus(), rsaSpec.getModulus(),
rsaSpec.getPublicExponent(), rsaSpec.getPublicExponent(),
rsaSpec.getPrivateExponent(), rsaSpec.getPrivateExponent(),
@ -378,7 +377,7 @@ public class RSAKeyFactory extends KeyFactorySpi {
RSAPrivateKeySpec rsaSpec = (RSAPrivateKeySpec)keySpec; RSAPrivateKeySpec rsaSpec = (RSAPrivateKeySpec)keySpec;
try { try {
return new RSAPrivateKeyImpl( return new RSAPrivateKeyImpl(
RSAUtil.createAlgorithmId(type, rsaSpec.getParams()), type, rsaSpec.getParams(),
rsaSpec.getModulus(), rsaSpec.getModulus(),
rsaSpec.getPrivateExponent() rsaSpec.getPrivateExponent()
); );

View file

@ -32,10 +32,10 @@ import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.RSAKeyGenParameterSpec;
import sun.security.jca.JCAUtil; import sun.security.jca.JCAUtil;
import sun.security.rsa.RSAUtil.KeyType;
import static sun.security.util.SecurityProviderConstants.DEF_RSA_KEY_SIZE; import static sun.security.util.SecurityProviderConstants.DEF_RSA_KEY_SIZE;
import static sun.security.util.SecurityProviderConstants.DEF_RSASSA_PSS_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;
/** /**
* RSA keypair generation. Standard algorithm, minimum key length 512 bit. * RSA keypair generation. Standard algorithm, minimum key length 512 bit.
@ -55,7 +55,7 @@ public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
private int keySize; private int keySize;
private final KeyType type; private final KeyType type;
private AlgorithmId rsaId; private AlgorithmParameterSpec keyParams;
// PRNG to use // PRNG to use
private SecureRandom random; private SecureRandom random;
@ -116,7 +116,7 @@ public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
} }
try { try {
this.rsaId = RSAUtil.createAlgorithmId(type, tmpParams); this.keyParams = RSAUtil.checkParamsAgainstType(type, tmpParams);
} catch (ProviderException e) { } catch (ProviderException e) {
throw new InvalidAlgorithmParameterException( throw new InvalidAlgorithmParameterException(
"Invalid key parameters", e); "Invalid key parameters", e);
@ -177,9 +177,10 @@ public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
BigInteger coeff = q.modInverse(p); BigInteger coeff = q.modInverse(p);
try { try {
PublicKey publicKey = new RSAPublicKeyImpl(rsaId, n, e); PublicKey publicKey = new RSAPublicKeyImpl(type, keyParams,
PrivateKey privateKey = new RSAPrivateCrtKeyImpl( n, e);
rsaId, n, e, d, p, q, pe, qe, coeff); PrivateKey privateKey = new RSAPrivateCrtKeyImpl(type,
keyParams, n, e, d, p, q, pe, qe, coeff);
return new KeyPair(publicKey, privateKey); return new KeyPair(publicKey, privateKey);
} catch (InvalidKeyException exc) { } catch (InvalidKeyException exc) {
// invalid key exception only thrown for keys < 512 bit, // invalid key exception only thrown for keys < 512 bit,

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -34,10 +34,9 @@ import java.security.interfaces.*;
import sun.security.util.*; import sun.security.util.*;
import sun.security.x509.AlgorithmId;
import sun.security.pkcs.PKCS8Key; import sun.security.pkcs.PKCS8Key;
import static sun.security.rsa.RSAUtil.KeyType; import sun.security.rsa.RSAUtil.KeyType;
/** /**
* RSA private key implementation for "RSA", "RSASSA-PSS" algorithms in CRT form. * RSA private key implementation for "RSA", "RSASSA-PSS" algorithms in CRT form.
@ -67,11 +66,12 @@ public final class RSAPrivateCrtKeyImpl
private BigInteger qe; // prime exponent q private BigInteger qe; // prime exponent q
private BigInteger coeff; // CRT coeffcient private BigInteger coeff; // CRT coeffcient
private transient KeyType type;
// Optional parameters associated with this RSA key // Optional parameters associated with this RSA key
// specified in the encoding of its AlgorithmId. // specified in the encoding of its AlgorithmId.
// Must be null for "RSA" keys. // Must be null for "RSA" keys.
@SuppressWarnings("serial") // Not statically typed as Serializable private transient AlgorithmParameterSpec keyParams;
private AlgorithmParameterSpec keyParams;
/** /**
* Generate a new key from its encoding. Returns a CRT key if possible * Generate a new key from its encoding. Returns a CRT key if possible
@ -89,7 +89,7 @@ public final class RSAPrivateCrtKeyImpl
(key.getPrimeQ().signum() == 0) || (key.getPrimeQ().signum() == 0) ||
(key.getCrtCoefficient().signum() == 0)) { (key.getCrtCoefficient().signum() == 0)) {
return new RSAPrivateKeyImpl( return new RSAPrivateKeyImpl(
key.algid, key.type, key.keyParams,
key.getModulus(), key.getModulus(),
key.getPrivateExponent() key.getPrivateExponent()
); );
@ -109,14 +109,13 @@ public final class RSAPrivateCrtKeyImpl
BigInteger p, BigInteger q, BigInteger pe, BigInteger qe, BigInteger p, BigInteger q, BigInteger pe, BigInteger qe,
BigInteger coeff) throws InvalidKeyException { BigInteger coeff) throws InvalidKeyException {
RSAPrivateKey key; RSAPrivateKey key;
AlgorithmId rsaId = RSAUtil.createAlgorithmId(type, params);
if ((e.signum() == 0) || (p.signum() == 0) || if ((e.signum() == 0) || (p.signum() == 0) ||
(q.signum() == 0) || (pe.signum() == 0) || (q.signum() == 0) || (pe.signum() == 0) ||
(qe.signum() == 0) || (coeff.signum() == 0)) { (qe.signum() == 0) || (coeff.signum() == 0)) {
// if any component is missing, return a non-CRT key // if any component is missing, return a non-CRT key
return new RSAPrivateKeyImpl(rsaId, n, d); return new RSAPrivateKeyImpl(type, params, n, d);
} else { } else {
return new RSAPrivateCrtKeyImpl(rsaId, n, e, d, return new RSAPrivateCrtKeyImpl(type, params, n, e, d,
p, q, pe, qe, coeff); p, q, pe, qe, coeff);
} }
} }
@ -132,8 +131,10 @@ public final class RSAPrivateCrtKeyImpl
decode(encoded); decode(encoded);
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e); RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
try { try {
// this will check the validity of params // check the validity of oid and params
this.keyParams = RSAUtil.getParamSpec(algid); Object[] o = RSAUtil.getTypeAndParamSpec(algid);
this.type = (KeyType) o[0];
this.keyParams = (AlgorithmParameterSpec) o[1];
} catch (ProviderException e) { } catch (ProviderException e) {
throw new InvalidKeyException(e); throw new InvalidKeyException(e);
} }
@ -143,7 +144,7 @@ public final class RSAPrivateCrtKeyImpl
* Construct a RSA key from its components. Used by the * Construct a RSA key from its components. Used by the
* RSAKeyFactory and the RSAKeyPairGenerator. * RSAKeyFactory and the RSAKeyPairGenerator.
*/ */
RSAPrivateCrtKeyImpl(AlgorithmId rsaId, RSAPrivateCrtKeyImpl(KeyType type, AlgorithmParameterSpec keyParams,
BigInteger n, BigInteger e, BigInteger d, BigInteger n, BigInteger e, BigInteger d,
BigInteger p, BigInteger q, BigInteger pe, BigInteger qe, BigInteger p, BigInteger q, BigInteger pe, BigInteger qe,
BigInteger coeff) throws InvalidKeyException { BigInteger coeff) throws InvalidKeyException {
@ -157,11 +158,19 @@ public final class RSAPrivateCrtKeyImpl
this.pe = pe; this.pe = pe;
this.qe = qe; this.qe = qe;
this.coeff = coeff; this.coeff = coeff;
this.keyParams = RSAUtil.getParamSpec(rsaId);
// generate the encoding
algid = rsaId;
try { try {
// validate and generate the algid encoding
algid = RSAUtil.createAlgorithmId(type, keyParams);
} catch (ProviderException exc) {
throw new InvalidKeyException(exc);
}
this.type = type;
this.keyParams = keyParams;
try {
// generate the key encoding
DerOutputStream out = new DerOutputStream(); DerOutputStream out = new DerOutputStream();
out.putInteger(0); // version must be 0 out.putInteger(0); // version must be 0
out.putInteger(n); out.putInteger(n);
@ -184,7 +193,7 @@ public final class RSAPrivateCrtKeyImpl
// see JCA doc // see JCA doc
@Override @Override
public String getAlgorithm() { public String getAlgorithm() {
return algid.getName(); return type.keyAlgo;
} }
// see JCA doc // see JCA doc
@ -244,9 +253,9 @@ public final class RSAPrivateCrtKeyImpl
// return a string representation of this key for debugging // return a string representation of this key for debugging
@Override @Override
public String toString() { public String toString() {
return "SunRsaSign " + getAlgorithm() + " private CRT key, " + n.bitLength() return "SunRsaSign " + type.keyAlgo + " private CRT key, "
+ " bits" + "\n params: " + keyParams + "\n modulus: " + n + n.bitLength() + " bits" + "\n params: " + keyParams
+ "\n private exponent: " + d; + "\n modulus: " + n + "\n private exponent: " + d;
} }
/** /**

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -33,9 +33,10 @@ import java.security.spec.AlgorithmParameterSpec;
import java.security.interfaces.*; import java.security.interfaces.*;
import sun.security.util.*; import sun.security.util.*;
import sun.security.x509.AlgorithmId;
import sun.security.pkcs.PKCS8Key; import sun.security.pkcs.PKCS8Key;
import sun.security.rsa.RSAUtil.KeyType;
/** /**
* RSA private key implementation for "RSA", "RSASSA-PSS" algorithms in non-CRT * RSA private key implementation for "RSA", "RSASSA-PSS" algorithms in non-CRT
* form (modulus, private exponent only). For CRT private keys, see * form (modulus, private exponent only). For CRT private keys, see
@ -58,27 +59,37 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey {
private final BigInteger n; // modulus private final BigInteger n; // modulus
private final BigInteger d; // private exponent private final BigInteger d; // private exponent
private transient final KeyType type;
// optional parameters associated with this RSA key // optional parameters associated with this RSA key
// specified in the encoding of its AlgorithmId. // specified in the encoding of its AlgorithmId.
// must be null for "RSA" keys. // must be null for "RSA" keys.
@SuppressWarnings("serial") // Not statically typed as Serializable private transient final AlgorithmParameterSpec keyParams;
private final AlgorithmParameterSpec keyParams;
/** /**
* Construct a key from its components. Used by the * Construct a key from its components. Used by the
* RSAKeyFactory and the RSAKeyPairGenerator. * RSAKeyFactory and the RSAKeyPairGenerator.
*/ */
RSAPrivateKeyImpl(AlgorithmId rsaId, BigInteger n, BigInteger d) RSAPrivateKeyImpl(KeyType type, AlgorithmParameterSpec keyParams,
throws InvalidKeyException { BigInteger n, BigInteger d) throws InvalidKeyException {
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), null); RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), null);
this.n = n; this.n = n;
this.d = d; this.d = d;
this.keyParams = RSAUtil.getParamSpec(rsaId);
// generate the encoding
algid = rsaId;
try { try {
// validate and generate the algid encoding
algid = RSAUtil.createAlgorithmId(type, keyParams);
} catch (ProviderException pe) {
throw new InvalidKeyException(pe);
}
this.type = type;
this.keyParams = keyParams;
try {
// generate the key encoding
DerOutputStream out = new DerOutputStream(); DerOutputStream out = new DerOutputStream();
out.putInteger(0); // version must be 0 out.putInteger(0); // version must be 0
out.putInteger(n); out.putInteger(n);
@ -101,7 +112,7 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey {
// see JCA doc // see JCA doc
@Override @Override
public String getAlgorithm() { public String getAlgorithm() {
return algid.getName(); return type.keyAlgo;
} }
// see JCA doc // see JCA doc
@ -125,7 +136,7 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey {
// return a string representation of this key for debugging // return a string representation of this key for debugging
@Override @Override
public String toString() { public String toString() {
return "Sun " + getAlgorithm() + " private key, " + n.bitLength() return "Sun " + type.keyAlgo + " private key, " + n.bitLength()
+ " bits" + "\n params: " + keyParams + "\n modulus: " + n + " bits" + "\n params: " + keyParams + "\n modulus: " + n
+ "\n private exponent: " + d; + "\n private exponent: " + d;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -34,9 +34,8 @@ import java.security.interfaces.*;
import sun.security.util.*; import sun.security.util.*;
import sun.security.x509.X509Key; import sun.security.x509.X509Key;
import sun.security.x509.AlgorithmId;
import static sun.security.rsa.RSAUtil.KeyType; import sun.security.rsa.RSAUtil.KeyType;
/** /**
* RSA public key implementation for "RSA", "RSASSA-PSS" algorithms. * RSA public key implementation for "RSA", "RSASSA-PSS" algorithms.
@ -59,11 +58,12 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
private BigInteger n; // modulus private BigInteger n; // modulus
private BigInteger e; // public exponent private BigInteger e; // public exponent
private transient KeyType type;
// optional parameters associated with this RSA key // optional parameters associated with this RSA key
// specified in the encoding of its AlgorithmId // specified in the encoding of its AlgorithmId
// must be null for "RSA" keys. // must be null for "RSA" keys.
@SuppressWarnings("serial") // Not statically typed as Serializable private transient AlgorithmParameterSpec keyParams;
private AlgorithmParameterSpec keyParams;
/** /**
* Generate a new RSAPublicKey from the specified encoding. * Generate a new RSAPublicKey from the specified encoding.
@ -81,26 +81,34 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
public static RSAPublicKey newKey(KeyType type, public static RSAPublicKey newKey(KeyType type,
AlgorithmParameterSpec params, BigInteger n, BigInteger e) AlgorithmParameterSpec params, BigInteger n, BigInteger e)
throws InvalidKeyException { throws InvalidKeyException {
AlgorithmId rsaId = RSAUtil.createAlgorithmId(type, params); return new RSAPublicKeyImpl(type, params, n, e);
return new RSAPublicKeyImpl(rsaId, n, e);
} }
/** /**
* Construct a RSA key from AlgorithmId and its components. Used by * Construct a RSA key from the specified type and components. Used by
* RSAKeyFactory and RSAKeyPairGenerator. * RSAKeyFactory and RSAKeyPairGenerator.
*/ */
RSAPublicKeyImpl(AlgorithmId rsaId, BigInteger n, BigInteger e) RSAPublicKeyImpl(KeyType type, AlgorithmParameterSpec keyParams,
throws InvalidKeyException { BigInteger n, BigInteger e) throws InvalidKeyException {
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e); RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
checkExponentRange(n, e); checkExponentRange(n, e);
this.n = n; this.n = n;
this.e = e; this.e = e;
this.keyParams = RSAUtil.getParamSpec(rsaId);
// generate the encoding
algid = rsaId;
try { try {
// validate and generate algid encoding
algid = RSAUtil.createAlgorithmId(type, keyParams);
} catch (ProviderException pe) {
throw new InvalidKeyException(pe);
}
this.type = type;
this.keyParams = keyParams;
try {
// generate the key encoding
DerOutputStream out = new DerOutputStream(); DerOutputStream out = new DerOutputStream();
out.putInteger(n); out.putInteger(n);
out.putInteger(e); out.putInteger(e);
@ -126,8 +134,10 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
checkExponentRange(n, e); checkExponentRange(n, e);
try { try {
// this will check the validity of params // check the validity of oid and params
this.keyParams = RSAUtil.getParamSpec(algid); Object[] o = RSAUtil.getTypeAndParamSpec(algid);
this.type = (KeyType) o[0];
this.keyParams = (AlgorithmParameterSpec) o[1];
} catch (ProviderException e) { } catch (ProviderException e) {
throw new InvalidKeyException(e); throw new InvalidKeyException(e);
} }
@ -150,7 +160,7 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
// see JCA doc // see JCA doc
@Override @Override
public String getAlgorithm() { public String getAlgorithm() {
return algid.getName(); return type.keyAlgo;
} }
// see JCA doc // see JCA doc
@ -195,7 +205,7 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
// return a string representation of this key for debugging // return a string representation of this key for debugging
@Override @Override
public String toString() { public String toString() {
return "Sun " + getAlgorithm() + " public key, " + n.bitLength() return "Sun " + type.keyAlgo + " public key, " + n.bitLength()
+ " bits" + "\n params: " + keyParams + "\n modulus: " + n + " bits" + "\n params: " + keyParams + "\n modulus: " + n
+ "\n public exponent: " + e; + "\n public exponent: " + e;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -40,52 +40,71 @@ import sun.security.x509.AlgorithmId;
public class RSAUtil { public class RSAUtil {
public enum KeyType { public enum KeyType {
RSA ("RSA"), RSA ("RSA", AlgorithmId.RSAEncryption_oid, null),
PSS ("RSASSA-PSS") PSS ("RSASSA-PSS", AlgorithmId.RSASSA_PSS_oid, PSSParameterSpec.class)
; ;
private final String algo; final String keyAlgo;
final ObjectIdentifier oid;
final Class<? extends AlgorithmParameterSpec> paramSpecCls;
KeyType(String keyAlgo) { KeyType(String keyAlgo, ObjectIdentifier oid,
this.algo = keyAlgo; Class<? extends AlgorithmParameterSpec> paramSpecCls) {
this.keyAlgo = keyAlgo;
this.oid = oid;
this.paramSpecCls = paramSpecCls;
} }
public String keyAlgo() {
return algo; public static KeyType lookup(String name) throws ProviderException {
}
public static KeyType lookup(String name) requireNonNull(name, "Key algorithm should not be null");
throws InvalidKeyException, ProviderException {
if (name == null) { // match loosely in order to work with 3rd party providers which
throw new InvalidKeyException("Null key algorithm"); // may not follow the standard names
if (name.indexOf("PSS") != -1) {
return PSS;
} else if (name.indexOf("RSA") != -1) {
return RSA;
} else { // no match
throw new ProviderException("Unsupported algorithm " + name);
} }
for (KeyType kt : KeyType.values()) {
if (kt.keyAlgo().equalsIgnoreCase(name)) {
return kt;
}
}
// no match
throw new ProviderException("Unsupported algorithm " + name);
} }
} }
public static void checkParamsAgainstType(KeyType type, private static void requireNonNull(Object obj, String msg) {
if (obj == null) throw new ProviderException(msg);
}
public static AlgorithmParameterSpec checkParamsAgainstType(KeyType type,
AlgorithmParameterSpec paramSpec) throws ProviderException { AlgorithmParameterSpec paramSpec) throws ProviderException {
switch (type) {
case RSA: // currently no check for null parameter spec
if (paramSpec != null) { // assumption is parameter spec is optional and can be null
throw new ProviderException("null params expected for " + if (paramSpec == null) return null;
type.keyAlgo());
} Class<? extends AlgorithmParameterSpec> expCls = type.paramSpecCls;
break; if (expCls == null) {
case PSS: throw new ProviderException("null params expected for " +
if ((paramSpec != null) && type.keyAlgo);
!(paramSpec instanceof PSSParameterSpec)) { } else if (!expCls.isInstance(paramSpec)) {
throw new ProviderException throw new ProviderException
("PSSParmeterSpec expected for " + type.keyAlgo()); (expCls + " expected for " + type.keyAlgo);
} }
break; return paramSpec;
default: }
throw new ProviderException
("Unsupported RSA algorithm " + type); public static AlgorithmParameters getParams(KeyType type,
AlgorithmParameterSpec spec) throws ProviderException {
if (spec == null) return null;
try {
AlgorithmParameters params =
AlgorithmParameters.getInstance(type.keyAlgo);
params.init(spec);
return params;
} catch (NoSuchAlgorithmException | InvalidParameterSpecException ex) {
throw new ProviderException(ex);
} }
} }
@ -94,69 +113,53 @@ public class RSAUtil {
checkParamsAgainstType(type, paramSpec); checkParamsAgainstType(type, paramSpec);
ObjectIdentifier oid = null; ObjectIdentifier oid = type.oid;
AlgorithmParameters params = null; AlgorithmParameters params = getParams(type, paramSpec);
try { return new AlgorithmId(oid, params);
switch (type) {
case RSA:
oid = AlgorithmId.RSAEncryption_oid;
break;
case PSS:
if (paramSpec != null) {
params = AlgorithmParameters.getInstance(type.keyAlgo());
params.init(paramSpec);
}
oid = AlgorithmId.RSASSA_PSS_oid;
break;
default:
throw new ProviderException
("Unsupported RSA algorithm " + type);
}
AlgorithmId result;
if (params == null) {
result = new AlgorithmId(oid);
} else {
result = new AlgorithmId(oid, params);
}
return result;
} catch (NoSuchAlgorithmException | InvalidParameterSpecException e) {
// should not happen
throw new ProviderException(e);
}
} }
public static AlgorithmParameterSpec getParamSpec(AlgorithmId algid) public static AlgorithmParameterSpec getParamSpec(
throws ProviderException { AlgorithmParameters params) throws ProviderException {
if (algid == null) {
throw new ProviderException("AlgorithmId should not be null");
}
return getParamSpec(algid.getParameters());
}
public static AlgorithmParameterSpec getParamSpec(AlgorithmParameters params)
throws ProviderException {
if (params == null) return null; if (params == null) return null;
String algName = params.getAlgorithm();
KeyType type = KeyType.lookup(algName);
Class<? extends AlgorithmParameterSpec> specCls = type.paramSpecCls;
if (specCls == null) {
throw new ProviderException("No params accepted for " +
type.keyAlgo);
}
try { try {
String algName = params.getAlgorithm();
KeyType type = KeyType.lookup(algName);
Class<? extends AlgorithmParameterSpec> specCls;
switch (type) {
case RSA:
throw new ProviderException("No params accepted for " +
type.keyAlgo());
case PSS:
specCls = PSSParameterSpec.class;
break;
default:
throw new ProviderException("Unsupported RSA algorithm: " + algName);
}
return params.getParameterSpec(specCls); return params.getParameterSpec(specCls);
} catch (ProviderException pe) { } catch (InvalidParameterSpecException ex) {
// pass it up throw new ProviderException(ex);
throw pe;
} catch (Exception e) {
throw new ProviderException(e);
} }
} }
public static Object[] getTypeAndParamSpec(AlgorithmId algid)
throws ProviderException {
requireNonNull(algid, "AlgorithmId should not be null");
Object[] result = new Object[2];
String algName = algid.getName();
try {
result[0] = KeyType.lookup(algName);
} catch (ProviderException pe) {
// accommodate RSA keys encoded with various RSA signature oids
// for backward compatibility
if (algName.indexOf("RSA") != -1) {
result[0] = KeyType.RSA;
} else {
// pass it up
throw pe;
}
}
result[1] = getParamSpec(algid.getParameters());
return result;
}
} }

View file

@ -355,6 +355,11 @@ public enum KnownOIDs {
boolean registerNames() { return false; } boolean registerNames() { return false; }
}, },
OIW_SHA1withRSA_Odd("1.3.14.3.2.15", "SHA1withRSA") {
@Override
boolean registerNames() { return false; }
},
SHA_1("1.3.14.3.2.26", "SHA-1", "SHA", "SHA1"), SHA_1("1.3.14.3.2.26", "SHA-1", "SHA", "SHA1"),
OIW_SHA1withDSA("1.3.14.3.2.27", "SHA1withDSA") { OIW_SHA1withDSA("1.3.14.3.2.27", "SHA1withDSA") {

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8242897
* @summary Ensure that RSA key factory can parse X.509 encodings containing
* non-standard RSA oid as in older JDK releases before JDK-8146293
* @run main TestRSAOidSupport
*/
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
public class TestRSAOidSupport {
// SubjectKeyInfo DER encoding w/ Algorithm id 1.3.14.3.2.15
// which can be used to generate RSA Public Key before PSS
// support is added
private static String DER_BYTES =
"3058300906052b0e03020f0500034b003048024100d7157c65e8f22557d8" +
"a857122cfe85bddfaba3064c21b345e2a7cdd8a6751e519ab861c5109fb8" +
"8cce45d161b9817bc0eccdc30fda69e62cc577775f2c1d66bd0203010001";
// utility method for converting hex string to byte array
static byte[] toByteArray(String s) {
byte[] bytes = new byte[s.length() / 2];
for (int i = 0; i < bytes.length; i++) {
int index = i * 2;
int v = Integer.parseInt(s.substring(index, index + 2), 16);
bytes[i] = (byte) v;
}
return bytes;
}
public static void main(String[] args) throws Exception {
X509EncodedKeySpec x509Spec = new X509EncodedKeySpec
(toByteArray(DER_BYTES));
String keyAlgo = "RSA";
KeyFactory kf = KeyFactory.getInstance(keyAlgo, "SunRsaSign");
RSAPublicKey rsaKey = (RSAPublicKey) kf.generatePublic(x509Spec);
if (rsaKey.getAlgorithm() != keyAlgo) {
throw new RuntimeException("Key algo should be " + keyAlgo +
", but got " + rsaKey.getAlgorithm());
}
kf = KeyFactory.getInstance("RSASSA-PSS", "SunRsaSign");
try {
kf.generatePublic(x509Spec);
throw new RuntimeException("Should throw IKSE");
} catch (InvalidKeySpecException ikse) {
System.out.println("Expected IKSE exception thrown");
}
}
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -29,8 +29,7 @@ import java.security.*;
import java.security.spec.AlgorithmParameterSpec; import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.RSAKeyGenParameterSpec;
import sun.security.x509.AlgorithmId; import sun.security.rsa.RSAUtil.KeyType;
import static sun.security.rsa.RSAUtil.KeyType;
/** /**
* A fake RSA keypair generation. * A fake RSA keypair generation.
@ -44,7 +43,7 @@ public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
private int keySize; private int keySize;
private final KeyType type; private final KeyType type;
private AlgorithmId rsaId; private AlgorithmParameterSpec keyParams;
RSAKeyPairGenerator(KeyType type, int defKeySize) { RSAKeyPairGenerator(KeyType type, int defKeySize) {
this.type = type; this.type = type;
@ -98,7 +97,7 @@ public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
} }
try { try {
this.rsaId = RSAUtil.createAlgorithmId(type, tmpParams); this.keyParams = RSAUtil.checkParamsAgainstType(type, tmpParams);
} catch (ProviderException e) { } catch (ProviderException e) {
throw new InvalidAlgorithmParameterException( throw new InvalidAlgorithmParameterException(
"Invalid key parameters", e); "Invalid key parameters", e);
@ -436,9 +435,9 @@ public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
BigInteger coeff = q.modInverse(p); BigInteger coeff = q.modInverse(p);
try { try {
PublicKey publicKey = new RSAPublicKeyImpl(rsaId, n, e); PublicKey publicKey = new RSAPublicKeyImpl(type, keyParams, n, e);
PrivateKey privateKey = new RSAPrivateCrtKeyImpl( PrivateKey privateKey = new RSAPrivateCrtKeyImpl(
rsaId, n, e, d, p, q, pe, qe, coeff); type, keyParams, n, e, d, p, q, pe, qe, coeff);
return new KeyPair(publicKey, privateKey); return new KeyPair(publicKey, privateKey);
} catch (InvalidKeyException exc) { } catch (InvalidKeyException exc) {
// invalid key exception only thrown for keys < 512 bit, // invalid key exception only thrown for keys < 512 bit,