8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,456 @@
/*
* Copyright (c) 2003, 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.rsa;
import java.math.BigInteger;
import java.util.*;
import java.security.SecureRandom;
import java.security.interfaces.*;
import javax.crypto.BadPaddingException;
import sun.security.jca.JCAUtil;
/**
* Core of the RSA implementation. Has code to perform public and private key
* RSA operations (with and without CRT for private key ops). Private CRT ops
* also support blinding to twart timing attacks.
*
* The code in this class only does the core RSA operation. Padding and
* unpadding must be done externally.
*
* Note: RSA keys should be at least 512 bits long
*
* @since 1.5
* @author Andreas Sterbenz
*/
public final class RSACore {
// globally enable/disable use of blinding
private static final boolean ENABLE_BLINDING = true;
// cache for blinding parameters. Map<BigInteger, BlindingParameters>
// use a weak hashmap so that cached values are automatically cleared
// when the modulus is GC'ed
private static final Map<BigInteger, BlindingParameters>
blindingCache = new WeakHashMap<>();
private RSACore() {
// empty
}
/**
* Return the number of bytes required to store the magnitude byte[] of
* this BigInteger. Do not count a 0x00 byte toByteArray() would
* prefix for 2's complement form.
*/
public static int getByteLength(BigInteger b) {
int n = b.bitLength();
return (n + 7) >> 3;
}
/**
* Return the number of bytes required to store the modulus of this
* RSA key.
*/
public static int getByteLength(RSAKey key) {
return getByteLength(key.getModulus());
}
// temporary, used by RSACipher and RSAPadding. Move this somewhere else
public static byte[] convert(byte[] b, int ofs, int len) {
if ((ofs == 0) && (len == b.length)) {
return b;
} else {
byte[] t = new byte[len];
System.arraycopy(b, ofs, t, 0, len);
return t;
}
}
/**
* Perform an RSA public key operation.
*/
public static byte[] rsa(byte[] msg, RSAPublicKey key)
throws BadPaddingException {
return crypt(msg, key.getModulus(), key.getPublicExponent());
}
/**
* Perform an RSA private key operation. Uses CRT if the key is a
* CRT key with additional verification check after the signature
* is computed.
*/
@Deprecated
public static byte[] rsa(byte[] msg, RSAPrivateKey key)
throws BadPaddingException {
return rsa(msg, key, true);
}
/**
* Perform an RSA private key operation. Uses CRT if the key is a
* CRT key. Set 'verify' to true if this function is used for
* generating a signature.
*/
public static byte[] rsa(byte[] msg, RSAPrivateKey key, boolean verify)
throws BadPaddingException {
if (key instanceof RSAPrivateCrtKey) {
return crtCrypt(msg, (RSAPrivateCrtKey)key, verify);
} else {
return priCrypt(msg, key.getModulus(), key.getPrivateExponent());
}
}
/**
* RSA public key ops. Simple modPow().
*/
private static byte[] crypt(byte[] msg, BigInteger n, BigInteger exp)
throws BadPaddingException {
BigInteger m = parseMsg(msg, n);
BigInteger c = m.modPow(exp, n);
return toByteArray(c, getByteLength(n));
}
/**
* RSA non-CRT private key operations.
*/
private static byte[] priCrypt(byte[] msg, BigInteger n, BigInteger exp)
throws BadPaddingException {
BigInteger c = parseMsg(msg, n);
BlindingRandomPair brp = null;
BigInteger m;
if (ENABLE_BLINDING) {
brp = getBlindingRandomPair(null, exp, n);
c = c.multiply(brp.u).mod(n);
m = c.modPow(exp, n);
m = m.multiply(brp.v).mod(n);
} else {
m = c.modPow(exp, n);
}
return toByteArray(m, getByteLength(n));
}
/**
* RSA private key operations with CRT. Algorithm and variable naming
* are taken from PKCS#1 v2.1, section 5.1.2.
*/
private static byte[] crtCrypt(byte[] msg, RSAPrivateCrtKey key,
boolean verify) throws BadPaddingException {
BigInteger n = key.getModulus();
BigInteger c0 = parseMsg(msg, n);
BigInteger c = c0;
BigInteger p = key.getPrimeP();
BigInteger q = key.getPrimeQ();
BigInteger dP = key.getPrimeExponentP();
BigInteger dQ = key.getPrimeExponentQ();
BigInteger qInv = key.getCrtCoefficient();
BigInteger e = key.getPublicExponent();
BigInteger d = key.getPrivateExponent();
BlindingRandomPair brp;
if (ENABLE_BLINDING) {
brp = getBlindingRandomPair(e, d, n);
c = c.multiply(brp.u).mod(n);
}
// m1 = c ^ dP mod p
BigInteger m1 = c.modPow(dP, p);
// m2 = c ^ dQ mod q
BigInteger m2 = c.modPow(dQ, q);
// h = (m1 - m2) * qInv mod p
BigInteger mtmp = m1.subtract(m2);
if (mtmp.signum() < 0) {
mtmp = mtmp.add(p);
}
BigInteger h = mtmp.multiply(qInv).mod(p);
// m = m2 + q * h
BigInteger m = h.multiply(q).add(m2);
if (ENABLE_BLINDING) {
m = m.multiply(brp.v).mod(n);
}
if (verify && !c0.equals(m.modPow(e, n))) {
throw new BadPaddingException("RSA private key operation failed");
}
return toByteArray(m, getByteLength(n));
}
/**
* Parse the msg into a BigInteger and check against the modulus n.
*/
private static BigInteger parseMsg(byte[] msg, BigInteger n)
throws BadPaddingException {
BigInteger m = new BigInteger(1, msg);
if (m.compareTo(n) >= 0) {
throw new BadPaddingException("Message is larger than modulus");
}
return m;
}
/**
* Return the encoding of this BigInteger that is exactly len bytes long.
* Prefix/strip off leading 0x00 bytes if necessary.
* Precondition: bi must fit into len bytes
*/
private static byte[] toByteArray(BigInteger bi, int len) {
byte[] b = bi.toByteArray();
int n = b.length;
if (n == len) {
return b;
}
// BigInteger prefixed a 0x00 byte for 2's complement form, remove it
if ((n == len + 1) && (b[0] == 0)) {
byte[] t = new byte[len];
System.arraycopy(b, 1, t, 0, len);
return t;
}
// must be smaller
assert (n < len);
byte[] t = new byte[len];
System.arraycopy(b, 0, t, (len - n), n);
return t;
}
/**
* Parameters (u,v) for RSA Blinding. This is described in the RSA
* Bulletin#2 (Jan 96) and other places:
*
* ftp://ftp.rsa.com/pub/pdfs/bull-2.pdf
*
* The standard RSA Blinding decryption requires the public key exponent
* (e) and modulus (n), and converts ciphertext (c) to plaintext (p).
*
* Before the modular exponentiation operation, the input message should
* be multiplied by (u (mod n)), and afterward the result is corrected
* by multiplying with (v (mod n)). The system should reject messages
* equal to (0 (mod n)). That is:
*
* 1. Generate r between 0 and n-1, relatively prime to n.
* 2. Compute x = (c*u) mod n
* 3. Compute y = (x^d) mod n
* 4. Compute p = (y*v) mod n
*
* The Java APIs allows for either standard RSAPrivateKey or
* RSAPrivateCrtKey RSA keys.
*
* If the public exponent is available to us (e.g. RSAPrivateCrtKey),
* choose a random r, then let (u, v):
*
* u = r ^ e mod n
* v = r ^ (-1) mod n
*
* The proof follows:
*
* p = (((c * u) ^ d mod n) * v) mod n
* = ((c ^ d) * (u ^ d) * v) mod n
* = ((c ^ d) * (r ^ e) ^ d) * (r ^ (-1))) mod n
* = ((c ^ d) * (r ^ (e * d)) * (r ^ (-1))) mod n
* = ((c ^ d) * (r ^ 1) * (r ^ (-1))) mod n (see below)
* = (c ^ d) mod n
*
* because in RSA cryptosystem, d is the multiplicative inverse of e:
*
* (r^(e * d)) mod n
* = (r ^ 1) mod n
* = r mod n
*
* However, if the public exponent is not available (e.g. RSAPrivateKey),
* we mitigate the timing issue by using a similar random number blinding
* approach using the private key:
*
* u = r
* v = ((r ^ (-1)) ^ d) mod n
*
* This returns the same plaintext because:
*
* p = (((c * u) ^ d mod n) * v) mod n
* = ((c ^ d) * (u ^ d) * v) mod n
* = ((c ^ d) * (u ^ d) * ((u ^ (-1)) ^d)) mod n
* = (c ^ d) mod n
*
* Computing inverses mod n and random number generation is slow, so
* it is often not practical to generate a new random (u, v) pair for
* each new exponentiation. The calculation of parameters might even be
* subject to timing attacks. However, (u, v) pairs should not be
* reused since they themselves might be compromised by timing attacks,
* leaving the private exponent vulnerable. An efficient solution to
* this problem is update u and v before each modular exponentiation
* step by computing:
*
* u = u ^ 2
* v = v ^ 2
*
* The total performance cost is small.
*/
private static final class BlindingRandomPair {
final BigInteger u;
final BigInteger v;
BlindingRandomPair(BigInteger u, BigInteger v) {
this.u = u;
this.v = v;
}
}
/**
* Set of blinding parameters for a given RSA key.
*
* The RSA modulus is usually unique, so we index by modulus in
* {@code blindingCache}. However, to protect against the unlikely
* case of two keys sharing the same modulus, we also store the public
* or the private exponent. This means we cannot cache blinding
* parameters for multiple keys that share the same modulus, but
* since sharing moduli is fundamentally broken and insecure, this
* does not matter.
*/
private static final class BlindingParameters {
private static final BigInteger BIG_TWO = BigInteger.valueOf(2L);
// RSA public exponent
private final BigInteger e;
// hash code of RSA private exponent
private final BigInteger d;
// r ^ e mod n (CRT), or r mod n (Non-CRT)
private BigInteger u;
// r ^ (-1) mod n (CRT) , or ((r ^ (-1)) ^ d) mod n (Non-CRT)
private BigInteger v;
// e: the public exponent
// d: the private exponent
// n: the modulus
BlindingParameters(BigInteger e, BigInteger d, BigInteger n) {
this.u = null;
this.v = null;
this.e = e;
this.d = d;
int len = n.bitLength();
SecureRandom random = JCAUtil.getSecureRandom();
u = new BigInteger(len, random).mod(n);
// Although the possibility is very much limited that u is zero
// or is not relatively prime to n, we still want to be careful
// about the special value.
//
// Secure random generation is expensive, try to use BigInteger.ONE
// this time if this new generated random number is zero or is not
// relatively prime to n. Next time, new generated secure random
// number will be used instead.
if (u.equals(BigInteger.ZERO)) {
u = BigInteger.ONE; // use 1 this time
}
try {
// The call to BigInteger.modInverse() checks that u is
// relatively prime to n. Otherwise, ArithmeticException is
// thrown.
v = u.modInverse(n);
} catch (ArithmeticException ae) {
// if u is not relatively prime to n, use 1 this time
u = BigInteger.ONE;
v = BigInteger.ONE;
}
if (e != null) {
u = u.modPow(e, n); // e: the public exponent
// u: random ^ e
// v: random ^ (-1)
} else {
v = v.modPow(d, n); // d: the private exponent
// u: random
// v: random ^ (-d)
}
}
// return null if need to reset the parameters
BlindingRandomPair getBlindingRandomPair(
BigInteger e, BigInteger d, BigInteger n) {
if ((this.e != null && this.e.equals(e)) ||
(this.d != null && this.d.equals(d))) {
BlindingRandomPair brp = null;
synchronized (this) {
if (!u.equals(BigInteger.ZERO) &&
!v.equals(BigInteger.ZERO)) {
brp = new BlindingRandomPair(u, v);
if (u.compareTo(BigInteger.ONE) <= 0 ||
v.compareTo(BigInteger.ONE) <= 0) {
// need to reset the random pair next time
u = BigInteger.ZERO;
v = BigInteger.ZERO;
} else {
u = u.modPow(BIG_TWO, n);
v = v.modPow(BIG_TWO, n);
}
} // Otherwise, need to reset the random pair.
}
return brp;
}
return null;
}
}
private static BlindingRandomPair getBlindingRandomPair(
BigInteger e, BigInteger d, BigInteger n) {
BlindingParameters bps = null;
synchronized (blindingCache) {
bps = blindingCache.get(n);
}
if (bps == null) {
bps = new BlindingParameters(e, d, n);
synchronized (blindingCache) {
blindingCache.putIfAbsent(n, bps);
}
}
BlindingRandomPair brp = bps.getBlindingRandomPair(e, d, n);
if (brp == null) {
// need to reset the blinding parameters
bps = new BlindingParameters(e, d, n);
synchronized (blindingCache) {
blindingCache.replace(n, bps);
}
brp = bps.getBlindingRandomPair(e, d, n);
}
return brp;
}
}

View file

@ -0,0 +1,400 @@
/*
* Copyright (c) 2003, 2011, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.rsa;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import sun.security.action.GetPropertyAction;
/**
* KeyFactory for RSA keys. Keys must be instances of PublicKey or PrivateKey
* and getAlgorithm() must return "RSA". For such keys, it supports conversion
* between the following:
*
* For public keys:
* . PublicKey with an X.509 encoding
* . RSAPublicKey
* . RSAPublicKeySpec
* . X509EncodedKeySpec
*
* For private keys:
* . PrivateKey with a PKCS#8 encoding
* . RSAPrivateKey
* . RSAPrivateCrtKey
* . RSAPrivateKeySpec
* . RSAPrivateCrtKeySpec
* . PKCS8EncodedKeySpec
* (of course, CRT variants only for CRT keys)
*
* Note: as always, RSA keys should be at least 512 bits long
*
* @since 1.5
* @author Andreas Sterbenz
*/
public final class RSAKeyFactory extends KeyFactorySpi {
private static final Class<?> rsaPublicKeySpecClass =
RSAPublicKeySpec.class;
private static final Class<?> rsaPrivateKeySpecClass =
RSAPrivateKeySpec.class;
private static final Class<?> rsaPrivateCrtKeySpecClass =
RSAPrivateCrtKeySpec.class;
private static final Class<?> x509KeySpecClass = X509EncodedKeySpec.class;
private static final Class<?> pkcs8KeySpecClass = PKCS8EncodedKeySpec.class;
public static final int MIN_MODLEN = 512;
public static final int MAX_MODLEN = 16384;
/*
* If the modulus length is above this value, restrict the size of
* the exponent to something that can be reasonably computed. We
* could simply hardcode the exp len to something like 64 bits, but
* this approach allows flexibility in case impls would like to use
* larger module and exponent values.
*/
public static final int MAX_MODLEN_RESTRICT_EXP = 3072;
public static final int MAX_RESTRICTED_EXPLEN = 64;
private static final boolean restrictExpLen =
"true".equalsIgnoreCase(GetPropertyAction.privilegedGetProperty(
"sun.security.rsa.restrictRSAExponent", "true"));
// instance used for static translateKey();
private static final RSAKeyFactory INSTANCE = new RSAKeyFactory();
public RSAKeyFactory() {
// empty
}
/**
* Static method to convert Key into an instance of RSAPublicKeyImpl
* or RSAPrivate(Crt)KeyImpl. If the key is not an RSA key or cannot be
* used, throw an InvalidKeyException.
*
* Used by RSASignature and RSACipher.
*/
public static RSAKey toRSAKey(Key key) throws InvalidKeyException {
if ((key instanceof RSAPrivateKeyImpl) ||
(key instanceof RSAPrivateCrtKeyImpl) ||
(key instanceof RSAPublicKeyImpl)) {
return (RSAKey)key;
} else {
return (RSAKey)INSTANCE.engineTranslateKey(key);
}
}
/*
* Single test entry point for all of the mechanisms in the SunRsaSign
* provider (RSA*KeyImpls). All of the tests are the same.
*
* For compatibility, we round up to the nearest byte here:
* some Key impls might pass in a value within a byte of the
* real value.
*/
static void checkRSAProviderKeyLengths(int modulusLen, BigInteger exponent)
throws InvalidKeyException {
checkKeyLengths(((modulusLen + 7) & ~7), exponent,
RSAKeyFactory.MIN_MODLEN, Integer.MAX_VALUE);
}
/**
* Check the length of an RSA key modulus/exponent to make sure it
* is not too short or long. Some impls have their own min and
* max key sizes that may or may not match with a system defined value.
*
* @param modulusLen the bit length of the RSA modulus.
* @param exponent the RSA exponent
* @param minModulusLen if {@literal > 0}, check to see if modulusLen is at
* least this long, otherwise unused.
* @param maxModulusLen caller will allow this max number of bits.
* Allow the smaller of the system-defined maximum and this param.
*
* @throws InvalidKeyException if any of the values are unacceptable.
*/
public static void checkKeyLengths(int modulusLen, BigInteger exponent,
int minModulusLen, int maxModulusLen) throws InvalidKeyException {
if ((minModulusLen > 0) && (modulusLen < (minModulusLen))) {
throw new InvalidKeyException( "RSA keys must be at least " +
minModulusLen + " bits long");
}
// Even though our policy file may allow this, we don't want
// either value (mod/exp) to be too big.
int maxLen = Math.min(maxModulusLen, MAX_MODLEN);
// If a RSAPrivateKey/RSAPublicKey, make sure the
// modulus len isn't too big.
if (modulusLen > maxLen) {
throw new InvalidKeyException(
"RSA keys must be no longer than " + maxLen + " bits");
}
// If a RSAPublicKey, make sure the exponent isn't too big.
if (restrictExpLen && (exponent != null) &&
(modulusLen > MAX_MODLEN_RESTRICT_EXP) &&
(exponent.bitLength() > MAX_RESTRICTED_EXPLEN)) {
throw new InvalidKeyException(
"RSA exponents can be no longer than " +
MAX_RESTRICTED_EXPLEN + " bits " +
" if modulus is greater than " +
MAX_MODLEN_RESTRICT_EXP + " bits");
}
}
/**
* Translate an RSA key into a SunRsaSign RSA key. If conversion is
* not possible, throw an InvalidKeyException.
* See also JCA doc.
*/
protected Key engineTranslateKey(Key key) throws InvalidKeyException {
if (key == null) {
throw new InvalidKeyException("Key must not be null");
}
String keyAlg = key.getAlgorithm();
if (keyAlg.equals("RSA") == false) {
throw new InvalidKeyException("Not an RSA key: " + keyAlg);
}
if (key instanceof PublicKey) {
return translatePublicKey((PublicKey)key);
} else if (key instanceof PrivateKey) {
return translatePrivateKey((PrivateKey)key);
} else {
throw new InvalidKeyException("Neither a public nor a private key");
}
}
// see JCA doc
protected PublicKey engineGeneratePublic(KeySpec keySpec)
throws InvalidKeySpecException {
try {
return generatePublic(keySpec);
} catch (InvalidKeySpecException e) {
throw e;
} catch (GeneralSecurityException e) {
throw new InvalidKeySpecException(e);
}
}
// see JCA doc
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
throws InvalidKeySpecException {
try {
return generatePrivate(keySpec);
} catch (InvalidKeySpecException e) {
throw e;
} catch (GeneralSecurityException e) {
throw new InvalidKeySpecException(e);
}
}
// internal implementation of translateKey() for public keys. See JCA doc
private PublicKey translatePublicKey(PublicKey key)
throws InvalidKeyException {
if (key instanceof RSAPublicKey) {
if (key instanceof RSAPublicKeyImpl) {
return key;
}
RSAPublicKey rsaKey = (RSAPublicKey)key;
try {
return new RSAPublicKeyImpl(
rsaKey.getModulus(),
rsaKey.getPublicExponent()
);
} catch (RuntimeException e) {
// catch providers that incorrectly implement RSAPublicKey
throw new InvalidKeyException("Invalid key", e);
}
} else if ("X.509".equals(key.getFormat())) {
byte[] encoded = key.getEncoded();
return new RSAPublicKeyImpl(encoded);
} else {
throw new InvalidKeyException("Public keys must be instance "
+ "of RSAPublicKey or have X.509 encoding");
}
}
// internal implementation of translateKey() for private keys. See JCA doc
private PrivateKey translatePrivateKey(PrivateKey key)
throws InvalidKeyException {
if (key instanceof RSAPrivateCrtKey) {
if (key instanceof RSAPrivateCrtKeyImpl) {
return key;
}
RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key;
try {
return new RSAPrivateCrtKeyImpl(
rsaKey.getModulus(),
rsaKey.getPublicExponent(),
rsaKey.getPrivateExponent(),
rsaKey.getPrimeP(),
rsaKey.getPrimeQ(),
rsaKey.getPrimeExponentP(),
rsaKey.getPrimeExponentQ(),
rsaKey.getCrtCoefficient()
);
} catch (RuntimeException e) {
// catch providers that incorrectly implement RSAPrivateCrtKey
throw new InvalidKeyException("Invalid key", e);
}
} else if (key instanceof RSAPrivateKey) {
if (key instanceof RSAPrivateKeyImpl) {
return key;
}
RSAPrivateKey rsaKey = (RSAPrivateKey)key;
try {
return new RSAPrivateKeyImpl(
rsaKey.getModulus(),
rsaKey.getPrivateExponent()
);
} catch (RuntimeException e) {
// catch providers that incorrectly implement RSAPrivateKey
throw new InvalidKeyException("Invalid key", e);
}
} else if ("PKCS#8".equals(key.getFormat())) {
byte[] encoded = key.getEncoded();
return RSAPrivateCrtKeyImpl.newKey(encoded);
} else {
throw new InvalidKeyException("Private keys must be instance "
+ "of RSAPrivate(Crt)Key or have PKCS#8 encoding");
}
}
// internal implementation of generatePublic. See JCA doc
private PublicKey generatePublic(KeySpec keySpec)
throws GeneralSecurityException {
if (keySpec instanceof X509EncodedKeySpec) {
X509EncodedKeySpec x509Spec = (X509EncodedKeySpec)keySpec;
return new RSAPublicKeyImpl(x509Spec.getEncoded());
} else if (keySpec instanceof RSAPublicKeySpec) {
RSAPublicKeySpec rsaSpec = (RSAPublicKeySpec)keySpec;
return new RSAPublicKeyImpl(
rsaSpec.getModulus(),
rsaSpec.getPublicExponent()
);
} else {
throw new InvalidKeySpecException("Only RSAPublicKeySpec "
+ "and X509EncodedKeySpec supported for RSA public keys");
}
}
// internal implementation of generatePrivate. See JCA doc
private PrivateKey generatePrivate(KeySpec keySpec)
throws GeneralSecurityException {
if (keySpec instanceof PKCS8EncodedKeySpec) {
PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec)keySpec;
return RSAPrivateCrtKeyImpl.newKey(pkcsSpec.getEncoded());
} else if (keySpec instanceof RSAPrivateCrtKeySpec) {
RSAPrivateCrtKeySpec rsaSpec = (RSAPrivateCrtKeySpec)keySpec;
return new RSAPrivateCrtKeyImpl(
rsaSpec.getModulus(),
rsaSpec.getPublicExponent(),
rsaSpec.getPrivateExponent(),
rsaSpec.getPrimeP(),
rsaSpec.getPrimeQ(),
rsaSpec.getPrimeExponentP(),
rsaSpec.getPrimeExponentQ(),
rsaSpec.getCrtCoefficient()
);
} else if (keySpec instanceof RSAPrivateKeySpec) {
RSAPrivateKeySpec rsaSpec = (RSAPrivateKeySpec)keySpec;
return new RSAPrivateKeyImpl(
rsaSpec.getModulus(),
rsaSpec.getPrivateExponent()
);
} else {
throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "
+ "and PKCS8EncodedKeySpec supported for RSA private keys");
}
}
protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
throws InvalidKeySpecException {
try {
// convert key to one of our keys
// this also verifies that the key is a valid RSA key and ensures
// that the encoding is X.509/PKCS#8 for public/private keys
key = engineTranslateKey(key);
} catch (InvalidKeyException e) {
throw new InvalidKeySpecException(e);
}
if (key instanceof RSAPublicKey) {
RSAPublicKey rsaKey = (RSAPublicKey)key;
if (rsaPublicKeySpecClass.isAssignableFrom(keySpec)) {
return keySpec.cast(new RSAPublicKeySpec(
rsaKey.getModulus(),
rsaKey.getPublicExponent()
));
} else if (x509KeySpecClass.isAssignableFrom(keySpec)) {
return keySpec.cast(new X509EncodedKeySpec(key.getEncoded()));
} else {
throw new InvalidKeySpecException
("KeySpec must be RSAPublicKeySpec or "
+ "X509EncodedKeySpec for RSA public keys");
}
} else if (key instanceof RSAPrivateKey) {
if (pkcs8KeySpecClass.isAssignableFrom(keySpec)) {
return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded()));
} else if (rsaPrivateCrtKeySpecClass.isAssignableFrom(keySpec)) {
if (key instanceof RSAPrivateCrtKey) {
RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey)key;
return keySpec.cast(new RSAPrivateCrtKeySpec(
crtKey.getModulus(),
crtKey.getPublicExponent(),
crtKey.getPrivateExponent(),
crtKey.getPrimeP(),
crtKey.getPrimeQ(),
crtKey.getPrimeExponentP(),
crtKey.getPrimeExponentQ(),
crtKey.getCrtCoefficient()
));
} else {
throw new InvalidKeySpecException
("RSAPrivateCrtKeySpec can only be used with CRT keys");
}
} else if (rsaPrivateKeySpecClass.isAssignableFrom(keySpec)) {
RSAPrivateKey rsaKey = (RSAPrivateKey)key;
return keySpec.cast(new RSAPrivateKeySpec(
rsaKey.getModulus(),
rsaKey.getPrivateExponent()
));
} else {
throw new InvalidKeySpecException
("KeySpec must be RSAPrivate(Crt)KeySpec or "
+ "PKCS8EncodedKeySpec for RSA private keys");
}
} else {
// should not occur, caught in engineTranslateKey()
throw new InvalidKeySpecException("Neither public nor private key");
}
}
}

View file

@ -0,0 +1,180 @@
/*
* Copyright (c) 2003, 2016, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
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;
/**
* RSA keypair generation. Standard algorithm, minimum key length 512 bit.
* We generate two random primes until we find two where phi is relative
* prime to the public exponent. Default exponent is 65537. It has only bit 0
* and bit 4 set, which makes it particularly efficient.
*
* @since 1.5
* @author Andreas Sterbenz
*/
public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// public exponent to use
private BigInteger publicExponent;
// size of the key to generate, >= RSAKeyFactory.MIN_MODLEN
private int keySize;
// PRNG to use
private SecureRandom random;
public RSAKeyPairGenerator() {
// initialize to default in case the app does not call initialize()
initialize(2048, null);
}
// initialize the generator. See JCA doc
public void initialize(int keySize, SecureRandom random) {
// do not allow unreasonably small or large key sizes,
// probably user error
try {
RSAKeyFactory.checkKeyLengths(keySize, RSAKeyGenParameterSpec.F4,
512, 64 * 1024);
} catch (InvalidKeyException e) {
throw new InvalidParameterException(e.getMessage());
}
this.keySize = keySize;
this.random = random;
this.publicExponent = RSAKeyGenParameterSpec.F4;
}
// second initialize method. See JCA doc.
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();
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");
}
}
// do not allow unreasonably large key sizes, probably user error
try {
RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPublicExponent,
512, 64 * 1024);
} catch (InvalidKeyException e) {
throw new InvalidAlgorithmParameterException(
"Invalid key sizes", e);
}
this.keySize = tmpKeySize;
this.publicExponent = tmpPublicExponent;
this.random = random;
}
// generate the keypair. See JCA doc
public KeyPair generateKeyPair() {
// accommodate odd key sizes in case anybody wants to use them
int lp = (keySize + 1) >> 1;
int lq = keySize - lp;
if (random == null) {
random = JCAUtil.getSecureRandom();
}
BigInteger e = publicExponent;
while (true) {
// generate two random primes of size lp/lq
BigInteger p = BigInteger.probablePrime(lp, random);
BigInteger q, n;
do {
q = BigInteger.probablePrime(lq, random);
// convention is for p > q
if (p.compareTo(q) < 0) {
BigInteger tmp = p;
p = q;
q = tmp;
}
// modulus n = p * q
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
// otherwise RSA just won't work ;-)
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
// the first try will succeed when using F4
if (e.gcd(phi).equals(BigInteger.ONE) == false) {
continue;
}
// private exponent d is the inverse of e mod phi
BigInteger d = e.modInverse(phi);
// 1st prime exponent pe = d mod (p - 1)
BigInteger pe = d.mod(p1);
// 2nd prime exponent qe = d mod (q - 1)
BigInteger qe = d.mod(q1);
// crt coefficient coeff is the inverse of q mod p
BigInteger coeff = q.modInverse(p);
try {
PublicKey publicKey = new RSAPublicKeyImpl(n, e);
PrivateKey privateKey =
new RSAPrivateCrtKeyImpl(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,
// will not happen here
throw new RuntimeException(exc);
}
}
}
}

View file

@ -0,0 +1,542 @@
/*
* Copyright (c) 2003, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.rsa;
import java.util.*;
import java.security.*;
import java.security.spec.*;
import javax.crypto.BadPaddingException;
import javax.crypto.spec.PSource;
import javax.crypto.spec.OAEPParameterSpec;
import sun.security.jca.JCAUtil;
/**
* RSA padding and unpadding.
*
* The various PKCS#1 versions can be found in the EMC/RSA Labs
* web site, which is currently:
*
* http://www.emc.com/emc-plus/rsa-labs/index.htm
*
* or in the IETF RFCs derived from the above PKCS#1 standards.
*
* RFC 2313: v1.5
* RFC 2437: v2.0
* RFC 3447: v2.1
*
* The format of PKCS#1 v1.5 padding is:
*
* 0x00 | BT | PS...PS | 0x00 | data...data
*
* where BT is the blocktype (1 or 2). The length of the entire string
* must be the same as the size of the modulus (i.e. 128 byte for a 1024 bit
* key). Per spec, the padding string must be at least 8 bytes long. That
* leaves up to (length of key in bytes) - 11 bytes for the data.
*
* OAEP padding was introduced in PKCS#1 v2.0 and is a bit more complicated
* and has a number of options. We support:
*
* . arbitrary hash functions ('Hash' in the specification), MessageDigest
* implementation must be available
* . MGF1 as the mask generation function
* . the empty string as the default value for label L and whatever
* specified in javax.crypto.spec.OAEPParameterSpec
*
* The algorithms (representations) are forwards-compatible: that is,
* the algorithm described in previous releases are in later releases.
* However, additional comments/checks/clarifications were added to the
* later versions based on real-world experience (e.g. stricter v1.5
* format checking.)
*
* Note: RSA keys should be at least 512 bits long
*
* @since 1.5
* @author Andreas Sterbenz
*/
public final class RSAPadding {
// NOTE: the constants below are embedded in the JCE RSACipher class
// file. Do not change without coordinating the update
// PKCS#1 v1.5 padding, blocktype 1 (signing)
public static final int PAD_BLOCKTYPE_1 = 1;
// PKCS#1 v1.5 padding, blocktype 2 (encryption)
public static final int PAD_BLOCKTYPE_2 = 2;
// nopadding. Does not do anything, but allows simpler RSACipher code
public static final int PAD_NONE = 3;
// PKCS#1 v2.1 OAEP padding
public static final int PAD_OAEP_MGF1 = 4;
// type, one of PAD_*
private final int type;
// size of the padded block (i.e. size of the modulus)
private final int paddedSize;
// PRNG used to generate padding bytes (PAD_BLOCKTYPE_2, PAD_OAEP_MGF1)
private SecureRandom random;
// maximum size of the data
private final int maxDataSize;
// OAEP: main messagedigest
private MessageDigest md;
// OAEP: message digest for MGF1
private MessageDigest mgfMd;
// OAEP: value of digest of data (user-supplied or zero-length) using md
private byte[] lHash;
/**
* Get a RSAPadding instance of the specified type.
* Keys used with this padding must be paddedSize bytes long.
*/
public static RSAPadding getInstance(int type, int paddedSize)
throws InvalidKeyException, InvalidAlgorithmParameterException {
return new RSAPadding(type, paddedSize, null, null);
}
/**
* Get a RSAPadding instance of the specified type.
* Keys used with this padding must be paddedSize bytes long.
*/
public static RSAPadding getInstance(int type, int paddedSize,
SecureRandom random) throws InvalidKeyException,
InvalidAlgorithmParameterException {
return new RSAPadding(type, paddedSize, random, null);
}
/**
* Get a RSAPadding instance of the specified type, which must be
* OAEP. Keys used with this padding must be paddedSize bytes long.
*/
public static RSAPadding getInstance(int type, int paddedSize,
SecureRandom random, OAEPParameterSpec spec)
throws InvalidKeyException, InvalidAlgorithmParameterException {
return new RSAPadding(type, paddedSize, random, spec);
}
// internal constructor
private RSAPadding(int type, int paddedSize, SecureRandom random,
OAEPParameterSpec spec) throws InvalidKeyException,
InvalidAlgorithmParameterException {
this.type = type;
this.paddedSize = paddedSize;
this.random = random;
if (paddedSize < 64) {
// sanity check, already verified in RSASignature/RSACipher
throw new InvalidKeyException("Padded size must be at least 64");
}
switch (type) {
case PAD_BLOCKTYPE_1:
case PAD_BLOCKTYPE_2:
maxDataSize = paddedSize - 11;
break;
case PAD_NONE:
maxDataSize = paddedSize;
break;
case PAD_OAEP_MGF1:
String mdName = "SHA-1";
String mgfMdName = "SHA-1";
byte[] digestInput = null;
try {
if (spec != null) {
mdName = spec.getDigestAlgorithm();
String mgfName = spec.getMGFAlgorithm();
if (!mgfName.equalsIgnoreCase("MGF1")) {
throw new InvalidAlgorithmParameterException
("Unsupported MGF algo: " + mgfName);
}
mgfMdName = ((MGF1ParameterSpec)spec.getMGFParameters())
.getDigestAlgorithm();
PSource pSrc = spec.getPSource();
String pSrcAlgo = pSrc.getAlgorithm();
if (!pSrcAlgo.equalsIgnoreCase("PSpecified")) {
throw new InvalidAlgorithmParameterException
("Unsupported pSource algo: " + pSrcAlgo);
}
digestInput = ((PSource.PSpecified) pSrc).getValue();
}
md = MessageDigest.getInstance(mdName);
mgfMd = MessageDigest.getInstance(mgfMdName);
} catch (NoSuchAlgorithmException e) {
throw new InvalidKeyException
("Digest " + mdName + " not available", e);
}
lHash = getInitialHash(md, digestInput);
int digestLen = lHash.length;
maxDataSize = paddedSize - 2 - 2 * digestLen;
if (maxDataSize <= 0) {
throw new InvalidKeyException
("Key is too short for encryption using OAEPPadding" +
" with " + mdName + " and MGF1" + mgfMdName);
}
break;
default:
throw new InvalidKeyException("Invalid padding: " + type);
}
}
// cache of hashes of zero length data
private static final Map<String,byte[]> emptyHashes =
Collections.synchronizedMap(new HashMap<String,byte[]>());
/**
* Return the value of the digest using the specified message digest
* <code>md</code> and the digest input <code>digestInput</code>.
* if <code>digestInput</code> is null or 0-length, zero length
* is used to generate the initial digest.
* Note: the md object must be in reset state
*/
private static byte[] getInitialHash(MessageDigest md,
byte[] digestInput) {
byte[] result;
if ((digestInput == null) || (digestInput.length == 0)) {
String digestName = md.getAlgorithm();
result = emptyHashes.get(digestName);
if (result == null) {
result = md.digest();
emptyHashes.put(digestName, result);
}
} else {
result = md.digest(digestInput);
}
return result;
}
/**
* Return the maximum size of the plaintext data that can be processed
* using this object.
*/
public int getMaxDataSize() {
return maxDataSize;
}
/**
* Pad the data and return the padded block.
*/
public byte[] pad(byte[] data, int ofs, int len)
throws BadPaddingException {
return pad(RSACore.convert(data, ofs, len));
}
/**
* Pad the data and return the padded block.
*/
public byte[] pad(byte[] data) throws BadPaddingException {
if (data.length > maxDataSize) {
throw new BadPaddingException("Data must be shorter than "
+ (maxDataSize + 1) + " bytes but received "
+ data.length + " bytes.");
}
switch (type) {
case PAD_NONE:
return data;
case PAD_BLOCKTYPE_1:
case PAD_BLOCKTYPE_2:
return padV15(data);
case PAD_OAEP_MGF1:
return padOAEP(data);
default:
throw new AssertionError();
}
}
/**
* Unpad the padded block and return the data.
*/
public byte[] unpad(byte[] padded, int ofs, int len)
throws BadPaddingException {
return unpad(RSACore.convert(padded, ofs, len));
}
/**
* Unpad the padded block and return the data.
*/
public byte[] unpad(byte[] padded) throws BadPaddingException {
if (padded.length != paddedSize) {
throw new BadPaddingException("Decryption error." +
"The padded array length (" + padded.length +
") is not the specified padded size (" + paddedSize + ")");
}
switch (type) {
case PAD_NONE:
return padded;
case PAD_BLOCKTYPE_1:
case PAD_BLOCKTYPE_2:
return unpadV15(padded);
case PAD_OAEP_MGF1:
return unpadOAEP(padded);
default:
throw new AssertionError();
}
}
/**
* PKCS#1 v1.5 padding (blocktype 1 and 2).
*/
private byte[] padV15(byte[] data) throws BadPaddingException {
byte[] padded = new byte[paddedSize];
System.arraycopy(data, 0, padded, paddedSize - data.length,
data.length);
int psSize = paddedSize - 3 - data.length;
int k = 0;
padded[k++] = 0;
padded[k++] = (byte)type;
if (type == PAD_BLOCKTYPE_1) {
// blocktype 1: all padding bytes are 0xff
while (psSize-- > 0) {
padded[k++] = (byte)0xff;
}
} else {
// blocktype 2: padding bytes are random non-zero bytes
if (random == null) {
random = JCAUtil.getSecureRandom();
}
// generate non-zero padding bytes
// use a buffer to reduce calls to SecureRandom
while (psSize > 0) {
// extra bytes to avoid zero bytes,
// number of zero bytes <= 4 in 98% cases
byte[] r = new byte[psSize + 4];
random.nextBytes(r);
for (int i = 0; i < r.length && psSize > 0; i++) {
if (r[i] != 0) {
padded[k++] = r[i];
psSize--;
}
}
}
}
return padded;
}
/**
* PKCS#1 v1.5 unpadding (blocktype 1 (signature) and 2 (encryption)).
*
* Note that we want to make it a constant-time operation
*/
private byte[] unpadV15(byte[] padded) throws BadPaddingException {
int k = 0;
boolean bp = false;
if (padded[k++] != 0) {
bp = true;
}
if (padded[k++] != type) {
bp = true;
}
int p = 0;
while (k < padded.length) {
int b = padded[k++] & 0xff;
if ((b == 0) && (p == 0)) {
p = k;
}
if ((k == padded.length) && (p == 0)) {
bp = true;
}
if ((type == PAD_BLOCKTYPE_1) && (b != 0xff) &&
(p == 0)) {
bp = true;
}
}
int n = padded.length - p;
if (n > maxDataSize) {
bp = true;
}
// copy useless padding array for a constant-time method
byte[] padding = new byte[p];
System.arraycopy(padded, 0, padding, 0, p);
byte[] data = new byte[n];
System.arraycopy(padded, p, data, 0, n);
BadPaddingException bpe = new BadPaddingException("Decryption error");
if (bp) {
throw bpe;
} else {
return data;
}
}
/**
* PKCS#1 v2.0 OAEP padding (MGF1).
* Paragraph references refer to PKCS#1 v2.1 (June 14, 2002)
*/
private byte[] padOAEP(byte[] M) throws BadPaddingException {
if (random == null) {
random = JCAUtil.getSecureRandom();
}
int hLen = lHash.length;
// 2.d: generate a random octet string seed of length hLen
// if necessary
byte[] seed = new byte[hLen];
random.nextBytes(seed);
// buffer for encoded message EM
byte[] EM = new byte[paddedSize];
// start and length of seed (as index into EM)
int seedStart = 1;
int seedLen = hLen;
// copy seed into EM
System.arraycopy(seed, 0, EM, seedStart, seedLen);
// start and length of data block DB in EM
// we place it inside of EM to reduce copying
int dbStart = hLen + 1;
int dbLen = EM.length - dbStart;
// start of message M in EM
int mStart = paddedSize - M.length;
// build DB
// 2.b: Concatenate lHash, PS, a single octet with hexadecimal value
// 0x01, and the message M to form a data block DB of length
// k - hLen -1 octets as DB = lHash || PS || 0x01 || M
// (note that PS is all zeros)
System.arraycopy(lHash, 0, EM, dbStart, hLen);
EM[mStart - 1] = 1;
System.arraycopy(M, 0, EM, mStart, M.length);
// produce maskedDB
mgf1(EM, seedStart, seedLen, EM, dbStart, dbLen);
// produce maskSeed
mgf1(EM, dbStart, dbLen, EM, seedStart, seedLen);
return EM;
}
/**
* PKCS#1 v2.1 OAEP unpadding (MGF1).
*/
private byte[] unpadOAEP(byte[] padded) throws BadPaddingException {
byte[] EM = padded;
boolean bp = false;
int hLen = lHash.length;
if (EM[0] != 0) {
bp = true;
}
int seedStart = 1;
int seedLen = hLen;
int dbStart = hLen + 1;
int dbLen = EM.length - dbStart;
mgf1(EM, dbStart, dbLen, EM, seedStart, seedLen);
mgf1(EM, seedStart, seedLen, EM, dbStart, dbLen);
// verify lHash == lHash'
for (int i = 0; i < hLen; i++) {
if (lHash[i] != EM[dbStart + i]) {
bp = true;
}
}
int padStart = dbStart + hLen;
int onePos = -1;
for (int i = padStart; i < EM.length; i++) {
int value = EM[i];
if (onePos == -1) {
if (value == 0x00) {
// continue;
} else if (value == 0x01) {
onePos = i;
} else { // Anything other than {0,1} is bad.
bp = true;
}
}
}
// We either ran off the rails or found something other than 0/1.
if (onePos == -1) {
bp = true;
onePos = EM.length - 1; // Don't inadvertently return any data.
}
int mStart = onePos + 1;
// copy useless padding array for a constant-time method
byte [] tmp = new byte[mStart - padStart];
System.arraycopy(EM, padStart, tmp, 0, tmp.length);
byte [] m = new byte[EM.length - mStart];
System.arraycopy(EM, mStart, m, 0, m.length);
BadPaddingException bpe = new BadPaddingException("Decryption error");
if (bp) {
throw bpe;
} else {
return m;
}
}
/**
* Compute MGF1 using mgfMD as the message digest.
* Note that we combine MGF1 with the XOR operation to reduce data
* copying.
*
* We generate maskLen bytes of MGF1 from the seed and XOR it into
* out[] starting at outOfs;
*/
private void mgf1(byte[] seed, int seedOfs, int seedLen,
byte[] out, int outOfs, int maskLen) throws BadPaddingException {
byte[] C = new byte[4]; // 32 bit counter
byte[] digest = new byte[mgfMd.getDigestLength()];
while (maskLen > 0) {
mgfMd.update(seed, seedOfs, seedLen);
mgfMd.update(C);
try {
mgfMd.digest(digest, 0, digest.length);
} catch (DigestException e) {
// should never happen
throw new BadPaddingException(e.toString());
}
for (int i = 0; (i < digest.length) && (maskLen > 0); maskLen--) {
out[outOfs++] ^= digest[i++];
}
if (maskLen > 0) {
// increment counter
for (int i = C.length - 1; (++C[i] == 0) && (i > 0); i--) {
// empty
}
}
}
}
}

View file

@ -0,0 +1,217 @@
/*
* Copyright (c) 2003, 2017, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.rsa;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import sun.security.util.*;
import sun.security.x509.AlgorithmId;
import sun.security.pkcs.PKCS8Key;
/**
* Key implementation for RSA private keys, CRT form. For non-CRT private
* keys, see RSAPrivateKeyImpl. We need separate classes to ensure
* correct behavior in instanceof checks, etc.
*
* Note: RSA keys must be at least 512 bits long
*
* @see RSAPrivateKeyImpl
* @see RSAKeyFactory
*
* @since 1.5
* @author Andreas Sterbenz
*/
public final class RSAPrivateCrtKeyImpl
extends PKCS8Key implements RSAPrivateCrtKey {
private static final long serialVersionUID = -1326088454257084918L;
private BigInteger n; // modulus
private BigInteger e; // public exponent
private BigInteger d; // private exponent
private BigInteger p; // prime p
private BigInteger q; // prime q
private BigInteger pe; // prime exponent p
private BigInteger qe; // prime exponent q
private BigInteger coeff; // CRT coeffcient
// algorithmId used to identify RSA keys
static final AlgorithmId rsaId =
new AlgorithmId(AlgorithmId.RSAEncryption_oid);
/**
* Generate a new key from its encoding. Returns a CRT key if possible
* and a non-CRT key otherwise. Used by RSAKeyFactory.
*/
public static RSAPrivateKey newKey(byte[] encoded)
throws InvalidKeyException {
RSAPrivateCrtKeyImpl key = new RSAPrivateCrtKeyImpl(encoded);
if (key.getPublicExponent().signum() == 0) {
// public exponent is missing, return a non-CRT key
return new RSAPrivateKeyImpl(
key.getModulus(),
key.getPrivateExponent()
);
} else {
return key;
}
}
/**
* Construct a key from its encoding. Called from newKey above.
*/
RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException {
decode(encoded);
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
}
/**
* Construct a key from its components. Used by the
* RSAKeyFactory and the RSAKeyPairGenerator.
*/
RSAPrivateCrtKeyImpl(BigInteger n, BigInteger e, BigInteger d,
BigInteger p, BigInteger q, BigInteger pe, BigInteger qe,
BigInteger coeff) throws InvalidKeyException {
this.n = n;
this.e = e;
this.d = d;
this.p = p;
this.q = q;
this.pe = pe;
this.qe = qe;
this.coeff = coeff;
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
// generate the encoding
algid = rsaId;
try {
DerOutputStream out = new DerOutputStream();
out.putInteger(0); // version must be 0
out.putInteger(n);
out.putInteger(e);
out.putInteger(d);
out.putInteger(p);
out.putInteger(q);
out.putInteger(pe);
out.putInteger(qe);
out.putInteger(coeff);
DerValue val =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
key = val.toByteArray();
} catch (IOException exc) {
// should never occur
throw new InvalidKeyException(exc);
}
}
// see JCA doc
public String getAlgorithm() {
return "RSA";
}
// see JCA doc
public BigInteger getModulus() {
return n;
}
// see JCA doc
public BigInteger getPublicExponent() {
return e;
}
// see JCA doc
public BigInteger getPrivateExponent() {
return d;
}
// see JCA doc
public BigInteger getPrimeP() {
return p;
}
// see JCA doc
public BigInteger getPrimeQ() {
return q;
}
// see JCA doc
public BigInteger getPrimeExponentP() {
return pe;
}
// see JCA doc
public BigInteger getPrimeExponentQ() {
return qe;
}
// see JCA doc
public BigInteger getCrtCoefficient() {
return coeff;
}
/**
* Parse the key. Called by PKCS8Key.
*/
protected void parseKeyBits() throws InvalidKeyException {
try {
DerInputStream in = new DerInputStream(key);
DerValue derValue = in.getDerValue();
if (derValue.tag != DerValue.tag_Sequence) {
throw new IOException("Not a SEQUENCE");
}
DerInputStream data = derValue.data;
int version = data.getInteger();
if (version != 0) {
throw new IOException("Version must be 0");
}
/*
* Some implementations do not correctly encode ASN.1 INTEGER values
* in 2's complement format, resulting in a negative integer when
* decoded. Correct the error by converting it to a positive integer.
*
* See CR 6255949
*/
n = data.getPositiveBigInteger();
e = data.getPositiveBigInteger();
d = data.getPositiveBigInteger();
p = data.getPositiveBigInteger();
q = data.getPositiveBigInteger();
pe = data.getPositiveBigInteger();
qe = data.getPositiveBigInteger();
coeff = data.getPositiveBigInteger();
if (derValue.data.available() != 0) {
throw new IOException("Extra data available");
}
} catch (IOException e) {
throw new InvalidKeyException("Invalid RSA private key", e);
}
}
}

View file

@ -0,0 +1,101 @@
/*
* Copyright (c) 2003, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.rsa;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import sun.security.util.*;
import sun.security.pkcs.PKCS8Key;
/**
* Key implementation for RSA private keys, non-CRT form (modulus, private
* exponent only). For CRT private keys, see RSAPrivateCrtKeyImpl. We need
* separate classes to ensure correct behavior in instanceof checks, etc.
*
* Note: RSA keys must be at least 512 bits long
*
* @see RSAPrivateCrtKeyImpl
* @see RSAKeyFactory
*
* @since 1.5
* @author Andreas Sterbenz
*/
public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey {
private static final long serialVersionUID = -33106691987952810L;
private final BigInteger n; // modulus
private final BigInteger d; // private exponent
/**
* Construct a key from its components. Used by the
* RSAKeyFactory and the RSAKeyPairGenerator.
*/
RSAPrivateKeyImpl(BigInteger n, BigInteger d) throws InvalidKeyException {
this.n = n;
this.d = d;
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), null);
// generate the encoding
algid = RSAPrivateCrtKeyImpl.rsaId;
try {
DerOutputStream out = new DerOutputStream();
out.putInteger(0); // version must be 0
out.putInteger(n);
out.putInteger(0);
out.putInteger(d);
out.putInteger(0);
out.putInteger(0);
out.putInteger(0);
out.putInteger(0);
out.putInteger(0);
DerValue val =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
key = val.toByteArray();
} catch (IOException exc) {
// should never occur
throw new InvalidKeyException(exc);
}
}
// see JCA doc
public String getAlgorithm() {
return "RSA";
}
// see JCA doc
public BigInteger getModulus() {
return n;
}
// see JCA doc
public BigInteger getPrivateExponent() {
return d;
}
}

View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2003, 2017, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.rsa;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import sun.security.util.*;
import sun.security.x509.X509Key;
/**
* Key implementation for RSA public keys.
*
* Note: RSA keys must be at least 512 bits long
*
* @see RSAPrivateCrtKeyImpl
* @see RSAKeyFactory
*
* @since 1.5
* @author Andreas Sterbenz
*/
public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
private static final long serialVersionUID = 2644735423591199609L;
private BigInteger n; // modulus
private BigInteger e; // public exponent
/**
* Construct a key from its components. Used by the
* RSAKeyFactory and the RSAKeyPairGenerator.
*/
public RSAPublicKeyImpl(BigInteger n, BigInteger e)
throws InvalidKeyException {
this.n = n;
this.e = e;
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
// generate the encoding
algid = RSAPrivateCrtKeyImpl.rsaId;
try {
DerOutputStream out = new DerOutputStream();
out.putInteger(n);
out.putInteger(e);
byte[] keyArray =
new DerValue(DerValue.tag_Sequence,
out.toByteArray()).toByteArray();
setKey(new BitArray(keyArray.length*8, keyArray));
} catch (IOException exc) {
// should never occur
throw new InvalidKeyException(exc);
}
}
/**
* Construct a key from its encoding. Used by RSAKeyFactory.
*/
public RSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException {
decode(encoded);
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
}
// see JCA doc
public String getAlgorithm() {
return "RSA";
}
// see JCA doc
public BigInteger getModulus() {
return n;
}
// see JCA doc
public BigInteger getPublicExponent() {
return e;
}
/**
* Parse the key. Called by X509Key.
*/
protected void parseKeyBits() throws InvalidKeyException {
try {
DerInputStream in = new DerInputStream(getKey().toByteArray());
DerValue derValue = in.getDerValue();
if (derValue.tag != DerValue.tag_Sequence) {
throw new IOException("Not a SEQUENCE");
}
DerInputStream data = derValue.data;
n = data.getPositiveBigInteger();
e = data.getPositiveBigInteger();
if (derValue.data.available() != 0) {
throw new IOException("Extra data available");
}
} catch (IOException e) {
throw new InvalidKeyException("Invalid RSA public key", e);
}
}
// return a string representation of this key for debugging
public String toString() {
return "Sun RSA public key, " + n.bitLength() + " bits\n modulus: "
+ n + "\n public exponent: " + e;
}
protected Object writeReplace() throws java.io.ObjectStreamException {
return new KeyRep(KeyRep.Type.PUBLIC,
getAlgorithm(),
getFormat(),
getEncoded());
}
}

View file

@ -0,0 +1,312 @@
/*
* Copyright (c) 2003, 2016, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.rsa;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.*;
import java.security.interfaces.*;
import sun.security.util.*;
import sun.security.x509.AlgorithmId;
/**
* PKCS#1 RSA signatures with the various message digest algorithms.
* This file contains an abstract base class with all the logic plus
* a nested static class for each of the message digest algorithms
* (see end of the file). We support MD2, MD5, SHA-1, SHA-224, SHA-256,
* SHA-384, and SHA-512.
*
* @since 1.5
* @author Andreas Sterbenz
*/
public abstract class RSASignature extends SignatureSpi {
// we sign an ASN.1 SEQUENCE of AlgorithmId and digest
// it has the form 30:xx:30:xx:[digestOID]:05:00:04:xx:[digest]
// this means the encoded length is (8 + digestOID.length + digest.length)
private static final int baseLength = 8;
// object identifier for the message digest algorithm used
private final ObjectIdentifier digestOID;
// length of the encoded signature blob
private final int encodedLength;
// message digest implementation we use
private final MessageDigest md;
// flag indicating whether the digest is reset
private boolean digestReset;
// private key, if initialized for signing
private RSAPrivateKey privateKey;
// public key, if initialized for verifying
private RSAPublicKey publicKey;
// padding to use, set when the initSign/initVerify is called
private RSAPadding padding;
/**
* Construct a new RSASignature. Used by subclasses.
*/
RSASignature(String algorithm, ObjectIdentifier digestOID, int oidLength) {
this.digestOID = digestOID;
try {
md = MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
throw new ProviderException(e);
}
digestReset = true;
encodedLength = baseLength + oidLength + md.getDigestLength();
}
// initialize for verification. See JCA doc
protected void engineInitVerify(PublicKey publicKey)
throws InvalidKeyException {
RSAPublicKey rsaKey = (RSAPublicKey)RSAKeyFactory.toRSAKey(publicKey);
this.privateKey = null;
this.publicKey = rsaKey;
initCommon(rsaKey, null);
}
// initialize for signing. See JCA doc
protected void engineInitSign(PrivateKey privateKey)
throws InvalidKeyException {
engineInitSign(privateKey, null);
}
// initialize for signing. See JCA doc
protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
throws InvalidKeyException {
RSAPrivateKey rsaKey =
(RSAPrivateKey)RSAKeyFactory.toRSAKey(privateKey);
this.privateKey = rsaKey;
this.publicKey = null;
initCommon(rsaKey, random);
}
/**
* Init code common to sign and verify.
*/
private void initCommon(RSAKey rsaKey, SecureRandom random)
throws InvalidKeyException {
resetDigest();
int keySize = RSACore.getByteLength(rsaKey);
try {
padding = RSAPadding.getInstance
(RSAPadding.PAD_BLOCKTYPE_1, keySize, random);
} catch (InvalidAlgorithmParameterException iape) {
throw new InvalidKeyException(iape.getMessage());
}
int maxDataSize = padding.getMaxDataSize();
if (encodedLength > maxDataSize) {
throw new InvalidKeyException
("Key is too short for this signature algorithm");
}
}
/**
* Reset the message digest if it is not already reset.
*/
private void resetDigest() {
if (digestReset == false) {
md.reset();
digestReset = true;
}
}
/**
* Return the message digest value.
*/
private byte[] getDigestValue() {
digestReset = true;
return md.digest();
}
// update the signature with the plaintext data. See JCA doc
protected void engineUpdate(byte b) throws SignatureException {
md.update(b);
digestReset = false;
}
// update the signature with the plaintext data. See JCA doc
protected void engineUpdate(byte[] b, int off, int len)
throws SignatureException {
md.update(b, off, len);
digestReset = false;
}
// update the signature with the plaintext data. See JCA doc
protected void engineUpdate(ByteBuffer b) {
md.update(b);
digestReset = false;
}
// sign the data and return the signature. See JCA doc
protected byte[] engineSign() throws SignatureException {
byte[] digest = getDigestValue();
try {
byte[] encoded = encodeSignature(digestOID, digest);
byte[] padded = padding.pad(encoded);
byte[] encrypted = RSACore.rsa(padded, privateKey, true);
return encrypted;
} catch (GeneralSecurityException e) {
throw new SignatureException("Could not sign data", e);
} catch (IOException e) {
throw new SignatureException("Could not encode data", e);
}
}
// verify the data and return the result. See JCA doc
// should be reset to the state after engineInitVerify call.
protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
try {
if (sigBytes.length != RSACore.getByteLength(publicKey)) {
throw new SignatureException("Signature length not correct: got " +
sigBytes.length + " but was expecting " +
RSACore.getByteLength(publicKey));
}
byte[] digest = getDigestValue();
byte[] decrypted = RSACore.rsa(sigBytes, publicKey);
byte[] unpadded = padding.unpad(decrypted);
byte[] decodedDigest = decodeSignature(digestOID, unpadded);
return MessageDigest.isEqual(digest, decodedDigest);
} catch (javax.crypto.BadPaddingException e) {
// occurs if the app has used the wrong RSA public key
// or if sigBytes is invalid
// return false rather than propagating the exception for
// compatibility/ease of use
return false;
} catch (IOException e) {
throw new SignatureException("Signature encoding error", e);
} finally {
resetDigest();
}
}
/**
* Encode the digest, return the to-be-signed data.
* Also used by the PKCS#11 provider.
*/
public static byte[] encodeSignature(ObjectIdentifier oid, byte[] digest)
throws IOException {
DerOutputStream out = new DerOutputStream();
new AlgorithmId(oid).encode(out);
out.putOctetString(digest);
DerValue result =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
return result.toByteArray();
}
/**
* Decode the signature data. Verify that the object identifier matches
* and return the message digest.
*/
public static byte[] decodeSignature(ObjectIdentifier oid, byte[] sig)
throws IOException {
// Enforce strict DER checking for signatures
DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
DerValue[] values = in.getSequence(2);
if ((values.length != 2) || (in.available() != 0)) {
throw new IOException("SEQUENCE length error");
}
AlgorithmId algId = AlgorithmId.parse(values[0]);
if (algId.getOID().equals(oid) == false) {
throw new IOException("ObjectIdentifier mismatch: "
+ algId.getOID());
}
if (algId.getEncodedParams() != null) {
throw new IOException("Unexpected AlgorithmId parameters");
}
byte[] digest = values[1].getOctetString();
return digest;
}
// set parameter, not supported. See JCA doc
@Deprecated
protected void engineSetParameter(String param, Object value)
throws InvalidParameterException {
throw new UnsupportedOperationException("setParameter() not supported");
}
// get parameter, not supported. See JCA doc
@Deprecated
protected Object engineGetParameter(String param)
throws InvalidParameterException {
throw new UnsupportedOperationException("getParameter() not supported");
}
// Nested class for MD2withRSA signatures
public static final class MD2withRSA extends RSASignature {
public MD2withRSA() {
super("MD2", AlgorithmId.MD2_oid, 10);
}
}
// Nested class for MD5withRSA signatures
public static final class MD5withRSA extends RSASignature {
public MD5withRSA() {
super("MD5", AlgorithmId.MD5_oid, 10);
}
}
// Nested class for SHA1withRSA signatures
public static final class SHA1withRSA extends RSASignature {
public SHA1withRSA() {
super("SHA-1", AlgorithmId.SHA_oid, 7);
}
}
// Nested class for SHA224withRSA signatures
public static final class SHA224withRSA extends RSASignature {
public SHA224withRSA() {
super("SHA-224", AlgorithmId.SHA224_oid, 11);
}
}
// Nested class for SHA256withRSA signatures
public static final class SHA256withRSA extends RSASignature {
public SHA256withRSA() {
super("SHA-256", AlgorithmId.SHA256_oid, 11);
}
}
// Nested class for SHA384withRSA signatures
public static final class SHA384withRSA extends RSASignature {
public SHA384withRSA() {
super("SHA-384", AlgorithmId.SHA384_oid, 11);
}
}
// Nested class for SHA512withRSA signatures
public static final class SHA512withRSA extends RSASignature {
public SHA512withRSA() {
super("SHA-512", AlgorithmId.SHA512_oid, 11);
}
}
}

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2003, 2016, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.rsa;
import java.util.*;
import java.security.*;
import sun.security.action.PutAllAction;
import static sun.security.util.SecurityConstants.PROVIDER_VER;
/**
* Provider class for the RSA signature provider. Supports RSA keyfactory,
* keypair generation, and RSA signatures.
*
* @since 1.5
* @author Andreas Sterbenz
*/
public final class SunRsaSign extends Provider {
private static final long serialVersionUID = 866040293550393045L;
public SunRsaSign() {
super("SunRsaSign", PROVIDER_VER, "Sun RSA signature provider");
// if there is no security manager installed, put directly into
// the provider. Otherwise, create a temporary map and use a
// doPrivileged() call at the end to transfer the contents
if (System.getSecurityManager() == null) {
SunRsaSignEntries.putEntries(this);
} else {
// use LinkedHashMap to preserve the order of the PRNGs
Map<Object, Object> map = new HashMap<>();
SunRsaSignEntries.putEntries(map);
AccessController.doPrivileged(new PutAllAction(this, map));
}
}
}

View file

@ -0,0 +1,107 @@
/*
* Copyright (c) 2003, 2012, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.rsa;
import java.util.Map;
/**
* Defines the entries of the SunRsaSign provider.
*
* @author Andreas Sterbenz
*/
public final class SunRsaSignEntries {
private SunRsaSignEntries() {
// empty
}
public static void putEntries(Map<Object, Object> map) {
// main algorithms
map.put("KeyFactory.RSA",
"sun.security.rsa.RSAKeyFactory");
map.put("KeyPairGenerator.RSA",
"sun.security.rsa.RSAKeyPairGenerator");
map.put("Signature.MD2withRSA",
"sun.security.rsa.RSASignature$MD2withRSA");
map.put("Signature.MD5withRSA",
"sun.security.rsa.RSASignature$MD5withRSA");
map.put("Signature.SHA1withRSA",
"sun.security.rsa.RSASignature$SHA1withRSA");
map.put("Signature.SHA224withRSA",
"sun.security.rsa.RSASignature$SHA224withRSA");
map.put("Signature.SHA256withRSA",
"sun.security.rsa.RSASignature$SHA256withRSA");
map.put("Signature.SHA384withRSA",
"sun.security.rsa.RSASignature$SHA384withRSA");
map.put("Signature.SHA512withRSA",
"sun.security.rsa.RSASignature$SHA512withRSA");
// attributes for supported key classes
String rsaKeyClasses = "java.security.interfaces.RSAPublicKey" +
"|java.security.interfaces.RSAPrivateKey";
map.put("Signature.MD2withRSA SupportedKeyClasses", rsaKeyClasses);
map.put("Signature.MD5withRSA SupportedKeyClasses", rsaKeyClasses);
map.put("Signature.SHA1withRSA SupportedKeyClasses", rsaKeyClasses);
map.put("Signature.SHA224withRSA SupportedKeyClasses", rsaKeyClasses);
map.put("Signature.SHA256withRSA SupportedKeyClasses", rsaKeyClasses);
map.put("Signature.SHA384withRSA SupportedKeyClasses", rsaKeyClasses);
map.put("Signature.SHA512withRSA SupportedKeyClasses", rsaKeyClasses);
// aliases
map.put("Alg.Alias.KeyFactory.1.2.840.113549.1.1", "RSA");
map.put("Alg.Alias.KeyFactory.OID.1.2.840.113549.1.1", "RSA");
map.put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1", "RSA");
map.put("Alg.Alias.KeyPairGenerator.OID.1.2.840.113549.1.1", "RSA");
map.put("Alg.Alias.Signature.1.2.840.113549.1.1.2", "MD2withRSA");
map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.2", "MD2withRSA");
map.put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5withRSA");
map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.4", "MD5withRSA");
map.put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5", "SHA1withRSA");
map.put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1withRSA");
map.put("Alg.Alias.Signature.1.2.840.113549.1.1.14", "SHA224withRSA");
map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.14", "SHA224withRSA");
map.put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA256withRSA");
map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.11", "SHA256withRSA");
map.put("Alg.Alias.Signature.1.2.840.113549.1.1.12", "SHA384withRSA");
map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.12", "SHA384withRSA");
map.put("Alg.Alias.Signature.1.2.840.113549.1.1.13", "SHA512withRSA");
map.put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.13", "SHA512withRSA");
}
}