Path: blob/master/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java
41159 views
/*1* Copyright (c) 2003, 2021, 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.*;32import java.util.Arrays;3334import sun.security.action.GetPropertyAction;35import 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* . RSA PublicKey with an X.509 encoding47* . RSA PublicKey with an PKCS#1 encoding48* . RSAPublicKey49* . RSAPublicKeySpec50* . X509EncodedKeySpec51*52* For private keys:53* . RSA PrivateKey with a PKCS#8 encoding54* . RSA PrivateKey with a PKCS#1 encoding55* . RSAPrivateKey56* . RSAPrivateCrtKey57* . RSAPrivateKeySpec58* . RSAPrivateCrtKeySpec59* . PKCS8EncodedKeySpec60* (of course, CRT variants only for CRT keys)61*62* Note: as always, RSA keys should be at least 512 bits long63*64* @since 1.565* @author Andreas Sterbenz66*/67public class RSAKeyFactory extends KeyFactorySpi {6869private static final Class<?> RSA_PUB_KEYSPEC_CLS = RSAPublicKeySpec.class;70private static final Class<?> RSA_PRIV_KEYSPEC_CLS =71RSAPrivateKeySpec.class;72private static final Class<?> RSA_PRIVCRT_KEYSPEC_CLS =73RSAPrivateCrtKeySpec.class;74private static final Class<?> X509_KEYSPEC_CLS = X509EncodedKeySpec.class;75private static final Class<?> PKCS8_KEYSPEC_CLS = PKCS8EncodedKeySpec.class;7677public static final int MIN_MODLEN = 512;78public static final int MAX_MODLEN = 16384;7980private final KeyType type;8182/*83* If the modulus length is above this value, restrict the size of84* the exponent to something that can be reasonably computed. We85* could simply hardcode the exp len to something like 64 bits, but86* this approach allows flexibility in case impls would like to use87* larger module and exponent values.88*/89public static final int MAX_MODLEN_RESTRICT_EXP = 3072;90public static final int MAX_RESTRICTED_EXPLEN = 64;9192private static final boolean restrictExpLen =93"true".equalsIgnoreCase(GetPropertyAction.privilegedGetProperty(94"sun.security.rsa.restrictRSAExponent", "true"));9596static RSAKeyFactory getInstance(KeyType type) {97return new RSAKeyFactory(type);98}99100// pkg-private utility method for checking key algorithm101static void checkKeyAlgo(Key key, String expectedAlg)102throws InvalidKeyException {103String keyAlg = key.getAlgorithm();104if (keyAlg == null || !(keyAlg.equalsIgnoreCase(expectedAlg))) {105throw new InvalidKeyException("Expected a " + expectedAlg106+ " key, but got " + keyAlg);107}108}109110/**111* Static method to convert Key into an instance of RSAPublicKeyImpl112* or RSAPrivate(Crt)KeyImpl. If the key is not an RSA key or cannot be113* used, throw an InvalidKeyException.114*115* Used by RSASignature and RSACipher.116*/117public static RSAKey toRSAKey(Key key) throws InvalidKeyException {118if (key == null) {119throw new InvalidKeyException("Key must not be null");120}121if ((key instanceof RSAPrivateKeyImpl) ||122(key instanceof RSAPrivateCrtKeyImpl) ||123(key instanceof RSAPublicKeyImpl)) {124return (RSAKey)key;125} else {126try {127KeyType type = KeyType.lookup(key.getAlgorithm());128RSAKeyFactory kf = RSAKeyFactory.getInstance(type);129return (RSAKey) kf.engineTranslateKey(key);130} catch (ProviderException e) {131throw new InvalidKeyException(e);132}133}134}135136/*137* Single test entry point for all of the mechanisms in the SunRsaSign138* provider (RSA*KeyImpls). All of the tests are the same.139*140* For compatibility, we round up to the nearest byte here:141* some Key impls might pass in a value within a byte of the142* real value.143*/144static void checkRSAProviderKeyLengths(int modulusLen, BigInteger exponent)145throws InvalidKeyException {146checkKeyLengths(((modulusLen + 7) & ~7), exponent,147RSAKeyFactory.MIN_MODLEN, Integer.MAX_VALUE);148}149150/**151* Check the length of an RSA key modulus/exponent to make sure it152* is not too short or long. Some impls have their own min and153* max key sizes that may or may not match with a system defined value.154*155* @param modulusLen the bit length of the RSA modulus.156* @param exponent the RSA exponent157* @param minModulusLen if {@literal > 0}, check to see if modulusLen is at158* least this long, otherwise unused.159* @param maxModulusLen caller will allow this max number of bits.160* Allow the smaller of the system-defined maximum and this param.161*162* @throws InvalidKeyException if any of the values are unacceptable.163*/164public static void checkKeyLengths(int modulusLen, BigInteger exponent,165int minModulusLen, int maxModulusLen) throws InvalidKeyException {166167if ((minModulusLen > 0) && (modulusLen < (minModulusLen))) {168throw new InvalidKeyException( "RSA keys must be at least " +169minModulusLen + " bits long");170}171172// Even though our policy file may allow this, we don't want173// either value (mod/exp) to be too big.174175int maxLen = Math.min(maxModulusLen, MAX_MODLEN);176177// If a RSAPrivateKey/RSAPublicKey, make sure the178// modulus len isn't too big.179if (modulusLen > maxLen) {180throw new InvalidKeyException(181"RSA keys must be no longer than " + maxLen + " bits");182}183184// If a RSAPublicKey, make sure the exponent isn't too big.185if (restrictExpLen && (exponent != null) &&186(modulusLen > MAX_MODLEN_RESTRICT_EXP) &&187(exponent.bitLength() > MAX_RESTRICTED_EXPLEN)) {188throw new InvalidKeyException(189"RSA exponents can be no longer than " +190MAX_RESTRICTED_EXPLEN + " bits " +191" if modulus is greater than " +192MAX_MODLEN_RESTRICT_EXP + " bits");193}194}195196// disallowed as KeyType is required197private RSAKeyFactory() {198this.type = KeyType.RSA;199}200201public RSAKeyFactory(KeyType type) {202this.type = type;203}204205/**206* Translate an RSA key into a SunRsaSign RSA key. If conversion is207* not possible, throw an InvalidKeyException.208* See also JCA doc.209*/210protected Key engineTranslateKey(Key key) throws InvalidKeyException {211if (key == null) {212throw new InvalidKeyException("Key must not be null");213}214// ensure the key algorithm matches the current KeyFactory instance215checkKeyAlgo(key, type.keyAlgo);216217// no translation needed if the key is already our own impl218if ((key instanceof RSAPrivateKeyImpl) ||219(key instanceof RSAPrivateCrtKeyImpl) ||220(key instanceof RSAPublicKeyImpl)) {221return key;222}223if (key instanceof PublicKey) {224return translatePublicKey((PublicKey)key);225} else if (key instanceof PrivateKey) {226return translatePrivateKey((PrivateKey)key);227} else {228throw new InvalidKeyException("Neither a public nor a private key");229}230}231232// see JCA doc233protected PublicKey engineGeneratePublic(KeySpec keySpec)234throws InvalidKeySpecException {235try {236return generatePublic(keySpec);237} catch (InvalidKeySpecException e) {238throw e;239} catch (GeneralSecurityException e) {240throw new InvalidKeySpecException(e);241}242}243244// see JCA doc245protected PrivateKey engineGeneratePrivate(KeySpec keySpec)246throws InvalidKeySpecException {247try {248return generatePrivate(keySpec);249} catch (InvalidKeySpecException e) {250throw e;251} catch (GeneralSecurityException e) {252throw new InvalidKeySpecException(e);253}254}255256// internal implementation of translateKey() for public keys. See JCA doc257private PublicKey translatePublicKey(PublicKey key)258throws InvalidKeyException {259if (key instanceof RSAPublicKey) {260RSAPublicKey rsaKey = (RSAPublicKey)key;261try {262return new RSAPublicKeyImpl(263type, rsaKey.getParams(),264rsaKey.getModulus(),265rsaKey.getPublicExponent());266} catch (ProviderException e) {267// catch providers that incorrectly implement RSAPublicKey268throw new InvalidKeyException("Invalid key", e);269}270} else {271// create new key based on the format and encoding of current 'key'272return RSAPublicKeyImpl.newKey(type, key.getFormat(),273key.getEncoded());274}275}276277// internal implementation of translateKey() for private keys. See JCA doc278private PrivateKey translatePrivateKey(PrivateKey key)279throws InvalidKeyException {280if (key instanceof RSAPrivateCrtKey) {281RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key;282try {283return new RSAPrivateCrtKeyImpl(284type, rsaKey.getParams(),285rsaKey.getModulus(),286rsaKey.getPublicExponent(),287rsaKey.getPrivateExponent(),288rsaKey.getPrimeP(),289rsaKey.getPrimeQ(),290rsaKey.getPrimeExponentP(),291rsaKey.getPrimeExponentQ(),292rsaKey.getCrtCoefficient()293);294} catch (ProviderException e) {295// catch providers that incorrectly implement RSAPrivateCrtKey296throw new InvalidKeyException("Invalid key", e);297}298} else if (key instanceof RSAPrivateKey) {299RSAPrivateKey rsaKey = (RSAPrivateKey)key;300try {301return new RSAPrivateKeyImpl(302type, rsaKey.getParams(),303rsaKey.getModulus(),304rsaKey.getPrivateExponent()305);306} catch (ProviderException e) {307// catch providers that incorrectly implement RSAPrivateKey308throw new InvalidKeyException("Invalid key", e);309}310} else {311byte[] encoded = key.getEncoded();312try {313return RSAPrivateCrtKeyImpl.newKey(type, key.getFormat(), encoded);314} finally {315if (encoded != null) {316Arrays.fill(encoded, (byte)0);317}318}319}320}321322// internal implementation of generatePublic. See JCA doc323private PublicKey generatePublic(KeySpec keySpec)324throws GeneralSecurityException {325if (keySpec instanceof X509EncodedKeySpec) {326return RSAPublicKeyImpl.newKey(type, "X.509",327((X509EncodedKeySpec)keySpec).getEncoded());328} else if (keySpec instanceof RSAPublicKeySpec) {329RSAPublicKeySpec rsaSpec = (RSAPublicKeySpec)keySpec;330try {331return new RSAPublicKeyImpl(332type, rsaSpec.getParams(),333rsaSpec.getModulus(),334rsaSpec.getPublicExponent()335);336} catch (ProviderException e) {337throw new InvalidKeySpecException(e);338}339} else {340throw new InvalidKeySpecException("Only RSAPublicKeySpec "341+ "and X509EncodedKeySpec supported for RSA public keys");342}343}344345// internal implementation of generatePrivate. See JCA doc346private PrivateKey generatePrivate(KeySpec keySpec)347throws GeneralSecurityException {348if (keySpec instanceof PKCS8EncodedKeySpec) {349byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();350try {351return RSAPrivateCrtKeyImpl.newKey(type, "PKCS#8", encoded);352} finally {353Arrays.fill(encoded, (byte)0);354}355} else if (keySpec instanceof RSAPrivateCrtKeySpec) {356RSAPrivateCrtKeySpec rsaSpec = (RSAPrivateCrtKeySpec)keySpec;357try {358return new RSAPrivateCrtKeyImpl(359type, rsaSpec.getParams(),360rsaSpec.getModulus(),361rsaSpec.getPublicExponent(),362rsaSpec.getPrivateExponent(),363rsaSpec.getPrimeP(),364rsaSpec.getPrimeQ(),365rsaSpec.getPrimeExponentP(),366rsaSpec.getPrimeExponentQ(),367rsaSpec.getCrtCoefficient()368);369} catch (ProviderException e) {370throw new InvalidKeySpecException(e);371}372} else if (keySpec instanceof RSAPrivateKeySpec) {373RSAPrivateKeySpec rsaSpec = (RSAPrivateKeySpec)keySpec;374try {375return new RSAPrivateKeyImpl(376type, rsaSpec.getParams(),377rsaSpec.getModulus(),378rsaSpec.getPrivateExponent()379);380} catch (ProviderException e) {381throw new InvalidKeySpecException(e);382}383} else {384throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "385+ "and PKCS8EncodedKeySpec supported for RSA private keys");386}387}388389protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)390throws InvalidKeySpecException {391try {392// convert key to one of our keys393// this also verifies that the key is a valid RSA key and ensures394// that the encoding is X.509/PKCS#8 or PKCS#1 for public/private395// keys396key = engineTranslateKey(key);397} catch (InvalidKeyException e) {398throw new InvalidKeySpecException(e);399}400if (key instanceof RSAPublicKey) {401RSAPublicKey rsaKey = (RSAPublicKey)key;402if (keySpec.isAssignableFrom(RSA_PUB_KEYSPEC_CLS)) {403return keySpec.cast(new RSAPublicKeySpec(404rsaKey.getModulus(),405rsaKey.getPublicExponent(),406rsaKey.getParams()407));408} else if (keySpec.isAssignableFrom(X509_KEYSPEC_CLS)) {409return keySpec.cast(new X509EncodedKeySpec(key.getEncoded()));410} else {411throw new InvalidKeySpecException412("KeySpec must be RSAPublicKeySpec or "413+ "X509EncodedKeySpec for RSA public keys");414}415} else if (key instanceof RSAPrivateKey) {416if (keySpec.isAssignableFrom(PKCS8_KEYSPEC_CLS)) {417byte[] encoded = key.getEncoded();418try {419return keySpec.cast(new PKCS8EncodedKeySpec(encoded));420} finally {421Arrays.fill(encoded, (byte)0);422}423} else if (keySpec.isAssignableFrom(RSA_PRIVCRT_KEYSPEC_CLS)) {424// All supported keyspecs (other than PKCS8_KEYSPEC_CLS) descend from RSA_PRIVCRT_KEYSPEC_CLS425if (key instanceof RSAPrivateCrtKey) {426RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey)key;427return keySpec.cast(new RSAPrivateCrtKeySpec(428crtKey.getModulus(),429crtKey.getPublicExponent(),430crtKey.getPrivateExponent(),431crtKey.getPrimeP(),432crtKey.getPrimeQ(),433crtKey.getPrimeExponentP(),434crtKey.getPrimeExponentQ(),435crtKey.getCrtCoefficient(),436crtKey.getParams()437));438} else { // RSAPrivateKey (non-CRT)439if (!keySpec.isAssignableFrom(RSA_PRIV_KEYSPEC_CLS)) {440throw new InvalidKeySpecException441("RSAPrivateCrtKeySpec can only be used with CRT keys");442}443444// fall through to RSAPrivateKey (non-CRT)445RSAPrivateKey rsaKey = (RSAPrivateKey) key;446return keySpec.cast(new RSAPrivateKeySpec(447rsaKey.getModulus(),448rsaKey.getPrivateExponent(),449rsaKey.getParams()450));451}452} else {453throw new InvalidKeySpecException454("KeySpec must be RSAPrivate(Crt)KeySpec or "455+ "PKCS8EncodedKeySpec for RSA private keys");456}457} else {458// should not occur, caught in engineTranslateKey()459throw new InvalidKeySpecException("Neither public nor private key");460}461}462463public static final class Legacy extends RSAKeyFactory {464public Legacy() {465super(KeyType.RSA);466}467}468469public static final class PSS extends RSAKeyFactory {470public PSS() {471super(KeyType.PSS);472}473}474}475476477