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