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/envelopedData/EnvelopedDataDemo.java 40 12.02.25 17:58 Dbratko $
059 // $Revision: 40 $
060 //
061
062
063 package demo.cms.envelopedData;
064
065 import java.io.ByteArrayInputStream;
066 import java.io.ByteArrayOutputStream;
067 import java.io.IOException;
068 import java.io.InputStream;
069 import java.security.InvalidKeyException;
070 import java.security.Key;
071 import java.security.NoSuchAlgorithmException;
072 import java.security.PrivateKey;
073 import java.security.SecureRandom;
074 import java.util.Arrays;
075
076 import javax.crypto.KeyGenerator;
077 import javax.crypto.SecretKey;
078
079 import demo.DemoUtil;
080 import demo.keystore.CMSKeyStore;
081 import iaik.asn1.structures.AlgorithmID;
082 import iaik.cms.CMSException;
083 import iaik.cms.CertificateIdentifier;
084 import iaik.cms.EncryptedContentInfo;
085 import iaik.cms.EncryptedContentInfoStream;
086 import iaik.cms.EnvelopedData;
087 import iaik.cms.EnvelopedDataStream;
088 import iaik.cms.IssuerAndSerialNumber;
089 import iaik.cms.KEKIdentifier;
090 import iaik.cms.KEKRecipientInfo;
091 import iaik.cms.KeyAgreeRecipientInfo;
092 import iaik.cms.KeyIdentifier;
093 import iaik.cms.KeyTransRecipientInfo;
094 import iaik.cms.RecipientInfo;
095 import iaik.cms.RecipientKeyIdentifier;
096 import iaik.cms.SecurityProvider;
097 import iaik.cms.SubjectKeyID;
098 import iaik.security.random.SecRandom;
099 import iaik.utils.Util;
100 import iaik.x509.X509Certificate;
101
102
103 /**
104 * Demonstrates the usage of class {@link iaik.cms.EnvelopedDataStream} and
105 * {@link iaik.cms.EnvelopedData} for encrypting data using the CMS type
106 * EnvelopedData.
107 * <p>
108 * This demo creates an EnvelopedData object and subsequently shows several
109 * ways that may be used for decrypting the content for some particular
110 * recipient.
111 * <p>
112 * Keys and certificates are retrieved from the demo KeyStore ("cms.keystore")
113 * which has to be located in your current working directory and may be
114 * created by running the {@link demo.keystore.SetupCMSKeyStore
115 * SetupCMSKeyStore} program.
116 * <p>
117 * This demo uses TripleDES which has been deprecated by S/MIMEv4 (RFC 8551),
118 * see {@link AESEnvelopedDataDemo AESEnvelopedDataDemo} for an AES based demo.
119 *
120 * @see iaik.cms.EnvelopedDataStream
121 * @see iaik.cms.EnvelopedData
122 * @see iaik.cms.RecipientInfo
123 * @see iaik.cms.KeyTransRecipientInfo
124 * @see iaik.cms.KeyAgreeRecipientInfo
125 * @see iaik.cms.KEKRecipientInfo
126 */
127 public class EnvelopedDataDemo {
128
129 // certificate of rsaUser 1
130 X509Certificate rsaUser1_;
131 // private key of rsaUser 1
132 PrivateKey rsaUser1Pk_;
133 // certificate of rsaUser 2
134 X509Certificate rsaUser2_;
135 // private key of rsaUser 2
136 PrivateKey rsaUser2Pk_;
137
138 // certificate of esdhUser 1
139 X509Certificate esdhUser1_;
140 // private key of esdhUser 1
141 PrivateKey esdhUser1Pk_;
142 // certificate of esdhUser 2
143 X509Certificate esdhUser2_;
144 // private key of esdhUser 2
145 PrivateKey esdhUser2Pk_;
146
147 // key encryption key for KEKRecipientInfo
148 SecretKey kek_;
149 byte[] kekID_;
150
151 // content encryption algorithm to be used
152 AlgorithmID contentEncAlg_;
153 // cek algorithm
154 String cekAlg_;
155 // key wrap algorithm to be used
156 AlgorithmID keyWrapAlg_;
157 // key length (same for content encryption key and key encryption key
158 int keyLength_;
159
160 // secure random number generator
161 SecureRandom random_;
162
163 /**
164 * Creates an EnvelopedDataDemo and setups the demo certificates.
165 * <br>
166 * Keys and certificates are retrieved from the demo KeyStore ("cms.keystore")
167 * file which has to be located in your current working directory and may be
168 * created by running {@link demo.keystore.SetupCMSKeyStore
169 * SetupCMSKeyStore}.
170 * <br>
171 * TripleDES and TripleDES KeyWrap are used for content encryption and
172 * content encryption key wrapping.
173 *
174 * @throws IOException if an file read error occurs
175 * @throws NoSuchAlgorithmException if the requested TripleDES or TripleDES KeyWrap
176 * algorithms are not supported
177 */
178 public EnvelopedDataDemo() throws IOException, NoSuchAlgorithmException {
179 this((AlgorithmID)AlgorithmID.des_EDE3_CBC.clone(),
180 (AlgorithmID)AlgorithmID.cms_3DES_wrap.clone(),
181 (AlgorithmID)AlgorithmID.cms_3DES_wrap.clone(),
182 192);
183 }
184
185 /**
186 * Creates an EnvelopedDataDemo and setups the demo certificates.
187 * <br>
188 * Keys and certificates are retrieved from the demo KeyStore ("cms.keystore")
189 * file which has to be located in your current working directory and may be
190 * created by running {@link demo.keystore.SetupCMSKeyStore
191 * SetupCMSKeyStore}.
192 *
193 * @param contentEncAlg the content encryption algorithm to be used
194 * @param keyWrapAlg the key wrap algorithm to be used for wrapping the content
195 * encryption key (for KeyAgreeRecipientInfos)
196 * @param keyLength the key length to be used (same for content encryption key
197 * and key encryption key) (for KeyAgreeRecipientInfos and
198 * KEKRecipientInfos)
199 *
200 * @throws IOException if an file read error occurs
201 * @throws NoSuchAlgorithmException if the requested algorithms are not supported
202 */
203 public EnvelopedDataDemo(AlgorithmID contentEncAlg,
204 AlgorithmID keyWrapAlg,
205 int keyLength) throws IOException, NoSuchAlgorithmException {
206 this(contentEncAlg, keyWrapAlg, keyWrapAlg, keyLength);
207
208 }
209
210
211 /**
212 * Creates an EnvelopedDataDemo and setups the demo certificates.
213 * <br>
214 * Keys and certificates are retrieved from the demo KeyStore ("cms.keystore")
215 * file which has to be located in your current working directory and may be
216 * created by running {@link demo.keystore.SetupCMSKeyStore
217 * SetupCMSKeyStore}.
218 *
219 * @param contentEncAlg the content encryption algorithm to be used
220 * @param keyWrapAlg the key wrap algorithm to be used for wrapping the content
221 * encryption key (for KeyAgreeRecipientInfos)
222 * @param kekAlg the name of the key encryption key algorithm to be used
223 * (for KEKRecipientInfos)
224 * @param keyLength the key length to be used (same for content encryption key
225 * and key encryption key) (for KeyAgreeRecipientInfos and
226 * KEKRecipientInfos)
227 *
228 * @throws IOException if an file read error occurs
229 * @throws NoSuchAlgorithmException if the requested algorithms are not supported
230 */
231 public EnvelopedDataDemo(AlgorithmID contentEncAlg,
232 AlgorithmID keyWrapAlg,
233 AlgorithmID kekAlg,
234 int keyLength) throws IOException, NoSuchAlgorithmException {
235
236 System.out.println();
237 System.out.println("**********************************************************************************");
238 System.out.println(" EnvelopedDataDemo " + contentEncAlg.getName());
239 System.out.println(" (shows the usage of the CMS EnvelopedData type implementation) ");
240 System.out.println("**********************************************************************************");
241 System.out.println();
242
243 // add all certificates to the list
244 X509Certificate[] certs = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1);
245 rsaUser1_ = certs[0];
246 rsaUser1Pk_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1);
247 rsaUser2_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2)[0];
248 rsaUser2Pk_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2);
249
250 esdhUser1_ = CMSKeyStore.getCertificateChain(CMSKeyStore.ESDH, CMSKeyStore.SZ_2048_CRYPT_1)[0];
251 esdhUser1Pk_ = CMSKeyStore.getPrivateKey(CMSKeyStore.ESDH, CMSKeyStore.SZ_2048_CRYPT_1);
252 esdhUser2_ = CMSKeyStore.getCertificateChain(CMSKeyStore.ESDH, CMSKeyStore.SZ_2048_CRYPT_2)[0];
253 esdhUser2Pk_ = CMSKeyStore.getPrivateKey(CMSKeyStore.ESDH, CMSKeyStore.SZ_2048_CRYPT_2);
254 random_ = SecRandom.getDefault();
255
256 contentEncAlg_ = contentEncAlg;
257 keyWrapAlg_ = keyWrapAlg;
258 keyLength_ = keyLength;
259
260 // create a secret key encryption key for a KEKRecipientInfo
261 KeyGenerator kg = SecurityProvider.getSecurityProvider().getKeyGenerator(kekAlg, keyLength_);
262 kek_ = kg.generateKey();
263 kekID_ = new byte[] { 00, 00, 00, 01 };
264 }
265
266
267 /**
268 * Creates a CMS <code>EnvelopedDataStream</code> message.
269 *
270 * @param message the message to be enveloped, as byte representation
271 * @return the DER encoding of the <code>EnvelopedData</code> object just created
272 * @throws CMSException if the <code>EnvelopedData</code> object cannot
273 * be created
274 * @throws IOException if an I/O error occurs
275 */
276 public byte[] createEnvelopedDataStream(byte[] message) throws CMSException, IOException {
277
278 EnvelopedDataStream enveloped_data;
279
280 // we are testing the stream interface
281 ByteArrayInputStream is = new ByteArrayInputStream(message);
282 // create a new EnvelopedData object encrypted with TripleDES CBC
283 try {
284 enveloped_data = new EnvelopedDataStream(is, (AlgorithmID)contentEncAlg_.clone());
285 } catch (NoSuchAlgorithmException ex) {
286 throw new CMSException("No implementation for content encryption algorithm: " + ex.toString());
287 }
288
289 // create the recipient infos
290 RecipientInfo[] recipients = createRecipients();
291 // specify the recipients of the encrypted message
292 enveloped_data.setRecipientInfos(recipients);
293
294 // return the EnvelopedDate as DER encoded byte array with block size 2048
295 ByteArrayOutputStream os = new ByteArrayOutputStream();
296 enveloped_data.writeTo(os, 2048);
297 return os.toByteArray();
298 }
299
300 /**
301 * Decrypts the encrypted content of the given <code>EnvelopedData</code> object for
302 * the recipient identified by its index into the recipientInfos field.
303 * <p>
304 * This way of decrypting the content may be used for any type of RecipientInfo
305 * (KeyTransRecipientInfo, KeyAgreeRecipientInfo, KEKRecipientInfo), but requires to
306 * know at what index of the recipientInfo field the RecipientInfo for the
307 * particular recipient in mind can be found. If the recipient in mind uses
308 * a RecipientInfo of type KeyAgreeRecipientInfo some processing overhead may
309 * take place because a KeyAgreeRecipientInfo may contain encrypted content-encryption
310 * keys for more than only one recipient; since the recipientInfoIndex only
311 * specifies the RecipientInfo but not the encrypted content encryption key
312 * -- if there are more than only one -- repeated decryption runs may be
313 * required as long as the decryption process completes successfully.
314 *
315 * @param encoding the <code>EnvelopedData</code> object as DER encoded byte array
316 * @param key the key to decrypt the message
317 * @param recipientInfoIndex the index into the <code>RecipientInfo</code> array
318 * to which the specified key belongs
319 *
320 * @return the recovered message, as byte array
321 * @throws CMSException if the message cannot be recovered
322 * @throws IOException if a stream read/write error occurs
323 */
324 public byte[] getEnvelopedDataStream(byte[] encoding, Key key, int recipientInfoIndex)
325 throws CMSException, IOException {
326
327 // create the EnvelopedData object from a DER encoded byte array
328 // we are testing the stream interface
329 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
330 EnvelopedDataStream enveloped_data = new EnvelopedDataStream(is);
331
332 System.out.println("Information about the encrypted data:");
333 EncryptedContentInfoStream eci = (EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo();
334 System.out.println("Content type: "+eci.getContentType().getName());
335 System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
336
337 System.out.println("\nThis message can be decrypted by the owners of the following certificates:");
338 RecipientInfo[] recipients = enveloped_data.getRecipientInfos();
339
340 // for demonstration purposes we only look one time for all recipients included:
341 if (recipientInfoIndex == 0) {
342 int k = 0;
343 for (int i=0; i<recipients.length; i++) {
344 KeyIdentifier[] recipientIDs = recipients[i].getRecipientIdentifiers();
345 for (int j = 0; j < recipientIDs.length; j++) {
346 System.out.println("Recipient "+(++k)+":");
347 System.out.println(recipientIDs[j]);
348 }
349 }
350 }
351 // decrypt the message for the first recipient
352 try {
353 enveloped_data.setupCipher(key, recipientInfoIndex);
354 InputStream decrypted = enveloped_data.getInputStream();
355 ByteArrayOutputStream os = new ByteArrayOutputStream();
356 Util.copyStream(decrypted, os, null);
357
358 return os.toByteArray();
359
360 } catch (InvalidKeyException ex) {
361 throw new CMSException("Private key error: "+ex.getMessage());
362 } catch (NoSuchAlgorithmException ex) {
363 throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
364 }
365 }
366
367 /**
368 * Decrypts the encrypted content of the given <code>EnvelopedData</code> object for
369 * the recipient identified by recipient identifier.
370 * <p>
371 * This way of decrypting the content may be used for any type of RecipientInfo
372 * (KeyTransRecipientInfo, KeyAgreeRecipientInfo, KEKRecipientInfo). The
373 * recipient in mind is identified by its recipient identifier.
374 *
375 * @param encoding the <code>EnvelopedData</code> object as DER encoded byte array
376 * @param key the key to decrypt the message
377 * @param recipientID the recipient identifier uniquely identifying the key of the
378 * recipient
379 *
380 * @return the recovered message, as byte array
381 * @throws CMSException if the message cannot be recovered
382 * @throws IOException if a stream read/write error occurs
383 */
384 public byte[] getEnvelopedDataStream(byte[] encoding, Key key, KeyIdentifier recipientID)
385 throws CMSException, IOException {
386
387 // create the EnvelopedData object from a DER encoded byte array
388 // we are testing the stream interface
389 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
390 EnvelopedDataStream enveloped_data = new EnvelopedDataStream(is);
391
392 System.out.println("Information about the encrypted data:");
393 EncryptedContentInfoStream eci = (EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo();
394 System.out.println("Content type: "+eci.getContentType().getName());
395 System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
396
397 // get the right RecipientInfo
398 System.out.println("\nSearch for RecipientInfo:");
399 RecipientInfo recipient = enveloped_data.getRecipientInfo(recipientID);
400 if (recipient != null) {
401 System.out.println("RecipientInfo: " + recipient);
402 } else {
403 throw new CMSException("No recipient with ID: " + recipientID);
404 }
405 // decrypt the content encryption key and the content
406 try {
407 System.out.println("Decrypt encrypted content encryption key...");
408 SecretKey cek = recipient.decryptKey(key, recipientID);
409 System.out.println("Decrypt content with decrypted content encryption key...");
410 enveloped_data.setupCipher(cek);
411 InputStream decrypted = enveloped_data.getInputStream();
412 ByteArrayOutputStream os = new ByteArrayOutputStream();
413 Util.copyStream(decrypted, os, null);
414
415 return os.toByteArray();
416
417 } catch (InvalidKeyException ex) {
418 throw new CMSException("Private key error: "+ex.getMessage());
419 } catch (NoSuchAlgorithmException ex) {
420 throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
421 }
422 }
423
424 /**
425 * Decrypts the encrypted content of the given <code>EnvelopedData</code> object for
426 * the recipient identified by its recipient certificate or kekID.
427 * <p>
428 * Since recipient certificates only may be used for for RecipientInfos of type
429 * KeyTransRecipientInfo or KeyAgreeRecipientInfo, a key id has to be supplied
430 * for decrypting the content for a recipient using a KEKRecipientInfo.
431 *
432 * @param encoding the <code>EnvelopedData</code> object as DER encoded byte array
433 * @param key the key to decrypt the message
434 * @param recipientCert the certificate of the recipient having a RecipientInfo of
435 * type KeyTransRecipientInfo or KeyAgreeRecipientInfo
436 * @param kekID the kekID identifying the recipient key when using a RecipientInfo
437 * of type KEKRecipientInfo
438 *
439 * @return the recovered message, as byte array
440 * @throws CMSException if the message cannot be recovered
441 * @throws IOException if a stream read/write error occurs
442 */
443 public byte[] getEnvelopedDataStream(byte[] encoding, Key key, X509Certificate recipientCert, byte[] kekID)
444 throws CMSException, IOException {
445
446 // create the EnvelopedData object from a DER encoded byte array
447 // we are testing the stream interface
448 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
449 EnvelopedDataStream enveloped_data = new EnvelopedDataStream(is);
450
451 System.out.println("Information about the encrypted data:");
452 EncryptedContentInfoStream eci = (EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo();
453 System.out.println("Content type: "+eci.getContentType().getName());
454 System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
455
456 // decrypt the content encryption key and the content
457 try {
458 System.out.println("Decrypt the content...");
459 if (recipientCert != null) {
460 enveloped_data.setupCipher(key, recipientCert);
461 } else {
462 // KEKRecipientInfo
463 enveloped_data.setupCipher(key, new KEKIdentifier(kekID));
464 }
465 InputStream decrypted = enveloped_data.getInputStream();
466 ByteArrayOutputStream os = new ByteArrayOutputStream();
467 Util.copyStream(decrypted, os, null);
468
469 return os.toByteArray();
470
471 } catch (InvalidKeyException ex) {
472 throw new CMSException("Private key error: "+ex.getMessage());
473 } catch (NoSuchAlgorithmException ex) {
474 throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
475 }
476 }
477
478
479 // non stream
480
481 /**
482 * Creates a CMS <code>EnvelopedData</code> message.
483 *
484 * @param message the message to be enveloped, as byte representation
485 *
486 * @return the encoded <code>EnvelopedData</code>, as byte array
487 *
488 * @throws CMSException if the <code>EnvelopedData</code> object cannot
489 * be created
490 */
491 public byte[] createEnvelopedData(byte[] message) throws CMSException {
492
493 EnvelopedData enveloped_data;
494
495 // create a new EnvelopedData object encrypted with TripleDES CBC
496 try {
497 enveloped_data = new EnvelopedData(message, (AlgorithmID)contentEncAlg_.clone());
498 } catch (NoSuchAlgorithmException ex) {
499 throw new CMSException("No implementation for content encryption algorithm: " + ex.toString());
500 }
501
502 // set the RecipientInfos
503 RecipientInfo[] recipients = createRecipients();
504 enveloped_data.setRecipientInfos(recipients);
505
506 // return encoded EnvelopedData
507 return enveloped_data.getEncoded();
508 }
509
510
511 /**
512 * Decrypts the encrypted content of the given <code>EnvelopedData</code> object for
513 * the recipient identified by its index into the recipientInfos field.
514 * <p>
515 * This way of decrypting the content may be used for any type of RecipientInfo
516 * (KeyTransRecipientInfo, KeyAgreeRecipientInfo, KEKRecipientInfo), but requires to
517 * know at what index of the recipientInfo field the RecipientInfo for the
518 * particular recipient in mind can be found. If the recipient in mind uses
519 * a RecipientInfo of type KeyAgreeRecipientInfo some processing overhead may
520 * take place because a KeyAgreeRecipientInfo may contain encrypted content-encryption
521 * keys for more than only one recipient; since the recipientInfoIndex only
522 * specifies the RecipientInfo but not the encrypted content encryption key
523 * -- if there are more than only one -- repeated decryption runs may be
524 * required as long as the decryption process completes successfully.
525 *
526 * @param enc the encoded <code>EnvelopedData</code>
527 *
528 * @param key the key to decrypt the message
529 *
530 * @param recipientInfoIndex the index into the <code>RecipientInfo</code> array
531 * to which the specified key belongs
532 *
533 * @return the recovered message, as byte array
534 *
535 * @throws CMSException if the message cannot be recovered
536 * @throws IOException if an I/O error occurs
537 */
538 public byte[] getEnvelopedData(byte[] enc, Key key, int recipientInfoIndex)
539 throws CMSException, IOException {
540 ByteArrayInputStream bais = new ByteArrayInputStream(enc);
541 EnvelopedData enveloped_data = new EnvelopedData(bais);
542
543 System.out.println("Information about the encrypted data:");
544 EncryptedContentInfo eci = (EncryptedContentInfo)enveloped_data.getEncryptedContentInfo();
545 System.out.println("Content type: "+eci.getContentType().getName());
546 System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
547
548 System.out.println("\nThis message can be decrypted by the owners of the following certificates:");
549 RecipientInfo[] recipients = enveloped_data.getRecipientInfos();
550
551 // for demonstration purposes we only look one time for all recipients included:
552 if (recipientInfoIndex == 0) {
553 int k = 0;
554 for (int i=0; i<recipients.length; i++) {
555 KeyIdentifier[] recipientIDs = recipients[i].getRecipientIdentifiers();
556 for (int j = 0; j < recipientIDs.length; j++) {
557 System.out.println("Recipient "+(++k)+":");
558 System.out.println(recipientIDs[j]);
559 }
560 }
561 }
562
563 // decrypt the message
564 try {
565 enveloped_data.setupCipher(key, recipientInfoIndex);
566 return enveloped_data.getContent();
567
568 } catch (InvalidKeyException ex) {
569 throw new CMSException("Private key error: "+ex.getMessage());
570 } catch (NoSuchAlgorithmException ex) {
571 throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
572 }
573 }
574
575 /**
576 * Decrypts the encrypted content of the given <code>EnvelopedData</code> object for
577 * the recipient identified by recipient identifier.
578 * <p>
579 * This way of decrypting the content may be used for any type of RecipientInfo
580 * (KeyTransRecipientInfo, KeyAgreeRecipientInfo, KEKRecipientInfo). The
581 * recipient in mind is identified by its recipient identifier.
582 *
583 * @param enc the DER encoded <code>EnvelopedData</code> ASN.1 object
584 * @param key the key to decrypt the message
585 * @param recipientID the recipient identifier uniquely identifying the key of the
586 * recipient
587 *
588 * @return the recovered message, as byte array
589 * @throws CMSException if the message cannot be recovered
590 * @throws IOException if an I/O error occurs
591 */
592 public byte[] getEnvelopedData(byte[] enc, Key key, KeyIdentifier recipientID)
593 throws CMSException, IOException {
594 ByteArrayInputStream bais = new ByteArrayInputStream(enc);
595 EnvelopedData enveloped_data = new EnvelopedData(bais);
596
597 System.out.println("Information about the encrypted data:");
598 EncryptedContentInfo eci = (EncryptedContentInfo)enveloped_data.getEncryptedContentInfo();
599 System.out.println("Content type: "+eci.getContentType().getName());
600 System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
601
602 System.out.println("\nThis message can be decrypted by the owners of the following certificates:");
603
604 // get the right RecipientInfo
605 System.out.println("\nSearch for RecipientInfo:");
606 RecipientInfo recipient = enveloped_data.getRecipientInfo(recipientID);
607 if (recipient != null) {
608 System.out.println("RecipientInfo: " + recipient);
609 } else {
610 throw new CMSException("No recipient with ID: " + recipientID);
611 }
612 // decrypt the content encryption key and the content
613 try {
614 System.out.println("Decrypt encrypted content encryption key...");
615 SecretKey cek = recipient.decryptKey(key, recipientID);
616 System.out.println("Decrypt content with decrypted content encryption key...");
617 enveloped_data.setupCipher(cek);
618 return enveloped_data.getContent();
619
620 } catch (InvalidKeyException ex) {
621 throw new CMSException("Private key error: "+ex.getMessage());
622 } catch (NoSuchAlgorithmException ex) {
623 throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
624 }
625 }
626
627 /**
628 * Decrypts the encrypted content of the given <code>EnvelopedData</code> object for
629 * the recipient identified by its recipient certificate or keyID.
630 * <p>
631 * Since recipient certificates only may be used for for RecipientInfos of type
632 * KeyTransRecipientInfo or KeyAgreeRecipientInfo, a key id has to be supplied
633 * for decrypting the content for a recipient using a KEKRecipientInfo.
634 *
635 * @param enc the DER encoded <code>EnvelopedData</code> ASN.1 object
636 * @param key the key to decrypt the message
637 * @param recipientCert the certificate of the recipient having a RecipientInfo of
638 * type KeyTransRecipientInfo or KeyAgreeRecipientInfo
639 * @param kekID the kekID identifying the recipient key when using a RecipientInfo
640 * of type KEKRecipientInfo
641 *
642 * @return the recovered message, as byte array
643 * @throws CMSException if the message cannot be recovered
644 */
645 public byte[] getEnvelopedData(byte[] enc, Key key, X509Certificate recipientCert, byte[] kekID)
646 throws CMSException, IOException {
647 ByteArrayInputStream bais = new ByteArrayInputStream(enc);
648 EnvelopedData enveloped_data = new EnvelopedData(bais);
649
650 System.out.println("Information about the encrypted data:");
651 EncryptedContentInfo eci = (EncryptedContentInfo)enveloped_data.getEncryptedContentInfo();
652 System.out.println("Content type: "+eci.getContentType().getName());
653 System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
654
655 System.out.println("\nThis message can be decrypted by the owners of the following certificates:");
656
657 // decrypt the content encryption key and the content
658 try {
659 System.out.println("Decrypt the content...");
660 if (recipientCert != null) {
661 enveloped_data.setupCipher(key, recipientCert);
662 } else {
663 // KEKRecipientInfo
664 enveloped_data.setupCipher(key, new KEKIdentifier(kekID));
665 }
666 return enveloped_data.getContent();
667
668 } catch (InvalidKeyException ex) {
669 throw new CMSException("Private key error: "+ex.getMessage());
670 } catch (NoSuchAlgorithmException ex) {
671 throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
672 }
673 }
674
675 /**
676 * Creates the RecipientInfos.
677 *
678 * @return the RecipientInfos created, two KeyTransRecipientInfos, one
679 * KeyAgreeRecipientInfo (for two recipients with same domain
680 * parameters), and one KEKRecipientInfo
681 *
682 * @throws CMSException if an error occurs when creating the recipient infos
683 */
684 public RecipientInfo[] createRecipients() throws CMSException {
685
686 RecipientInfo[] recipients = new RecipientInfo[4];
687 try {
688 // rsaUser1 is the first receiver (cert identified by IssuerAndSerialNumber)
689 recipients[0] = new KeyTransRecipientInfo(rsaUser1_,
690 (AlgorithmID)AlgorithmID.rsaEncryption.clone());
691 // rsaUser2 is the second receiver (cert identifief by SubjectKeyIdentifier)
692 recipients[1] = new KeyTransRecipientInfo(rsaUser2_,
693 CertificateIdentifier.SUBJECT_KEY_IDENTIFIER,
694 (AlgorithmID)AlgorithmID.rsaEncryption.clone());
695
696 // next recipients use key agreement
697 // the key encryption (key agreement) algorithm to use:
698 AlgorithmID keyEA = (AlgorithmID)AlgorithmID.esdhKeyAgreement.clone();
699 // the key wrap algorithm to use:
700 AlgorithmID keyWrapAlg = (AlgorithmID)keyWrapAlg_.clone();
701 // the length of the key encryption key to be generated:
702 int kekLength = keyLength_;
703 recipients[2] = new KeyAgreeRecipientInfo(keyEA, keyWrapAlg, kekLength);
704 // esdhUser1 is the third receiver (cert identified by IssuerAndSerialNumber)
705 ((KeyAgreeRecipientInfo)recipients[2]).addRecipient(esdhUser1_, CertificateIdentifier.ISSUER_AND_SERIALNUMBER);
706 // esdhUser2 is the fourth receiver (cert identified by RecipientKeyIdentifier)
707 ((KeyAgreeRecipientInfo)recipients[2]).addRecipient(esdhUser2_, CertificateIdentifier.RECIPIENT_KEY_IDENTIFIER);
708
709 // last receiver uses a symmetric key encryption key
710 AlgorithmID kea = (AlgorithmID)keyWrapAlg_.clone();
711 KEKIdentifier kekIdentifier = new KEKIdentifier(kekID_);
712 recipients[3] = new KEKRecipientInfo(kekIdentifier, kea, kek_);
713 } catch (Exception ex) {
714 throw new CMSException("Error adding recipients: " + ex.getMessage());
715 }
716 return recipients;
717 }
718
719 /**
720 * Parses an EnvelopedData and decrypts the content for all test recipients
721 * using the index into the recipientInfos field for identifying the recipient.
722 *
723 * @param stream whether to use EnvelopedDataStream or EnvelopedData
724 * @param message the original message (to be compared to the decryption result)
725 * @param encodedEnvelopedData the encoded EnvelopedData object
726 *
727 * @throws Exception if some error occurs during decoding/decryption
728 */
729 public void parseEnvelopedDataWithRecipientInfoIndex(boolean stream,
730 byte[] message, byte[] encodedEnvelopedData) throws Exception {
731 byte[] receivedMessage;
732 if (stream) {
733 // rsaUser1
734 System.out.println("\nDecrypt for rsaUser1:");
735 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, rsaUser1Pk_, 0);
736 if (!Arrays.equals(message, receivedMessage)) {
737 throw new IOException("Decryption error!");
738 }
739 System.out.print("\nDecrypted content: ");
740 System.out.println(new String(receivedMessage));
741 // rsaUser2
742 System.out.println("\nDecrypt for rsaUser2:");
743 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, rsaUser2Pk_, 1);
744 if (!Arrays.equals(message, receivedMessage)) {
745 throw new IOException("Decryption error!");
746 }
747 System.out.print("\nDecrypted content: ");
748 System.out.println(new String(receivedMessage));
749 // esdhUser1
750 System.out.println("\nDecrypt for esdhUser1:");
751 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, esdhUser1Pk_, 2);
752 if (!Arrays.equals(message, receivedMessage)) {
753 throw new IOException("Decryption error!");
754 }
755 System.out.print("\nDecrypted content: ");
756 System.out.println(new String(receivedMessage));
757 // esdhUser2
758 System.out.println("\nDecrypt for esdhUser2:");
759 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, esdhUser2Pk_, 2);
760 if (!Arrays.equals(message, receivedMessage)) {
761 throw new IOException("Decryption error!");
762 }
763 System.out.print("\nDecrypted content: ");
764 System.out.println(new String(receivedMessage));
765 // kekUser
766 System.out.println("\nDecrypt for kekUser:");
767 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, kek_, 3);
768 if (!Arrays.equals(message, receivedMessage)) {
769 throw new IOException("Decryption error!");
770 }
771 System.out.print("\nDecrypted content: ");
772 System.out.println(new String(receivedMessage));
773 } else {
774 // rsaUser1
775 System.out.println("\nDecrypt for rsaUser1:");
776 receivedMessage = getEnvelopedData(encodedEnvelopedData, rsaUser1Pk_, 0);
777 if (!Arrays.equals(message, receivedMessage)) {
778 throw new IOException("Decryption error!");
779 }
780 System.out.print("\nDecrypted content: ");
781 System.out.println(new String(receivedMessage));
782 // rsaUser2
783 System.out.println("\nDecrypt for rsaUser2:");
784 receivedMessage = getEnvelopedData(encodedEnvelopedData, rsaUser2Pk_, 1);
785 if (!Arrays.equals(message, receivedMessage)) {
786 throw new IOException("Decryption error!");
787 }
788 System.out.print("\nDecrypted content: ");
789 System.out.println(new String(receivedMessage));
790 // esdhUser1
791 System.out.println("\nDecrypt for esdhUser1:");
792 receivedMessage = getEnvelopedData(encodedEnvelopedData, esdhUser1Pk_, 2);
793 if (!Arrays.equals(message, receivedMessage)) {
794 throw new IOException("Decryption error!");
795 }
796 System.out.print("\nDecrypted content: ");
797 System.out.println(new String(receivedMessage));
798 // esdhUser2
799 System.out.println("\nDecrypt for esdhUser2:");
800 receivedMessage = getEnvelopedData(encodedEnvelopedData, esdhUser2Pk_, 2);
801 if (!Arrays.equals(message, receivedMessage)) {
802 throw new IOException("Decryption error!");
803 }
804 System.out.print("\nDecrypted content: ");
805 System.out.println(new String(receivedMessage));
806 // kekUser
807 System.out.println("\nDecrypt for kekUser:");
808 receivedMessage = getEnvelopedData(encodedEnvelopedData, kek_, 3);
809 if (!Arrays.equals(message, receivedMessage)) {
810 throw new IOException("Decryption error!");
811 }
812 System.out.print("\nDecrypted content: ");
813 System.out.println(new String(receivedMessage));
814 }
815 }
816
817 /**
818 * Parses an EnvelopedData and decrypts the content for all test recipients
819 * using their recipient identifiers for identifying the recipient.
820 *
821 * @param stream whether to use EnvelopedDataStream or EnvelopedData
822 * @param message the original message (to be compared to the decryption result)
823 * @param encodedEnvelopedData the encoded EnvelopedData object
824 *
825 * @throws Exception if some error occurs during decoding/decryption
826 */
827 public void parseEnvelopedDataWithRecipientIdentifier(boolean stream,
828 byte[] message, byte[] encodedEnvelopedData) throws Exception {
829 byte[] receivedMessage;
830 if (stream) {
831 // rsaUser1
832 System.out.println("\nDecrypt for rsaUser1:");
833 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, rsaUser1Pk_, new IssuerAndSerialNumber(rsaUser1_));
834 if (!Arrays.equals(message, receivedMessage)) {
835 throw new IOException("Decryption error!");
836 }
837 System.out.print("\nDecrypted content: ");
838 System.out.println(new String(receivedMessage));
839 // rsaUser2
840 System.out.println("\nDecrypt for rsaUser2:");
841 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, rsaUser2Pk_, new SubjectKeyID(rsaUser2_));
842 if (!Arrays.equals(message, receivedMessage)) {
843 throw new IOException("Decryption error!");
844 }
845 System.out.print("\nDecrypted content: ");
846 System.out.println(new String(receivedMessage));
847 // esdhUser1
848 System.out.println("\nDecrypt for esdhUser1:");
849 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, esdhUser1Pk_, new IssuerAndSerialNumber(esdhUser1_));
850 if (!Arrays.equals(message, receivedMessage)) {
851 throw new IOException("Decryption error!");
852 }
853 System.out.print("\nDecrypted content: ");
854 System.out.println(new String(receivedMessage));
855 // esdhUser2
856 System.out.println("\nDecrypt for esdhUser2:");
857 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, esdhUser2Pk_, new RecipientKeyIdentifier(esdhUser2_));
858 if (!Arrays.equals(message, receivedMessage)) {
859 throw new IOException("Decryption error!");
860 }
861 System.out.print("\nDecrypted content: ");
862 System.out.println(new String(receivedMessage));
863 // kekUser
864 System.out.println("\nDecrypt for kekUser:");
865 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, kek_, new KEKIdentifier(kekID_));
866 if (!Arrays.equals(message, receivedMessage)) {
867 throw new IOException("Decryption error!");
868 }
869 System.out.print("\nDecrypted content: ");
870 System.out.println(new String(receivedMessage));
871 } else {
872 // rsaUser1
873 System.out.println("\nDecrypt for rsaUser1:");
874 receivedMessage = getEnvelopedData(encodedEnvelopedData, rsaUser1Pk_, new IssuerAndSerialNumber(rsaUser1_));
875 if (!Arrays.equals(message, receivedMessage)) {
876 throw new IOException("Decryption error!");
877 }
878 System.out.print("\nDecrypted content: ");
879 System.out.println(new String(receivedMessage));
880 // rsaUser2
881 System.out.println("\nDecrypt for rsaUser2:");
882 receivedMessage = getEnvelopedData(encodedEnvelopedData, rsaUser2Pk_, new SubjectKeyID(rsaUser2_));
883 if (!Arrays.equals(message, receivedMessage)) {
884 throw new IOException("Decryption error!");
885 }
886 System.out.print("\nDecrypted content: ");
887 System.out.println(new String(receivedMessage));
888 // esdhUser1
889 System.out.println("\nDecrypt for esdhUser1:");
890 receivedMessage = getEnvelopedData(encodedEnvelopedData, esdhUser1Pk_, new IssuerAndSerialNumber(esdhUser1_));
891 if (!Arrays.equals(message, receivedMessage)) {
892 throw new IOException("Decryption error!");
893 }
894 System.out.print("\nDecrypted content: ");
895 System.out.println(new String(receivedMessage));
896 // esdhUser2
897 System.out.println("\nDecrypt for esdhUser2:");
898 receivedMessage = getEnvelopedData(encodedEnvelopedData, esdhUser2Pk_, new RecipientKeyIdentifier(esdhUser2_));
899 if (!Arrays.equals(message, receivedMessage)) {
900 throw new IOException("Decryption error!");
901 }
902 System.out.print("\nDecrypted content: ");
903 System.out.println(new String(receivedMessage));
904 // kekUser
905 System.out.println("\nDecrypt for kekUser:");
906 receivedMessage = getEnvelopedData(encodedEnvelopedData, kek_, new KEKIdentifier(kekID_));
907 if (!Arrays.equals(message, receivedMessage)) {
908 throw new IOException("Decryption error!");
909 }
910 System.out.print("\nDecrypted content: ");
911 System.out.println(new String(receivedMessage));
912 }
913 }
914
915 /**
916 * Parses an EnvelopedData and decrypts the content for all test recipients
917 * using their recipient certificate (for RecipientInfos of type KeyTransRecipientInfo
918 * or KeyAgreeRecipientInfo) or key id (for RecipientInfos of type KEKRecipientInfo)
919 * for identifying the recipient.
920 *
921 * @param stream whether to use EnvelopedDataStream or EnvelopedData
922 * @param message the original message (to be compared to the decryption result)
923 * @param encodedEnvelopedData the encoded EnvelopedData object
924 *
925 * @throws Exception if some error occurs during decoding/decryption
926 */
927 public void parseEnvelopedDataWithRecipientCertOrKEKId(boolean stream,
928 byte[] message, byte[] encodedEnvelopedData) throws Exception {
929 byte[] receivedMessage;
930 if (stream) {
931 // rsaUser1
932 System.out.println("\nDecrypt for rsaUser1:");
933 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, rsaUser1Pk_, rsaUser1_, null);
934 if (!Arrays.equals(message, receivedMessage)) {
935 throw new IOException("Decryption error!");
936 }
937 System.out.print("\nDecrypted content: ");
938 System.out.println(new String(receivedMessage));
939 // rsaUser2
940 System.out.println("\nDecrypt for rsaUser2:");
941 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, rsaUser2Pk_, rsaUser2_, null);
942 if (!Arrays.equals(message, receivedMessage)) {
943 throw new IOException("Decryption error!");
944 }
945 System.out.print("\nDecrypted content: ");
946 System.out.println(new String(receivedMessage));
947 // esdhUser1
948 System.out.println("\nDecrypt for esdhUser1:");
949 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, esdhUser1Pk_, esdhUser1_, null);
950 if (!Arrays.equals(message, receivedMessage)) {
951 throw new IOException("Decryption error!");
952 }
953 System.out.print("\nDecrypted content: ");
954 System.out.println(new String(receivedMessage));
955 // esdhUser2
956 System.out.println("\nDecrypt for esdhUser2:");
957 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, esdhUser2Pk_, esdhUser2_, null);
958 if (!Arrays.equals(message, receivedMessage)) {
959 throw new IOException("Decryption error!");
960 }
961 System.out.print("\nDecrypted content: ");
962 System.out.println(new String(receivedMessage));
963 // kekUser
964 System.out.println("\nDecrypt for kekUser:");
965 receivedMessage = getEnvelopedDataStream(encodedEnvelopedData, kek_, null, kekID_);
966 if (!Arrays.equals(message, receivedMessage)) {
967 throw new IOException("Decryption error!");
968 }
969 System.out.print("\nDecrypted content: ");
970 System.out.println(new String(receivedMessage));
971 } else {
972 // rsaUser1
973 System.out.println("\nDecrypt for rsaUser1:");
974 receivedMessage = getEnvelopedData(encodedEnvelopedData, rsaUser1Pk_, rsaUser1_, null);
975 if (!Arrays.equals(message, receivedMessage)) {
976 throw new IOException("Decryption error!");
977 }
978 System.out.print("\nDecrypted content: ");
979 System.out.println(new String(receivedMessage));
980 // rsaUser2
981 System.out.println("\nDecrypt for rsaUser2:");
982 receivedMessage = getEnvelopedData(encodedEnvelopedData, rsaUser2Pk_, rsaUser2_, null);
983 if (!Arrays.equals(message, receivedMessage)) {
984 throw new IOException("Decryption error!");
985 }
986 System.out.print("\nDecrypted content: ");
987 System.out.println(new String(receivedMessage));
988 // esdhUser1
989 System.out.println("\nDecrypt for esdhUser1:");
990 receivedMessage = getEnvelopedData(encodedEnvelopedData, esdhUser1Pk_, esdhUser1_, null);
991 if (!Arrays.equals(message, receivedMessage)) {
992 throw new IOException("Decryption error!");
993 }
994 System.out.print("\nDecrypted content: ");
995 System.out.println(new String(receivedMessage));
996 // esdhUser2
997 System.out.println("\nDecrypt for esdhUser2:");
998 receivedMessage = getEnvelopedData(encodedEnvelopedData, esdhUser2Pk_, esdhUser2_, null);
999 if (!Arrays.equals(message, receivedMessage)) {
1000 throw new IOException("Decryption error!");
1001 }
1002 System.out.print("\nDecrypted content: ");
1003 System.out.println(new String(receivedMessage));
1004 // kekUser
1005 System.out.println("\nDecrypt for kekUser:");
1006 receivedMessage = getEnvelopedData(encodedEnvelopedData, kek_, null, kekID_);
1007 if (!Arrays.equals(message, receivedMessage)) {
1008 throw new IOException("Decryption error!");
1009 }
1010 System.out.print("\nDecrypted content: ");
1011 System.out.println(new String(receivedMessage));
1012 }
1013 }
1014
1015 /**
1016 * Starts the test.
1017 */
1018 public void start() {
1019 // the test message
1020 String m = "This is the test message.";
1021 System.out.println("Test message: \""+m+"\"");
1022 System.out.println();
1023 byte[] message = m.getBytes();
1024
1025 try {
1026 byte[] data;
1027 System.out.println("Stream implementation demos");
1028 System.out.println("===========================");
1029
1030
1031 // the stream implementation
1032 //
1033 // test CMS EnvelopedDataStream
1034 //
1035 System.out.println("\nCMS EnvelopedDataStream demo [create]:\n");
1036 data = createEnvelopedDataStream(message);
1037 // transmit data
1038 System.out.println("\nCMS EnvelopedDataStream demo [parse]:\n");
1039 System.out.println("Decrypt for the several recipients using their index into the recipientInfos field.");
1040 parseEnvelopedDataWithRecipientInfoIndex(true, message, data);
1041 System.out.println("Decrypt for the several recipients using their RecipientIdentifier.");
1042 parseEnvelopedDataWithRecipientIdentifier(true, message, data);
1043 System.out.println("Decrypt for the several recipients using their certificate or symmetric kek.");
1044 parseEnvelopedDataWithRecipientCertOrKEKId(true, message, data);
1045
1046 // the non-stream implementation
1047 System.out.println("\nNon-stream implementation demos");
1048 System.out.println("===============================");
1049
1050
1051 //
1052 // test CMS EnvelopedData
1053 //
1054 System.out.println("\nCMS EnvelopedData demo [create]:\n");
1055 data = createEnvelopedData(message);
1056 // transmit data
1057 System.out.println("\nCMS EnvelopedData demo [parse]:\n");
1058 System.out.println("Decrypt for the several recipients using their index into the recipientInfos field.");
1059 parseEnvelopedDataWithRecipientInfoIndex(false, message, data);
1060 System.out.println("Decrypt for the several recipients using their RecipientIdentifier.");
1061 parseEnvelopedDataWithRecipientIdentifier(false, message, data);
1062 System.out.println("Decrypt for the several recipients using their certificate or symmetric kek.");
1063 parseEnvelopedDataWithRecipientCertOrKEKId(false, message, data);
1064
1065
1066 } catch (Exception ex) {
1067 ex.printStackTrace();
1068 throw new RuntimeException(ex.toString());
1069 }
1070 }
1071
1072 /**
1073 * Main method.
1074 *
1075 * @throws IOException
1076 * if an I/O error occurs when reading required keys
1077 * and certificates from files
1078 */
1079 public static void main(String argv[]) throws Exception {
1080
1081 DemoUtil.initDemos();
1082 (new EnvelopedDataDemo()).start();
1083 System.out.println("\nReady!");
1084 DemoUtil.waitKey();
1085 }
1086 }