Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/rsa/RSAKeyFactory.java
38830 views
/*1* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.rsa;2627import java.math.BigInteger;2829import java.security.*;30import java.security.interfaces.*;31import java.security.spec.*;3233import sun.security.action.GetPropertyAction;34import sun.security.x509.AlgorithmId;35import static sun.security.rsa.RSAUtil.KeyType;3637/**38* KeyFactory for RSA keys, e.g. "RSA", "RSASSA-PSS".39* Keys must be instances of PublicKey or PrivateKey40* and getAlgorithm() must return a value which matches the type which are41* specified during construction time of the KeyFactory object.42* For such keys, it supports conversion43* between the following:44*45* For public keys:46* . PublicKey with an X.509 encoding47* . RSAPublicKey48* . RSAPublicKeySpec49* . X509EncodedKeySpec50*51* For private keys:52* . PrivateKey with a PKCS#8 encoding53* . RSAPrivateKey54* . RSAPrivateCrtKey55* . RSAPrivateKeySpec56* . RSAPrivateCrtKeySpec57* . PKCS8EncodedKeySpec58* (of course, CRT variants only for CRT keys)59*60* Note: as always, RSA keys should be at least 512 bits long61*62* @since 1.563* @author Andreas Sterbenz64*/65public class RSAKeyFactory extends KeyFactorySpi {6667private static final Class<?> RSA_PUB_KEYSPEC_CLS = RSAPublicKeySpec.class;68private static final Class<?> RSA_PRIV_KEYSPEC_CLS =69RSAPrivateKeySpec.class;70private static final Class<?> RSA_PRIVCRT_KEYSPEC_CLS =71RSAPrivateCrtKeySpec.class;72private static final Class<?> X509_KEYSPEC_CLS = X509EncodedKeySpec.class;73private static final Class<?> PKCS8_KEYSPEC_CLS = PKCS8EncodedKeySpec.class;7475public final static int MIN_MODLEN = 512;76public final static int MAX_MODLEN = 16384;7778private final KeyType type;7980/*81* If the modulus length is above this value, restrict the size of82* the exponent to something that can be reasonably computed. We83* could simply hardcode the exp len to something like 64 bits, but84* this approach allows flexibility in case impls would like to use85* larger module and exponent values.86*/87public final static int MAX_MODLEN_RESTRICT_EXP = 3072;88public final static int MAX_RESTRICTED_EXPLEN = 64;8990private static final boolean restrictExpLen =91"true".equalsIgnoreCase(AccessController.doPrivileged(92new GetPropertyAction(93"sun.security.rsa.restrictRSAExponent", "true")));9495static RSAKeyFactory getInstance(KeyType type) {96return new RSAKeyFactory(type);97}9899// Internal utility method for checking key algorithm100private static void checkKeyAlgo(Key key, String expectedAlg)101throws InvalidKeyException {102String keyAlg = key.getAlgorithm();103if (keyAlg == null || !(keyAlg.equalsIgnoreCase(expectedAlg))) {104throw new InvalidKeyException("Expected a " + expectedAlg105+ " key, but got " + keyAlg);106}107}108109/**110* Static method to convert Key into an instance of RSAPublicKeyImpl111* or RSAPrivate(Crt)KeyImpl. If the key is not an RSA key or cannot be112* used, throw an InvalidKeyException.113*114* Used by RSASignature and RSACipher.115*/116public static RSAKey toRSAKey(Key key) throws InvalidKeyException {117if (key == null) {118throw new InvalidKeyException("Key must not be null");119}120if ((key instanceof RSAPrivateKeyImpl) ||121(key instanceof RSAPrivateCrtKeyImpl) ||122(key instanceof RSAPublicKeyImpl)) {123return (RSAKey)key;124} else {125try {126KeyType type = KeyType.lookup(key.getAlgorithm());127RSAKeyFactory kf = RSAKeyFactory.getInstance(type);128return (RSAKey) kf.engineTranslateKey(key);129} catch (ProviderException e) {130throw new InvalidKeyException(e);131}132}133}134135/*136* Single test entry point for all of the mechanisms in the SunRsaSign137* provider (RSA*KeyImpls). All of the tests are the same.138*139* For compatibility, we round up to the nearest byte here:140* some Key impls might pass in a value within a byte of the141* real value.142*/143static void checkRSAProviderKeyLengths(int modulusLen, BigInteger exponent)144throws InvalidKeyException {145checkKeyLengths(((modulusLen + 7) & ~7), exponent,146RSAKeyFactory.MIN_MODLEN, Integer.MAX_VALUE);147}148149/**150* Check the length of an RSA key modulus/exponent to make sure it151* is not too short or long. Some impls have their own min and152* max key sizes that may or may not match with a system defined value.153*154* @param modulusLen the bit length of the RSA modulus.155* @param exponent the RSA exponent156* @param minModulusLen if > 0, check to see if modulusLen is at157* least this long, otherwise unused.158* @param maxModulusLen caller will allow this max number of bits.159* Allow the smaller of the system-defined maximum and this param.160*161* @throws InvalidKeyException if any of the values are unacceptable.162*/163public static void checkKeyLengths(int modulusLen, BigInteger exponent,164int minModulusLen, int maxModulusLen) throws InvalidKeyException {165166if ((minModulusLen > 0) && (modulusLen < (minModulusLen))) {167throw new InvalidKeyException( "RSA keys must be at least " +168minModulusLen + " bits long");169}170171// Even though our policy file may allow this, we don't want172// either value (mod/exp) to be too big.173174int maxLen = Math.min(maxModulusLen, MAX_MODLEN);175176// If a RSAPrivateKey/RSAPublicKey, make sure the177// modulus len isn't too big.178if (modulusLen > maxLen) {179throw new InvalidKeyException(180"RSA keys must be no longer than " + maxLen + " bits");181}182183// If a RSAPublicKey, make sure the exponent isn't too big.184if (restrictExpLen && (exponent != null) &&185(modulusLen > MAX_MODLEN_RESTRICT_EXP) &&186(exponent.bitLength() > MAX_RESTRICTED_EXPLEN)) {187throw new InvalidKeyException(188"RSA exponents can be no longer than " +189MAX_RESTRICTED_EXPLEN + " bits " +190" if modulus is greater than " +191MAX_MODLEN_RESTRICT_EXP + " bits");192}193}194195// disallowed as KeyType is required196private RSAKeyFactory() {197this.type = KeyType.RSA;198}199200public RSAKeyFactory(KeyType type) {201this.type = type;202}203204/**205* Translate an RSA key into a SunRsaSign RSA key. If conversion is206* not possible, throw an InvalidKeyException.207* See also JCA doc.208*/209protected Key engineTranslateKey(Key key) throws InvalidKeyException {210if (key == null) {211throw new InvalidKeyException("Key must not be null");212}213// ensure the key algorithm matches the current KeyFactory instance214checkKeyAlgo(key, type.keyAlgo());215216// no translation needed if the key is already our own impl217if ((key instanceof RSAPrivateKeyImpl) ||218(key instanceof RSAPrivateCrtKeyImpl) ||219(key instanceof RSAPublicKeyImpl)) {220return key;221}222if (key instanceof PublicKey) {223return translatePublicKey((PublicKey)key);224} else if (key instanceof PrivateKey) {225return translatePrivateKey((PrivateKey)key);226} else {227throw new InvalidKeyException("Neither a public nor a private key");228}229}230231// see JCA doc232protected PublicKey engineGeneratePublic(KeySpec keySpec)233throws InvalidKeySpecException {234try {235return generatePublic(keySpec);236} catch (InvalidKeySpecException e) {237throw e;238} catch (GeneralSecurityException e) {239throw new InvalidKeySpecException(e);240}241}242243// see JCA doc244protected PrivateKey engineGeneratePrivate(KeySpec keySpec)245throws InvalidKeySpecException {246try {247return generatePrivate(keySpec);248} catch (InvalidKeySpecException e) {249throw e;250} catch (GeneralSecurityException e) {251throw new InvalidKeySpecException(e);252}253}254255// internal implementation of translateKey() for public keys. See JCA doc256private PublicKey translatePublicKey(PublicKey key)257throws InvalidKeyException {258if (key instanceof RSAPublicKey) {259RSAPublicKey rsaKey = (RSAPublicKey)key;260try {261return new RSAPublicKeyImpl(262RSAUtil.createAlgorithmId(type, rsaKey.getParams()),263rsaKey.getModulus(),264rsaKey.getPublicExponent());265} catch (ProviderException e) {266// catch providers that incorrectly implement RSAPublicKey267throw new InvalidKeyException("Invalid key", e);268}269} else if ("X.509".equals(key.getFormat())) {270RSAPublicKey translated = new RSAPublicKeyImpl(key.getEncoded());271// ensure the key algorithm matches the current KeyFactory instance272checkKeyAlgo(translated, type.keyAlgo());273return translated;274} else {275throw new InvalidKeyException("Public keys must be instance "276+ "of RSAPublicKey or have X.509 encoding");277}278}279280// internal implementation of translateKey() for private keys. See JCA doc281private PrivateKey translatePrivateKey(PrivateKey key)282throws InvalidKeyException {283if (key instanceof RSAPrivateCrtKey) {284RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key;285try {286return new RSAPrivateCrtKeyImpl(287RSAUtil.createAlgorithmId(type, rsaKey.getParams()),288rsaKey.getModulus(),289rsaKey.getPublicExponent(),290rsaKey.getPrivateExponent(),291rsaKey.getPrimeP(),292rsaKey.getPrimeQ(),293rsaKey.getPrimeExponentP(),294rsaKey.getPrimeExponentQ(),295rsaKey.getCrtCoefficient()296);297} catch (ProviderException e) {298// catch providers that incorrectly implement RSAPrivateCrtKey299throw new InvalidKeyException("Invalid key", e);300}301} else if (key instanceof RSAPrivateKey) {302RSAPrivateKey rsaKey = (RSAPrivateKey)key;303try {304return new RSAPrivateKeyImpl(305RSAUtil.createAlgorithmId(type, rsaKey.getParams()),306rsaKey.getModulus(),307rsaKey.getPrivateExponent()308);309} catch (ProviderException e) {310// catch providers that incorrectly implement RSAPrivateKey311throw new InvalidKeyException("Invalid key", e);312}313} else if ("PKCS#8".equals(key.getFormat())) {314RSAPrivateKey translated =315RSAPrivateCrtKeyImpl.newKey(key.getEncoded());316// ensure the key algorithm matches the current KeyFactory instance317checkKeyAlgo(translated, type.keyAlgo());318return translated;319} else {320throw new InvalidKeyException("Private keys must be instance "321+ "of RSAPrivate(Crt)Key or have PKCS#8 encoding");322}323}324325// internal implementation of generatePublic. See JCA doc326private PublicKey generatePublic(KeySpec keySpec)327throws GeneralSecurityException {328if (keySpec instanceof X509EncodedKeySpec) {329X509EncodedKeySpec x509Spec = (X509EncodedKeySpec)keySpec;330RSAPublicKey generated = new RSAPublicKeyImpl(x509Spec.getEncoded());331// ensure the key algorithm matches the current KeyFactory instance332checkKeyAlgo(generated, type.keyAlgo());333return generated;334} else if (keySpec instanceof RSAPublicKeySpec) {335RSAPublicKeySpec rsaSpec = (RSAPublicKeySpec)keySpec;336try {337return new RSAPublicKeyImpl(338RSAUtil.createAlgorithmId(type, rsaSpec.getParams()),339rsaSpec.getModulus(),340rsaSpec.getPublicExponent()341);342} catch (ProviderException e) {343throw new InvalidKeySpecException(e);344}345} else {346throw new InvalidKeySpecException("Only RSAPublicKeySpec "347+ "and X509EncodedKeySpec supported for RSA public keys");348}349}350351// internal implementation of generatePrivate. See JCA doc352private PrivateKey generatePrivate(KeySpec keySpec)353throws GeneralSecurityException {354if (keySpec instanceof PKCS8EncodedKeySpec) {355PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec)keySpec;356RSAPrivateKey generated = RSAPrivateCrtKeyImpl.newKey(pkcsSpec.getEncoded());357// ensure the key algorithm matches the current KeyFactory instance358checkKeyAlgo(generated, type.keyAlgo());359return generated;360} else if (keySpec instanceof RSAPrivateCrtKeySpec) {361RSAPrivateCrtKeySpec rsaSpec = (RSAPrivateCrtKeySpec)keySpec;362try {363return new RSAPrivateCrtKeyImpl(364RSAUtil.createAlgorithmId(type, rsaSpec.getParams()),365rsaSpec.getModulus(),366rsaSpec.getPublicExponent(),367rsaSpec.getPrivateExponent(),368rsaSpec.getPrimeP(),369rsaSpec.getPrimeQ(),370rsaSpec.getPrimeExponentP(),371rsaSpec.getPrimeExponentQ(),372rsaSpec.getCrtCoefficient()373);374} catch (ProviderException e) {375throw new InvalidKeySpecException(e);376}377} else if (keySpec instanceof RSAPrivateKeySpec) {378RSAPrivateKeySpec rsaSpec = (RSAPrivateKeySpec)keySpec;379try {380return new RSAPrivateKeyImpl(381RSAUtil.createAlgorithmId(type, rsaSpec.getParams()),382rsaSpec.getModulus(),383rsaSpec.getPrivateExponent()384);385} catch (ProviderException e) {386throw new InvalidKeySpecException(e);387}388} else {389throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "390+ "and PKCS8EncodedKeySpec supported for RSA private keys");391}392}393394protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)395throws InvalidKeySpecException {396try {397// convert key to one of our keys398// this also verifies that the key is a valid RSA key and ensures399// that the encoding is X.509/PKCS#8 for public/private keys400key = engineTranslateKey(key);401} catch (InvalidKeyException e) {402throw new InvalidKeySpecException(e);403}404if (key instanceof RSAPublicKey) {405RSAPublicKey rsaKey = (RSAPublicKey)key;406if (RSA_PUB_KEYSPEC_CLS.isAssignableFrom(keySpec)) {407return keySpec.cast(new RSAPublicKeySpec(408rsaKey.getModulus(),409rsaKey.getPublicExponent(),410rsaKey.getParams()411));412} else if (X509_KEYSPEC_CLS.isAssignableFrom(keySpec)) {413return keySpec.cast(new X509EncodedKeySpec(key.getEncoded()));414} else {415throw new InvalidKeySpecException416("KeySpec must be RSAPublicKeySpec or "417+ "X509EncodedKeySpec for RSA public keys");418}419} else if (key instanceof RSAPrivateKey) {420if (PKCS8_KEYSPEC_CLS.isAssignableFrom(keySpec)) {421return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded()));422} else if (RSA_PRIVCRT_KEYSPEC_CLS.isAssignableFrom(keySpec)) {423if (key instanceof RSAPrivateCrtKey) {424RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey)key;425return keySpec.cast(new RSAPrivateCrtKeySpec(426crtKey.getModulus(),427crtKey.getPublicExponent(),428crtKey.getPrivateExponent(),429crtKey.getPrimeP(),430crtKey.getPrimeQ(),431crtKey.getPrimeExponentP(),432crtKey.getPrimeExponentQ(),433crtKey.getCrtCoefficient(),434crtKey.getParams()435));436} else {437throw new InvalidKeySpecException438("RSAPrivateCrtKeySpec can only be used with CRT keys");439}440} else if (RSA_PRIV_KEYSPEC_CLS.isAssignableFrom(keySpec)) {441RSAPrivateKey rsaKey = (RSAPrivateKey)key;442return keySpec.cast(new RSAPrivateKeySpec(443rsaKey.getModulus(),444rsaKey.getPrivateExponent(),445rsaKey.getParams()446));447} else {448throw new InvalidKeySpecException449("KeySpec must be RSAPrivate(Crt)KeySpec or "450+ "PKCS8EncodedKeySpec for RSA private keys");451}452} else {453// should not occur, caught in engineTranslateKey()454throw new InvalidKeySpecException("Neither public nor private key");455}456}457458public static final class Legacy extends RSAKeyFactory {459public Legacy() {460super(KeyType.RSA);461}462}463464public static final class PSS extends RSAKeyFactory {465public PSS() {466super(KeyType.PSS);467}468}469}470471472