blob: 911f1dae4dfde2237c5ca0c1b5862e3d0d97e850 [file] [log] [blame]
package org.bouncycastle.crypto.util;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
// Android-removed: Unsupported algorithms
// import org.bouncycastle.asn1.oiw.ElGamalParameter;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.DHParameter;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.sec.ECPrivateKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DHParameters;
import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECNamedDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
// Android-removed: Unsupported algorithms
// import org.bouncycastle.crypto.params.ElGamalParameters;
// import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
/**
* Factory for creating private key objects from PKCS8 PrivateKeyInfo objects.
*/
public class PrivateKeyFactory
{
/**
* Create a private key parameter from a PKCS8 PrivateKeyInfo encoding.
*
* @param privateKeyInfoData the PrivateKeyInfo encoding
* @return a suitable private key parameter
* @throws IOException on an error decoding the key
*/
public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) throws IOException
{
return createKey(PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(privateKeyInfoData)));
}
/**
* Create a private key parameter from a PKCS8 PrivateKeyInfo encoding read from a
* stream.
*
* @param inStr the stream to read the PrivateKeyInfo encoding from
* @return a suitable private key parameter
* @throws IOException on an error decoding the key
*/
public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException
{
return createKey(PrivateKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
}
/**
* Create a private key parameter from the passed in PKCS8 PrivateKeyInfo object.
*
* @param keyInfo the PrivateKeyInfo object containing the key material
* @return a suitable private key parameter
* @throws IOException on an error decoding the key
*/
public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) throws IOException
{
AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm();
if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption))
{
RSAPrivateKey keyStructure = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey());
return new RSAPrivateCrtKeyParameters(keyStructure.getModulus(),
keyStructure.getPublicExponent(), keyStructure.getPrivateExponent(),
keyStructure.getPrime1(), keyStructure.getPrime2(), keyStructure.getExponent1(),
keyStructure.getExponent2(), keyStructure.getCoefficient());
}
// TODO?
// else if (algId.getObjectId().equals(X9ObjectIdentifiers.dhpublicnumber))
else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
{
DHParameter params = DHParameter.getInstance(algId.getParameters());
ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
BigInteger lVal = params.getL();
int l = lVal == null ? 0 : lVal.intValue();
DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l);
return new DHPrivateKeyParameters(derX.getValue(), dhParams);
}
// BEGIN Android-removed: Unsupported algorithms
/*
else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
{
ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters());
ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(
params.getP(), params.getG()));
}
*/
// END Android-removed: Unsupported algorithms
else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa))
{
ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
ASN1Encodable de = algId.getParameters();
DSAParameters parameters = null;
if (de != null)
{
DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive());
parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
}
return new DSAPrivateKeyParameters(derX.getValue(), parameters);
}
else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
{
X962Parameters params = new X962Parameters((ASN1Primitive)algId.getParameters());
X9ECParameters x9;
ECDomainParameters dParams;
if (params.isNamedCurve())
{
ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
x9 = CustomNamedCurves.getByOID(oid);
if (x9 == null)
{
x9 = ECNamedCurveTable.getByOID(oid);
}
dParams = new ECNamedDomainParameters(
oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
}
else
{
x9 = X9ECParameters.getInstance(params.getParameters());
dParams = new ECDomainParameters(
x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
}
ECPrivateKey ec = ECPrivateKey.getInstance(keyInfo.parsePrivateKey());
BigInteger d = ec.getKey();
return new ECPrivateKeyParameters(d, dParams);
}
else
{
throw new RuntimeException("algorithm identifier in key not recognised");
}
}
}