• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.bouncycastle.jcajce.provider.asymmetric.util;
2 
3 import java.math.BigInteger;
4 import java.security.InvalidKeyException;
5 import java.security.PrivateKey;
6 import java.security.PublicKey;
7 import java.util.Enumeration;
8 
9 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
10 // BEGIN android-removed
11 // import org.bouncycastle.asn1.anssi.ANSSINamedCurves;
12 // import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
13 // END android-removed
14 import org.bouncycastle.asn1.nist.NISTNamedCurves;
15 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
16 import org.bouncycastle.asn1.sec.SECNamedCurves;
17 // BEGIN android-removed
18 // import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
19 // END android-removed
20 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
21 import org.bouncycastle.asn1.x9.ECNamedCurveTable;
22 import org.bouncycastle.asn1.x9.X962NamedCurves;
23 import org.bouncycastle.asn1.x9.X9ECParameters;
24 import org.bouncycastle.crypto.ec.CustomNamedCurves;
25 import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
26 import org.bouncycastle.crypto.params.ECDomainParameters;
27 import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
28 import org.bouncycastle.crypto.params.ECPublicKeyParameters;
29 import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
30 import org.bouncycastle.jce.interfaces.ECPrivateKey;
31 import org.bouncycastle.jce.interfaces.ECPublicKey;
32 import org.bouncycastle.jce.provider.BouncyCastleProvider;
33 import org.bouncycastle.jce.spec.ECParameterSpec;
34 
35 /**
36  * utility class for converting jce/jca ECDSA, ECDH, and ECDHC
37  * objects into their org.bouncycastle.crypto counterparts.
38  */
39 public class ECUtil
40 {
41     /**
42      * Returns a sorted array of middle terms of the reduction polynomial.
43      * @param k The unsorted array of middle terms of the reduction polynomial
44      * of length 1 or 3.
45      * @return the sorted array of middle terms of the reduction polynomial.
46      * This array always has length 3.
47      */
convertMidTerms( int[] k)48     static int[] convertMidTerms(
49         int[] k)
50     {
51         int[] res = new int[3];
52 
53         if (k.length == 1)
54         {
55             res[0] = k[0];
56         }
57         else
58         {
59             if (k.length != 3)
60             {
61                 throw new IllegalArgumentException("Only Trinomials and pentanomials supported");
62             }
63 
64             if (k[0] < k[1] && k[0] < k[2])
65             {
66                 res[0] = k[0];
67                 if (k[1] < k[2])
68                 {
69                     res[1] = k[1];
70                     res[2] = k[2];
71                 }
72                 else
73                 {
74                     res[1] = k[2];
75                     res[2] = k[1];
76                 }
77             }
78             else if (k[1] < k[2])
79             {
80                 res[0] = k[1];
81                 if (k[0] < k[2])
82                 {
83                     res[1] = k[0];
84                     res[2] = k[2];
85                 }
86                 else
87                 {
88                     res[1] = k[2];
89                     res[2] = k[0];
90                 }
91             }
92             else
93             {
94                 res[0] = k[2];
95                 if (k[0] < k[1])
96                 {
97                     res[1] = k[0];
98                     res[2] = k[1];
99                 }
100                 else
101                 {
102                     res[1] = k[1];
103                     res[2] = k[0];
104                 }
105             }
106         }
107 
108         return res;
109     }
110 
generatePublicKeyParameter( PublicKey key)111     public static AsymmetricKeyParameter generatePublicKeyParameter(
112         PublicKey    key)
113         throws InvalidKeyException
114     {
115         if (key instanceof ECPublicKey)
116         {
117             ECPublicKey    k = (ECPublicKey)key;
118             ECParameterSpec s = k.getParameters();
119 
120             if (s == null)
121             {
122                 s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
123 
124                 return new ECPublicKeyParameters(
125                             ((BCECPublicKey)k).engineGetQ(),
126                             new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
127             }
128             else
129             {
130                 return new ECPublicKeyParameters(
131                             k.getQ(),
132                             new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
133             }
134         }
135         else if (key instanceof java.security.interfaces.ECPublicKey)
136         {
137             java.security.interfaces.ECPublicKey pubKey = (java.security.interfaces.ECPublicKey)key;
138             ECParameterSpec s = EC5Util.convertSpec(pubKey.getParams(), false);
139             return new ECPublicKeyParameters(
140                 EC5Util.convertPoint(pubKey.getParams(), pubKey.getW(), false),
141                             new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
142         }
143         else
144         {
145             // see if we can build a key from key.getEncoded()
146             try
147             {
148                 byte[] bytes = key.getEncoded();
149 
150                 if (bytes == null)
151                 {
152                     throw new InvalidKeyException("no encoding for EC public key");
153                 }
154 
155                 PublicKey publicKey = BouncyCastleProvider.getPublicKey(SubjectPublicKeyInfo.getInstance(bytes));
156 
157                 if (publicKey instanceof java.security.interfaces.ECPublicKey)
158                 {
159                     return ECUtil.generatePublicKeyParameter(publicKey);
160                 }
161             }
162             catch (Exception e)
163             {
164                 throw new InvalidKeyException("cannot identify EC public key: " + e.toString());
165             }
166         }
167 
168         throw new InvalidKeyException("cannot identify EC public key.");
169     }
170 
generatePrivateKeyParameter( PrivateKey key)171     public static AsymmetricKeyParameter generatePrivateKeyParameter(
172         PrivateKey    key)
173         throws InvalidKeyException
174     {
175         if (key instanceof ECPrivateKey)
176         {
177             ECPrivateKey  k = (ECPrivateKey)key;
178             ECParameterSpec s = k.getParameters();
179 
180             if (s == null)
181             {
182                 s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
183             }
184 
185             return new ECPrivateKeyParameters(
186                             k.getD(),
187                             new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
188         }
189         else if (key instanceof java.security.interfaces.ECPrivateKey)
190         {
191             java.security.interfaces.ECPrivateKey privKey = (java.security.interfaces.ECPrivateKey)key;
192             ECParameterSpec s = EC5Util.convertSpec(privKey.getParams(), false);
193             return new ECPrivateKeyParameters(
194                             privKey.getS(),
195                             new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed()));
196         }
197         else
198         {
199             // see if we can build a key from key.getEncoded()
200             try
201             {
202                 byte[] bytes = key.getEncoded();
203 
204                 if (bytes == null)
205                 {
206                     throw new InvalidKeyException("no encoding for EC private key");
207                 }
208 
209                 PrivateKey privateKey = BouncyCastleProvider.getPrivateKey(PrivateKeyInfo.getInstance(bytes));
210 
211                 if (privateKey instanceof java.security.interfaces.ECPrivateKey)
212                 {
213                     return ECUtil.generatePrivateKeyParameter(privateKey);
214                 }
215             }
216             catch (Exception e)
217             {
218                 throw new InvalidKeyException("cannot identify EC private key: " + e.toString());
219             }
220         }
221 
222         throw new InvalidKeyException("can't identify EC private key.");
223     }
224 
getOrderBitLength(BigInteger order, BigInteger privateValue)225     public static int getOrderBitLength(BigInteger order, BigInteger privateValue)
226     {
227         if (order == null)     // implicitly CA
228         {
229             ECParameterSpec implicitCA = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
230 
231             if (implicitCA == null)
232             {
233                 return privateValue.bitLength();   // a guess but better than an exception!
234             }
235 
236             return implicitCA.getN().bitLength();
237         }
238         else
239         {
240             return order.bitLength();
241         }
242     }
243 
getNamedCurveOid( String curveName)244     public static ASN1ObjectIdentifier getNamedCurveOid(
245         String curveName)
246     {
247         String name;
248 
249         if (curveName.indexOf(' ') > 0)
250         {
251             name = curveName.substring(curveName.indexOf(' ') + 1);
252         }
253         else
254         {
255             name = curveName;
256         }
257 
258         try
259         {
260             if (name.charAt(0) >= '0' && name.charAt(0) <= '2')
261             {
262                 return new ASN1ObjectIdentifier(name);
263             }
264             else
265             {
266                 return lookupOidByName(name);
267             }
268         }
269         catch (IllegalArgumentException ex)
270         {
271             return lookupOidByName(name);
272         }
273     }
274 
lookupOidByName(String name)275     private static ASN1ObjectIdentifier lookupOidByName(String name)
276     {
277         ASN1ObjectIdentifier oid = X962NamedCurves.getOID(name);
278 
279         if (oid == null)
280         {
281             oid = SECNamedCurves.getOID(name);
282             if (oid == null)
283             {
284                 oid = NISTNamedCurves.getOID(name);
285             }
286             // BEGIN android-removed
287             // if (oid == null)
288             // {
289             //     oid = TeleTrusTNamedCurves.getOID(name);
290             // }
291             // if (oid == null)
292             // {
293             //     oid = ECGOST3410NamedCurves.getOID(name);
294             // }
295             // if (oid == null)
296             // {
297             //     oid = ANSSINamedCurves.getOID(name);
298             // }
299             // END android-removed
300         }
301 
302         return oid;
303     }
304 
getNamedCurveOid( ECParameterSpec ecParameterSpec)305     public static ASN1ObjectIdentifier getNamedCurveOid(
306         ECParameterSpec ecParameterSpec)
307     {
308         for (Enumeration names = ECNamedCurveTable.getNames(); names.hasMoreElements();)
309         {
310             String name = (String)names.nextElement();
311 
312             X9ECParameters params = ECNamedCurveTable.getByName(name);
313 
314             if (params.getN().equals(ecParameterSpec.getN())
315                 && params.getH().equals(ecParameterSpec.getH())
316                 && params.getCurve().equals(ecParameterSpec.getCurve())
317                 && params.getG().equals(ecParameterSpec.getG()))
318             {
319                 return org.bouncycastle.asn1.x9.ECNamedCurveTable.getOID(name);
320             }
321         }
322 
323         return null;
324     }
325 
getNamedCurveByOid( ASN1ObjectIdentifier oid)326     public static X9ECParameters getNamedCurveByOid(
327         ASN1ObjectIdentifier oid)
328     {
329         X9ECParameters params = CustomNamedCurves.getByOID(oid);
330 
331         if (params == null)
332         {
333             params = X962NamedCurves.getByOID(oid);
334             if (params == null)
335             {
336                 params = SECNamedCurves.getByOID(oid);
337             }
338             if (params == null)
339             {
340                 params = NISTNamedCurves.getByOID(oid);
341             }
342             // BEGIN android-removed
343             // if (params == null)
344             // {
345             //     params = TeleTrusTNamedCurves.getByOID(oid);
346             // }
347             // END android-removed
348         }
349 
350         return params;
351     }
352 
getNamedCurveByName( String curveName)353     public static X9ECParameters getNamedCurveByName(
354         String curveName)
355     {
356         X9ECParameters params = CustomNamedCurves.getByName(curveName);
357 
358         if (params == null)
359         {
360             params = X962NamedCurves.getByName(curveName);
361             if (params == null)
362             {
363                 params = SECNamedCurves.getByName(curveName);
364             }
365             if (params == null)
366             {
367                 params = NISTNamedCurves.getByName(curveName);
368             }
369             // BEGIN android-removed
370             // if (params == null)
371             // {
372             //     params = TeleTrusTNamedCurves.getByName(curveName);
373             // }
374             // END android-removed
375         }
376 
377         return params;
378     }
379 
getCurveName( ASN1ObjectIdentifier oid)380     public static String getCurveName(
381         ASN1ObjectIdentifier oid)
382     {
383         String name = X962NamedCurves.getName(oid);
384 
385         if (name == null)
386         {
387             name = SECNamedCurves.getName(oid);
388             if (name == null)
389             {
390                 name = NISTNamedCurves.getName(oid);
391             }
392             // BEGIN android-removed
393             // if (name == null)
394             // {
395             //     name = TeleTrusTNamedCurves.getName(oid);
396             // }
397             // if (name == null)
398             // {
399             //     name = ECGOST3410NamedCurves.getName(oid);
400             // }
401             // END android-removed
402         }
403 
404         return name;
405     }
406 }
407