0N/A/*
2362N/A * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.security.rsa;
0N/A
0N/Aimport java.math.BigInteger;
0N/A
0N/Aimport java.security.*;
0N/Aimport java.security.interfaces.*;
0N/Aimport java.security.spec.*;
0N/A
1111N/Aimport sun.security.action.GetPropertyAction;
1111N/A
0N/A/**
0N/A * KeyFactory for RSA keys. Keys must be instances of PublicKey or PrivateKey
0N/A * and getAlgorithm() must return "RSA". For such keys, it supports conversion
0N/A * between the following:
0N/A *
0N/A * For public keys:
0N/A * . PublicKey with an X.509 encoding
0N/A * . RSAPublicKey
0N/A * . RSAPublicKeySpec
0N/A * . X509EncodedKeySpec
0N/A *
0N/A * For private keys:
0N/A * . PrivateKey with a PKCS#8 encoding
0N/A * . RSAPrivateKey
0N/A * . RSAPrivateCrtKey
0N/A * . RSAPrivateKeySpec
0N/A * . RSAPrivateCrtKeySpec
0N/A * . PKCS8EncodedKeySpec
0N/A * (of course, CRT variants only for CRT keys)
0N/A *
0N/A * Note: as always, RSA keys should be at least 512 bits long
0N/A *
0N/A * @since 1.5
0N/A * @author Andreas Sterbenz
0N/A */
0N/Apublic final class RSAKeyFactory extends KeyFactorySpi {
0N/A
0N/A private final static Class<?> rsaPublicKeySpecClass =
0N/A RSAPublicKeySpec.class;
0N/A private final static Class<?> rsaPrivateKeySpecClass =
0N/A RSAPrivateKeySpec.class;
0N/A private final static Class<?> rsaPrivateCrtKeySpecClass =
0N/A RSAPrivateCrtKeySpec.class;
0N/A
0N/A private final static Class<?> x509KeySpecClass = X509EncodedKeySpec.class;
0N/A private final static Class<?> pkcs8KeySpecClass = PKCS8EncodedKeySpec.class;
0N/A
1111N/A public final static int MIN_MODLEN = 512;
1111N/A public final static int MAX_MODLEN = 16384;
1111N/A
1111N/A /*
1111N/A * If the modulus length is above this value, restrict the size of
1111N/A * the exponent to something that can be reasonably computed. We
1111N/A * could simply hardcode the exp len to something like 64 bits, but
1111N/A * this approach allows flexibility in case impls would like to use
1111N/A * larger module and exponent values.
1111N/A */
1111N/A public final static int MAX_MODLEN_RESTRICT_EXP = 3072;
1111N/A public final static int MAX_RESTRICTED_EXPLEN = 64;
1111N/A
1111N/A private static final boolean restrictExpLen =
1111N/A "true".equalsIgnoreCase(AccessController.doPrivileged(
1111N/A new GetPropertyAction(
1111N/A "sun.security.rsa.restrictRSAExponent", "true")));
1111N/A
0N/A // instance used for static translateKey();
0N/A private final static RSAKeyFactory INSTANCE = new RSAKeyFactory();
0N/A
0N/A public RSAKeyFactory() {
0N/A // empty
0N/A }
0N/A
0N/A /**
1111N/A * Static method to convert Key into an instance of RSAPublicKeyImpl
1111N/A * or RSAPrivate(Crt)KeyImpl. If the key is not an RSA key or cannot be
1111N/A * used, throw an InvalidKeyException.
0N/A *
0N/A * Used by RSASignature and RSACipher.
0N/A */
0N/A public static RSAKey toRSAKey(Key key) throws InvalidKeyException {
1111N/A if ((key instanceof RSAPrivateKeyImpl) ||
1111N/A (key instanceof RSAPrivateCrtKeyImpl) ||
1111N/A (key instanceof RSAPublicKeyImpl)) {
1111N/A return (RSAKey)key;
0N/A } else {
0N/A return (RSAKey)INSTANCE.engineTranslateKey(key);
0N/A }
0N/A }
0N/A
1111N/A /*
1111N/A * Single test entry point for all of the mechanisms in the SunRsaSign
1111N/A * provider (RSA*KeyImpls). All of the tests are the same.
1111N/A *
1111N/A * For compatibility, we round up to the nearest byte here:
1111N/A * some Key impls might pass in a value within a byte of the
1111N/A * real value.
0N/A */
1111N/A static void checkRSAProviderKeyLengths(int modulusLen, BigInteger exponent)
1111N/A throws InvalidKeyException {
1111N/A checkKeyLengths(((modulusLen + 7) & ~7), exponent,
1111N/A RSAKeyFactory.MIN_MODLEN, Integer.MAX_VALUE);
0N/A }
0N/A
0N/A /**
1111N/A * Check the length of an RSA key modulus/exponent to make sure it
1111N/A * is not too short or long. Some impls have their own min and
1111N/A * max key sizes that may or may not match with a system defined value.
1111N/A *
1111N/A * @param modulusLen the bit length of the RSA modulus.
1111N/A * @param exponent the RSA exponent
1111N/A * @param minModulusLen if > 0, check to see if modulusLen is at
1111N/A * least this long, otherwise unused.
1111N/A * @param maxModulusLen caller will allow this max number of bits.
1111N/A * Allow the smaller of the system-defined maximum and this param.
1111N/A *
1111N/A * @throws InvalidKeyException if any of the values are unacceptable.
0N/A */
1111N/A public static void checkKeyLengths(int modulusLen, BigInteger exponent,
1111N/A int minModulusLen, int maxModulusLen) throws InvalidKeyException {
1111N/A
1111N/A if ((minModulusLen > 0) && (modulusLen < (minModulusLen))) {
1111N/A throw new InvalidKeyException( "RSA keys must be at least " +
1111N/A minModulusLen + " bits long");
1111N/A }
1111N/A
1111N/A // Even though our policy file may allow this, we don't want
1111N/A // either value (mod/exp) to be too big.
1111N/A
1111N/A int maxLen = Math.min(maxModulusLen, MAX_MODLEN);
1111N/A
1111N/A // If a RSAPrivateKey/RSAPublicKey, make sure the
1111N/A // modulus len isn't too big.
1111N/A if (modulusLen > maxLen) {
1111N/A throw new InvalidKeyException(
1111N/A "RSA keys must be no longer than " + maxLen + " bits");
1111N/A }
1111N/A
1111N/A // If a RSAPublicKey, make sure the exponent isn't too big.
1111N/A if (restrictExpLen && (exponent != null) &&
1111N/A (modulusLen > MAX_MODLEN_RESTRICT_EXP) &&
1111N/A (exponent.bitLength() > MAX_RESTRICTED_EXPLEN)) {
1111N/A throw new InvalidKeyException(
1111N/A "RSA exponents can be no longer than " +
1111N/A MAX_RESTRICTED_EXPLEN + " bits " +
1111N/A " if modulus is greater than " +
1111N/A MAX_MODLEN_RESTRICT_EXP + " bits");
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Translate an RSA key into a SunRsaSign RSA key. If conversion is
0N/A * not possible, throw an InvalidKeyException.
0N/A * See also JCA doc.
0N/A */
0N/A protected Key engineTranslateKey(Key key) throws InvalidKeyException {
0N/A if (key == null) {
0N/A throw new InvalidKeyException("Key must not be null");
0N/A }
0N/A String keyAlg = key.getAlgorithm();
0N/A if (keyAlg.equals("RSA") == false) {
0N/A throw new InvalidKeyException("Not an RSA key: " + keyAlg);
0N/A }
0N/A if (key instanceof PublicKey) {
0N/A return translatePublicKey((PublicKey)key);
0N/A } else if (key instanceof PrivateKey) {
0N/A return translatePrivateKey((PrivateKey)key);
0N/A } else {
0N/A throw new InvalidKeyException("Neither a public nor a private key");
0N/A }
0N/A }
0N/A
0N/A // see JCA doc
0N/A protected PublicKey engineGeneratePublic(KeySpec keySpec)
0N/A throws InvalidKeySpecException {
0N/A try {
0N/A return generatePublic(keySpec);
0N/A } catch (InvalidKeySpecException e) {
0N/A throw e;
0N/A } catch (GeneralSecurityException e) {
0N/A throw new InvalidKeySpecException(e);
0N/A }
0N/A }
0N/A
0N/A // see JCA doc
0N/A protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
0N/A throws InvalidKeySpecException {
0N/A try {
0N/A return generatePrivate(keySpec);
0N/A } catch (InvalidKeySpecException e) {
0N/A throw e;
0N/A } catch (GeneralSecurityException e) {
0N/A throw new InvalidKeySpecException(e);
0N/A }
0N/A }
0N/A
0N/A // internal implementation of translateKey() for public keys. See JCA doc
0N/A private PublicKey translatePublicKey(PublicKey key)
0N/A throws InvalidKeyException {
0N/A if (key instanceof RSAPublicKey) {
0N/A if (key instanceof RSAPublicKeyImpl) {
0N/A return key;
0N/A }
0N/A RSAPublicKey rsaKey = (RSAPublicKey)key;
0N/A try {
0N/A return new RSAPublicKeyImpl(
0N/A rsaKey.getModulus(),
0N/A rsaKey.getPublicExponent()
0N/A );
0N/A } catch (RuntimeException e) {
0N/A // catch providers that incorrectly implement RSAPublicKey
0N/A throw new InvalidKeyException("Invalid key", e);
0N/A }
0N/A } else if ("X.509".equals(key.getFormat())) {
0N/A byte[] encoded = key.getEncoded();
0N/A return new RSAPublicKeyImpl(encoded);
0N/A } else {
0N/A throw new InvalidKeyException("Public keys must be instance "
0N/A + "of RSAPublicKey or have X.509 encoding");
0N/A }
0N/A }
0N/A
0N/A // internal implementation of translateKey() for private keys. See JCA doc
0N/A private PrivateKey translatePrivateKey(PrivateKey key)
0N/A throws InvalidKeyException {
0N/A if (key instanceof RSAPrivateCrtKey) {
0N/A if (key instanceof RSAPrivateCrtKeyImpl) {
0N/A return key;
0N/A }
0N/A RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key;
0N/A try {
0N/A return new RSAPrivateCrtKeyImpl(
0N/A rsaKey.getModulus(),
0N/A rsaKey.getPublicExponent(),
0N/A rsaKey.getPrivateExponent(),
0N/A rsaKey.getPrimeP(),
0N/A rsaKey.getPrimeQ(),
0N/A rsaKey.getPrimeExponentP(),
0N/A rsaKey.getPrimeExponentQ(),
0N/A rsaKey.getCrtCoefficient()
0N/A );
0N/A } catch (RuntimeException e) {
0N/A // catch providers that incorrectly implement RSAPrivateCrtKey
0N/A throw new InvalidKeyException("Invalid key", e);
0N/A }
0N/A } else if (key instanceof RSAPrivateKey) {
0N/A if (key instanceof RSAPrivateKeyImpl) {
0N/A return key;
0N/A }
0N/A RSAPrivateKey rsaKey = (RSAPrivateKey)key;
0N/A try {
0N/A return new RSAPrivateKeyImpl(
0N/A rsaKey.getModulus(),
0N/A rsaKey.getPrivateExponent()
0N/A );
0N/A } catch (RuntimeException e) {
0N/A // catch providers that incorrectly implement RSAPrivateKey
0N/A throw new InvalidKeyException("Invalid key", e);
0N/A }
0N/A } else if ("PKCS#8".equals(key.getFormat())) {
0N/A byte[] encoded = key.getEncoded();
0N/A return RSAPrivateCrtKeyImpl.newKey(encoded);
0N/A } else {
0N/A throw new InvalidKeyException("Private keys must be instance "
0N/A + "of RSAPrivate(Crt)Key or have PKCS#8 encoding");
0N/A }
0N/A }
0N/A
0N/A // internal implementation of generatePublic. See JCA doc
0N/A private PublicKey generatePublic(KeySpec keySpec)
0N/A throws GeneralSecurityException {
0N/A if (keySpec instanceof X509EncodedKeySpec) {
0N/A X509EncodedKeySpec x509Spec = (X509EncodedKeySpec)keySpec;
0N/A return new RSAPublicKeyImpl(x509Spec.getEncoded());
0N/A } else if (keySpec instanceof RSAPublicKeySpec) {
0N/A RSAPublicKeySpec rsaSpec = (RSAPublicKeySpec)keySpec;
0N/A return new RSAPublicKeyImpl(
0N/A rsaSpec.getModulus(),
0N/A rsaSpec.getPublicExponent()
0N/A );
0N/A } else {
0N/A throw new InvalidKeySpecException("Only RSAPublicKeySpec "
0N/A + "and X509EncodedKeySpec supported for RSA public keys");
0N/A }
0N/A }
0N/A
0N/A // internal implementation of generatePrivate. See JCA doc
0N/A private PrivateKey generatePrivate(KeySpec keySpec)
0N/A throws GeneralSecurityException {
0N/A if (keySpec instanceof PKCS8EncodedKeySpec) {
0N/A PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec)keySpec;
0N/A return RSAPrivateCrtKeyImpl.newKey(pkcsSpec.getEncoded());
0N/A } else if (keySpec instanceof RSAPrivateCrtKeySpec) {
0N/A RSAPrivateCrtKeySpec rsaSpec = (RSAPrivateCrtKeySpec)keySpec;
0N/A return new RSAPrivateCrtKeyImpl(
0N/A rsaSpec.getModulus(),
0N/A rsaSpec.getPublicExponent(),
0N/A rsaSpec.getPrivateExponent(),
0N/A rsaSpec.getPrimeP(),
0N/A rsaSpec.getPrimeQ(),
0N/A rsaSpec.getPrimeExponentP(),
0N/A rsaSpec.getPrimeExponentQ(),
0N/A rsaSpec.getCrtCoefficient()
0N/A );
0N/A } else if (keySpec instanceof RSAPrivateKeySpec) {
0N/A RSAPrivateKeySpec rsaSpec = (RSAPrivateKeySpec)keySpec;
0N/A return new RSAPrivateKeyImpl(
0N/A rsaSpec.getModulus(),
0N/A rsaSpec.getPrivateExponent()
0N/A );
0N/A } else {
0N/A throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "
0N/A + "and PKCS8EncodedKeySpec supported for RSA private keys");
0N/A }
0N/A }
0N/A
0N/A protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
0N/A throws InvalidKeySpecException {
0N/A try {
0N/A // convert key to one of our keys
0N/A // this also verifies that the key is a valid RSA key and ensures
0N/A // that the encoding is X.509/PKCS#8 for public/private keys
0N/A key = engineTranslateKey(key);
0N/A } catch (InvalidKeyException e) {
0N/A throw new InvalidKeySpecException(e);
0N/A }
0N/A if (key instanceof RSAPublicKey) {
0N/A RSAPublicKey rsaKey = (RSAPublicKey)key;
0N/A if (rsaPublicKeySpecClass.isAssignableFrom(keySpec)) {
0N/A return (T) new RSAPublicKeySpec(
0N/A rsaKey.getModulus(),
0N/A rsaKey.getPublicExponent()
0N/A );
0N/A } else if (x509KeySpecClass.isAssignableFrom(keySpec)) {
0N/A return (T) new X509EncodedKeySpec(key.getEncoded());
0N/A } else {
0N/A throw new InvalidKeySpecException
0N/A ("KeySpec must be RSAPublicKeySpec or "
0N/A + "X509EncodedKeySpec for RSA public keys");
0N/A }
0N/A } else if (key instanceof RSAPrivateKey) {
0N/A if (pkcs8KeySpecClass.isAssignableFrom(keySpec)) {
0N/A return (T) new PKCS8EncodedKeySpec(key.getEncoded());
0N/A } else if (rsaPrivateCrtKeySpecClass.isAssignableFrom(keySpec)) {
0N/A if (key instanceof RSAPrivateCrtKey) {
0N/A RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey)key;
0N/A return (T) new RSAPrivateCrtKeySpec(
0N/A crtKey.getModulus(),
0N/A crtKey.getPublicExponent(),
0N/A crtKey.getPrivateExponent(),
0N/A crtKey.getPrimeP(),
0N/A crtKey.getPrimeQ(),
0N/A crtKey.getPrimeExponentP(),
0N/A crtKey.getPrimeExponentQ(),
0N/A crtKey.getCrtCoefficient()
0N/A );
0N/A } else {
0N/A throw new InvalidKeySpecException
0N/A ("RSAPrivateCrtKeySpec can only be used with CRT keys");
0N/A }
0N/A } else if (rsaPrivateKeySpecClass.isAssignableFrom(keySpec)) {
0N/A RSAPrivateKey rsaKey = (RSAPrivateKey)key;
0N/A return (T) new RSAPrivateKeySpec(
0N/A rsaKey.getModulus(),
0N/A rsaKey.getPrivateExponent()
0N/A );
0N/A } else {
0N/A throw new InvalidKeySpecException
0N/A ("KeySpec must be RSAPrivate(Crt)KeySpec or "
0N/A + "PKCS8EncodedKeySpec for RSA private keys");
0N/A }
0N/A } else {
0N/A // should not occur, caught in engineTranslateKey()
0N/A throw new InvalidKeySpecException("Neither public nor private key");
0N/A }
0N/A }
0N/A}