1
package org.bouncycastle.cms;
3
import java.io.IOException;
4
import java.security.AlgorithmParameterGenerator;
5
import java.security.AlgorithmParameters;
6
import java.security.InvalidAlgorithmParameterException;
7
import java.security.InvalidKeyException;
8
import java.security.KeyPair;
9
import java.security.NoSuchAlgorithmException;
10
import java.security.NoSuchProviderException;
11
import java.security.PrivateKey;
12
import java.security.Provider;
13
import java.security.PublicKey;
14
import java.security.SecureRandom;
15
import java.security.cert.X509Certificate;
16
import java.util.ArrayList;
17
import java.util.Collection;
18
import java.util.Collections;
19
import java.util.List;
21
import javax.crypto.SecretKey;
22
import javax.crypto.spec.RC2ParameterSpec;
23
import javax.crypto.spec.SecretKeySpec;
25
import org.bouncycastle.asn1.ASN1Object;
26
import org.bouncycastle.asn1.DEREncodable;
27
import org.bouncycastle.asn1.DERNull;
28
import org.bouncycastle.asn1.DERObjectIdentifier;
29
import org.bouncycastle.asn1.DEROctetString;
30
import org.bouncycastle.asn1.cms.KEKIdentifier;
31
import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers;
32
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
33
import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
34
import org.bouncycastle.asn1.pkcs.PBKDF2Params;
35
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
36
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
37
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
40
* General class for generating a CMS enveloped-data message.
42
public class CMSEnvelopedGenerator
44
public static final String DES_EDE3_CBC = PKCSObjectIdentifiers.des_EDE3_CBC.getId();
45
public static final String RC2_CBC = PKCSObjectIdentifiers.RC2_CBC.getId();
46
public static final String IDEA_CBC = "1.3.6.1.4.1.188.7.1.1.2";
47
public static final String CAST5_CBC = "1.2.840.113533.7.66.10";
48
public static final String AES128_CBC = NISTObjectIdentifiers.id_aes128_CBC.getId();
49
public static final String AES192_CBC = NISTObjectIdentifiers.id_aes192_CBC.getId();
50
public static final String AES256_CBC = NISTObjectIdentifiers.id_aes256_CBC.getId();
51
public static final String CAMELLIA128_CBC = NTTObjectIdentifiers.id_camellia128_cbc.getId();
52
public static final String CAMELLIA192_CBC = NTTObjectIdentifiers.id_camellia192_cbc.getId();
53
public static final String CAMELLIA256_CBC = NTTObjectIdentifiers.id_camellia256_cbc.getId();
54
public static final String SEED_CBC = KISAObjectIdentifiers.id_seedCBC.getId();
56
public static final String DES_EDE3_WRAP = PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId();
57
public static final String AES128_WRAP = NISTObjectIdentifiers.id_aes128_wrap.getId();
58
public static final String AES192_WRAP = NISTObjectIdentifiers.id_aes192_wrap.getId();
59
public static final String AES256_WRAP = NISTObjectIdentifiers.id_aes256_wrap.getId();
60
public static final String CAMELLIA128_WRAP = NTTObjectIdentifiers.id_camellia128_wrap.getId();
61
public static final String CAMELLIA192_WRAP = NTTObjectIdentifiers.id_camellia192_wrap.getId();
62
public static final String CAMELLIA256_WRAP = NTTObjectIdentifiers.id_camellia256_wrap.getId();
63
public static final String SEED_WRAP = KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap.getId();
65
public static final String ECDH_SHA1KDF = X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme.getId();
66
public static final String ECMQV_SHA1KDF = X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme.getId();
68
final List oldRecipientInfoGenerators = new ArrayList();
69
final List recipientInfoGenerators = new ArrayList();
71
protected CMSAttributeTableGenerator unprotectedAttributeGenerator = null;
73
final SecureRandom rand;
78
public CMSEnvelopedGenerator()
80
this(new SecureRandom());
84
* constructor allowing specific source of randomness
85
* @param rand instance of SecureRandom to use
87
public CMSEnvelopedGenerator(
93
public void setUnprotectedAttributeGenerator(CMSAttributeTableGenerator unprotectedAttributeGenerator)
95
this.unprotectedAttributeGenerator = unprotectedAttributeGenerator;
101
* @deprecated use the addRecipientGenerator and JceKeyTransRecipientInfoGenerator
102
* @param cert recipient's public key certificate
103
* @exception IllegalArgumentException if there is a problem with the certificate
105
public void addKeyTransRecipient(
106
X509Certificate cert)
107
throws IllegalArgumentException
109
KeyTransIntRecipientInfoGenerator ktrig = new KeyTransIntRecipientInfoGenerator();
110
ktrig.setRecipientCert(cert);
112
oldRecipientInfoGenerators.add(ktrig);
118
* @deprecated use the addRecipientGenerator and JceKeyTransRecipientInfoGenerator
119
* @param key the public key used by the recipient
120
* @param subKeyId the identifier for the recipient's public key
121
* @exception IllegalArgumentException if there is a problem with the key
123
public void addKeyTransRecipient(
126
throws IllegalArgumentException
128
KeyTransIntRecipientInfoGenerator ktrig = new KeyTransIntRecipientInfoGenerator();
129
ktrig.setRecipientPublicKey(key);
130
ktrig.setSubjectKeyIdentifier(new DEROctetString(subKeyId));
132
oldRecipientInfoGenerators.add(ktrig);
136
* add a KEK recipient.
138
* @deprecated use the addRecipientGenerator and JceKEKRecipientInfoGenerator
139
* @param key the secret key to use for wrapping
140
* @param keyIdentifier the byte string that identifies the key
142
public void addKEKRecipient(
144
byte[] keyIdentifier)
146
addKEKRecipient(key, new KEKIdentifier(keyIdentifier, null, null));
150
* add a KEK recipient.
152
* @deprecated use the addRecipientGenerator and JceKEKRecipientInfoGenerator
153
* @param key the secret key to use for wrapping
154
* @param kekIdentifier a KEKIdentifier structure (identifies the key)
156
public void addKEKRecipient(
158
KEKIdentifier kekIdentifier)
160
KEKIntRecipientInfoGenerator kekrig = new KEKIntRecipientInfoGenerator();
161
kekrig.setKEKIdentifier(kekIdentifier);
162
kekrig.setKeyEncryptionKey(key);
164
oldRecipientInfoGenerators.add(kekrig);
168
* @deprecated use addRecipientGenerator and JcePasswordRecipientInfoGenerator
169
* @param pbeKey PBE key
170
* @param kekAlgorithmOid key encryption algorithm to use.
172
public void addPasswordRecipient(
174
String kekAlgorithmOid)
176
PBKDF2Params params = new PBKDF2Params(pbeKey.getSalt(), pbeKey.getIterationCount());
178
PasswordIntRecipientInfoGenerator prig = new PasswordIntRecipientInfoGenerator();
179
prig.setKeyDerivationAlgorithm(new AlgorithmIdentifier(PKCSObjectIdentifiers.id_PBKDF2, params));
180
prig.setKeyEncryptionKey(new SecretKeySpec(pbeKey.getEncoded(kekAlgorithmOid), kekAlgorithmOid));
182
oldRecipientInfoGenerators.add(prig);
186
* Add a key agreement based recipient.
188
* @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
189
* @param agreementAlgorithm key agreement algorithm to use.
190
* @param senderPrivateKey private key to initialise sender side of agreement with.
191
* @param senderPublicKey sender public key to include with message.
192
* @param recipientCert recipient's public key certificate.
193
* @param cekWrapAlgorithm OID for key wrapping algorithm to use.
194
* @param provider provider to use for the agreement calculation.
195
* @exception NoSuchProviderException if the specified provider cannot be found
196
* @exception NoSuchAlgorithmException if the algorithm requested cannot be found
197
* @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
199
public void addKeyAgreementRecipient(
200
String agreementAlgorithm,
201
PrivateKey senderPrivateKey,
202
PublicKey senderPublicKey,
203
X509Certificate recipientCert,
204
String cekWrapAlgorithm,
206
throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException
208
addKeyAgreementRecipient(agreementAlgorithm, senderPrivateKey, senderPublicKey, recipientCert, cekWrapAlgorithm, CMSUtils.getProvider(provider));
212
* Add a key agreement based recipient.
214
* @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
215
* @param agreementAlgorithm key agreement algorithm to use.
216
* @param senderPrivateKey private key to initialise sender side of agreement with.
217
* @param senderPublicKey sender public key to include with message.
218
* @param recipientCert recipient's public key certificate.
219
* @param cekWrapAlgorithm OID for key wrapping algorithm to use.
220
* @param provider provider to use for the agreement calculation.
221
* @exception NoSuchAlgorithmException if the algorithm requested cannot be found
222
* @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
224
public void addKeyAgreementRecipient(
225
String agreementAlgorithm,
226
PrivateKey senderPrivateKey,
227
PublicKey senderPublicKey,
228
X509Certificate recipientCert,
229
String cekWrapAlgorithm,
231
throws NoSuchAlgorithmException, InvalidKeyException
233
addKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey,
234
Collections.singletonList(recipientCert), cekWrapAlgorithm, provider);
238
* Add multiple key agreement based recipients (sharing a single KeyAgreeRecipientInfo structure).
240
* @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
241
* @param agreementAlgorithm key agreement algorithm to use.
242
* @param senderPrivateKey private key to initialise sender side of agreement with.
243
* @param senderPublicKey sender public key to include with message.
244
* @param recipientCerts recipients' public key certificates.
245
* @param cekWrapAlgorithm OID for key wrapping algorithm to use.
246
* @param provider provider to use for the agreement calculation.
247
* @exception NoSuchAlgorithmException if the algorithm requested cannot be found
248
* @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
250
public void addKeyAgreementRecipients(
251
String agreementAlgorithm,
252
PrivateKey senderPrivateKey,
253
PublicKey senderPublicKey,
254
Collection recipientCerts,
255
String cekWrapAlgorithm,
257
throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException
259
addKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey, recipientCerts, cekWrapAlgorithm, CMSUtils.getProvider(provider));
263
* Add multiple key agreement based recipients (sharing a single KeyAgreeRecipientInfo structure).
265
* @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
266
* @param agreementAlgorithm key agreement algorithm to use.
267
* @param senderPrivateKey private key to initialise sender side of agreement with.
268
* @param senderPublicKey sender public key to include with message.
269
* @param recipientCerts recipients' public key certificates.
270
* @param cekWrapAlgorithm OID for key wrapping algorithm to use.
271
* @param provider provider to use for the agreement calculation.
272
* @exception NoSuchAlgorithmException if the algorithm requested cannot be found
273
* @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
275
public void addKeyAgreementRecipients(
276
String agreementAlgorithm,
277
PrivateKey senderPrivateKey,
278
PublicKey senderPublicKey,
279
Collection recipientCerts,
280
String cekWrapAlgorithm,
282
throws NoSuchAlgorithmException, InvalidKeyException
285
* "a recipient X.509 version 3 certificate that contains a key usage extension MUST
286
* assert the keyAgreement bit."
289
KeyAgreeIntRecipientInfoGenerator karig = new KeyAgreeIntRecipientInfoGenerator();
290
karig.setKeyAgreementOID(new DERObjectIdentifier(agreementAlgorithm));
291
karig.setKeyEncryptionOID(new DERObjectIdentifier(cekWrapAlgorithm));
292
karig.setRecipientCerts(recipientCerts);
293
karig.setSenderKeyPair(new KeyPair(senderPublicKey, senderPrivateKey));
295
oldRecipientInfoGenerators.add(karig);
299
* Add a generator to produce the recipient info required.
301
* @param recipientGenerator a generator of a recipient info object.
303
public void addRecipientInfoGenerator(RecipientInfoGenerator recipientGenerator)
305
recipientInfoGenerators.add(recipientGenerator);
308
protected AlgorithmIdentifier getAlgorithmIdentifier(String encryptionOID, AlgorithmParameters params) throws IOException
310
DEREncodable asn1Params;
313
asn1Params = ASN1Object.fromByteArray(params.getEncoded("ASN.1"));
317
asn1Params = DERNull.INSTANCE;
320
return new AlgorithmIdentifier(
321
new DERObjectIdentifier(encryptionOID),
325
protected AlgorithmParameters generateParameters(String encryptionOID, SecretKey encKey, Provider encProvider)
330
AlgorithmParameterGenerator pGen = AlgorithmParameterGenerator.getInstance(encryptionOID, encProvider);
332
if (encryptionOID.equals(RC2_CBC))
334
byte[] iv = new byte[8];
340
pGen.init(new RC2ParameterSpec(encKey.getEncoded().length * 8, iv), rand);
342
catch (InvalidAlgorithmParameterException e)
344
throw new CMSException("parameters generation error: " + e, e);
348
return pGen.generateParameters();
350
catch (NoSuchAlgorithmException e)