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 AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE); 139 params.put("SHA1WITHRSAANDMGF1", creatPSSParams(sha1AlgId, 20)); 140 141 // BEGIN android-removed 142 // AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha224, DERNull.INSTANCE); 143 // params.put("SHA224WITHRSAANDMGF1", creatPSSParams(sha224AlgId, 28)); 144 // END android-removed 145 146 AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, DERNull.INSTANCE); 147 params.put("SHA256WITHRSAANDMGF1", creatPSSParams(sha256AlgId, 32)); 148 149 AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha384, DERNull.INSTANCE); 150 params.put("SHA384WITHRSAANDMGF1", creatPSSParams(sha384AlgId, 48)); 151 152 AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha512, DERNull.INSTANCE); 153 params.put("SHA512WITHRSAANDMGF1", creatPSSParams(sha512AlgId, 64)); 154 } 155 156 private static RSASSAPSSparams creatPSSParams(AlgorithmIdentifier hashAlgId, int saltSize) 157 { 158 return new RSASSAPSSparams( 159 hashAlgId, 160 new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hashAlgId), 161 new ASN1Integer(saltSize), 162 new ASN1Integer(1)); 163 } 164 165 static DERObjectIdentifier getAlgorithmOID( 166 String algorithmName) 167 { 168 algorithmName = Strings.toUpperCase(algorithmName); 169 170 if (algorithms.containsKey(algorithmName)) 171 { 172 return (DERObjectIdentifier)algorithms.get(algorithmName); 173 } 174 175 return new DERObjectIdentifier(algorithmName); 176 } 177 178 static AlgorithmIdentifier getSigAlgID( 179 DERObjectIdentifier sigOid, 180 String algorithmName) 181 { 182 if (noParams.contains(sigOid)) 183 { 184 return new AlgorithmIdentifier(sigOid); 185 } 186 187 algorithmName = Strings.toUpperCase(algorithmName); 188 189 if (params.containsKey(algorithmName)) 190 { 191 return new AlgorithmIdentifier(sigOid, (ASN1Encodable)params.get(algorithmName)); 192 } 193 else 194 { 195 return new AlgorithmIdentifier(sigOid, DERNull.INSTANCE); 196 } 197 } 198 199 static Iterator getAlgNames() 200 { 201 Enumeration e = algorithms.keys(); 202 List l = new ArrayList(); 203 204 while (e.hasMoreElements()) 205 { 206 l.add(e.nextElement()); 207 } 208 209 return l.iterator(); 210 } 211 212 static Signature getSignatureInstance( 213 String algorithm) 214 throws NoSuchAlgorithmException 215 { 216 return Signature.getInstance(algorithm); 217 } 218 219 static Signature getSignatureInstance( 220 String algorithm, 221 String provider) 222 throws NoSuchProviderException, NoSuchAlgorithmException 223 { 224 if (provider != null) 225 { 226 return Signature.getInstance(algorithm, provider); 227 } 228 else 229 { 230 return Signature.getInstance(algorithm); 231 } 232 } 233 234 static byte[] calculateSignature( 235 DERObjectIdentifier sigOid, 236 String sigName, 237 PrivateKey key, 238 SecureRandom random, 239 ASN1Encodable object) 240 throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException 241 { 242 Signature sig; 243 244 if (sigOid == null) 245 { 246 throw new IllegalStateException("no signature algorithm specified"); 247 } 248 249 sig = X509Util.getSignatureInstance(sigName); 250 251 if (random != null) 252 { 253 sig.initSign(key, random); 254 } 255 else 256 { 257 sig.initSign(key); 258 } 259 260 sig.update(object.toASN1Primitive().getEncoded(ASN1Encoding.DER)); 261 262 return sig.sign(); 263 } 264 265 static byte[] calculateSignature( 266 DERObjectIdentifier sigOid, 267 String sigName, 268 String provider, 269 PrivateKey key, 270 SecureRandom random, 271 ASN1Encodable object) 272 throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, SignatureException 273 { 274 Signature sig; 275 276 if (sigOid == null) 277 { 278 throw new IllegalStateException("no signature algorithm specified"); 279 } 280 281 sig = X509Util.getSignatureInstance(sigName, provider); 282 283 if (random != null) 284 { 285 sig.initSign(key, random); 286 } 287 else 288 { 289 sig.initSign(key); 290 } 291 292 sig.update(object.toASN1Primitive().getEncoded(ASN1Encoding.DER)); 293 294 return sig.sign(); 295 } 296 297 static X509Principal convertPrincipal( 298 X500Principal principal) 299 { 300 try 301 { 302 return new X509Principal(principal.getEncoded()); 303 } 304 catch (IOException e) 305 { 306 throw new IllegalArgumentException("cannot convert principal"); 307 } 308 } 309 310 static class Implementation 311 { 312 Object engine; 313 Provider provider; 314 315 Implementation( 316 Object engine, 317 Provider provider) 318 { 319 this.engine = engine; 320 this.provider = provider; 321 } 322 323 Object getEngine() 324 { 325 return engine; 326 } 327 328 Provider getProvider() 329 { 330 return provider; 331 } 332 } 333 334 /** 335 * see if we can find an algorithm (or its alias and what it represents) in 336 * the property table for the given provider. 337 */ 338 static Implementation getImplementation( 339 String baseName, 340 String algorithm, 341 Provider prov) 342 throws NoSuchAlgorithmException 343 { 344 algorithm = Strings.toUpperCase(algorithm); 345 346 String alias; 347 348 while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null) 349 { 350 algorithm = alias; 351 } 352 353 String className = prov.getProperty(baseName + "." + algorithm); 354 355 if (className != null) 356 { 357 try 358 { 359 Class cls; 360 ClassLoader clsLoader = prov.getClass().getClassLoader(); 361 362 if (clsLoader != null) 363 { 364 cls = clsLoader.loadClass(className); 365 } 366 else 367 { 368 cls = Class.forName(className); 369 } 370 371 return new Implementation(cls.newInstance(), prov); 372 } 373 catch (ClassNotFoundException e) 374 { 375 throw new IllegalStateException( 376 "algorithm " + algorithm + " in provider " + prov.getName() + " but no class \"" + className + "\" found!"); 377 } 378 catch (Exception e) 379 { 380 throw new IllegalStateException( 381 "algorithm " + algorithm + " in provider " + prov.getName() + " but class \"" + className + "\" inaccessible!"); 382 } 383 } 384 385 throw new NoSuchAlgorithmException("cannot find implementation " + algorithm + " for provider " + prov.getName()); 386 } 387 388 /** 389 * return an implementation for a given algorithm/provider. 390 * If the provider is null, we grab the first avalaible who has the required algorithm. 391 */ 392 static Implementation getImplementation( 393 String baseName, 394 String algorithm) 395 throws NoSuchAlgorithmException 396 { 397 Provider[] prov = Security.getProviders(); 398 399 // 400 // search every provider looking for the algorithm we want. 401 // 402 for (int i = 0; i != prov.length; i++) 403 { 404 // 405 // try case insensitive 406 // 407 Implementation imp = getImplementation(baseName, Strings.toUpperCase(algorithm), prov[i]); 408 if (imp != null) 409 { 410 return imp; 411 } 412 413 try 414 { 415 imp = getImplementation(baseName, algorithm, prov[i]); 416 } 417 catch (NoSuchAlgorithmException e) 418 { 419 // continue 420 } 421 } 422 423 throw new NoSuchAlgorithmException("cannot find implementation " + algorithm); 424 } 425 426 static Provider getProvider(String provider) 427 throws NoSuchProviderException 428 { 429 Provider prov = Security.getProvider(provider); 430 431 if (prov == null) 432 { 433 throw new NoSuchProviderException("Provider " + provider + " not found"); 434 } 435 436 return prov; 437 } 438} 439