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