001: package org.bouncycastle.x509;
002:
003: import org.bouncycastle.asn1.ASN1Encodable;
004: import org.bouncycastle.asn1.DEREncodable;
005: import org.bouncycastle.asn1.DERInteger;
006: import org.bouncycastle.asn1.DERNull;
007: import org.bouncycastle.asn1.DERObjectIdentifier;
008: import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
009: import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
010: import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
011: import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
012: import org.bouncycastle.asn1.pkcs.RSASSAPSSparams;
013: import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
014: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
015: import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
016: import org.bouncycastle.jce.X509Principal;
017: import org.bouncycastle.util.Strings;
018:
019: import javax.security.auth.x500.X500Principal;
020: import java.io.IOException;
021: import java.security.InvalidKeyException;
022: import java.security.NoSuchAlgorithmException;
023: import java.security.NoSuchProviderException;
024: import java.security.PrivateKey;
025: import java.security.Provider;
026: import java.security.SecureRandom;
027: import java.security.Security;
028: import java.security.Signature;
029: import java.security.SignatureException;
030: import java.util.ArrayList;
031: import java.util.Enumeration;
032: import java.util.HashSet;
033: import java.util.Hashtable;
034: import java.util.Iterator;
035: import java.util.List;
036: import java.util.Set;
037:
038: class X509Util {
039: private static Hashtable algorithms = new Hashtable();
040: private static Hashtable params = new Hashtable();
041: private static Set noParams = new HashSet();
042:
043: static {
044: algorithms.put("MD2WITHRSAENCRYPTION",
045: PKCSObjectIdentifiers.md2WithRSAEncryption);
046: algorithms.put("MD2WITHRSA",
047: PKCSObjectIdentifiers.md2WithRSAEncryption);
048: algorithms.put("MD5WITHRSAENCRYPTION",
049: PKCSObjectIdentifiers.md5WithRSAEncryption);
050: algorithms.put("MD5WITHRSA",
051: PKCSObjectIdentifiers.md5WithRSAEncryption);
052: algorithms.put("SHA1WITHRSAENCRYPTION",
053: PKCSObjectIdentifiers.sha1WithRSAEncryption);
054: algorithms.put("SHA1WITHRSA",
055: PKCSObjectIdentifiers.sha1WithRSAEncryption);
056: algorithms.put("SHA224WITHRSAENCRYPTION",
057: PKCSObjectIdentifiers.sha224WithRSAEncryption);
058: algorithms.put("SHA224WITHRSA",
059: PKCSObjectIdentifiers.sha224WithRSAEncryption);
060: algorithms.put("SHA256WITHRSAENCRYPTION",
061: PKCSObjectIdentifiers.sha256WithRSAEncryption);
062: algorithms.put("SHA256WITHRSA",
063: PKCSObjectIdentifiers.sha256WithRSAEncryption);
064: algorithms.put("SHA384WITHRSAENCRYPTION",
065: PKCSObjectIdentifiers.sha384WithRSAEncryption);
066: algorithms.put("SHA384WITHRSA",
067: PKCSObjectIdentifiers.sha384WithRSAEncryption);
068: algorithms.put("SHA512WITHRSAENCRYPTION",
069: PKCSObjectIdentifiers.sha512WithRSAEncryption);
070: algorithms.put("SHA512WITHRSA",
071: PKCSObjectIdentifiers.sha512WithRSAEncryption);
072: algorithms.put("SHA1WITHRSAANDMGF1",
073: PKCSObjectIdentifiers.id_RSASSA_PSS);
074: algorithms.put("SHA224WITHRSAANDMGF1",
075: PKCSObjectIdentifiers.id_RSASSA_PSS);
076: algorithms.put("SHA256WITHRSAANDMGF1",
077: PKCSObjectIdentifiers.id_RSASSA_PSS);
078: algorithms.put("SHA384WITHRSAANDMGF1",
079: PKCSObjectIdentifiers.id_RSASSA_PSS);
080: algorithms.put("SHA512WITHRSAANDMGF1",
081: PKCSObjectIdentifiers.id_RSASSA_PSS);
082: algorithms.put("RIPEMD160WITHRSAENCRYPTION",
083: TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
084: algorithms.put("RIPEMD160WITHRSA",
085: TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
086: algorithms.put("RIPEMD128WITHRSAENCRYPTION",
087: TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
088: algorithms.put("RIPEMD128WITHRSA",
089: TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
090: algorithms.put("RIPEMD256WITHRSAENCRYPTION",
091: TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
092: algorithms.put("RIPEMD256WITHRSA",
093: TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
094: algorithms.put("SHA1WITHDSA",
095: X9ObjectIdentifiers.id_dsa_with_sha1);
096: algorithms.put("DSAWITHSHA1",
097: X9ObjectIdentifiers.id_dsa_with_sha1);
098: algorithms.put("SHA224WITHDSA",
099: NISTObjectIdentifiers.dsa_with_sha224);
100: algorithms.put("SHA256WITHDSA",
101: NISTObjectIdentifiers.dsa_with_sha256);
102: algorithms.put("SHA1WITHECDSA",
103: X9ObjectIdentifiers.ecdsa_with_SHA1);
104: algorithms.put("ECDSAWITHSHA1",
105: X9ObjectIdentifiers.ecdsa_with_SHA1);
106: algorithms.put("SHA224WITHECDSA",
107: X9ObjectIdentifiers.ecdsa_with_SHA224);
108: algorithms.put("SHA256WITHECDSA",
109: X9ObjectIdentifiers.ecdsa_with_SHA256);
110: algorithms.put("SHA384WITHECDSA",
111: X9ObjectIdentifiers.ecdsa_with_SHA384);
112: algorithms.put("SHA512WITHECDSA",
113: X9ObjectIdentifiers.ecdsa_with_SHA512);
114: algorithms
115: .put(
116: "GOST3411WITHGOST3410",
117: CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
118: algorithms
119: .put(
120: "GOST3411WITHGOST3410-94",
121: CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
122: algorithms
123: .put(
124: "GOST3411WITHECGOST3410",
125: CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
126: algorithms
127: .put(
128: "GOST3411WITHECGOST3410-2001",
129: CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
130: algorithms
131: .put(
132: "GOST3411WITHGOST3410-2001",
133: CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
134:
135: //
136: // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
137: // The parameters field SHALL be NULL for RSA based signature algorithms.
138: //
139: noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA1);
140: noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA224);
141: noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA256);
142: noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA384);
143: noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA512);
144: noParams.add(X9ObjectIdentifiers.id_dsa_with_sha1);
145: noParams.add(NISTObjectIdentifiers.dsa_with_sha224);
146: noParams.add(NISTObjectIdentifiers.dsa_with_sha256);
147:
148: //
149: // RFC 4491
150: //
151: noParams
152: .add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
153: noParams
154: .add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
155:
156: //
157: // explicit params
158: //
159: AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(
160: OIWObjectIdentifiers.idSHA1, new DERNull());
161: params.put("SHA1WITHRSAANDMGF1", creatPSSParams(sha1AlgId, 20));
162:
163: AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(
164: NISTObjectIdentifiers.id_sha224, new DERNull());
165: params.put("SHA224WITHRSAANDMGF1", creatPSSParams(sha224AlgId,
166: 28));
167:
168: AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(
169: NISTObjectIdentifiers.id_sha256, new DERNull());
170: params.put("SHA256WITHRSAANDMGF1", creatPSSParams(sha256AlgId,
171: 32));
172:
173: AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(
174: NISTObjectIdentifiers.id_sha384, new DERNull());
175: params.put("SHA384WITHRSAANDMGF1", creatPSSParams(sha384AlgId,
176: 48));
177:
178: AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(
179: NISTObjectIdentifiers.id_sha512, new DERNull());
180: params.put("SHA512WITHRSAANDMGF1", creatPSSParams(sha512AlgId,
181: 64));
182: }
183:
184: private static RSASSAPSSparams creatPSSParams(
185: AlgorithmIdentifier hashAlgId, int saltSize) {
186: return new RSASSAPSSparams(hashAlgId, new AlgorithmIdentifier(
187: PKCSObjectIdentifiers.id_mgf1, hashAlgId),
188: new DERInteger(saltSize), new DERInteger(1));
189: }
190:
191: static DERObjectIdentifier getAlgorithmOID(String algorithmName) {
192: algorithmName = Strings.toUpperCase(algorithmName);
193:
194: if (algorithms.containsKey(algorithmName)) {
195: return (DERObjectIdentifier) algorithms.get(algorithmName);
196: }
197:
198: return new DERObjectIdentifier(algorithmName);
199: }
200:
201: static AlgorithmIdentifier getSigAlgID(DERObjectIdentifier sigOid,
202: String algorithmName) {
203: if (noParams.contains(sigOid)) {
204: return new AlgorithmIdentifier(sigOid);
205: }
206:
207: algorithmName = Strings.toUpperCase(algorithmName);
208:
209: if (params.containsKey(algorithmName)) {
210: return new AlgorithmIdentifier(sigOid,
211: (DEREncodable) params.get(algorithmName));
212: } else {
213: return new AlgorithmIdentifier(sigOid, new DERNull());
214: }
215: }
216:
217: static Iterator getAlgNames() {
218: Enumeration e = algorithms.keys();
219: List l = new ArrayList();
220:
221: while (e.hasMoreElements()) {
222: l.add(e.nextElement());
223: }
224:
225: return l.iterator();
226: }
227:
228: static Signature getSignatureInstance(String algorithm)
229: throws NoSuchAlgorithmException {
230: return Signature.getInstance(algorithm);
231: }
232:
233: static Signature getSignatureInstance(String algorithm,
234: String provider) throws NoSuchProviderException,
235: NoSuchAlgorithmException {
236: if (provider != null) {
237: return Signature.getInstance(algorithm, provider);
238: } else {
239: return Signature.getInstance(algorithm);
240: }
241: }
242:
243: static byte[] calculateSignature(DERObjectIdentifier sigOid,
244: String sigName, PrivateKey key, SecureRandom random,
245: ASN1Encodable object) throws IOException,
246: NoSuchAlgorithmException, InvalidKeyException,
247: SignatureException {
248: Signature sig;
249:
250: if (sigOid == null) {
251: throw new IllegalStateException(
252: "no signature algorithm specified");
253: }
254:
255: sig = X509Util.getSignatureInstance(sigName);
256:
257: if (random != null) {
258: sig.initSign(key, random);
259: } else {
260: sig.initSign(key);
261: }
262:
263: sig.update(object.getEncoded(ASN1Encodable.DER));
264:
265: return sig.sign();
266: }
267:
268: static byte[] calculateSignature(DERObjectIdentifier sigOid,
269: String sigName, String provider, PrivateKey key,
270: SecureRandom random, ASN1Encodable object)
271: throws IOException, NoSuchProviderException,
272: NoSuchAlgorithmException, InvalidKeyException,
273: SignatureException {
274: Signature sig;
275:
276: if (sigOid == null) {
277: throw new IllegalStateException(
278: "no signature algorithm specified");
279: }
280:
281: sig = X509Util.getSignatureInstance(sigName, provider);
282:
283: if (random != null) {
284: sig.initSign(key, random);
285: } else {
286: sig.initSign(key);
287: }
288:
289: sig.update(object.getEncoded(ASN1Encodable.DER));
290:
291: return sig.sign();
292: }
293:
294: static X509Principal convertPrincipal(X500Principal principal) {
295: try {
296: return new X509Principal(principal.getEncoded());
297: } catch (IOException e) {
298: throw new IllegalArgumentException(
299: "cannot convert principal");
300: }
301: }
302:
303: static class Implementation {
304: Object engine;
305: Provider provider;
306:
307: Implementation(Object engine, Provider provider) {
308: this .engine = engine;
309: this .provider = provider;
310: }
311:
312: Object getEngine() {
313: return engine;
314: }
315:
316: Provider getProvider() {
317: return provider;
318: }
319: }
320:
321: /**
322: * see if we can find an algorithm (or its alias and what it represents) in
323: * the property table for the given provider.
324: */
325: static Implementation getImplementation(String baseName,
326: String algorithm, Provider prov)
327: throws NoSuchAlgorithmException {
328: algorithm = Strings.toUpperCase(algorithm);
329:
330: String alias;
331:
332: while ((alias = prov.getProperty("Alg.Alias." + baseName + "."
333: + algorithm)) != null) {
334: algorithm = alias;
335: }
336:
337: String className = prov.getProperty(baseName + "." + algorithm);
338:
339: if (className != null) {
340: try {
341: Class cls;
342: ClassLoader clsLoader = prov.getClass()
343: .getClassLoader();
344:
345: if (clsLoader != null) {
346: cls = clsLoader.loadClass(className);
347: } else {
348: cls = Class.forName(className);
349: }
350:
351: return new Implementation(cls.newInstance(), prov);
352: } catch (ClassNotFoundException e) {
353: throw new IllegalStateException("algorithm "
354: + algorithm + " in provider " + prov.getName()
355: + " but no class \"" + className + "\" found!");
356: } catch (Exception e) {
357: throw new IllegalStateException("algorithm "
358: + algorithm + " in provider " + prov.getName()
359: + " but class \"" + className
360: + "\" inaccessible!");
361: }
362: }
363:
364: throw new NoSuchAlgorithmException(
365: "cannot find implementation " + algorithm
366: + " for provider " + prov.getName());
367: }
368:
369: /**
370: * return an implementation for a given algorithm/provider.
371: * If the provider is null, we grab the first avalaible who has the required algorithm.
372: */
373: static Implementation getImplementation(String baseName,
374: String algorithm) throws NoSuchAlgorithmException {
375: Provider[] prov = Security.getProviders();
376:
377: //
378: // search every provider looking for the algorithm we want.
379: //
380: for (int i = 0; i != prov.length; i++) {
381: //
382: // try case insensitive
383: //
384: Implementation imp = getImplementation(baseName, Strings
385: .toUpperCase(algorithm), prov[i]);
386: if (imp != null) {
387: return imp;
388: }
389:
390: try {
391: imp = getImplementation(baseName, algorithm, prov[i]);
392: } catch (NoSuchAlgorithmException e) {
393: // continue
394: }
395: }
396:
397: throw new NoSuchAlgorithmException(
398: "cannot find implementation " + algorithm);
399: }
400:
401: static Provider getProvider(String provider)
402: throws NoSuchProviderException {
403: Provider prov = Security.getProvider(provider);
404:
405: if (prov == null) {
406: throw new NoSuchProviderException("Provider " + provider
407: + " not found");
408: }
409:
410: return prov;
411: }
412: }
|