001 // Copyright (C) 2002 IAIK
002 // https://jce.iaik.tugraz.at
003 //
004 // Copyright (C) 2003 - 2025 Stiftung Secure Information and
005 // Communication Technologies SIC
006 // https://sic.tech
007 //
008 // All rights reserved.
009 //
010 // Redistribution and use in source and binary forms, with or without
011 // modification, are permitted provided that the following conditions
012 // are met:
013 // 1. Redistributions of source code must retain the above copyright
014 // notice, this list of conditions and the following disclaimer.
015 // 2. Redistributions in binary form must reproduce the above copyright
016 // notice, this list of conditions and the following disclaimer in the
017 // documentation and/or other materials provided with the distribution.
018 //
019 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
020 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
023 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
024 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
025 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
027 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
028 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
029 // SUCH DAMAGE.
030
031 // Copyright (C) 2002 IAIK
032 // https://sic.tech/
033 //
034 // Copyright (C) 2003 - 2025 Stiftung Secure Information and
035 // Communication Technologies SIC
036 // https://sic.tech/
037 //
038 // All rights reserved.
039 //
040 // This source is provided for inspection purposes and recompilation only,
041 // unless specified differently in a contract with IAIK. This source has to
042 // be kept in strict confidence and must not be disclosed to any third party
043 // under any circumstances. Redistribution in source and binary forms, with
044 // or without modification, are <not> permitted in any case!
045 //
046 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
047 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
048 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
049 // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
050 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
051 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
052 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
053 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
054 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
055 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
056 // SUCH DAMAGE.
057 //
058 // $Header: /IAIK-CMS/current/src/demo/cms/pkcs7cms/PKCS7CMSEncryptedContentInfoDemo.java 25 12.02.25 17:58 Dbratko $
059 // $Revision: 25 $
060 //
061
062 package demo.cms.pkcs7cms;
063
064 import iaik.asn1.ASN;
065 import iaik.asn1.ASN1Object;
066 import iaik.asn1.INTEGER;
067 import iaik.asn1.OCTET_STRING;
068 import iaik.asn1.ObjectID;
069 import iaik.asn1.SEQUENCE;
070 import iaik.asn1.structures.AlgorithmID;
071 import iaik.cms.EncryptedContentInfoStream;
072 import iaik.cms.EnvelopedDataStream;
073 import iaik.cms.KeyTransRecipientInfo;
074 import iaik.cms.RecipientInfo;
075 import iaik.cms.SecurityProvider;
076 import iaik.security.random.SecRandom;
077 import iaik.utils.Util;
078 import iaik.x509.X509Certificate;
079
080 import java.io.ByteArrayInputStream;
081 import java.io.ByteArrayOutputStream;
082 import java.io.IOException;
083 import java.io.InputStream;
084 import java.math.BigInteger;
085 import java.security.PrivateKey;
086 import java.security.SecureRandom;
087 import java.security.spec.AlgorithmParameterSpec;
088
089 import javax.crypto.KeyGenerator;
090 import javax.crypto.SecretKey;
091 import javax.crypto.spec.IvParameterSpec;
092 import javax.crypto.spec.RC2ParameterSpec;
093
094 import demo.DemoUtil;
095 import demo.keystore.CMSKeyStore;
096
097 /**
098 * This class demonstrates the EnvelopedDataStream/EncryptedContentInfoStream usages
099 * for algorithms that may require a specific parameter handling.
100 * <p>
101 * This class shows the compatibility to PKCS#7.
102 * <p>
103 * All keys and certificates are read from a keystore created by the
104 * SetupCMSKeyStore program.
105 * <p>
106 * The following algorithms are demonstrated:
107 * <ul>
108 * <li>ARCFOUR: Variable-key-size stream cipher; no parameters to be sent
109 * <li>RC2_CBC: Variable-key-size block cipher; parameters as used by S/MIME:
110 * rc2ParamterVersion and IV; encoded as SEQUENCE:
111 * <pre>
112 * RC2-CBC parameter ::= SEQUENCE {
113 * rc2ParameterVersion INTEGER,
114 * iv OCTET STRING (8)}
115 *
116 * For the effective-key-bits of 40, 64, and 128, the
117 * rc2ParameterVersion values are 160, 120, 58 respectively.
118 * </pre>
119 * <li>CAST5_CBC: Feistel type block cipher with key sizes of 40-128 bit in 8 bit
120 * increments; parameters (RFC 2144):
121 * <pre>
122 * Parameters ::= SEQUENCE {
123 * iv OCTET STRING DEFAULT 0,
124 * keyLength INTEGER }
125 *
126 * </pre>
127 * </ul>
128 * This class shows how an EncryptedContentInfo is explicit created for encrypt�ng
129 * the content and supplying it to an EnvelopedDataStream object. Note that IAIK-CMS
130 * also allows to use EnvelopedData(Stream) for algorithms like RC2, ARCFOUR or CAST in
131 * without having the necessity of explicit key/parameter handling, see {@link
132 * demo.cms.envelopedData.RC2EnvelopedDataDemo RC2EnvelopedDataDemo} for an example.
133 * <p>
134 * Note that the usage of algorithms like RC2 is deprecated but used here for this
135 * demo since it requires a specific parameter handling.
136 */
137 public class PKCS7CMSEncryptedContentInfoDemo {
138
139 // certificate of user 1
140 X509Certificate user1;
141 // private key of user 1
142 PrivateKey user1_pk;
143 // certificate of user 2
144 X509Certificate user2;
145 // private key of user 2
146 PrivateKey user2_pk;
147 // secure random number generator
148 SecureRandom random;
149
150 /**
151 * Setup the demo certificate chains.
152 *
153 * Keys and certificate are retrieved from the demo KeyStore.
154 *
155 * @throws IOException if an file read error occurs
156 */
157 public PKCS7CMSEncryptedContentInfoDemo() throws IOException {
158
159 System.out.println();
160 System.out.println("********************************************************************************************************");
161 System.out.println("* PKCS7CMSEncryptedContentInfoDemo *");
162 System.out.println("* (tests the CMS EncryptedContentInfo against the IAIK-JCE PKCS#7 EncryptedContentInfo implementation) *");
163 System.out.println("********************************************************************************************************");
164 System.out.println();
165
166 // add all certificates to the list
167 X509Certificate[] certs = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1);
168 user1 = certs[0];
169 user1_pk = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1);
170 user2 = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2)[0];
171 user2_pk = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2);
172
173 random = SecRandom.getDefault();
174
175
176
177 }
178
179
180 /**
181 * Creates a CMS <code>EnvelopedDataStream</code> message.
182 *
183 * @param message the message to be enveloped, as byte representation
184 * @param contentEA the content encryption algorithm
185 * @param keyLength the key length for the symmetric key
186 * @return the DER encoding of the <code>EnvelopedData</code> object just created
187 * @throws Exception if the <code>EnvelopedData</code> object cannot be created
188 */
189 public byte[] createEnvelopedDataStream(byte[] message, AlgorithmID contentEA, int keyLength) throws Exception {
190
191 SecurityProvider provider = SecurityProvider.getSecurityProvider();
192 ByteArrayInputStream is = new ByteArrayInputStream(message);
193
194 AlgorithmParameterSpec params = null;
195 SecretKey secretKey = null;
196
197 // create iv
198 byte[] iv = new byte[8];
199 random.nextBytes(iv);
200
201 int rc2_param = 58;
202 if (contentEA.equals(AlgorithmID.rc2_CBC)) {
203
204 switch (keyLength) {
205 case 40:
206 rc2_param = 160;
207 break;
208 case 64:
209 rc2_param = 120;
210 break;
211 default: // 128
212 rc2_param = 58;
213 keyLength = 128;
214 }
215 // create the paramters (SEQUENCE) to be sent
216 SEQUENCE parameter = new SEQUENCE();
217 parameter.addComponent(new INTEGER(rc2_param));
218 parameter.addComponent(new OCTET_STRING(iv));
219 contentEA.setParameter(parameter);
220 params = new RC2ParameterSpec(keyLength,iv);
221 } else if (contentEA.equals(AlgorithmID.arcfour)){
222 // no params for ARCFOUR
223 params = null;
224 } else if (contentEA.equals(AlgorithmID.cast5_CBC)) {
225 SEQUENCE parameter = new SEQUENCE();
226 parameter.addComponent(new OCTET_STRING(iv));
227 parameter.addComponent(new INTEGER(keyLength));
228 contentEA.setParameter(parameter);
229 params = new IvParameterSpec(iv);
230
231 } else {
232 throw new Exception("Algorithm " + contentEA + " not supportted for this test!");
233 }
234
235 KeyGenerator keyGen = provider.getKeyGenerator(contentEA, keyLength);
236 // generate a new key
237 secretKey = keyGen.generateKey();
238
239 // create the EncryptedContentInfo for the content to be encrypted
240 EncryptedContentInfoStream eci = new EncryptedContentInfoStream(ObjectID.pkcs7_data, is);
241 // setup the cipher for encryption
242 eci.setupCipher(contentEA, secretKey, params);
243
244 // create the recipient infos
245 RecipientInfo[] recipients = new RecipientInfo[2];
246 // user1 is the first receiver
247 recipients[0] = new KeyTransRecipientInfo(user1, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
248 // encrypt the secret key for recipient 1
249 recipients[0].encryptKey(secretKey);
250 // user2 is the second receiver
251 recipients[1] = new KeyTransRecipientInfo(user2, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
252 // encrypt the secret key for recipient 2
253 recipients[1].encryptKey(secretKey);
254 // now create the EnvelopedDataStream
255 EnvelopedDataStream enveloped_data = new EnvelopedDataStream(recipients, eci);
256
257 // return the EnvelopedDate as DER encoded byte array with block size 2048
258 ByteArrayOutputStream os = new ByteArrayOutputStream();
259 enveloped_data.writeTo(os, 2048);
260 byte[] enc = os.toByteArray();
261 return enc;
262
263 }
264
265 /**
266 * Decrypts the encrypted content of the given CMS <code>EnvelopedData</code> object for the
267 * specified recipient and returns the decrypted (= original) message.
268 *
269 * @param encoding the <code>EnvelopedData</code> object as DER encoded byte array
270 * @param privateKey the private key to decrypt the message
271 * @param recipientInfoIndex the index into the <code>RecipientInfo</code> array
272 * to which the specified private key belongs
273 *
274 * @return the recovered message, as byte array
275 * @throws Exception if the message cannot be recovered
276 */
277 public byte[] getEnvelopedDataStream(byte[] encoding, PrivateKey privateKey, int recipientInfoIndex) throws Exception {
278
279 // create the EnvelopedData object from a DER encoded byte array
280 // we are testing the stream interface
281 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
282 EnvelopedDataStream enveloped_data = new EnvelopedDataStream(is);
283
284 AlgorithmParameterSpec params = null;
285 // get the recipient infos
286 RecipientInfo[] recipients = enveloped_data.getRecipientInfos();
287
288 System.out.println("\nThis message can be decrypted by the owners of the following certificates:");
289
290 for (int i=0; i<recipients.length; i++) {
291 System.out.println("Recipient "+(i+1)+":");
292 System.out.println(recipients[i].getRecipientIdentifiers()[0]);
293 }
294 // decrypt symmetric content encryption key, e.g.:
295 SecretKey secretKey = recipients[recipientInfoIndex].decryptKey(user1_pk);
296
297 //get the ECI from the enveloped data:
298 EncryptedContentInfoStream eci = (EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo();
299 //get the content encryption algorithm:
300 AlgorithmID contentEA = eci.getContentEncryptionAlgorithm();
301 System.out.println("Content Encryption Algorithm: " + contentEA);
302 if (contentEA.equals(AlgorithmID.rc2_CBC)) {
303 // get the parameters as SEQUENCE
304 SEQUENCE seq = (SEQUENCE)contentEA.getParameter();
305 // the iv is the second component
306 OCTET_STRING oct = (OCTET_STRING)seq.getComponentAt(1);
307 // create an IvParameterSpec:
308 //params = new IvParameterSpec((byte[])oct.getValue());
309 int rc2ParameterVersion = ((BigInteger)seq.getComponentAt(0).getValue()).intValue();
310 int effective_key_bits = 32;
311 switch (rc2ParameterVersion) {
312 case 160:
313 effective_key_bits = 40;
314 break;
315 case 120:
316 effective_key_bits = 64;
317 break;
318 case 58:
319 effective_key_bits = 128;
320 break;
321 default:
322 throw new Exception("Invalid rc2ParameterVersion " + rc2ParameterVersion + "!");
323
324 }
325 params = new RC2ParameterSpec(effective_key_bits,(byte[])seq.getComponentAt(1).getValue());
326
327 }
328 else if (contentEA.equals(AlgorithmID.rc5_CBC)) {
329 OCTET_STRING oct = (OCTET_STRING)contentEA.getParameter();
330 // create an IvParameterSpec:
331 params = new IvParameterSpec((byte[])oct.getValue());
332 } else if (contentEA.equals(AlgorithmID.arcfour)) {
333 params = null;
334 } else if (contentEA.equals(AlgorithmID.cast5_CBC)) {
335 // get the parameters
336 ASN1Object asn1Params = contentEA.getParameter();
337 if (asn1Params.isA(ASN.SEQUENCE)) {
338 // the iv is the first component
339 params = new IvParameterSpec((byte[])asn1Params.getComponentAt(0).getValue());
340 } else {
341 // to be compatible with (invalid) CAST AlgorithmIDs only using the IV as parameters
342 params = new IvParameterSpec((byte[])asn1Params.getValue());
343 }
344 } else {
345 throw new Exception("Algorithm " + contentEA + " not supportted for this test!");
346 }
347
348
349 //now setup the cipher with previously decrypted recipient key amd params
350 eci.setupCipher(secretKey, params);
351 //get and read the data thereby actually performing the decryption
352 InputStream data_is = eci.getInputStream();
353 ByteArrayOutputStream baos = new ByteArrayOutputStream();
354 Util.copyStream(data_is, baos, null);
355 byte[] decrypted = baos.toByteArray();
356 return decrypted;
357
358 }
359
360 // PKCS#7
361
362
363 /**
364 * Creates a PKCS#7 <code>EnvelopedDataStream</code> message.
365 * <p>
366 * The enveloped-data content type consists of encrypted content of any
367 * type and encrypted content-encryption keys for one or more recipients.
368 * The combination of encrypted content and encrypted content-encryption
369 * key for a recipient is a "digital envelope" for that recipient. Any type
370 * of content can be enveloped for any number of recipients in parallel.
371 *
372 * @param message the message to be enveloped, as byte representation
373 * @param cea the content encryption algorithm
374 * @param keyLength the key length for the symmetric key
375 * @return the DER encoding of the <code>EnvelopedData</code> object just created
376 * @throws Exception if the <code>EnvelopedData</code> object cannot
377 * be created
378 */
379 public byte[] createPKCS7EnvelopedDataStream(byte[] message, AlgorithmID cea, int keyLength) throws Exception {
380
381 SecurityProvider provider = SecurityProvider.getSecurityProvider();
382 ByteArrayInputStream is = new ByteArrayInputStream(message);
383 AlgorithmID contentEA = (AlgorithmID)cea.clone();
384 AlgorithmParameterSpec params = null;
385 KeyGenerator key_gen = null;
386 SecretKey secretKey = null;
387
388 // create iv
389 byte[] iv = new byte[8];
390 random.nextBytes(iv);
391
392 int rc2_param = 58;
393 if (contentEA.equals(AlgorithmID.rc2_CBC)) {
394 switch (keyLength) {
395 case 40:
396 rc2_param = 160;
397 break;
398 case 64:
399 rc2_param = 120;
400 break;
401 default: // 128
402 rc2_param = 58;
403 keyLength = 128;
404 }
405 // create the paramters (SEQUENCE) to be sent
406 SEQUENCE parameter = new SEQUENCE();
407 parameter.addComponent(new INTEGER(rc2_param));
408 parameter.addComponent(new OCTET_STRING(iv));
409 contentEA.setParameter(parameter);
410 params = new RC2ParameterSpec(keyLength,iv);
411 } else if (contentEA.equals(AlgorithmID.arcfour)){
412 // no params for ARCFOUR
413 params = null;
414 } else if (contentEA.equals(AlgorithmID.cast5_CBC)) {
415
416 SEQUENCE parameter = new SEQUENCE();
417 parameter.addComponent(new OCTET_STRING(iv));
418 parameter.addComponent(new INTEGER(keyLength));
419 contentEA.setParameter(parameter);
420 params = new IvParameterSpec(iv);
421
422 } else {
423 throw new Exception("Algorithm " + contentEA + " not supportted for this test!");
424 }
425
426 KeyGenerator keyGen = provider.getKeyGenerator(contentEA, keyLength);
427 // generate a new key
428 secretKey = keyGen.generateKey();
429
430 // create the EncryptedContentInfo for the content to be encrypted
431 iaik.pkcs.pkcs7.EncryptedContentInfoStream eci = new iaik.pkcs.pkcs7.EncryptedContentInfoStream(ObjectID.pkcs7_data, is);
432 // setup the cipher for encryption
433 eci.setupCipher(contentEA, secretKey, params);
434
435 // create the recipient infos
436 iaik.pkcs.pkcs7.RecipientInfo[] recipients = new iaik.pkcs.pkcs7.RecipientInfo[2];
437 // user1 is the first receiver
438 recipients[0] = new iaik.pkcs.pkcs7.RecipientInfo(user1, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
439 // encrypt the secret key for recipient 1
440 recipients[0].encryptKey(secretKey);
441 // user2 is the second receiver
442 recipients[1] = new iaik.pkcs.pkcs7.RecipientInfo(user2, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
443 // encrypt the secret key for recipient 2
444 recipients[1].encryptKey(secretKey);
445 // now create the EnvelopedDataStream
446 iaik.pkcs.pkcs7.EnvelopedDataStream enveloped_data =
447 new iaik.pkcs.pkcs7.EnvelopedDataStream(recipients, eci);
448
449 // return the EnvelopedDate as DER encoded byte array with block size 2048
450 ByteArrayOutputStream os = new ByteArrayOutputStream();
451 enveloped_data.writeTo(os, 2048);
452 byte[] enc = os.toByteArray();
453 return enc;
454
455 }
456
457 /**
458 * Decrypts the encrypted content of the given PKCS#7 <code>EnvelopedData</code> object for the
459 * specified recipient and returns the decrypted (= original) message.
460 *
461 * @param encoding the <code>EnvelopedData</code> object as DER encoded byte array
462 * @param privateKey the private key to decrypt the message
463 * @param recipientInfoIndex the index into the <code>RecipientInfo</code> array
464 * to which the specified private key belongs
465 *
466 * @return the recovered message, as byte array
467 * @throws Exception if the message cannot be recovered
468 */
469 public byte[] getPKCS7EnvelopedDataStream(byte[] encoding, PrivateKey privateKey, int recipientInfoIndex) throws Exception {
470
471 // create the EnvelopedData object from a DER encoded byte array
472 // we are testing the stream interface
473 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
474 iaik.pkcs.pkcs7.EnvelopedDataStream enveloped_data = new iaik.pkcs.pkcs7.EnvelopedDataStream(is);
475
476 AlgorithmParameterSpec params = null;
477 // get the recipient infos
478 iaik.pkcs.pkcs7.RecipientInfo[] recipients = enveloped_data.getRecipientInfos();
479
480 System.out.println("\nThis message can be decrypted by the owners of the following certificates:");
481
482 for (int i=0; i<recipients.length; i++) {
483 System.out.println("Recipient "+(i+1)+":");
484 System.out.println(recipients[i].getIssuerAndSerialNumber());
485 }
486 // decrypt symmetric content encryption key, e.g.:
487 SecretKey secretKey = recipients[recipientInfoIndex].decryptKey(user1_pk);
488
489 //get the ECI from the enveloped data:
490 iaik.pkcs.pkcs7.EncryptedContentInfoStream eci = (iaik.pkcs.pkcs7.EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo();
491 //get the content encryption algorithm:
492 AlgorithmID contentEA = eci.getContentEncryptionAlgorithm();
493 System.out.println("Content Encryption Algorithm: " + contentEA);
494 if (contentEA.equals(AlgorithmID.rc2_CBC)) {
495 // get the parameters as SEQUENCE
496 SEQUENCE seq = (SEQUENCE)contentEA.getParameter();
497 // the iv is the second component
498 OCTET_STRING oct = (OCTET_STRING)seq.getComponentAt(1);
499 // create an IvParameterSpec:
500 //params = new IvParameterSpec((byte[])oct.getValue());
501 int rc2ParameterVersion = ((BigInteger)seq.getComponentAt(0).getValue()).intValue();
502 int effective_key_bits = 32;
503 switch (rc2ParameterVersion) {
504 case 160:
505 effective_key_bits = 40;
506 break;
507 case 120:
508 effective_key_bits = 64;
509 break;
510 case 58:
511 effective_key_bits = 128;
512 break;
513 default:
514 throw new Exception("Invalid rc2ParameterVersion " + rc2ParameterVersion + "!");
515
516 }
517 params = new RC2ParameterSpec(effective_key_bits,(byte[])seq.getComponentAt(1).getValue());
518
519 }
520 else if (contentEA.equals(AlgorithmID.rc5_CBC)) {
521 OCTET_STRING oct = (OCTET_STRING)contentEA.getParameter();
522 // create an IvParameterSpec:
523 params = new IvParameterSpec((byte[])oct.getValue());
524 } else if (contentEA.equals(AlgorithmID.arcfour)) {
525 params = null;
526 } else if (contentEA.equals(AlgorithmID.cast5_CBC)) {
527 // get the parameters
528 ASN1Object asn1Params = contentEA.getParameter();
529 if (asn1Params.isA(ASN.SEQUENCE)) {
530 // the iv is the first component
531 params = new IvParameterSpec((byte[])asn1Params.getComponentAt(0).getValue());
532 } else {
533 // to be compatible with (invalid) CAST AlgorithmIDs only using the IV as parameters
534 params = new IvParameterSpec((byte[])asn1Params.getValue());
535 }
536 } else {
537 throw new Exception("Algorithm " + contentEA + " not supportted for this test!");
538 }
539
540
541 //now setup the cipher with previously decrypted recipient key amd params
542 eci.setupCipher(secretKey, params);
543 //get and read the data thereby actually performing the decryption
544 InputStream data_is = eci.getInputStream();
545 ByteArrayOutputStream baos = new ByteArrayOutputStream();
546 Util.copyStream(data_is, baos, null);
547 byte[] decrypted = baos.toByteArray();
548 return decrypted;
549
550 }
551
552
553
554 /**
555 * Starts the test.
556 */
557 public void start() {
558 // the test message
559 String m = "This is the test message.";
560 System.out.println("Test message: \""+m+"\"");
561 System.out.println();
562 byte[] message = m.getBytes();
563
564 try {
565 byte[] data;
566 byte[] received_message = null;
567
568
569 // the stream implementation
570 //
571 // test CMS EnvelopedDataStream
572 //
573
574 // ARCFOUR
575 System.out.println("\nEnvelopedDataStream demo for algorithm ARCFOUR [create]:\n");
576 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.arcfour.clone(), 128);
577 // transmit data
578 System.out.println("\nEnvelopedDataStream demo [parse]:\n");
579 // user1 means index 0 (hardcoded for this demo)
580 received_message = getEnvelopedDataStream(data, user1_pk, 0);
581 System.out.print("\nDecrypted content: ");
582 System.out.println(new String(received_message));
583
584 // RC2
585 System.out.println("\nEnvelopedDataStream demo for algorithm RC2 [create]:\n");
586 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.rc2_CBC.clone(), 128);
587 // transmit data
588 System.out.println("\nEnvelopedDataStream demo [parse]:\n");
589 // user1 means index 0 (hardcoded for this demo)
590 received_message = getEnvelopedDataStream(data, user1_pk, 0);
591 System.out.print("\nDecrypted content: ");
592 System.out.println(new String(received_message));
593
594 // CAST5_CBC
595 System.out.println("\nEnvelopedDataStream demo for algorithm CAST5_CBC [create]:\n");
596 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.cast5_CBC.clone(), 128);
597 // transmit data
598 System.out.println("\nEnvelopedDataStream demo [parse]:\n");
599 // user1 means index 0 (hardcoded for this demo)
600 received_message = getEnvelopedDataStream(data, user1_pk, 0);
601 System.out.print("\nDecrypted content: ");
602 System.out.println(new String(received_message));
603
604 // CMS <---> PKCS#7
605
606 System.out.println("Test compatibility to PKCS#7....");
607
608 // ARCFOUR
609 System.out.println("\nCMS EnvelopedDataStream demo for algorithm ARCFOUR [create]:\n");
610 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.arcfour.clone(), 128);
611 // transmit data
612 System.out.println("\nPKCS#7 EnvelopedDataStream demo [parse]:\n");
613 // user1 means index 0 (hardcoded for this demo)
614 received_message = getPKCS7EnvelopedDataStream(data, user1_pk, 0);
615 System.out.print("\nDecrypted content: ");
616 System.out.println(new String(received_message));
617
618 System.out.println("\nPKCS#7 EnvelopedDataStream demo for algorithm ARCFOUR [create]:\n");
619 data = createPKCS7EnvelopedDataStream(message, (AlgorithmID)AlgorithmID.arcfour.clone(), 128);
620 // transmit data
621 System.out.println("\nCMS EnvelopedDataStream demo [parse]:\n");
622 // user1 means index 0 (hardcoded for this demo)
623 received_message = getEnvelopedDataStream(data, user1_pk, 0);
624 System.out.print("\nDecrypted content: ");
625 System.out.println(new String(received_message));
626
627
628 // RC2
629 System.out.println("\nCMS EnvelopedDataStream demo for algorithm RC2 [create]:\n");
630 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.rc2_CBC.clone(), 128);
631 // transmit data
632 System.out.println("\nPKCS#7 EnvelopedDataStream demo [parse]:\n");
633 // user1 means index 0 (hardcoded for this demo)
634 received_message = getPKCS7EnvelopedDataStream(data, user1_pk, 0);
635 System.out.print("\nDecrypted content: ");
636 System.out.println(new String(received_message));
637
638 System.out.println("\nPKCS#7 EnvelopedDataStream demo for algorithm RC2 [create]:\n");
639 data = createPKCS7EnvelopedDataStream(message, (AlgorithmID)AlgorithmID.rc2_CBC.clone(), 128);
640 // transmit data
641 System.out.println("\nCMS EnvelopedDataStream demo [parse]:\n");
642 // user1 means index 0 (hardcoded for this demo)
643 received_message = getEnvelopedDataStream(data, user1_pk, 0);
644 System.out.print("\nDecrypted content: ");
645 System.out.println(new String(received_message));
646
647 // CAST5_CBC
648 System.out.println("\nCMS EnvelopedDataStream demo for algorithm CAST5_CBC [create]:\n");
649 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.cast5_CBC.clone(), 128);
650 // transmit data
651 System.out.println("\nPKCS#7 EnvelopedDataStream demo [parse]:\n");
652 // user1 means index 0 (hardcoded for this demo)
653 received_message = getPKCS7EnvelopedDataStream(data, user1_pk, 0);
654 System.out.print("\nDecrypted content: ");
655 System.out.println(new String(received_message));
656
657 System.out.println("\nPKCS#7 EnvelopedDataStream demo for algorithm CAST5_CBC [create]:\n");
658 data = createPKCS7EnvelopedDataStream(message, (AlgorithmID)AlgorithmID.cast5_CBC.clone(), 128);
659 // transmit data
660 System.out.println("\nCMS EnvelopedDataStream demo [parse]:\n");
661 // user1 means index 0 (hardcoded for this demo)
662 received_message = getEnvelopedDataStream(data, user1_pk, 0);
663 System.out.print("\nDecrypted content: ");
664 System.out.println(new String(received_message));
665
666 } catch (Exception ex) {
667 ex.printStackTrace();
668 throw new RuntimeException(ex.toString());
669 }
670 }
671
672 /**
673 * The main method.
674 *
675 * @throws IOException
676 * if an I/O error occurs when reading required keys
677 * and certificates from files
678 */
679 public static void main(String argv[]) throws Exception {
680
681 DemoUtil.initDemos();
682
683 (new PKCS7CMSEncryptedContentInfoDemo()).start();
684 System.out.println("\nReady!");
685 DemoUtil.waitKey();
686 }
687 }