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/PKCS7CMSEnvelopedDataDemo.java 22    12.02.25 17:58 Dbratko $
029// $Revision: 22 $
030//
031
032package demo.cms.pkcs7cms;
033
034import iaik.asn1.ASN1Object;
035import iaik.asn1.structures.AlgorithmID;
036import iaik.cms.CMSException;
037import iaik.cms.EncryptedContentInfo;
038import iaik.cms.EncryptedContentInfoStream;
039import iaik.cms.EnvelopedData;
040import iaik.cms.EnvelopedDataStream;
041import iaik.cms.KeyTransRecipientInfo;
042import iaik.cms.RecipientInfo;
043import iaik.pkcs.PKCSException;
044import iaik.security.random.SecRandom;
045import iaik.utils.Util;
046import iaik.x509.X509Certificate;
047
048import java.io.ByteArrayInputStream;
049import java.io.ByteArrayOutputStream;
050import java.io.IOException;
051import java.io.InputStream;
052import java.security.InvalidKeyException;
053import java.security.NoSuchAlgorithmException;
054import java.security.PrivateKey;
055import java.security.SecureRandom;
056
057import demo.DemoUtil;
058import demo.keystore.CMSKeyStore;
059
060
061/**
062 * Compares the usage of the IAIK CMS EnvelopedData(Stream) implementation against the
063 * IAIK PKCS#7 EnvelopedData(Stream) implementation.
064 */
065public class PKCS7CMSEnvelopedDataDemo {
066
067  // certificate of user 1
068  X509Certificate user1;
069  // private key of user 1
070  PrivateKey user1_pk;
071  // certificate of user 2
072  X509Certificate user2;
073  // private key of user 2
074  PrivateKey user2_pk;
075  // secure random number generator
076  SecureRandom random;
077
078  /**
079   * Setup the demo certificate chains.
080   *
081   * Keys and certificate are retrieved from the demo KeyStore.
082   *
083   * @throws IOException if an file read error occurs
084   */
085  public PKCS7CMSEnvelopedDataDemo() throws IOException {
086    
087    System.out.println();
088    System.out.println("***********************************************************************************************");
089    System.out.println("*                                 PKCS7CMSEnvelopedDataDemo                                   *");
090    System.out.println("* (tests the CMS EnvelopedData against the IAIK-JCE PKCS#7 EnvelopedData type implementation) *");
091    System.out.println("***********************************************************************************************");
092    System.out.println();
093    
094    // add all certificates to the list
095    X509Certificate[] certs = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1);
096    user1 = certs[0];
097    user1_pk = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1);
098    user2 = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2)[0];
099    user2_pk = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2);
100  
101    random = SecRandom.getDefault();
102
103  }
104
105
106  /**
107   * Creates a CMS <code>EnvelopedDataStream</code> message.
108   * <p>
109   * The enveloped-data content type consists of encrypted content of any
110   * type and encrypted content-encryption keys for one or more recipients.
111   * The combination of encrypted content and encrypted content-encryption
112   * key for a recipient is a "digital envelope" for that recipient. Any type
113   * of content can be enveloped for any number of recipients in parallel.
114   *
115   * @param message the message to be enveloped, as byte representation
116   * @return the DER encoding of the <code>EnvelopedData</code> object just created
117   * @throws CMSException if the <code>EnvelopedData</code> object cannot
118   *                          be created
119   * @throws IOException if an I/O error occurs
120   */
121  public byte[] createEnvelopedDataStream(byte[] message) throws CMSException, IOException {
122
123    EnvelopedDataStream enveloped_data;
124
125    // we are testing the stream interface
126    ByteArrayInputStream is = new ByteArrayInputStream(message);
127    // create a new EnvelopedData object encrypted with AES
128    try {
129      enveloped_data = new EnvelopedDataStream(is, (AlgorithmID)AlgorithmID.aes256_CBC.clone());
130    } catch (NoSuchAlgorithmException ex) {
131      throw new CMSException(ex.toString());
132    }
133
134
135    // create the recipient infos
136    KeyTransRecipientInfo[] recipients = new KeyTransRecipientInfo[2];
137    // user1 is the first receiver
138    recipients[0] = new KeyTransRecipientInfo(user1, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
139    // user2 is the second receiver
140    recipients[1] = new KeyTransRecipientInfo(user2, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
141    // specify the recipients of the encrypted message
142    enveloped_data.setRecipientInfos(recipients);
143
144    // return the EnvelopedDate as DER encoded byte array with block size 2048
145    ByteArrayOutputStream os = new ByteArrayOutputStream();
146    enveloped_data.writeTo(os, 2048);
147    return os.toByteArray();
148  }
149
150  /**
151   * Decrypts the encrypted content of the given <code>EnvelopedData</code> object for the
152   * specified recipient and returns the decrypted (= original) message.
153   *
154   * @param encoding the <code>EnvelopedData</code> object as DER encoded byte array
155   * @param privateKey the private key to decrypt the message
156   * @param recipientInfoIndex the index into the <code>RecipientInfo</code> array
157   *                           to which the specified private key belongs
158   *
159   * @return the recovered message, as byte array
160   * @throws CMSException if the message cannot be recovered
161   * @throws IOException if an I/O error occurs
162   */
163  public byte[] getEnvelopedDataStream(byte[] encoding, PrivateKey privateKey, int recipientInfoIndex)
164    throws CMSException, IOException {
165
166    // create the EnvelopedData object from a DER encoded byte array
167    // we are testing the stream interface
168    ByteArrayInputStream is = new ByteArrayInputStream(encoding);
169    EnvelopedDataStream enveloped_data = new EnvelopedDataStream(is);
170
171    System.out.println("Information about the encrypted data:");
172    EncryptedContentInfoStream eci = (EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo();
173    System.out.println("Content type: "+eci.getContentType().getName());
174    System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
175
176    System.out.println("\nThis message can be decrypted by the owners of the following certificates:");
177    RecipientInfo[] recipients = enveloped_data.getRecipientInfos();
178    for (int i=0; i<recipients.length; i++) {
179      System.out.println("Recipient "+(i+1)+":");
180      System.out.println(recipients[i].getRecipientIdentifiers()[0]);
181    }
182
183    // decrypt the message
184    try {
185      enveloped_data.setupCipher(privateKey, recipientInfoIndex);
186      InputStream decrypted = enveloped_data.getInputStream();
187      ByteArrayOutputStream os = new ByteArrayOutputStream();
188      Util.copyStream(decrypted, os, null);
189
190      return os.toByteArray();
191
192    } catch (InvalidKeyException ex) {
193      throw new CMSException("Private key error: "+ex.toString());
194    } catch (NoSuchAlgorithmException ex) {
195      throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
196    }
197  }
198
199
200  /**
201   * Creates a CMS <code>EnvelopedData</code> message.
202   * <p>
203   * The enveloped-data content type consists of encrypted content of any
204   * type and encrypted content-encryption keys for one or more recipients.
205   * The combination of encrypted content and encrypted content-encryption
206   * key for a recipient is a "digital envelope" for that recipient. Any type
207   * of content can be enveloped for any number of recipients in parallel.
208   *
209   * @param message the message to be enveloped, as byte representation
210   * @return the <code>EnvelopedData</code> as ASN.1 object
211   * @throws CMSException if the <code>EnvelopedData</code> object cannot
212   *                          be created
213   */
214  public ASN1Object createEnvelopedData(byte[] message) throws CMSException {
215
216    EnvelopedData enveloped_data;
217
218    // create a new EnvelopedData object encrypted with AES
219    try {
220      enveloped_data = new EnvelopedData(message, (AlgorithmID)AlgorithmID.aes256_CBC.clone());
221    } catch (NoSuchAlgorithmException ex) {
222      throw new CMSException(ex.toString());
223    }
224
225  
226    // create the recipient infos
227    KeyTransRecipientInfo[] recipients = new KeyTransRecipientInfo[2];
228    // user1 is the first receiver
229    recipients[0] = new KeyTransRecipientInfo(user1, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
230    // user2 is the second receiver
231    recipients[1] = new KeyTransRecipientInfo(user2, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
232    // specify the recipients of the encrypted message
233    enveloped_data.setRecipientInfos(recipients);
234
235    // return the EnvelopedDate as DER encoded byte array
236    return enveloped_data.toASN1Object();
237  }
238
239
240  /**
241   * Decrypts the encrypted content of the given <code>EnvelopedData</code> object for the
242   * specified recipient and returns the decrypted (= original) message.
243   *
244   * @param obj the <code>EnvelopedData</code> as ASN.1 object
245   * @param privateKey the private key to decrypt the message
246   * @param recipientInfoIndex the index into the <code>RecipientInfo</code> array
247   *                           to which the specified private key belongs
248   *
249   * @return the recovered message, as byte array
250   * @throws CMSException if the message cannot be recovered
251   */
252  public byte[] getEnvelopedData(ASN1Object obj, PrivateKey privateKey, int recipientInfoIndex) 
253    throws CMSException {
254
255    EnvelopedData enveloped_data = new EnvelopedData(obj);
256
257    System.out.println("Information about the encrypted data:");
258    EncryptedContentInfo eci = (EncryptedContentInfo)enveloped_data.getEncryptedContentInfo();
259    System.out.println("Content type: "+eci.getContentType().getName());
260    System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
261
262    System.out.println("\nThis message can be decrypted by the owners of the following certificates:");
263    RecipientInfo[] recipients = enveloped_data.getRecipientInfos();
264    for (int i=0; i<recipients.length; i++) {
265      System.out.println("Recipient "+(i+1)+":");
266      System.out.println(recipients[i].getRecipientIdentifiers()[0]);
267    }
268
269    // decrypt the message
270    try {
271      enveloped_data.setupCipher(privateKey, recipientInfoIndex);
272      return enveloped_data.getContent();
273
274    } catch (InvalidKeyException ex) {
275      throw new CMSException("Private key error: "+ex.toString());
276    } catch (NoSuchAlgorithmException ex) {
277      throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
278    }
279  }
280  
281  // PKCS#7
282  
283  /**
284   * Creates a PKCS#7 <code>EnvelopedDataStream</code> message.
285   * <p>
286   * The enveloped-data content type consists of encrypted content of any
287   * type and encrypted content-encryption keys for one or more recipients.
288   * The combination of encrypted content and encrypted content-encryption
289   * key for a recipient is a "digital envelope" for that recipient. Any type
290   * of content can be enveloped for any number of recipients in parallel.
291   *
292   * @param message the message to be enveloped, as byte representation
293   * @return the DER encoding of the <code>EnvelopedData</code> object just created
294   * @throws PKCSException if the <code>EnvelopedData</code> object cannot
295   *                          be created
296   * @throws IOException if an I/O error occurs
297   */
298  public byte[] createPKCS7EnvelopedDataStream(byte[] message) throws iaik.pkcs.PKCSException, IOException {
299
300    iaik.pkcs.pkcs7.EnvelopedDataStream enveloped_data;
301
302    // we are testing the stream interface
303    ByteArrayInputStream is = new ByteArrayInputStream(message);
304    // create a new EnvelopedData object encrypted with AES
305    try {
306      enveloped_data = new iaik.pkcs.pkcs7.EnvelopedDataStream(is, (AlgorithmID)AlgorithmID.aes256_CBC.clone());
307    } catch (NoSuchAlgorithmException ex) {
308      throw new iaik.pkcs.PKCSException(ex.toString());
309    }
310
311    try {
312      // create the recipient infos
313      iaik.pkcs.pkcs7.RecipientInfo[] recipients = new iaik.pkcs.pkcs7.RecipientInfo[2];
314      // user1 is the first receiver
315      recipients[0] = new iaik.pkcs.pkcs7.RecipientInfo(user1, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
316      // user2 is the second receiver
317      recipients[1] = new iaik.pkcs.pkcs7.RecipientInfo(user2, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
318
319      // specify the recipients of the encrypted message
320      enveloped_data.setRecipientInfos(recipients);
321    } catch (NoSuchAlgorithmException ex) {
322      throw new iaik.pkcs.PKCSException("Algorithm not supported: " + ex.toString());  
323    }
324
325    // return the EnvelopedDate as DER encoded byte array with block size 2048
326    ByteArrayOutputStream os = new ByteArrayOutputStream();
327    enveloped_data.writeTo(os, 2048);
328    return os.toByteArray();
329  }
330
331  /**
332   * Decrypts the encrypted content of the given <code>EnvelopedData</code> object for the
333   * specified recipient and returns the decrypted (= original) message.
334   *
335   * @param encoding the <code>EnvelopedData</code> object as DER encoded byte array
336   * @param privateKey the private key to decrypt the message
337   * @param recipientInfoIndex the index into the <code>RecipientInfo</code> array
338   *                           to which the specified private key belongs
339   *
340   * @return the recovered message, as byte array
341   * @throws PKCSException if the message cannot be recovered
342   * @throws IOException if an I/O error occurs
343   */
344  public byte[] getPKCS7EnvelopedDataStream(byte[] encoding, PrivateKey privateKey, int recipientInfoIndex) throws iaik.pkcs.PKCSException, IOException {
345
346    // create the EnvelopedData object from a DER encoded byte array
347    // we are testing the stream interface
348    ByteArrayInputStream is = new ByteArrayInputStream(encoding);
349    iaik.pkcs.pkcs7.EnvelopedDataStream enveloped_data = new iaik.pkcs.pkcs7.EnvelopedDataStream(is);
350
351    System.out.println("Information about the encrypted data:");
352    iaik.pkcs.pkcs7.EncryptedContentInfoStream eci = (iaik.pkcs.pkcs7.EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo();
353    System.out.println("Content type: "+eci.getContentType().getName());
354    System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
355
356    System.out.println("\nThis message can be decrypted by the owners of the following certificates:");
357    iaik.pkcs.pkcs7.RecipientInfo[] recipients = enveloped_data.getRecipientInfos();
358    for (int i=0; i<recipients.length; i++) {
359      System.out.println("Recipient "+(i+1)+":");
360      System.out.println(recipients[i].getIssuerAndSerialNumber());
361    }
362
363
364    // decrypt the message
365    try {
366      enveloped_data.setupCipher(privateKey, recipientInfoIndex);
367      InputStream decrypted = enveloped_data.getInputStream();
368      ByteArrayOutputStream os = new ByteArrayOutputStream();
369      Util.copyStream(decrypted, os, null);
370
371      return os.toByteArray();
372
373    } catch (InvalidKeyException ex) {
374      throw new iaik.pkcs.PKCSException("Private key error: "+ex.toString());
375    } catch (NoSuchAlgorithmException ex) {
376      throw new iaik.pkcs.PKCSException("Content encryption algorithm not implemented: "+ex.getMessage());
377    }
378  }
379
380
381  /**
382   * Creates a PKCS#7 <code>EnvelopedData</code> message.
383   * <p>
384   * The enveloped-data content type consists of encrypted content of any
385   * type and encrypted content-encryption keys for one or more recipients.
386   * The combination of encrypted content and encrypted content-encryption
387   * key for a recipient is a "digital envelope" for that recipient. Any type
388   * of content can be enveloped for any number of recipients in parallel.
389   *
390   * @param message the message to be enveloped, as byte representation
391   * @return the <code>EnvelopedData</code> as ASN.1 object
392   * @throws PKCSException if the <code>EnvelopedData</code> object cannot
393   *                          be created
394   * @throws IOException if an I/O error occurs
395   */
396  public ASN1Object createPKCS7EnvelopedData(byte[] message) throws iaik.pkcs.PKCSException, IOException {
397
398    iaik.pkcs.pkcs7.EnvelopedData enveloped_data;
399
400    // create a new EnvelopedData object encrypted with AES
401    try {
402      enveloped_data = new iaik.pkcs.pkcs7.EnvelopedData(message, (AlgorithmID)AlgorithmID.aes256_CBC.clone());
403    } catch (NoSuchAlgorithmException ex) {
404      throw new iaik.pkcs.PKCSException(ex.toString());
405    }
406
407    try {
408      // create the recipient infos
409      iaik.pkcs.pkcs7.RecipientInfo[] recipients = new iaik.pkcs.pkcs7.RecipientInfo[2];
410      // user1 is the first receiver
411      recipients[0] = new iaik.pkcs.pkcs7.RecipientInfo(user1, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
412      // user2 is the second receiver
413      recipients[1] = new iaik.pkcs.pkcs7.RecipientInfo(user2, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
414
415      // specify the recipients of the encrypted message
416      enveloped_data.setRecipientInfos(recipients);
417    } catch (NoSuchAlgorithmException ex) {
418      throw new iaik.pkcs.PKCSException("Algorithm not supported: " + ex.toString());
419    }
420
421    // return the EnvelopedDate as DER encoded byte array
422    return enveloped_data.toASN1Object();
423  }
424
425
426  /**
427   * Decrypts the encrypted content of the given <code>EnvelopedData</code> object for the
428   * specified recipient and returns the decrypted (= original) message.
429   *
430   * @param obj the <code>EnvelopedData</code> as ASN.1 object
431   * @param privateKey the private key to decrypt the message
432   * @param recipientInfoIndex the index into the <code>RecipientInfo</code> array
433   *                           to which the specified private key belongs
434   *
435   * @return the recovered message, as byte array
436   * @throws PKCSException if the message cannot be recovered
437   * @throws IOException if an I/O error occurs
438   */
439  public byte[] getPKCS7EnvelopedData(ASN1Object obj, PrivateKey privateKey, int recipientInfoIndex) throws iaik.pkcs.PKCSException, IOException {
440
441
442    iaik.pkcs.pkcs7.EnvelopedData enveloped_data = new iaik.pkcs.pkcs7.EnvelopedData(obj);
443
444    System.out.println("Information about the encrypted data:");
445    iaik.pkcs.pkcs7.EncryptedContentInfo eci = (iaik.pkcs.pkcs7.EncryptedContentInfo)enveloped_data.getEncryptedContentInfo();
446    System.out.println("Content type: "+eci.getContentType().getName());
447    System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
448
449    System.out.println("\nThis message can be decrypted by the owners of the following certificates:");
450    iaik.pkcs.pkcs7.RecipientInfo[] recipients = enveloped_data.getRecipientInfos();
451    for (int i=0; i<recipients.length; i++) {
452      System.out.println("Recipient "+(i+1)+":");
453      System.out.println(recipients[i].getIssuerAndSerialNumber());
454    }
455
456    // decrypt the message
457    try {
458      enveloped_data.setupCipher(privateKey, recipientInfoIndex);
459      return enveloped_data.getContent();
460
461    } catch (InvalidKeyException ex) {
462      throw new iaik.pkcs.PKCSException("Private key error: "+ex.toString());
463    } catch (NoSuchAlgorithmException ex) {
464      throw new iaik.pkcs.PKCSException("Content encryption algorithm not implemented: "+ex.getMessage());
465    }
466  }
467
468
469
470  /**
471   * Starts the test.
472   */
473  public void start() {
474     // the test message
475    String m = "This is the test message.";
476    System.out.println("Test message: \""+m+"\"");
477    System.out.println();
478    byte[] message = m.getBytes();
479
480    try {
481      byte[] data;
482      byte[] received_message = null;
483      System.out.println("Stream implementation demos");
484      System.out.println("===========================");
485
486
487      // the stream implementation
488      //
489      // test CMS EnvelopedDataStream
490      //
491      System.out.println("\nCMS EnvelopedDataStream demo [create]:\n");
492      data = createEnvelopedDataStream(message);
493      // transmit data
494      System.out.println("\nCMS EnvelopedDataStream demo [parse]:\n");
495      // user1 means index 0 (hardcoded for this demo)
496      received_message = getEnvelopedDataStream(data, user1_pk, 0);
497      System.out.print("\nDecrypted content: ");
498      System.out.println(new String(received_message));
499      
500      System.out.println("Testing compatibility to PKCS#7...");
501      
502      System.out.println("\nPKCS7 EnvelopedDataStream demo [create]:\n");
503      data = createPKCS7EnvelopedDataStream(message);
504      // transmit data
505      System.out.println("\nCMS EnvelopedDataStream demo [parse]:\n");
506      // user1 means index 0 (hardcoded for this demo)
507      received_message = getEnvelopedDataStream(data, user1_pk, 0);
508      System.out.print("\nDecrypted content: ");
509      System.out.println(new String(received_message));
510      
511      System.out.println("\nPKCS7 EnvelopedDataStream demo [create]:\n");
512      data = createPKCS7EnvelopedDataStream(message);
513      // transmit data
514      System.out.println("\nCMS EnvelopedDataStream demo [parse]:\n");
515      // user1 means index 0 (hardcoded for this demo)
516      received_message = getEnvelopedDataStream(data, user1_pk, 0);
517      System.out.print("\nDecrypted content: ");
518      System.out.println(new String(received_message));
519      
520      System.out.println("\nCMS EnvelopedDataStream demo [create]:\n");
521      data = createEnvelopedDataStream(message);
522      // transmit data
523      System.out.println("\nPKCS7 EnvelopedDataStream demo [parse]:\n");
524      // user1 means index 0 (hardcoded for this demo)
525      received_message = getPKCS7EnvelopedDataStream(data, user1_pk, 0);
526      System.out.print("\nDecrypted content: ");
527      System.out.println(new String(received_message));
528
529
530
531
532      // the non-stream implementation
533      System.out.println("\nNon-stream implementation demos");
534      System.out.println("===============================");
535
536      ASN1Object obj = null;
537
538      //
539      // test CMS EnvelopedData
540      //
541      obj = null;
542      System.out.println("\nCMS EnvelopedData demo [create]:\n");
543      obj = createEnvelopedData(message);
544      // transmit data
545      System.out.println("\nCMS EnvelopedData demo [parse]:\n");
546      // user1 means index 0 (hardcoded for this demo)
547      received_message = getEnvelopedData(obj, user1_pk, 0);
548      System.out.print("\nDecrypted content: ");
549      System.out.println(new String(received_message));
550      
551      System.out.println("Testing compatibility to PKCS#7...");
552      
553      obj = null;
554      System.out.println("\nPKCS7 EnvelopedData demo [create]:\n");
555      obj = createPKCS7EnvelopedData(message);
556      // transmit data
557      System.out.println("\nCMS EnvelopedData demo [parse]:\n");
558      // user1 means index 0 (hardcoded for this demo)
559      received_message = getEnvelopedData(obj, user1_pk, 0);
560      System.out.print("\nDecrypted content: ");
561      System.out.println(new String(received_message));
562      
563      obj = null;
564      System.out.println("\nCMS EnvelopedData demo [create]:\n");
565      obj = createPKCS7EnvelopedData(message);
566      // transmit data
567      System.out.println("\nPKCS7 EnvelopedData demo [parse]:\n");
568      // user1 means index 0 (hardcoded for this demo)
569      received_message = getPKCS7EnvelopedData(obj, user1_pk, 0);
570      System.out.print("\nDecrypted content: ");
571      System.out.println(new String(received_message));
572
573
574        } catch (Exception ex) {
575          ex.printStackTrace();
576          throw new RuntimeException(ex.toString());
577        }
578  }
579
580  /**
581   * The main method.
582   *
583   * @throws IOException
584   *            if an I/O error occurs when reading required keys
585   *            and certificates from files
586   */
587  public static void main(String argv[]) throws Exception {
588
589        DemoUtil.initDemos();
590
591    (new PKCS7CMSEnvelopedDataDemo()).start();
592    System.out.println("\nReady!");
593    DemoUtil.waitKey();
594  }
595}