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