1
package org.bouncycastle.cert.crmf.jcajce;
3
import java.io.IOException;
4
import java.security.AlgorithmParameterGenerator;
5
import java.security.AlgorithmParameters;
6
import java.security.GeneralSecurityException;
7
import java.security.InvalidAlgorithmParameterException;
8
import java.security.InvalidKeyException;
9
import java.security.Key;
10
import java.security.KeyFactory;
11
import java.security.MessageDigest;
12
import java.security.NoSuchAlgorithmException;
13
import java.security.NoSuchProviderException;
14
import java.security.PublicKey;
15
import java.security.SecureRandom;
16
import java.security.spec.InvalidKeySpecException;
17
import java.security.spec.InvalidParameterSpecException;
18
import java.security.spec.X509EncodedKeySpec;
19
import java.util.HashMap;
22
import javax.crypto.Cipher;
23
import javax.crypto.KeyGenerator;
24
import javax.crypto.Mac;
25
import javax.crypto.NoSuchPaddingException;
26
import javax.crypto.SecretKey;
27
import javax.crypto.spec.IvParameterSpec;
28
import javax.crypto.spec.RC2ParameterSpec;
30
import org.bouncycastle.asn1.ASN1Null;
31
import org.bouncycastle.asn1.ASN1Object;
32
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
33
import org.bouncycastle.asn1.ASN1OctetString;
34
import org.bouncycastle.asn1.DERBitString;
35
import org.bouncycastle.asn1.DEREncodable;
36
import org.bouncycastle.asn1.DERNull;
37
import org.bouncycastle.asn1.iana.IANAObjectIdentifiers;
38
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
39
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
40
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
41
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
42
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
43
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
44
import org.bouncycastle.cert.crmf.CRMFException;
45
import org.bouncycastle.cms.CMSAlgorithm;
46
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
47
import org.bouncycastle.jcajce.JcaJceHelper;
51
protected static final Map BASE_CIPHER_NAMES = new HashMap();
52
protected static final Map CIPHER_ALG_NAMES = new HashMap();
53
protected static final Map DIGEST_ALG_NAMES = new HashMap();
54
protected static final Map KEY_ALG_NAMES = new HashMap();
55
protected static final Map MAC_ALG_NAMES = new HashMap();
59
BASE_CIPHER_NAMES.put(PKCSObjectIdentifiers.des_EDE3_CBC, "DESEDE");
60
BASE_CIPHER_NAMES.put(NISTObjectIdentifiers.id_aes128_CBC, "AES");
61
BASE_CIPHER_NAMES.put(NISTObjectIdentifiers.id_aes192_CBC, "AES");
62
BASE_CIPHER_NAMES.put(NISTObjectIdentifiers.id_aes256_CBC, "AES");
64
CIPHER_ALG_NAMES.put(CMSAlgorithm.DES_EDE3_CBC, "DESEDE/CBC/PKCS5Padding");
65
CIPHER_ALG_NAMES.put(CMSAlgorithm.AES128_CBC, "AES/CBC/PKCS5Padding");
66
CIPHER_ALG_NAMES.put(CMSAlgorithm.AES192_CBC, "AES/CBC/PKCS5Padding");
67
CIPHER_ALG_NAMES.put(CMSAlgorithm.AES256_CBC, "AES/CBC/PKCS5Padding");
68
CIPHER_ALG_NAMES.put(new ASN1ObjectIdentifier(PKCSObjectIdentifiers.rsaEncryption.getId()), "RSA/ECB/PKCS1Padding");
70
DIGEST_ALG_NAMES.put(OIWObjectIdentifiers.idSHA1, "SHA1");
71
DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha224, "SHA224");
72
DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha256, "SHA256");
73
DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha384, "SHA384");
74
DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha512, "SHA512");
76
MAC_ALG_NAMES.put(IANAObjectIdentifiers.hmacSHA1, "HMACSHA1");
77
MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA1, "HMACSHA1");
78
MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA224, "HMACSHA224");
79
MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA256, "HMACSHA256");
80
MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA384, "HMACSHA384");
81
MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA512, "HMACSHA512");
83
KEY_ALG_NAMES.put(PKCSObjectIdentifiers.rsaEncryption, "RSA");
84
KEY_ALG_NAMES.put(X9ObjectIdentifiers.id_dsa, "DSA");
87
private JcaJceHelper helper;
89
CRMFHelper(JcaJceHelper helper)
94
PublicKey toPublicKey(SubjectPublicKeyInfo subjectPublicKeyInfo)
97
X509EncodedKeySpec xspec = new X509EncodedKeySpec(new DERBitString(subjectPublicKeyInfo).getBytes());
98
AlgorithmIdentifier keyAlg = subjectPublicKeyInfo.getAlgorithmId();
102
return createKeyFactory(keyAlg.getAlgorithm()).generatePublic(xspec);
104
catch (InvalidKeySpecException e)
106
throw new CRMFException("invalid key: " + e.getMessage(), e);
110
Cipher createCipher(ASN1ObjectIdentifier algorithm)
115
String cipherName = (String)CIPHER_ALG_NAMES.get(algorithm);
117
if (cipherName != null)
121
// this is reversed as the Sun policy files now allow unlimited strength RSA
122
return helper.createCipher(cipherName);
124
catch (NoSuchAlgorithmException e)
129
return helper.createCipher(algorithm.getId());
131
catch (GeneralSecurityException e)
133
throw new CRMFException("cannot create cipher: " + e.getMessage(), e);
137
public KeyGenerator createKeyGenerator(ASN1ObjectIdentifier algorithm)
142
String cipherName = (String)BASE_CIPHER_NAMES.get(algorithm);
144
if (cipherName != null)
148
// this is reversed as the Sun policy files now allow unlimited strength RSA
149
return helper.createKeyGenerator(cipherName);
151
catch (NoSuchAlgorithmException e)
156
return helper.createKeyGenerator(algorithm.getId());
158
catch (GeneralSecurityException e)
160
throw new CRMFException("cannot create key generator: " + e.getMessage(), e);
164
Cipher createContentCipher(final Key sKey, final AlgorithmIdentifier encryptionAlgID)
167
return (Cipher)execute(new JCECallback()
169
public Object doInJCE()
170
throws CRMFException, InvalidAlgorithmParameterException,
171
InvalidKeyException, InvalidParameterSpecException, NoSuchAlgorithmException,
172
NoSuchPaddingException, NoSuchProviderException
174
Cipher cipher = createCipher(encryptionAlgID.getAlgorithm());
175
ASN1Object sParams = (ASN1Object)encryptionAlgID.getParameters();
176
String encAlg = encryptionAlgID.getAlgorithm().getId();
178
if (sParams != null && !(sParams instanceof ASN1Null))
182
AlgorithmParameters params = createAlgorithmParameters(encryptionAlgID.getAlgorithm());
186
params.init(sParams.getEncoded(), "ASN.1");
188
catch (IOException e)
190
throw new CRMFException("error decoding algorithm parameters.", e);
193
cipher.init(Cipher.DECRYPT_MODE, sKey, params);
195
catch (NoSuchAlgorithmException e)
197
if (encAlg.equals(CMSEnvelopedDataGenerator.DES_EDE3_CBC)
198
|| encAlg.equals(CMSEnvelopedDataGenerator.IDEA_CBC)
199
|| encAlg.equals(CMSEnvelopedDataGenerator.AES128_CBC)
200
|| encAlg.equals(CMSEnvelopedDataGenerator.AES192_CBC)
201
|| encAlg.equals(CMSEnvelopedDataGenerator.AES256_CBC))
203
cipher.init(Cipher.DECRYPT_MODE, sKey, new IvParameterSpec(
204
ASN1OctetString.getInstance(sParams).getOctets()));
214
if (encAlg.equals(CMSEnvelopedDataGenerator.DES_EDE3_CBC)
215
|| encAlg.equals(CMSEnvelopedDataGenerator.IDEA_CBC)
216
|| encAlg.equals(CMSEnvelopedDataGenerator.CAST5_CBC))
218
cipher.init(Cipher.DECRYPT_MODE, sKey, new IvParameterSpec(new byte[8]));
222
cipher.init(Cipher.DECRYPT_MODE, sKey);
231
AlgorithmParameters createAlgorithmParameters(ASN1ObjectIdentifier algorithm)
232
throws NoSuchAlgorithmException, NoSuchProviderException
234
String algorithmName = (String)BASE_CIPHER_NAMES.get(algorithm);
236
if (algorithmName != null)
240
// this is reversed as the Sun policy files now allow unlimited strength RSA
241
return helper.createAlgorithmParameters(algorithmName);
243
catch (NoSuchAlgorithmException e)
248
return helper.createAlgorithmParameters(algorithm.getId());
251
KeyFactory createKeyFactory(ASN1ObjectIdentifier algorithm)
256
String algName = (String)KEY_ALG_NAMES.get(algorithm);
262
// this is reversed as the Sun policy files now allow unlimited strength RSA
263
return helper.createKeyFactory(algName);
265
catch (NoSuchAlgorithmException e)
270
return helper.createKeyFactory(algorithm.getId());
272
catch (GeneralSecurityException e)
274
throw new CRMFException("cannot create cipher: " + e.getMessage(), e);
278
MessageDigest createDigest(ASN1ObjectIdentifier algorithm)
283
String digestName = (String)DIGEST_ALG_NAMES.get(algorithm);
285
if (digestName != null)
289
// this is reversed as the Sun policy files now allow unlimited strength RSA
290
return helper.createDigest(digestName);
292
catch (NoSuchAlgorithmException e)
297
return helper.createDigest(algorithm.getId());
299
catch (GeneralSecurityException e)
301
throw new CRMFException("cannot create cipher: " + e.getMessage(), e);
305
Mac createMac(ASN1ObjectIdentifier algorithm)
310
String macName = (String)MAC_ALG_NAMES.get(algorithm);
316
// this is reversed as the Sun policy files now allow unlimited strength RSA
317
return helper.createMac(macName);
319
catch (NoSuchAlgorithmException e)
324
return helper.createMac(algorithm.getId());
326
catch (GeneralSecurityException e)
328
throw new CRMFException("cannot create mac: " + e.getMessage(), e);
332
AlgorithmParameterGenerator createAlgorithmParameterGenerator(ASN1ObjectIdentifier algorithm)
333
throws GeneralSecurityException
335
String algorithmName = (String)BASE_CIPHER_NAMES.get(algorithm);
337
if (algorithmName != null)
341
// this is reversed as the Sun policy files now allow unlimited strength RSA
342
return helper.createAlgorithmParameterGenerator(algorithmName);
344
catch (NoSuchAlgorithmException e)
349
return helper.createAlgorithmParameterGenerator(algorithm.getId());
352
AlgorithmParameters generateParameters(ASN1ObjectIdentifier encryptionOID, SecretKey encKey, SecureRandom rand)
357
AlgorithmParameterGenerator pGen = createAlgorithmParameterGenerator(encryptionOID);
359
if (encryptionOID.equals(CMSEnvelopedDataGenerator.RC2_CBC))
361
byte[] iv = new byte[8];
367
pGen.init(new RC2ParameterSpec(encKey.getEncoded().length * 8, iv), rand);
369
catch (InvalidAlgorithmParameterException e)
371
throw new CRMFException("parameters generation error: " + e, e);
375
return pGen.generateParameters();
377
catch (NoSuchAlgorithmException e)
381
catch (GeneralSecurityException e)
383
throw new CRMFException("exception creating algorithm parameter generator: " + e, e);
387
AlgorithmIdentifier getAlgorithmIdentifier(ASN1ObjectIdentifier encryptionOID, AlgorithmParameters params)
390
DEREncodable asn1Params;
395
asn1Params = ASN1Object.fromByteArray(params.getEncoded("ASN.1"));
397
catch (IOException e)
399
throw new CRMFException("cannot encode parameters: " + e.getMessage(), e);
404
asn1Params = DERNull.INSTANCE;
407
return new AlgorithmIdentifier(
412
static Object execute(JCECallback callback) throws CRMFException
416
return callback.doInJCE();
418
catch (NoSuchAlgorithmException e)
420
throw new CRMFException("can't find algorithm.", e);
422
catch (InvalidKeyException e)
424
throw new CRMFException("key invalid in message.", e);
426
catch (NoSuchProviderException e)
428
throw new CRMFException("can't find provider.", e);
430
catch (NoSuchPaddingException e)
432
throw new CRMFException("required padding not supported.", e);
434
catch (InvalidAlgorithmParameterException e)
436
throw new CRMFException("algorithm parameters invalid.", e);
438
catch (InvalidParameterSpecException e)
440
throw new CRMFException("MAC algorithm parameter spec invalid.", e);
444
static interface JCECallback
447
throws CRMFException, InvalidAlgorithmParameterException, InvalidKeyException, InvalidParameterSpecException,
448
NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException;