blob: 3ed5821368e9d13c64035102e7467789debe4d67 [file] [log] [blame]
package org.bouncycastle.jce.provider;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactorySpi;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHPrivateKeySpec;
import javax.crypto.spec.DHPublicKeySpec;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
// BEGIN android-removed
// import org.bouncycastle.jce.interfaces.ElGamalPrivateKey;
// import org.bouncycastle.jce.interfaces.ElGamalPublicKey;
// import org.bouncycastle.jce.spec.ElGamalPrivateKeySpec;
// import org.bouncycastle.jce.spec.ElGamalPublicKeySpec;
// import org.bouncycastle.jce.spec.GOST3410PrivateKeySpec;
// import org.bouncycastle.jce.spec.GOST3410PublicKeySpec;
// END android-removed
public abstract class JDKKeyFactory
extends KeyFactorySpi
{
// BEGIN android-removed
// protected boolean elGamalFactory = false;
// END android-removed
public JDKKeyFactory()
{
}
protected PrivateKey engineGeneratePrivate(
KeySpec keySpec)
throws InvalidKeySpecException
{
if (keySpec instanceof PKCS8EncodedKeySpec)
{
try
{
return JDKKeyFactory.createPrivateKeyFromDERStream(
((PKCS8EncodedKeySpec)keySpec).getEncoded());
}
catch (Exception e)
{
throw new InvalidKeySpecException(e.toString());
}
}
throw new InvalidKeySpecException("Unknown KeySpec type: " + keySpec.getClass().getName());
}
protected PublicKey engineGeneratePublic(
KeySpec keySpec)
throws InvalidKeySpecException
{
if (keySpec instanceof X509EncodedKeySpec)
{
try
{
return JDKKeyFactory.createPublicKeyFromDERStream(
((X509EncodedKeySpec)keySpec).getEncoded());
}
catch (Exception e)
{
throw new InvalidKeySpecException(e.toString());
}
}
throw new InvalidKeySpecException("Unknown KeySpec type: " + keySpec.getClass().getName());
}
protected KeySpec engineGetKeySpec(
Key key,
Class spec)
throws InvalidKeySpecException
{
if (spec.isAssignableFrom(PKCS8EncodedKeySpec.class) && key.getFormat().equals("PKCS#8"))
{
return new PKCS8EncodedKeySpec(key.getEncoded());
}
else if (spec.isAssignableFrom(X509EncodedKeySpec.class) && key.getFormat().equals("X.509"))
{
return new X509EncodedKeySpec(key.getEncoded());
}
else if (spec.isAssignableFrom(RSAPublicKeySpec.class) && key instanceof RSAPublicKey)
{
RSAPublicKey k = (RSAPublicKey)key;
return new RSAPublicKeySpec(k.getModulus(), k.getPublicExponent());
}
else if (spec.isAssignableFrom(RSAPrivateKeySpec.class) && key instanceof RSAPrivateKey)
{
RSAPrivateKey k = (RSAPrivateKey)key;
return new RSAPrivateKeySpec(k.getModulus(), k.getPrivateExponent());
}
else if (spec.isAssignableFrom(RSAPrivateCrtKeySpec.class) && key instanceof RSAPrivateCrtKey)
{
RSAPrivateCrtKey k = (RSAPrivateCrtKey)key;
return new RSAPrivateCrtKeySpec(
k.getModulus(), k.getPublicExponent(),
k.getPrivateExponent(),
k.getPrimeP(), k.getPrimeQ(),
k.getPrimeExponentP(), k.getPrimeExponentQ(),
k.getCrtCoefficient());
}
else if (spec.isAssignableFrom(DHPrivateKeySpec.class) && key instanceof DHPrivateKey)
{
DHPrivateKey k = (DHPrivateKey)key;
return new DHPrivateKeySpec(k.getX(), k.getParams().getP(), k.getParams().getG());
}
else if (spec.isAssignableFrom(DHPublicKeySpec.class) && key instanceof DHPublicKey)
{
DHPublicKey k = (DHPublicKey)key;
return new DHPublicKeySpec(k.getY(), k.getParams().getP(), k.getParams().getG());
}
// BEGIN android-added
else if (spec.isAssignableFrom(DSAPublicKeySpec.class) && key instanceof DSAPublicKey)
{
DSAPublicKey k = (DSAPublicKey)key;
return new DSAPublicKeySpec(k.getY(), k.getParams().getP(), k.getParams().getQ(), k.getParams().getG());
}
else if (spec.isAssignableFrom(DSAPrivateKeySpec.class) && key instanceof DSAPrivateKey)
{
DSAPrivateKey k = (DSAPrivateKey)key;
return new DSAPrivateKeySpec(k.getX(), k.getParams().getP(), k.getParams().getQ(), k.getParams().getG());
}
// END android-added
throw new RuntimeException("not implemented yet " + key + " " + spec);
}
protected Key engineTranslateKey(
Key key)
throws InvalidKeyException
{
if (key instanceof RSAPublicKey)
{
return new JCERSAPublicKey((RSAPublicKey)key);
}
else if (key instanceof RSAPrivateCrtKey)
{
return new JCERSAPrivateCrtKey((RSAPrivateCrtKey)key);
}
else if (key instanceof RSAPrivateKey)
{
return new JCERSAPrivateKey((RSAPrivateKey)key);
}
else if (key instanceof DHPublicKey)
{
// BEGIN android-removed
// if (elGamalFactory)
// {
// return new JCEElGamalPublicKey((DHPublicKey)key);
// }
// else
// {
// END android-removed
return new JCEDHPublicKey((DHPublicKey)key);
// BEGIN android-removed
// }
// END android-removed
}
else if (key instanceof DHPrivateKey)
{
// BEGIN android-removed
// if (elGamalFactory)
// {
// return new JCEElGamalPrivateKey((DHPrivateKey)key);
// }
// else
// {
// END android-removed
return new JCEDHPrivateKey((DHPrivateKey)key);
// BEGIN android-removed
// }
// END android-removed
}
else if (key instanceof DSAPublicKey)
{
return new JDKDSAPublicKey((DSAPublicKey)key);
}
else if (key instanceof DSAPrivateKey)
{
return new JDKDSAPrivateKey((DSAPrivateKey)key);
}
// BEGIN android-removed
// else if (key instanceof ElGamalPublicKey)
// {
// return new JCEElGamalPublicKey((ElGamalPublicKey)key);
// }
// else if (key instanceof ElGamalPrivateKey)
// {
// return new JCEElGamalPrivateKey((ElGamalPrivateKey)key);
// }
// END android-removed
throw new InvalidKeyException("key type unknown");
}
/**
* create a public key from the given DER encoded input stream.
*/
public static PublicKey createPublicKeyFromDERStream(
byte[] in)
throws IOException
{
return createPublicKeyFromPublicKeyInfo(
new SubjectPublicKeyInfo((ASN1Sequence) ASN1Object.fromByteArray(in)));
}
/**
* create a public key from the given public key info object.
*/
static PublicKey createPublicKeyFromPublicKeyInfo(
SubjectPublicKeyInfo info)
{
DERObjectIdentifier algOid = info.getAlgorithmId().getObjectId();
if (RSAUtil.isRsaOid(algOid))
{
return new JCERSAPublicKey(info);
}
else if (algOid.equals(PKCSObjectIdentifiers.dhKeyAgreement))
{
return new JCEDHPublicKey(info);
}
else if (algOid.equals(X9ObjectIdentifiers.dhpublicnumber))
{
return new JCEDHPublicKey(info);
}
// BEGIN android-removed
// else if (algOid.equals(OIWObjectIdentifiers.elGamalAlgorithm))
// {
// return new JCEElGamalPublicKey(info);
// }
// END android-removed
else if (algOid.equals(X9ObjectIdentifiers.id_dsa))
{
return new JDKDSAPublicKey(info);
}
else if (algOid.equals(OIWObjectIdentifiers.dsaWithSHA1))
{
return new JDKDSAPublicKey(info);
}
else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey))
{
return new JCEECPublicKey(info);
}
// BEGIN android-removed
// else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94))
// {
// return new JDKGOST3410PublicKey(info);
// }
// else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_2001))
// {
// return new JCEECPublicKey(info);
// }
else
{
throw new RuntimeException("algorithm identifier " + algOid + " in key not recognised");
}
}
/**
* create a private key from the given DER encoded input stream.
*/
protected static PrivateKey createPrivateKeyFromDERStream(
byte[] in)
throws IOException
{
return createPrivateKeyFromPrivateKeyInfo(
new PrivateKeyInfo((ASN1Sequence) ASN1Object.fromByteArray(in)));
}
/**
* create a private key from the given public key info object.
*/
static PrivateKey createPrivateKeyFromPrivateKeyInfo(
PrivateKeyInfo info)
{
DERObjectIdentifier algOid = info.getAlgorithmId().getObjectId();
if (RSAUtil.isRsaOid(algOid))
{
return new JCERSAPrivateCrtKey(info);
}
else if (algOid.equals(PKCSObjectIdentifiers.dhKeyAgreement))
{
return new JCEDHPrivateKey(info);
}
else if (algOid.equals(X9ObjectIdentifiers.dhpublicnumber))
{
return new JCEDHPrivateKey(info);
}
// BEGIN android-removed
// else if (algOid.equals(OIWObjectIdentifiers.elGamalAlgorithm))
// {
// return new JCEElGamalPrivateKey(info);
// }
// END android-removed
else if (algOid.equals(X9ObjectIdentifiers.id_dsa))
{
return new JDKDSAPrivateKey(info);
}
else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey))
{
return new JCEECPrivateKey(info);
}
// BEGIN android-removed
// else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94))
// {
// return new JDKGOST3410PrivateKey(info);
// }
// else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_2001))
// {
// return new JCEECPrivateKey(info);
// }
// END android-removed
else
{
throw new RuntimeException("algorithm identifier " + algOid + " in key not recognised");
}
}
public static class RSA
extends JDKKeyFactory
{
public RSA()
{
}
protected PrivateKey engineGeneratePrivate(
KeySpec keySpec)
throws InvalidKeySpecException
{
if (keySpec instanceof PKCS8EncodedKeySpec)
{
try
{
return JDKKeyFactory.createPrivateKeyFromDERStream(
((PKCS8EncodedKeySpec)keySpec).getEncoded());
}
catch (Exception e)
{
//
// in case it's just a RSAPrivateKey object...
//
try
{
return new JCERSAPrivateCrtKey(
new RSAPrivateKeyStructure(
(ASN1Sequence) ASN1Object.fromByteArray(((PKCS8EncodedKeySpec)keySpec).getEncoded())));
}
catch (Exception ex)
{
throw new InvalidKeySpecException(ex.toString());
}
}
}
else if (keySpec instanceof RSAPrivateCrtKeySpec)
{
return new JCERSAPrivateCrtKey((RSAPrivateCrtKeySpec)keySpec);
}
else if (keySpec instanceof RSAPrivateKeySpec)
{
return new JCERSAPrivateKey((RSAPrivateKeySpec)keySpec);
}
throw new InvalidKeySpecException("Unknown KeySpec type: " + keySpec.getClass().getName());
}
protected PublicKey engineGeneratePublic(
KeySpec keySpec)
throws InvalidKeySpecException
{
if (keySpec instanceof RSAPublicKeySpec)
{
return new JCERSAPublicKey((RSAPublicKeySpec)keySpec);
}
return super.engineGeneratePublic(keySpec);
}
}
public static class DH
extends JDKKeyFactory
{
public DH()
{
}
protected PrivateKey engineGeneratePrivate(
KeySpec keySpec)
throws InvalidKeySpecException
{
if (keySpec instanceof DHPrivateKeySpec)
{
return new JCEDHPrivateKey((DHPrivateKeySpec)keySpec);
}
return super.engineGeneratePrivate(keySpec);
}
protected PublicKey engineGeneratePublic(
KeySpec keySpec)
throws InvalidKeySpecException
{
if (keySpec instanceof DHPublicKeySpec)
{
return new JCEDHPublicKey((DHPublicKeySpec)keySpec);
}
return super.engineGeneratePublic(keySpec);
}
}
public static class DSA
extends JDKKeyFactory
{
public DSA()
{
}
protected PrivateKey engineGeneratePrivate(
KeySpec keySpec)
throws InvalidKeySpecException
{
if (keySpec instanceof DSAPrivateKeySpec)
{
return new JDKDSAPrivateKey((DSAPrivateKeySpec)keySpec);
}
return super.engineGeneratePrivate(keySpec);
}
protected PublicKey engineGeneratePublic(
KeySpec keySpec)
throws InvalidKeySpecException
{
if (keySpec instanceof DSAPublicKeySpec)
{
return new JDKDSAPublicKey((DSAPublicKeySpec)keySpec);
}
return super.engineGeneratePublic(keySpec);
}
}
// BEGIN android-removed
// public static class GOST3410
// extends JDKKeyFactory
// {
// public GOST3410()
// {
// }
//
// protected PrivateKey engineGeneratePrivate(
// KeySpec keySpec)
// throws InvalidKeySpecException
// {
// if (keySpec instanceof GOST3410PrivateKeySpec)
// {
// return new JDKGOST3410PrivateKey((GOST3410PrivateKeySpec)keySpec);
// }
//
// return super.engineGeneratePrivate(keySpec);
// }
//
// protected PublicKey engineGeneratePublic(
// KeySpec keySpec)
// throws InvalidKeySpecException
// {
// if (keySpec instanceof GOST3410PublicKeySpec)
// {
// return new JDKGOST3410PublicKey((GOST3410PublicKeySpec)keySpec);
// }
//
// return super.engineGeneratePublic(keySpec);
// }
// }
// public static class ElGamal
// extends JDKKeyFactory
// {
// public ElGamal()
// {
// elGamalFactory = true;
// }
//
// protected PrivateKey engineGeneratePrivate(
// KeySpec keySpec)
// throws InvalidKeySpecException
// {
// if (keySpec instanceof ElGamalPrivateKeySpec)
// {
// return new JCEElGamalPrivateKey((ElGamalPrivateKeySpec)keySpec);
// }
// else if (keySpec instanceof DHPrivateKeySpec)
// {
// return new JCEElGamalPrivateKey((DHPrivateKeySpec)keySpec);
// }
//
// return super.engineGeneratePrivate(keySpec);
// }
//
// protected PublicKey engineGeneratePublic(
// KeySpec keySpec)
// throws InvalidKeySpecException
// {
// if (keySpec instanceof ElGamalPublicKeySpec)
// {
// return new JCEElGamalPublicKey((ElGamalPublicKeySpec)keySpec);
// }
// else if (keySpec instanceof DHPublicKeySpec)
// {
// return new JCEElGamalPublicKey((DHPublicKeySpec)keySpec);
// }
//
// return super.engineGeneratePublic(keySpec);
// }
// }
//
//
//
// /**
// * This isn't really correct, however the class path project API seems to think such
// * a key factory will exist.
// */
// public static class X509
// extends JDKKeyFactory
// {
// public X509()
// {
// }
// }
// END android-removed
}