ECUtil.java revision a198e1ecc615e26a167d0f2dca9fa7e5fc62de10
1package org.bouncycastle.jcajce.provider.asymmetric.util;
2
3import java.security.InvalidKeyException;
4import java.security.PrivateKey;
5import java.security.PublicKey;
6
7import org.bouncycastle.asn1.ASN1ObjectIdentifier;
8// BEGIN android-removed
9// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
10// END android-removed
11import org.bouncycastle.asn1.nist.NISTNamedCurves;
12import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
13import org.bouncycastle.asn1.sec.SECNamedCurves;
14// BEGIN android-removed
15// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
16// END android-removed
17import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
18import org.bouncycastle.asn1.x9.X962NamedCurves;
19import org.bouncycastle.asn1.x9.X9ECParameters;
20import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
21import org.bouncycastle.crypto.params.ECDomainParameters;
22import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
23import org.bouncycastle.crypto.params.ECPublicKeyParameters;
24import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
25import org.bouncycastle.jce.interfaces.ECPrivateKey;
26import org.bouncycastle.jce.interfaces.ECPublicKey;
27import org.bouncycastle.jce.provider.BouncyCastleProvider;
28import org.bouncycastle.jce.spec.ECParameterSpec;
29
30/**
31 * utility class for converting jce/jca ECDSA, ECDH, and ECDHC
32 * objects into their org.bouncycastle.crypto counterparts.
33 */
34public class ECUtil
35{
36    /**
37     * Returns a sorted array of middle terms of the reduction polynomial.
38     * @param k The unsorted array of middle terms of the reduction polynomial
39     * of length 1 or 3.
40     * @return the sorted array of middle terms of the reduction polynomial.
41     * This array always has length 3.
42     */
43    static int[] convertMidTerms(
44        int[] k)
45    {
46        int[] res = new int[3];
47
48        if (k.length == 1)
49        {
50            res[0] = k[0];
51        }
52        else
53        {
54            if (k.length != 3)
55            {
56                throw new IllegalArgumentException("Only Trinomials and pentanomials supported");
57            }
58
59            if (k[0] < k[1] && k[0] < k[2])
60            {
61                res[0] = k[0];
62                if (k[1] < k[2])
63                {
64                    res[1] = k[1];
65                    res[2] = k[2];
66                }
67                else
68                {
69                    res[1] = k[2];
70                    res[2] = k[1];
71                }
72            }
73            else if (k[1] < k[2])
74            {
75                res[0] = k[1];
76                if (k[0] < k[2])
77                {
78                    res[1] = k[0];
79                    res[2] = k[2];
80                }
81                else
82                {
83                    res[1] = k[2];
84                    res[2] = k[0];
85                }
86            }
87            else
88            {
89                res[0] = k[2];
90                if (k[0] < k[1])
91                {
92                    res[1] = k[0];
93                    res[2] = k[1];
94                }
95                else
96                {
97                    res[1] = k[1];
98                    res[2] = k[0];
99                }
100            }
101        }
102
103        return res;
104    }
105
106    public static AsymmetricKeyParameter generatePublicKeyParameter(
107        PublicKey    key)
108        throws InvalidKeyException
109    {
110        if (key instanceof ECPublicKey)
111        {
112            ECPublicKey    k = (ECPublicKey)key;
113            ECParameterSpec s = k.getParameters();
114
115            if (s == null)
116            {
117                s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
118
119                return new ECPublicKeyParameters(
120                            ((BCECPublicKey)k).engineGetQ(),
121                            new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
122            }
123            else
124            {
125                return new ECPublicKeyParameters(
126                            k.getQ(),
127                            new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
128            }
129        }
130        else if (key instanceof java.security.interfaces.ECPublicKey)
131        {
132            java.security.interfaces.ECPublicKey pubKey = (java.security.interfaces.ECPublicKey)key;
133            ECParameterSpec s = EC5Util.convertSpec(pubKey.getParams(), false);
134            return new ECPublicKeyParameters(
135                EC5Util.convertPoint(pubKey.getParams(), pubKey.getW(), false),
136                            new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
137        }
138        else
139        {
140            // see if we can build a key from key.getEncoded()
141            try
142            {
143                byte[] bytes = key.getEncoded();
144
145                if (bytes == null)
146                {
147                    throw new InvalidKeyException("no encoding for EC public key");
148                }
149
150                PublicKey publicKey = BouncyCastleProvider.getPublicKey(SubjectPublicKeyInfo.getInstance(bytes));
151
152                if (publicKey instanceof java.security.interfaces.ECPublicKey)
153                {
154                    return ECUtil.generatePublicKeyParameter(publicKey);
155                }
156            }
157            catch (Exception e)
158            {
159                throw new InvalidKeyException("cannot identify EC public key: " + e.toString());
160            }
161        }
162
163        throw new InvalidKeyException("cannot identify EC public key.");
164    }
165
166    public static AsymmetricKeyParameter generatePrivateKeyParameter(
167        PrivateKey    key)
168        throws InvalidKeyException
169    {
170        if (key instanceof ECPrivateKey)
171        {
172            ECPrivateKey  k = (ECPrivateKey)key;
173            ECParameterSpec s = k.getParameters();
174
175            if (s == null)
176            {
177                s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
178            }
179
180            return new ECPrivateKeyParameters(
181                            k.getD(),
182                            new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
183        }
184        else if (key instanceof java.security.interfaces.ECPrivateKey)
185        {
186            java.security.interfaces.ECPrivateKey privKey = (java.security.interfaces.ECPrivateKey)key;
187            ECParameterSpec s = EC5Util.convertSpec(privKey.getParams(), false);
188            return new ECPrivateKeyParameters(
189                            privKey.getS(),
190                            new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
191        }
192        else
193        {
194            // see if we can build a key from key.getEncoded()
195            try
196            {
197                byte[] bytes = key.getEncoded();
198
199                if (bytes == null)
200                {
201                    throw new InvalidKeyException("no encoding for EC private key");
202                }
203
204                PrivateKey privateKey = BouncyCastleProvider.getPrivateKey(PrivateKeyInfo.getInstance(bytes));
205
206                if (privateKey instanceof java.security.interfaces.ECPrivateKey)
207                {
208                    return ECUtil.generatePrivateKeyParameter(privateKey);
209                }
210            }
211            catch (Exception e)
212            {
213                throw new InvalidKeyException("cannot identify EC private key: " + e.toString());
214            }
215        }
216
217        throw new InvalidKeyException("can't identify EC private key.");
218    }
219
220    public static ASN1ObjectIdentifier getNamedCurveOid(
221        String name)
222    {
223        ASN1ObjectIdentifier oid = X962NamedCurves.getOID(name);
224
225        if (oid == null)
226        {
227            oid = SECNamedCurves.getOID(name);
228            if (oid == null)
229            {
230                oid = NISTNamedCurves.getOID(name);
231            }
232            // BEGIN android-removed
233            // if (oid == null)
234            // {
235            //     oid = TeleTrusTNamedCurves.getOID(name);
236            // }
237            // if (oid == null)
238            // {
239            //     oid = ECGOST3410NamedCurves.getOID(name);
240            // }
241            // END android-removed
242        }
243
244        return oid;
245    }
246
247    public static X9ECParameters getNamedCurveByOid(
248        ASN1ObjectIdentifier oid)
249    {
250        X9ECParameters params = X962NamedCurves.getByOID(oid);
251
252        if (params == null)
253        {
254            params = SECNamedCurves.getByOID(oid);
255            if (params == null)
256            {
257                params = NISTNamedCurves.getByOID(oid);
258            }
259            // BEGIN android-removed
260            // if (params == null)
261            // {
262            //     params = TeleTrusTNamedCurves.getByOID(oid);
263            // }
264            // END android-removed
265        }
266
267        return params;
268    }
269
270    public static String getCurveName(
271        ASN1ObjectIdentifier oid)
272    {
273        String name = X962NamedCurves.getName(oid);
274
275        if (name == null)
276        {
277            name = SECNamedCurves.getName(oid);
278            if (name == null)
279            {
280                name = NISTNamedCurves.getName(oid);
281            }
282            // BEGIN android-removed
283            // if (name == null)
284            // {
285            //     name = TeleTrusTNamedCurves.getName(oid);
286            // }
287            // if (name == null)
288            // {
289            //     name = ECGOST3410NamedCurves.getName(oid);
290            // }
291            // END android-removed
292        }
293
294        return name;
295    }
296}
297