|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.rsa; |
|
|
|
import java.io.IOException; |
|
import java.math.BigInteger; |
|
|
|
import java.security.*; |
|
import java.security.spec.*; |
|
import java.security.interfaces.*; |
|
|
|
import sun.security.util.*; |
|
|
|
import sun.security.x509.AlgorithmId; |
|
import sun.security.pkcs.PKCS8Key; |
|
|
|
import static sun.security.rsa.RSAUtil.KeyType; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final class RSAPrivateCrtKeyImpl |
|
extends PKCS8Key implements RSAPrivateCrtKey { |
|
|
|
private static final long serialVersionUID = -1326088454257084918L; |
|
|
|
private BigInteger n; |
|
private BigInteger e; |
|
private BigInteger d; |
|
private BigInteger p; |
|
private BigInteger q; |
|
private BigInteger pe; |
|
private BigInteger qe; |
|
private BigInteger coeff; |
|
|
|
// Optional parameters associated with this RSA key |
|
// specified in the encoding of its AlgorithmId. |
|
|
|
private AlgorithmParameterSpec keyParams; |
|
|
|
|
|
|
|
|
|
*/ |
|
public static RSAPrivateKey newKey(byte[] encoded) |
|
throws InvalidKeyException { |
|
RSAPrivateCrtKeyImpl key = new RSAPrivateCrtKeyImpl(encoded); |
|
// check all CRT-specific components are available, if any one |
|
|
|
if ((key.getPublicExponent().signum() == 0) || |
|
(key.getPrimeExponentP().signum() == 0) || |
|
(key.getPrimeExponentQ().signum() == 0) || |
|
(key.getPrimeP().signum() == 0) || |
|
(key.getPrimeQ().signum() == 0) || |
|
(key.getCrtCoefficient().signum() == 0)) { |
|
return new RSAPrivateKeyImpl( |
|
key.algid, |
|
key.getModulus(), |
|
key.getPrivateExponent() |
|
); |
|
} else { |
|
return key; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static RSAPrivateKey newKey(KeyType type, |
|
AlgorithmParameterSpec params, |
|
BigInteger n, BigInteger e, BigInteger d, |
|
BigInteger p, BigInteger q, BigInteger pe, BigInteger qe, |
|
BigInteger coeff) throws InvalidKeyException { |
|
RSAPrivateKey key; |
|
AlgorithmId rsaId = RSAUtil.createAlgorithmId(type, params); |
|
if ((e.signum() == 0) || (p.signum() == 0) || |
|
(q.signum() == 0) || (pe.signum() == 0) || |
|
(qe.signum() == 0) || (coeff.signum() == 0)) { |
|
|
|
return new RSAPrivateKeyImpl(rsaId, n, d); |
|
} else { |
|
return new RSAPrivateCrtKeyImpl(rsaId, n, e, d, |
|
p, q, pe, qe, coeff); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException { |
|
if (encoded == null || encoded.length == 0) { |
|
throw new InvalidKeyException("Missing key encoding"); |
|
} |
|
|
|
decode(encoded); |
|
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e); |
|
try { |
|
|
|
this.keyParams = RSAUtil.getParamSpec(algid); |
|
} catch (ProviderException e) { |
|
throw new InvalidKeyException(e); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
RSAPrivateCrtKeyImpl(AlgorithmId rsaId, |
|
BigInteger n, BigInteger e, BigInteger d, |
|
BigInteger p, BigInteger q, BigInteger pe, BigInteger qe, |
|
BigInteger coeff) throws InvalidKeyException { |
|
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e); |
|
|
|
this.n = n; |
|
this.e = e; |
|
this.d = d; |
|
this.p = p; |
|
this.q = q; |
|
this.pe = pe; |
|
this.qe = qe; |
|
this.coeff = coeff; |
|
this.keyParams = RSAUtil.getParamSpec(rsaId); |
|
|
|
|
|
algid = rsaId; |
|
try { |
|
DerOutputStream out = new DerOutputStream(); |
|
out.putInteger(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) { |
|
|
|
throw new InvalidKeyException(exc); |
|
} |
|
} |
|
|
|
|
|
@Override |
|
public String getAlgorithm() { |
|
return algid.getName(); |
|
} |
|
|
|
|
|
@Override |
|
public BigInteger getModulus() { |
|
return n; |
|
} |
|
|
|
|
|
@Override |
|
public BigInteger getPublicExponent() { |
|
return e; |
|
} |
|
|
|
|
|
@Override |
|
public BigInteger getPrivateExponent() { |
|
return d; |
|
} |
|
|
|
|
|
@Override |
|
public BigInteger getPrimeP() { |
|
return p; |
|
} |
|
|
|
|
|
@Override |
|
public BigInteger getPrimeQ() { |
|
return q; |
|
} |
|
|
|
|
|
@Override |
|
public BigInteger getPrimeExponentP() { |
|
return pe; |
|
} |
|
|
|
|
|
@Override |
|
public BigInteger getPrimeExponentQ() { |
|
return qe; |
|
} |
|
|
|
|
|
@Override |
|
public BigInteger getCrtCoefficient() { |
|
return coeff; |
|
} |
|
|
|
|
|
@Override |
|
public AlgorithmParameterSpec getParams() { |
|
return keyParams; |
|
} |
|
|
|
|
|
@Override |
|
public String toString() { |
|
return "SunRsaSign " + getAlgorithm() + " private CRT key, " + n.bitLength() |
|
+ " bits" + "\n params: " + keyParams + "\n modulus: " + n |
|
+ "\n private exponent: " + d; |
|
} |
|
|
|
|
|
|
|
*/ |
|
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"); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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); |
|
} |
|
} |
|
} |