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