PrivateKeyFactory.java revision e6bf3e8dfa2804891a82075cb469b736321b4827
1package org.bouncycastle.crypto.util;
2
3import java.io.IOException;
4import java.io.InputStream;
5import java.math.BigInteger;
6
7import org.bouncycastle.asn1.ASN1Encodable;
8import org.bouncycastle.asn1.ASN1InputStream;
9import org.bouncycastle.asn1.ASN1ObjectIdentifier;
10import org.bouncycastle.asn1.ASN1Primitive;
11import org.bouncycastle.asn1.ASN1Sequence;
12import org.bouncycastle.asn1.DERInteger;
13import org.bouncycastle.asn1.nist.NISTNamedCurves;
14// BEGIN android-removed
15// import org.bouncycastle.asn1.oiw.ElGamalParameter;
16// END android-removed
17import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
18import org.bouncycastle.asn1.pkcs.DHParameter;
19import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
20import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
21import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
22import org.bouncycastle.asn1.sec.ECPrivateKey;
23import org.bouncycastle.asn1.sec.SECNamedCurves;
24// BEGIN android-removed
25// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
26// END android-removed
27import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
28import org.bouncycastle.asn1.x509.DSAParameter;
29import org.bouncycastle.asn1.x9.X962NamedCurves;
30import org.bouncycastle.asn1.x9.X962Parameters;
31import org.bouncycastle.asn1.x9.X9ECParameters;
32import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
33import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
34import org.bouncycastle.crypto.params.DHParameters;
35import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
36import org.bouncycastle.crypto.params.DSAParameters;
37import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
38import org.bouncycastle.crypto.params.ECDomainParameters;
39import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
40// BEGIN android-removed
41// import org.bouncycastle.crypto.params.ElGamalParameters;
42// import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
43// END android-removed
44import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
45
46/**
47 * Factory for creating private key objects from PKCS8 PrivateKeyInfo objects.
48 */
49public class PrivateKeyFactory
50{
51    /**
52     * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding.
53     *
54     * @param privateKeyInfoData the PrivateKeyInfo encoding
55     * @return a suitable private key parameter
56     * @throws IOException on an error decoding the key
57     */
58    public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) throws IOException
59    {
60        return createKey(PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(privateKeyInfoData)));
61    }
62
63    /**
64     * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding read from a
65     * stream.
66     *
67     * @param inStr the stream to read the PrivateKeyInfo encoding from
68     * @return a suitable private key parameter
69     * @throws IOException on an error decoding the key
70     */
71    public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException
72    {
73        return createKey(PrivateKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
74    }
75
76    /**
77     * Create a private key parameter from the passed in PKCS8 PrivateKeyInfo object.
78     *
79     * @param keyInfo the PrivateKeyInfo object containing the key material
80     * @return a suitable private key parameter
81     * @throws IOException on an error decoding the key
82     */
83    public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) throws IOException
84    {
85        AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm();
86
87        if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption))
88        {
89            RSAPrivateKey keyStructure = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey());
90
91            return new RSAPrivateCrtKeyParameters(keyStructure.getModulus(),
92                keyStructure.getPublicExponent(), keyStructure.getPrivateExponent(),
93                keyStructure.getPrime1(), keyStructure.getPrime2(), keyStructure.getExponent1(),
94                keyStructure.getExponent2(), keyStructure.getCoefficient());
95        }
96        // TODO?
97//      else if (algId.getObjectId().equals(X9ObjectIdentifiers.dhpublicnumber))
98        else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
99        {
100            DHParameter params = DHParameter.getInstance(algId.getParameters());
101            DERInteger derX = (DERInteger)keyInfo.parsePrivateKey();
102
103            BigInteger lVal = params.getL();
104            int l = lVal == null ? 0 : lVal.intValue();
105            DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l);
106
107            return new DHPrivateKeyParameters(derX.getValue(), dhParams);
108        }
109        // BEGIN android-removed
110        // else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
111        // {
112        //     ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
113        //     DERInteger derX = (DERInteger)keyInfo.parsePrivateKey();
114        //
115        //     return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(
116        //         params.getP(), params.getG()));
117        // }
118        // END android-removed
119        else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa))
120        {
121            DERInteger derX = (DERInteger)keyInfo.parsePrivateKey();
122            ASN1Encodable de = algId.getParameters();
123
124            DSAParameters parameters = null;
125            if (de != null)
126            {
127                DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive());
128                parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
129            }
130
131            return new DSAPrivateKeyParameters(derX.getValue(), parameters);
132        }
133        else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
134        {
135            X962Parameters params = new X962Parameters((ASN1Primitive)algId.getParameters());
136
137            X9ECParameters x9;
138            if (params.isNamedCurve())
139            {
140                ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
141                x9 = X962NamedCurves.getByOID(oid);
142
143                if (x9 == null)
144                {
145                    x9 = SECNamedCurves.getByOID(oid);
146
147                    if (x9 == null)
148                    {
149                        x9 = NISTNamedCurves.getByOID(oid);
150
151                        // BEGIN android-removed
152                        // if (x9 == null)
153                        // {
154                        //     x9 = TeleTrusTNamedCurves.getByOID(oid);
155                        // }
156                        // END android-removed
157                    }
158                }
159            }
160            else
161            {
162                x9 = X9ECParameters.getInstance(params.getParameters());
163            }
164
165            ECPrivateKey ec = ECPrivateKey.getInstance(keyInfo.parsePrivateKey());
166            BigInteger d = ec.getKey();
167
168            // TODO We lose any named parameters here
169
170            ECDomainParameters dParams = new ECDomainParameters(
171                    x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
172
173            return new ECPrivateKeyParameters(d, dParams);
174        }
175        else
176        {
177            throw new RuntimeException("algorithm identifier in key not recognised");
178        }
179    }
180}
181