X509Util.java revision e6bf3e8dfa2804891a82075cb469b736321b4827
1package org.bouncycastle.x509;
2
3import java.io.IOException;
4import java.security.InvalidKeyException;
5import java.security.NoSuchAlgorithmException;
6import java.security.NoSuchProviderException;
7import java.security.PrivateKey;
8import java.security.Provider;
9import java.security.SecureRandom;
10import java.security.Security;
11import java.security.Signature;
12import java.security.SignatureException;
13import java.util.ArrayList;
14import java.util.Enumeration;
15import java.util.HashSet;
16import java.util.Hashtable;
17import java.util.Iterator;
18import java.util.List;
19import java.util.Set;
20
21import javax.security.auth.x500.X500Principal;
22
23import org.bouncycastle.asn1.ASN1Encodable;
24import org.bouncycastle.asn1.ASN1Encoding;
25import org.bouncycastle.asn1.ASN1Integer;
26import org.bouncycastle.asn1.DERNull;
27import org.bouncycastle.asn1.DERObjectIdentifier;
28// BEGIN android-removed
29// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
30// END android-removed
31import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
32import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
33import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
34import org.bouncycastle.asn1.pkcs.RSASSAPSSparams;
35// BEGIN android-removed
36// import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
37// END android-removed
38import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
39import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
40import org.bouncycastle.jce.X509Principal;
41import org.bouncycastle.util.Strings;
42
43class X509Util
44{
45    private static Hashtable algorithms = new Hashtable();
46    private static Hashtable params = new Hashtable();
47    private static Set       noParams = new HashSet();
48
49    static
50    {
51        // BEGIN android-removed
52        // algorithms.put("MD2WITHRSAENCRYPTION", PKCSObjectIdentifiers.md2WithRSAEncryption);
53        // algorithms.put("MD2WITHRSA", PKCSObjectIdentifiers.md2WithRSAEncryption);
54        // END android-removed
55        algorithms.put("MD5WITHRSAENCRYPTION", PKCSObjectIdentifiers.md5WithRSAEncryption);
56        algorithms.put("MD5WITHRSA", PKCSObjectIdentifiers.md5WithRSAEncryption);
57        algorithms.put("SHA1WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha1WithRSAEncryption);
58        algorithms.put("SHA1WITHRSA", PKCSObjectIdentifiers.sha1WithRSAEncryption);
59        // BEGIN android-removed
60        // algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption);
61        // algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption);
62        // END android-removed
63        algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption);
64        algorithms.put("SHA256WITHRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption);
65        algorithms.put("SHA384WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha384WithRSAEncryption);
66        algorithms.put("SHA384WITHRSA", PKCSObjectIdentifiers.sha384WithRSAEncryption);
67        algorithms.put("SHA512WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha512WithRSAEncryption);
68        algorithms.put("SHA512WITHRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption);
69        algorithms.put("SHA1WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
70        // BEGIN android-removed
71        // algorithms.put("SHA224WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
72        // END android-removed
73        algorithms.put("SHA256WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
74        algorithms.put("SHA384WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
75        algorithms.put("SHA512WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
76        // BEGIN android-removed
77        // algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
78        // algorithms.put("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
79        // algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
80        // algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
81        // algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
82        // algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
83        // END android-removed
84        algorithms.put("SHA1WITHDSA", X9ObjectIdentifiers.id_dsa_with_sha1);
85        algorithms.put("DSAWITHSHA1", X9ObjectIdentifiers.id_dsa_with_sha1);
86        // BEGIN android-removed
87        // algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224);
88        // END android-removed
89        algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256);
90        algorithms.put("SHA384WITHDSA", NISTObjectIdentifiers.dsa_with_sha384);
91        algorithms.put("SHA512WITHDSA", NISTObjectIdentifiers.dsa_with_sha512);
92        algorithms.put("SHA1WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA1);
93        algorithms.put("ECDSAWITHSHA1", X9ObjectIdentifiers.ecdsa_with_SHA1);
94        // BEGIN android-removed
95        // algorithms.put("SHA224WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA224);
96        // END android-removed
97        algorithms.put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256);
98        algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384);
99        algorithms.put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512);
100        // BEGIN android-removed
101        // algorithms.put("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
102        // algorithms.put("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
103        // algorithms.put("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
104        // algorithms.put("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
105        // algorithms.put("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
106        // END android-removed
107
108        //
109        // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
110        // The parameters field SHALL be NULL for RSA based signature algorithms.
111        //
112        noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA1);
113        // BEGIN android-removed
114        // noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA224);
115        // END android-removed
116        noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA256);
117        noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA384);
118        noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA512);
119        noParams.add(X9ObjectIdentifiers.id_dsa_with_sha1);
120        // BEGIN android-removed
121        // noParams.add(NISTObjectIdentifiers.dsa_with_sha224);
122        // END android-removed
123        noParams.add(NISTObjectIdentifiers.dsa_with_sha256);
124        noParams.add(NISTObjectIdentifiers.dsa_with_sha384);
125        noParams.add(NISTObjectIdentifiers.dsa_with_sha512);
126
127        //
128        // RFC 4491
129        //
130        // BEGIN android-removed
131        // noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
132        // noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
133        // END android-removed
134
135        //
136        // explicit params
137        //
138        // BEGIN android-changed
139        AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
140        // END android-changed
141        params.put("SHA1WITHRSAANDMGF1", creatPSSParams(sha1AlgId, 20));
142
143        // BEGIN android-removed
144        // // BEGIN android-changed
145        // AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha224, DERNull.INSTANCE);
146        // // END android-changed
147        // params.put("SHA224WITHRSAANDMGF1", creatPSSParams(sha224AlgId, 28));
148        // END android-removed
149
150        // BEGIN android-changed
151        AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, DERNull.INSTANCE);
152        // END android-changed
153        params.put("SHA256WITHRSAANDMGF1", creatPSSParams(sha256AlgId, 32));
154
155        // BEGIN android-changed
156        AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha384, DERNull.INSTANCE);
157        // END android-changed
158        params.put("SHA384WITHRSAANDMGF1", creatPSSParams(sha384AlgId, 48));
159
160        // BEGIN android-changed
161        AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha512, DERNull.INSTANCE);
162        // END android-changed
163        params.put("SHA512WITHRSAANDMGF1", creatPSSParams(sha512AlgId, 64));
164    }
165
166    private static RSASSAPSSparams creatPSSParams(AlgorithmIdentifier hashAlgId, int saltSize)
167    {
168        return new RSASSAPSSparams(
169            hashAlgId,
170            new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hashAlgId),
171            new ASN1Integer(saltSize),
172            new ASN1Integer(1));
173    }
174
175    static DERObjectIdentifier getAlgorithmOID(
176        String algorithmName)
177    {
178        algorithmName = Strings.toUpperCase(algorithmName);
179
180        if (algorithms.containsKey(algorithmName))
181        {
182            return (DERObjectIdentifier)algorithms.get(algorithmName);
183        }
184
185        return new DERObjectIdentifier(algorithmName);
186    }
187
188    static AlgorithmIdentifier getSigAlgID(
189        DERObjectIdentifier sigOid,
190        String              algorithmName)
191    {
192        if (noParams.contains(sigOid))
193        {
194            return new AlgorithmIdentifier(sigOid);
195        }
196
197        algorithmName = Strings.toUpperCase(algorithmName);
198
199        if (params.containsKey(algorithmName))
200        {
201            return new AlgorithmIdentifier(sigOid, (ASN1Encodable)params.get(algorithmName));
202        }
203        else
204        {
205            // BEGIN android-changed
206            return new AlgorithmIdentifier(sigOid, DERNull.INSTANCE);
207            // END android-changed
208        }
209    }
210
211    static Iterator getAlgNames()
212    {
213        Enumeration e = algorithms.keys();
214        List        l = new ArrayList();
215
216        while (e.hasMoreElements())
217        {
218            l.add(e.nextElement());
219        }
220
221        return l.iterator();
222    }
223
224    static Signature getSignatureInstance(
225        String algorithm)
226        throws NoSuchAlgorithmException
227    {
228        return Signature.getInstance(algorithm);
229    }
230
231    static Signature getSignatureInstance(
232        String algorithm,
233        String provider)
234        throws NoSuchProviderException, NoSuchAlgorithmException
235    {
236        if (provider != null)
237        {
238            return Signature.getInstance(algorithm, provider);
239        }
240        else
241        {
242            return Signature.getInstance(algorithm);
243        }
244    }
245
246    static byte[] calculateSignature(
247        DERObjectIdentifier sigOid,
248        String              sigName,
249        PrivateKey          key,
250        SecureRandom        random,
251        ASN1Encodable       object)
252        throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException
253    {
254        Signature sig;
255
256        if (sigOid == null)
257        {
258            throw new IllegalStateException("no signature algorithm specified");
259        }
260
261        sig = X509Util.getSignatureInstance(sigName);
262
263        if (random != null)
264        {
265            sig.initSign(key, random);
266        }
267        else
268        {
269            sig.initSign(key);
270        }
271
272        sig.update(object.toASN1Primitive().getEncoded(ASN1Encoding.DER));
273
274        return sig.sign();
275    }
276
277    static byte[] calculateSignature(
278        DERObjectIdentifier sigOid,
279        String              sigName,
280        String              provider,
281        PrivateKey          key,
282        SecureRandom        random,
283        ASN1Encodable       object)
284        throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, SignatureException
285    {
286        Signature sig;
287
288        if (sigOid == null)
289        {
290            throw new IllegalStateException("no signature algorithm specified");
291        }
292
293        sig = X509Util.getSignatureInstance(sigName, provider);
294
295        if (random != null)
296        {
297            sig.initSign(key, random);
298        }
299        else
300        {
301            sig.initSign(key);
302        }
303
304        sig.update(object.toASN1Primitive().getEncoded(ASN1Encoding.DER));
305
306        return sig.sign();
307    }
308
309    static X509Principal convertPrincipal(
310        X500Principal principal)
311    {
312        try
313        {
314            return new X509Principal(principal.getEncoded());
315        }
316        catch (IOException e)
317        {
318            throw new IllegalArgumentException("cannot convert principal");
319        }
320    }
321
322    static class Implementation
323    {
324        Object      engine;
325        Provider provider;
326
327        Implementation(
328            Object      engine,
329            Provider    provider)
330        {
331            this.engine = engine;
332            this.provider = provider;
333        }
334
335        Object getEngine()
336        {
337            return engine;
338        }
339
340        Provider getProvider()
341        {
342            return provider;
343        }
344    }
345
346    /**
347     * see if we can find an algorithm (or its alias and what it represents) in
348     * the property table for the given provider.
349     */
350    static Implementation getImplementation(
351        String      baseName,
352        String      algorithm,
353        Provider    prov)
354        throws NoSuchAlgorithmException
355    {
356        algorithm = Strings.toUpperCase(algorithm);
357
358        String      alias;
359
360        while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null)
361        {
362            algorithm = alias;
363        }
364
365        String      className = prov.getProperty(baseName + "." + algorithm);
366
367        if (className != null)
368        {
369            try
370            {
371                Class       cls;
372                ClassLoader clsLoader = prov.getClass().getClassLoader();
373
374                if (clsLoader != null)
375                {
376                    cls = clsLoader.loadClass(className);
377                }
378                else
379                {
380                    cls = Class.forName(className);
381                }
382
383                return new Implementation(cls.newInstance(), prov);
384            }
385            catch (ClassNotFoundException e)
386            {
387                throw new IllegalStateException(
388                    "algorithm " + algorithm + " in provider " + prov.getName() + " but no class \"" + className + "\" found!");
389            }
390            catch (Exception e)
391            {
392                throw new IllegalStateException(
393                    "algorithm " + algorithm + " in provider " + prov.getName() + " but class \"" + className + "\" inaccessible!");
394            }
395        }
396
397        throw new NoSuchAlgorithmException("cannot find implementation " + algorithm + " for provider " + prov.getName());
398    }
399
400    /**
401     * return an implementation for a given algorithm/provider.
402     * If the provider is null, we grab the first avalaible who has the required algorithm.
403     */
404    static Implementation getImplementation(
405        String      baseName,
406        String      algorithm)
407        throws NoSuchAlgorithmException
408    {
409        Provider[] prov = Security.getProviders();
410
411        //
412        // search every provider looking for the algorithm we want.
413        //
414        for (int i = 0; i != prov.length; i++)
415        {
416            //
417            // try case insensitive
418            //
419            Implementation imp = getImplementation(baseName, Strings.toUpperCase(algorithm), prov[i]);
420            if (imp != null)
421            {
422                return imp;
423            }
424
425            try
426            {
427                imp = getImplementation(baseName, algorithm, prov[i]);
428            }
429            catch (NoSuchAlgorithmException e)
430            {
431                // continue
432            }
433        }
434
435        throw new NoSuchAlgorithmException("cannot find implementation " + algorithm);
436    }
437
438    static Provider getProvider(String provider)
439        throws NoSuchProviderException
440    {
441        Provider prov = Security.getProvider(provider);
442
443        if (prov == null)
444        {
445            throw new NoSuchProviderException("Provider " + provider + " not found");
446        }
447
448        return prov;
449    }
450}
451