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/authenticatedData/AuthenticatedDataDemo.java 25 12.02.25 17:58 Dbratko $
059 // $Revision: 25 $
060
061 package demo.cms.authenticatedData;
062
063
064 import java.io.ByteArrayInputStream;
065 import java.io.ByteArrayOutputStream;
066 import java.io.IOException;
067 import java.io.InputStream;
068 import java.security.InvalidKeyException;
069 import java.security.Key;
070 import java.security.NoSuchAlgorithmException;
071 import java.security.PrivateKey;
072 import java.security.SecureRandom;
073
074 import javax.crypto.KeyGenerator;
075 import javax.crypto.SecretKey;
076
077 import demo.DemoUtil;
078 import demo.keystore.CMSKeyStore;
079 import iaik.asn1.ObjectID;
080 import iaik.asn1.structures.AlgorithmID;
081 import iaik.asn1.structures.Attribute;
082 import iaik.cms.AuthenticatedData;
083 import iaik.cms.AuthenticatedDataStream;
084 import iaik.cms.CMSAlgorithmID;
085 import iaik.cms.CMSException;
086 import iaik.cms.CertificateIdentifier;
087 import iaik.cms.ContentInfo;
088 import iaik.cms.ContentInfoStream;
089 import iaik.cms.IssuerAndSerialNumber;
090 import iaik.cms.KEKIdentifier;
091 import iaik.cms.KEKRecipientInfo;
092 import iaik.cms.KeyAgreeRecipientInfo;
093 import iaik.cms.KeyIdentifier;
094 import iaik.cms.KeyTransRecipientInfo;
095 import iaik.cms.OriginatorInfo;
096 import iaik.cms.RecipientInfo;
097 import iaik.cms.RecipientKeyIdentifier;
098 import iaik.cms.SecurityProvider;
099 import iaik.cms.SubjectKeyID;
100 import iaik.cms.attributes.CMSContentType;
101 import iaik.security.random.SecRandom;
102 import iaik.utils.Util;
103 import iaik.x509.X509Certificate;
104
105 /**
106 * Demonstrates the usage of class {@link iaik.cms.AuthenticatedDataStream} and
107 * {@link iaik.cms.AuthenticatedData} for recipient-specific protecting the
108 * integrity of a message using the CMS type AuthenticatedData.
109 * <p>
110 * This demo requires that you have <code>iaik_esdh.jar</code>
111 * (or <code>iaik_jce_full.jar</code>) in your classpath.
112 * You can download it from <a href="https://sic.tech/products/core-crypto-toolkits/jca-jce/" target="_blank">
113 * https://sic.tech/products/core-crypto-toolkits/jca-jce/</a>.
114 *
115 *
116 * @see iaik.cms.AuthenticatedDataStream
117 * @see iaik.cms.AuthenticatedData
118 *
119 */
120 public class AuthenticatedDataDemo {
121
122 // certificate of rsaUser 1
123 X509Certificate rsaUser1Cert_;
124 // private key of rsaUser 1
125 PrivateKey rsaUser1PrivKey_;
126 // certificate of rsaUser 2
127 X509Certificate rsaUser2Cert_;
128 // private key of rsaUser 2
129 PrivateKey rsaUser2PrivKey_;
130
131 // certificate of (originator) User 1 (static-static Diffie-Hellman)
132 X509Certificate ssdhUser1Cert_;
133 X509Certificate[] originatorCerts_;
134 // private key of SSDH User 1
135 PrivateKey ssdhUser1PrivKey_;
136 // certificate of SSDH User 2 (static-static Diffie-Hellman)
137 X509Certificate ssdhUser2Cert_;
138 // private key of SSDH User 2
139 PrivateKey ssdhUser2PrivKey_;
140
141 // key wrap algorithm to be used
142 AlgorithmID keyWrapAlg_;
143 // kek length
144 int kekLength_;
145 // key encryption key for KEKRecipientInfo
146 SecretKey kek_;
147 byte[] kekID_;
148
149
150 // secure random number generator
151 SecureRandom random_;
152
153 /**
154 * Creates and AuthenticatedDataDemo object and setups the demo certificates.
155 *
156 * Keys and certificate are retrieved from the demo KeyStore which
157 * has to be located in your current working directory and may be
158 * created by running {@link demo.keystore.SetupCMSKeyStore
159 * SetupCMSKeyStore}.
160 * <p>
161 * CMS-AES256-Wrap is used as key wrap algorithm.
162 *
163 * @throws IOException if an file read error occurs
164 * @throws NoSuchAlgorithmException if no implementation for the requested key wrap algorithm is available
165 */
166 public AuthenticatedDataDemo() throws IOException, NoSuchAlgorithmException {
167 this((AlgorithmID)CMSAlgorithmID.cms_aes256_wrap.clone(), 256);
168 }
169
170 /**
171 * Creates and AuthenticatedDataDemo object and setups the demo certificates.
172 *
173 * Keys and certificate are retrieved from the demo KeyStore which
174 * has to be located in your current working directory and may be
175 * created by running {@link demo.keystore.SetupCMSKeyStore
176 * SetupCMSKeyStore}.
177 *
178 * @param keyWrapAlg the key wrap algorithm to be used
179 * @param kekLength the length of the key encryption key
180 *
181 * @throws IOException if an file read error occurs
182 * @throws NoSuchAlgorithmException if no implementation for the requested key wrap algorithm is available
183 */
184 public AuthenticatedDataDemo(AlgorithmID keyWrapAlg, int kekLength) throws IOException, NoSuchAlgorithmException {
185
186 System.out.println();
187 System.out.println("**********************************************************************************");
188 System.out.println("* AuthenticatedDataDemo *");
189 System.out.println("* (shows the usage of the CMS AuthenticatedData type implementation) *");
190 System.out.println("**********************************************************************************");
191 System.out.println();
192
193 // add all certificates to the list
194 rsaUser1Cert_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1)[0];
195 rsaUser1PrivKey_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1);
196 rsaUser2Cert_ = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2)[0];
197 rsaUser2PrivKey_ = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2);
198
199 originatorCerts_ = CMSKeyStore.getCertificateChain(CMSKeyStore.SSDH, CMSKeyStore.SZ_2048_CRYPT_1);
200 ssdhUser1Cert_ = originatorCerts_[0];
201 ssdhUser1PrivKey_ = CMSKeyStore.getPrivateKey(CMSKeyStore.SSDH, CMSKeyStore.SZ_2048_CRYPT_1);
202 ssdhUser2Cert_ = CMSKeyStore.getCertificateChain(CMSKeyStore.SSDH, CMSKeyStore.SZ_2048_CRYPT_2)[0];
203 ssdhUser2PrivKey_ = CMSKeyStore.getPrivateKey(CMSKeyStore.SSDH, CMSKeyStore.SZ_2048_CRYPT_2);
204
205 random_ = SecRandom.getDefault();
206 keyWrapAlg_ = keyWrapAlg;
207 kekLength_ = kekLength;
208 // create a secret key encryption key for a KEKRecipientInfo
209 KeyGenerator kg = SecurityProvider.getSecurityProvider().getKeyGenerator(keyWrapAlg_, kekLength_);
210 kek_ = kg.generateKey();
211 kekID_ = new byte[] { 00, 00, 00, 01 };
212
213 }
214
215
216 /**
217 * Creates a CMS <code>AuthenticatedDataStream</code> for the given message message.
218 *
219 * @param message the message to be authenticated, as byte representation
220 * @param macAlgorithm the mac algorithm to be used
221 * @param macKeyLength the length of the temporary MAC key to be generated
222 * @param digestAlgorithm the digest algorithm to be used to calculate a digest
223 * from the content if authenticated attributes should
224 * be included
225 * @param mode whether to include the content into the AuthenticatedData ({@link
226 * AuthenticatedDataStream#IMPLICIT implicit}) or to not include it
227 * ({@link AuthenticatedDataStream#EXPLICIT explicit})
228 *
229 * @return the BER encoding of the <code>AuthenticatedData</code> object just created
230 *
231 * @throws CMSException if the <code>AuthenticatedData</code> object cannot
232 * be created
233 * @throws IOException if an I/O error occurs
234 */
235 public byte[] createAuthenticatedDataStream(byte[] message,
236 AlgorithmID macAlgorithm,
237 int macKeyLength,
238 AlgorithmID digestAlgorithm,
239 int mode)
240 throws CMSException, IOException {
241
242 AlgorithmID macAlg = (AlgorithmID)macAlgorithm.clone();
243 AlgorithmID digestAlg = null;
244 if (digestAlgorithm != null) {
245 digestAlg = (AlgorithmID)digestAlgorithm.clone();
246 }
247 ObjectID contentType = ObjectID.cms_data;
248
249 AuthenticatedDataStream authenticatedData;
250
251 // we are testing the stream interface
252 ByteArrayInputStream is = new ByteArrayInputStream(message);
253 // create a new AuthenticatedData object
254 try {
255 authenticatedData = new AuthenticatedDataStream(contentType,
256 is,
257 macAlg,
258 macKeyLength,
259 null,
260 digestAlg,
261 mode);
262 } catch (NoSuchAlgorithmException ex) {
263 throw new CMSException(ex.toString());
264 }
265
266 // static-static mode: set OriginatorInfo
267 OriginatorInfo originator = new OriginatorInfo();
268 originator.setCertificates(originatorCerts_);
269 authenticatedData.setOriginatorInfo(originator);
270 // create the recipient infos
271 RecipientInfo[] recipients = createRecipients();
272 // specify the recipients of the authenticated message
273 authenticatedData.setRecipientInfos(recipients);
274
275 if (digestAlgorithm != null) {
276 // create some authenticated attributes
277 // (the message digest attribute is automatically added)
278 try {
279 Attribute[] attributes = { new Attribute(new CMSContentType(contentType)) };
280 authenticatedData.setAuthenticatedAttributes(attributes);
281 } catch (Exception ex) {
282 throw new CMSException("Error creating attribute: " + ex.toString());
283 }
284 }
285
286 // in explicit mode get the content and write it to any out-of-band place
287 if (mode == AuthenticatedDataStream.EXPLICIT) {
288 InputStream data_is = authenticatedData.getInputStream();
289 byte[] buf = new byte[2048];
290 int r;
291 while ((r = data_is.read(buf)) > 0)
292 ; // skip data
293 }
294
295 // return the AuthenticatedData as BER encoded byte array with block size 16
296 // (just for testing; in real application we will use a proper blocksize,
297 // e.g. 2048, 4096,..)
298 authenticatedData.setBlockSize(16);
299 // return the AuthenticatedDate as BER encoded byte array with block size 2048
300 ByteArrayOutputStream os = new ByteArrayOutputStream();
301 // wrap into ContentInfo
302 ContentInfoStream contentInfo = new ContentInfoStream(authenticatedData);
303 contentInfo.writeTo(os);
304 return os.toByteArray();
305 }
306
307 /**
308 * Decrypts the encrypted MAC key for the recipient identified by its index
309 * into the recipientInfos field and uses the MAC key to verify
310 * the authenticated data.
311 * <p>
312 * This way of decrypting the MAC key and verifying the content may be used for
313 * any type of RecipientInfo (KeyTransRecipientInfo, KeyAgreeRecipientInfo,
314 * KEKRecipientInfo, PasswordRecipeintInfo, OtherRecipientInfo), but requires to
315 * know at what index of the recipientInfos field the RecipientInfo for the
316 * particular recipient in mind can be found.
317 * If the recipient in mind uses a RecipientInfo of type KeyAgreeRecipientInfo
318 * some processing overhead may take place because a KeyAgreeRecipientInfo may
319 * contain encrypted mac keys for more than only one recipient; since the
320 * recipientInfoIndex only specifies the RecipientInfo but not the encrypted
321 * mac key -- if there are more than only one -- repeated decryption runs may be
322 * required as long as the decryption process completes successfully.
323 *
324 * @param encoding the <code>AuthenticatedData</code> object as BER encoded byte array
325 * @param message the content message, if transmitted by other means (explicit mode)
326 * @param key the key to decrypt the mac key
327 * @param recipientInfoIndex the index of the right <code>RecipientInfo</code> to
328 * which the given key belongs
329 *
330 * @return the verified message, as byte array
331 *
332 * @throws CMSException if the authenticated data cannot be verified
333 * @throws IOException if a stream read/write error occurs
334 */
335 public byte[] getAuthenticatedDataStream(byte[] encoding,
336 byte[] message,
337 Key key,
338 int recipientInfoIndex)
339 throws CMSException, IOException {
340
341 // create the AuthenticatedData object from a DER encoded byte array
342 // we are testing the stream interface
343 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
344 AuthenticatedDataStream authenticatedData = new AuthenticatedDataStream(is);
345
346 if (authenticatedData.getMode() == AuthenticatedDataStream.EXPLICIT) {
347 // in explicit mode explicitly supply the content for hash/mac computation
348 authenticatedData.setInputStream(new ByteArrayInputStream(message));
349 }
350
351 System.out.println("\nThis message can be verified by the following recipients:");
352 RecipientInfo[] recipients = authenticatedData.getRecipientInfos();
353
354 // for demonstration purposes we only look one time for all recipients included:
355 if (recipientInfoIndex == 0) {
356 int k = 0;
357 for (int i=0; i<recipients.length; i++) {
358 KeyIdentifier[] recipientIDs = recipients[i].getRecipientIdentifiers();
359 for (int j = 0; j < recipientIDs.length; j++) {
360 System.out.println("Recipient "+(++k)+":");
361 System.out.println(recipientIDs[j]);
362 }
363 }
364 }
365 // decrypt the mac key and verify the mac for the indented recipient
366 try {
367 authenticatedData.setupMac(key, recipientInfoIndex);
368 InputStream contentStream = authenticatedData.getInputStream();
369 ByteArrayOutputStream os = new ByteArrayOutputStream();
370 Util.copyStream(contentStream, os, null);
371
372 if (authenticatedData.verifyMac() == false) {
373 throw new CMSException("Mac verification error!");
374 }
375 System.out.println("Mac successfully verified!");
376
377 return os.toByteArray();
378
379 } catch (InvalidKeyException ex) {
380 throw new CMSException("Key error: "+ex.getMessage());
381 } catch (NoSuchAlgorithmException ex) {
382 throw new CMSException(ex.toString());
383 }
384 }
385
386 /**
387 * Decrypts the encrypted MAC key for the recipient identified by recipient identifier
388 * and uses the MAC key to verify the authenticated data.
389 * <p>
390 * This way of decrypting the mac key may be used for any type of RecipientInfo
391 * (KeyTransRecipientInfo, KeyAgreeRecipientInfo, KEKRecipientInfo). The
392 * recipient in mind is identified by its recipient identifier.
393 *
394 * @param encoding the <code>AuthenticatedData</code> object as BER encoded byte array
395 * @param message the content message, if transmitted by other means (explicit mode)
396 * @param key the key to decrypt the encrypted mac key
397 * @param recipientID the recipient identifier uniquely identifying the key of the
398 * recipient
399 *
400 * @return the verified message, as byte array
401 *
402 * @throws CMSException if the authenticated data cannot be verified
403 * @throws IOException if a stream read/write error occurs
404 */
405 public byte[] getAuthenticatedDataStream(byte[] encoding,
406 byte[] message,
407 Key key,
408 KeyIdentifier recipientID)
409 throws CMSException, IOException {
410
411 // create the AuthenticatedData object from a BER encoded byte array
412 // we are testing the stream interface
413 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
414 AuthenticatedDataStream authenticatedData = new AuthenticatedDataStream(is);
415
416 if (authenticatedData.getMode() == AuthenticatedDataStream.EXPLICIT) {
417 // in explicit mode explicitly supply the content for hash/mac computation
418 authenticatedData.setInputStream(new ByteArrayInputStream(message));
419 }
420
421 // get the right RecipientInfo
422 System.out.println("\nSearch for RecipientInfo:");
423 RecipientInfo recipient = authenticatedData.getRecipientInfo(recipientID);
424 if (recipient != null) {
425 System.out.println("RecipientInfo: " + recipient);
426 } else {
427 throw new CMSException("No recipient with ID: " + recipientID);
428 }
429 // decrypt the mac key and verify the content mac
430 try {
431 System.out.println("Decrypt encrypted mac key...");
432 SecretKey cek = recipient.decryptKey(key, recipientID);
433 System.out.println("Verify content mac with decrypted mac key...");
434 authenticatedData.setupMac(cek);
435 InputStream contentStream = authenticatedData.getInputStream();
436 ByteArrayOutputStream os = new ByteArrayOutputStream();
437 Util.copyStream(contentStream, os, null);
438
439 if (authenticatedData.verifyMac() == false) {
440 throw new CMSException("Mac verification error!");
441 }
442 System.out.println("Mac successfully verified!");
443
444 return os.toByteArray();
445
446 } catch (InvalidKeyException ex) {
447 throw new CMSException("Key error: "+ex.getMessage());
448 } catch (NoSuchAlgorithmException ex) {
449 throw new CMSException(ex.toString());
450 }
451 }
452
453 /**
454 * Decrypts the encrypted content of the given <code>AuthenticatedData</code> object for
455 * the recipient identified by its recipient certificate or kekID.
456 * <p>
457 *
458 * @param encoding the <code>AuthenticatedData</code> object as DER encoded byte array
459 * @param message the content message, if transmitted by other means (explicit mode)
460 * @param key the key to decrypt the message
461 * @param recipientCert the certificate of the recipient having a RecipientInfo of
462 * type KeyTransRecipientInfo or KeyAgreeRecipientInfo
463 * @param kekID the kekID identifying the recipient key when using a RecipientInfo
464 * of type KEKRecipientInfo
465 *
466 * @return the recovered message, as byte array
467 * @throws CMSException if the message cannot be recovered
468 * @throws IOException if a stream read/write error occurs
469 */
470 public byte[] getAuthenticatedDataStream(byte[] encoding,
471 byte[] message,
472 Key key,
473 X509Certificate recipientCert,
474 byte[] kekID)
475 throws CMSException, IOException {
476
477 // create the AuthenticatedData object from a DER encoded byte array
478 // we are testing the stream interface
479 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
480 AuthenticatedDataStream authenticatedData = new AuthenticatedDataStream(is);
481
482 if (authenticatedData.getMode() == AuthenticatedDataStream.EXPLICIT) {
483 // in explicit mode explicitly supply the content for hash/mac computation
484 authenticatedData.setInputStream(new ByteArrayInputStream(message));
485 }
486
487
488 // decrypt the mac key and verify the content mac
489 try {
490 System.out.println("Verify mac...");
491 if (recipientCert != null) {
492 authenticatedData.setupMac(key, recipientCert);
493 } else {
494 // KEKRecipientInfo
495 authenticatedData.setupMac(key, new KEKIdentifier(kekID));
496 }
497 InputStream contentStream = authenticatedData.getInputStream();
498 ByteArrayOutputStream os = new ByteArrayOutputStream();
499 Util.copyStream(contentStream, os, null);
500
501 if (authenticatedData.verifyMac() == false) {
502 throw new CMSException("Mac verification error!");
503 }
504 System.out.println("Mac successfully verified!");
505
506 return os.toByteArray();
507
508 } catch (InvalidKeyException ex) {
509 throw new CMSException("Key error: "+ex.getMessage());
510 } catch (NoSuchAlgorithmException ex) {
511 throw new CMSException(ex.toString());
512 }
513 }
514
515
516 // non stream
517
518 /**
519 * Creates a CMS <code>AuthenticatedData</code> for the given message message.
520 *
521 * @param message the message to be authenticated, as byte representation
522 * @param macAlgorithm the mac algorithm to be used
523 * @param macKeyLength the length of the temporary MAC key to be generated
524 * @param digestAlgorithm the digest algorithm to be used to calculate a digest
525 * from the content if authenticated attributes should
526 * be included
527 * @param mode whether to include the content into the AuthenticatedData ({@link
528 * AuthenticatedDataStream#IMPLICIT implicit}) or to not include it
529 * ({@link AuthenticatedDataStream#EXPLICIT explicit})
530 *
531 * @return the BER encoding of the <code>AuthenticatedData</code> object just created
532 *
533 * @throws CMSException if the <code>AuthenticatedData</code> object cannot
534 * be created
535 */
536 public byte[] createAuthenticatedData(byte[] message,
537 AlgorithmID macAlgorithm,
538 int macKeyLength,
539 AlgorithmID digestAlgorithm,
540 int mode)
541 throws CMSException {
542
543 AlgorithmID macAlg = (AlgorithmID)macAlgorithm.clone();
544 AlgorithmID digestAlg = null;
545 if (digestAlgorithm != null) {
546 digestAlg = (AlgorithmID)digestAlgorithm.clone();
547 }
548 ObjectID contentType = ObjectID.cms_data;
549
550 AuthenticatedData authenticatedData;
551
552 // create a new AuthenticatedData object
553 try {
554 authenticatedData = new AuthenticatedData(contentType,
555 message,
556 macAlg,
557 macKeyLength,
558 null,
559 digestAlg,
560 mode);
561 } catch (NoSuchAlgorithmException ex) {
562 throw new CMSException(ex.toString());
563 }
564
565 // static-static mode: set OriginatorInfo
566 OriginatorInfo originator = new OriginatorInfo();
567 originator.setCertificates(originatorCerts_);
568 authenticatedData.setOriginatorInfo(originator);
569 // create the recipient infos
570 RecipientInfo[] recipients = createRecipients();
571 // specify the recipients of the authenticated message
572 authenticatedData.setRecipientInfos(recipients);
573
574 if (digestAlgorithm != null) {
575 // create some authenticated attributes
576 // (the message digest attribute is automatically added)
577 try {
578 Attribute[] attributes = { new Attribute(new CMSContentType(contentType)) };
579 authenticatedData.setAuthenticatedAttributes(attributes);
580 } catch (Exception ex) {
581 throw new CMSException("Error creating attribute: " + ex.toString());
582 }
583 }
584
585 // wrap into ContentInfo
586 ContentInfo contentInfo = new ContentInfo(authenticatedData);
587 // return encoded EnvelopedData
588 return contentInfo.getEncoded();
589
590 }
591
592
593 /**
594 * Gets the content of the given <code>AuthenticatedData</code> object and
595 * verifies the mac for the recipient identified by its index
596 * into the recipientInfos field and uses the MAC key to verify
597 * the authenticated data.
598 * <p>
599 * This way of decrypting the MAC key and verifying the content may be used for
600 * any type of RecipientInfo (KeyTransRecipientInfo, KeyAgreeRecipientInfo,
601 * KEKRecipientInfo), but requires to know at what index of the recipientInfos
602 * field the RecipientInfo for the particular recipient in mind can be found.
603 * If the recipient in mind uses a RecipientInfo of type KeyAgreeRecipientInfo
604 * some processing overhead may take place because a KeyAgreeRecipientInfo may
605 * contain encrypted mac keys for more than only one recipient; since the
606 * recipientInfoIndex only specifies the RecipientInfo but not the encrypted
607 * mac key -- if there are more than only one -- repeated decryption runs may be
608 * required as long as the decryption process completes successfully.
609 *
610 * @param encoding the <code>AuthenticatedData</code> object as BER encoded byte array
611 * @param message the content message, if transmitted by other means (explicit mode)
612 * @param key the key to decrypt the mac key
613 * @param recipientInfoIndex the index of the right <code>RecipientInfo</code> to
614 * which the given key belongs
615 *
616 * @return the verified message, as byte array
617 * @throws CMSException if the authenticated data cannot be verified
618 * @throws IOException if a IO read/write error occurs
619 */
620 public byte[] getAuthenticatedData(byte[] encoding,
621 byte[] message,
622 Key key,
623 int recipientInfoIndex)
624 throws CMSException, IOException {
625
626 // create the AuthenticatedData object from a DER encoded byte array
627 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
628 AuthenticatedData authenticatedData = new AuthenticatedData(is);
629
630 if (authenticatedData.getMode() == AuthenticatedData.EXPLICIT) {
631 // in explicit mode explicitly supply the content for hash/mac computation
632 authenticatedData.setContent(message);
633 }
634
635 System.out.println("\nThis message can be verified by the owners of the following recipients:");
636 RecipientInfo[] recipients = authenticatedData.getRecipientInfos();
637
638 // for demonstration purposes we only look one time for all recipients included:
639 if (recipientInfoIndex == 0) {
640 int k = 0;
641 for (int i=0; i<recipients.length; i++) {
642 KeyIdentifier[] recipientIDs = recipients[i].getRecipientIdentifiers();
643 for (int j = 0; j < recipientIDs.length; j++) {
644 System.out.println("Recipient "+(++k)+":");
645 System.out.println(recipientIDs[j]);
646 }
647 }
648 }
649 // decrypt the mac key and verify the mac for the first recipient
650 try {
651 authenticatedData.setupMac(key, recipientInfoIndex);
652 if (authenticatedData.verifyMac() == false) {
653 throw new CMSException("Mac verification error!");
654 }
655 System.out.println("Mac successfully verified!");
656
657 return authenticatedData.getContent();
658
659 } catch (InvalidKeyException ex) {
660 throw new CMSException("Key error: "+ex.getMessage());
661 } catch (NoSuchAlgorithmException ex) {
662 throw new CMSException(ex.toString());
663 }
664 }
665
666 /**
667 * Gets the content of the given <code>AuthenticatedData</code> object and
668 * verifies the mac for the recipient identified by recipient identifier.
669 * <p>
670 * This way of decrypting the content may be used for any type of RecipientInfo
671 * (KeyTransRecipientInfo, KeyAgreeRecipientInfo, KEKRecipientInfo). The
672 * recipient in mind is identified by its recipient identifier.
673 *
674 * @param encoding the DER encoeded <code>AuthenticatedData</code> object#
675 * @param message the content message, if transmitted by other means (explicit mode)
676 * @param key the key to decrypt the message
677 * @param recipientID the recipient identifier uniquely identifying the key of the
678 * recipient
679 *
680 * @return the recovered message, as byte array
681 * @throws CMSException if the message cannot be recovered
682 * @throws IOException if an I/O error occurs
683 */
684 public byte[] getAuthenticatedData(byte[] encoding,
685 byte[] message,
686 Key key,
687 KeyIdentifier recipientID)
688 throws CMSException, IOException {
689
690 // create the AuthenticatedData object from a DER encoded byte array
691 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
692 AuthenticatedData authenticatedData = new AuthenticatedData(is);
693
694 if (authenticatedData.getMode() == AuthenticatedData.EXPLICIT) {
695 // in explicit mode explicitly supply the content for hash/mac computation
696 authenticatedData.setContent(message);
697 }
698
699 // get the right RecipientInfo
700 System.out.println("\nSearch for RecipientInfo:");
701 RecipientInfo recipient = authenticatedData.getRecipientInfo(recipientID);
702 if (recipient != null) {
703 System.out.println("RecipientInfo: " + recipient);
704 } else {
705 throw new CMSException("No recipient with ID " + recipientID);
706 }
707 // decrypt the mac key and verify the content mac
708 try {
709 System.out.println("Decrypt encrypted mac key...");
710 SecretKey cek = recipient.decryptKey(key, recipientID);
711 System.out.println("Verify content mac with decrypted mac key...");
712 authenticatedData.setupMac(cek);
713
714 if (authenticatedData.verifyMac() == false) {
715 throw new CMSException("Mac verification error!");
716 }
717 System.out.println("Mac successfully verified!");
718
719 return authenticatedData.getContent();
720
721 } catch (InvalidKeyException ex) {
722 throw new CMSException("Key error: "+ex.getMessage());
723 }
724 }
725
726 /**
727 * Gets the content of the given <code>AuthenticatedData</code> object and
728 * verifies the mac for the recipient identified by its recipient certificate or kekID.
729 * <p>
730 *
731 * @param encoding the DER encoded <code>AuthenticatedData</code> ASN.1 object
732 * @param message the content message, if transmitted by other means (explicit mode)
733 * @param key the key to decrypt the message
734 * @param recipientCert the certificate of the recipient having a RecipientInfo of
735 * type KeyTransRecipientInfo or KeyAgreeRecipientInfo
736 * @param kekID the kekID identifying the recipient key when using a RecipientInfo
737 * of type KEKRecipientInfo
738 *
739 * @return the recovered message, as byte array
740 * @throws CMSException if the message cannot be recovered
741 */
742 public byte[] getAuthenticatedData(byte[] encoding,
743 byte[] message,
744 Key key,
745 X509Certificate recipientCert,
746 byte[] kekID)
747 throws CMSException, IOException {
748
749 // create the AuthenticatedData object from a DER encoded byte array
750 ByteArrayInputStream is = new ByteArrayInputStream(encoding);
751 AuthenticatedData authenticatedData = new AuthenticatedData(is);
752
753 if (authenticatedData.getMode() == AuthenticatedData.EXPLICIT) {
754 // in explicit mode explicitly supply the content for hash/mac computation
755 authenticatedData.setContent(message);
756 }
757
758 // decrypt the mac key and verify the content mac
759 try {
760 System.out.println("Verify mac...");
761 if (recipientCert != null) {
762 authenticatedData.setupMac(key, recipientCert);
763 } else {
764 // KEKRecipientInfo
765 authenticatedData.setupMac(key, new KEKIdentifier(kekID));
766 }
767
768 if (authenticatedData.verifyMac() == false) {
769 throw new CMSException("Mac verification error!");
770 }
771 System.out.println("Mac successfully verified!");
772
773 return authenticatedData.getContent();
774
775 } catch (InvalidKeyException ex) {
776 throw new CMSException("Key error: "+ex.getMessage());
777 } catch (NoSuchAlgorithmException ex) {
778 throw new CMSException(ex.toString());
779 }
780 }
781
782 /**
783 * Creates the RecipientInfos.
784 *
785 * @return the RecipientInfos created
786 *
787 * @throws CMSException if an error occurs when creating the recipient infos
788 */
789 public RecipientInfo[] createRecipients() throws CMSException {
790
791 RecipientInfo[] recipients = new RecipientInfo[4];
792 try {
793
794 // rsaUser1 is the first receiver (cert identified by IssuerAndSerialNumber)
795 recipients[0] = new KeyTransRecipientInfo(rsaUser1Cert_,
796 (AlgorithmID)AlgorithmID.rsaEncryption.clone());
797 // rsaUser2 is the second receiver (cert identifief by SubjectKeyIdentifier)
798 recipients[1] = new KeyTransRecipientInfo(rsaUser2Cert_,
799 CertificateIdentifier.SUBJECT_KEY_IDENTIFIER,
800 (AlgorithmID)AlgorithmID.rsaEncryption.clone());
801
802 // next recipients use key agreement (Static-Static Diffie-Hellman)
803 // the key encryption (key agreement) algorithm to use:
804 AlgorithmID keyEA = (AlgorithmID)AlgorithmID.ssdhKeyAgreement.clone();
805 // the key wrap algorithm to use:
806 AlgorithmID keyWrapAlg = (AlgorithmID)keyWrapAlg_.clone();
807 // the length of the key encryption key to be generated:
808 int kekLength = kekLength_;
809 // in static-static mode we may supply user keying material
810 byte[] ukm = new byte[64];
811 random_.nextBytes(ukm);
812 // ssdhUser1 is originator
813 recipients[2] = new KeyAgreeRecipientInfo(ssdhUser1Cert_,
814 ssdhUser1PrivKey_,
815 KeyIdentifier.ISSUER_AND_SERIALNUMBER,
816 keyEA,
817 keyWrapAlg,
818 kekLength,
819 ukm);
820 // add ssdhUser1 (originator) as recipient, too
821 ((KeyAgreeRecipientInfo)recipients[2]).addRecipient(ssdhUser1Cert_, CertificateIdentifier.ISSUER_AND_SERIALNUMBER);
822 // ssdhUser2 is the recipient (cert identified by RecipientKeyIdentifier)
823 ((KeyAgreeRecipientInfo)recipients[2]).addRecipient(ssdhUser2Cert_, CertificateIdentifier.RECIPIENT_KEY_IDENTIFIER);
824
825 // last receiver uses a symmetric key encryption key
826 AlgorithmID kea = (AlgorithmID)keyWrapAlg_.clone();
827 KEKIdentifier kekIdentifier = new KEKIdentifier(kekID_);
828 recipients[3] = new KEKRecipientInfo(kekIdentifier, kea, kek_);
829
830 } catch (Exception ex) {
831 throw new CMSException("Error adding recipients: " + ex.getMessage());
832 }
833 return recipients;
834 }
835
836 /**
837 * Parses an AuthenticatedData and verifies the mac for all test recipients
838 * using the index into the recipientInfos field for identifying the recipient.
839 *
840 * @param stream whether to use AuthenticatedDataStream or AuthenticatedData
841 * @param encodedAuthenticatedData the encoded AuthenticatedData object
842 * @param message the content message, if transmitted by other means (explicit mode)
843 *
844 * @throws Exception if some error occurs during mac key decryption / mac verification
845 */
846 public void parseAuthenticatedDataWithRecipientInfoIndex(boolean stream,
847 byte[] encodedAuthenticatedData,
848 byte[] message)
849 throws Exception {
850
851 byte[] receivedMessage;
852 if (stream) {
853
854 // rsaUser1
855 System.out.println("\nVerify MAC for rsaUser1:");
856
857 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
858 message,
859 rsaUser1PrivKey_,
860 0);
861 System.out.print("\nContent: ");
862 System.out.println(new String(receivedMessage));
863
864 // rsaUser2
865 System.out.println("\nVerify MAC for rsaUser2:");
866 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
867 message,
868 rsaUser2PrivKey_,
869 1);
870
871 // ssdhUser1
872 System.out.println("\nVerify MAC for ssdhUser1:");
873
874 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
875 message,
876 ssdhUser1PrivKey_,
877 2);
878 System.out.print("\nContent: ");
879 System.out.println(new String(receivedMessage));
880
881 // ssdhUser2
882 System.out.println("\nVerify MAC for ssdhUser2:");
883 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
884 message,
885 ssdhUser2PrivKey_,
886 2);
887 System.out.print("\nContent: ");
888 System.out.println(new String(receivedMessage));
889
890 // kekUser
891 System.out.println("\nVerify MAC for kekUser:");
892 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
893 message,
894 kek_,
895 3);
896 System.out.print("\nContent: ");
897 System.out.println(new String(receivedMessage));
898
899 } else {
900
901 // rsaUser1
902 System.out.println("\nVerify MAC for rsaUser1:");
903
904 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
905 message,
906 rsaUser1PrivKey_,
907 0);
908 System.out.print("\nContent: ");
909 System.out.println(new String(receivedMessage));
910
911 // rsaUser2
912 System.out.println("\nVerify MAC for rsaUser2:");
913 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
914 message,
915 rsaUser2PrivKey_,
916 1);
917
918 // ssdhUser1
919 System.out.println("\nVerify MAC for ssdhUser1:");
920 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
921 message,
922 ssdhUser1PrivKey_,
923 2);
924 System.out.print("\nContent: ");
925 System.out.println(new String(receivedMessage));
926 // ssdhUser2
927 System.out.println("\nVerify MAC for ssdhUser2:");
928 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
929 message,
930 ssdhUser2PrivKey_,
931 2);
932
933 // kekUser
934 System.out.println("\nVerify MAC for kekUser:");
935 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
936 message,
937 kek_,
938 3);
939
940 System.out.print("\nContent: ");
941 System.out.println(new String(receivedMessage));
942 }
943 }
944
945 /**
946 * Parses an AuthenticatedData and verifies the mac for all recipients
947 * identified by their recipient identifiers.
948 *
949 * @param stream whether to use AuthenticatedDataStream or AuthenticatedData
950 * @param encodedAuthenticatedData the encoded AuthenticatedData object
951 * @param message the content message, if transmitted by other means (explicit mode)
952 *
953 * @throws Exception if some error occurs during mac key decryption / mac verification
954 */
955 public void parseAuthenticatedDataWithRecipientIdentifier(boolean stream,
956 byte[] encodedAuthenticatedData,
957 byte[] message)
958 throws Exception {
959
960 byte[] receivedMessage;
961 if (stream) {
962
963 // rsaUser1
964 System.out.println("\nVerify MAC for rsaUser1:");
965 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
966 message,
967 rsaUser1PrivKey_,
968 new IssuerAndSerialNumber(rsaUser1Cert_));
969 System.out.print("\nContent: ");
970 System.out.println(new String(receivedMessage));
971
972 // rsaUser2
973 System.out.println("\nVerify MAC for rsaUser2:");
974 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
975 message,
976 rsaUser2PrivKey_,
977 new SubjectKeyID(rsaUser2Cert_));
978
979 // ssdhUser1
980 System.out.println("\nVerify MAC for ssdhUser1:");
981 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
982 message,
983 ssdhUser1PrivKey_,
984 new IssuerAndSerialNumber(ssdhUser1Cert_));
985 System.out.print("\nContent: ");
986 System.out.println(new String(receivedMessage));
987 // ssdhUser2
988 System.out.println("\nVerify MAC for ssdhUser2:");
989 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
990 message,
991 ssdhUser2PrivKey_,
992 new RecipientKeyIdentifier(ssdhUser2Cert_));
993 // kekUser
994 System.out.println("\nVerify MAC for kekUser:");
995 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
996 message,
997 kek_,
998 new KEKIdentifier(kekID_));
999
1000 System.out.print("\nContent: ");
1001 System.out.println(new String(receivedMessage));
1002
1003 } else {
1004
1005 // rsaUser1
1006 System.out.println("\nVerify MAC for rsaUser1:");
1007 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
1008 message,
1009 rsaUser1PrivKey_,
1010 new IssuerAndSerialNumber(rsaUser1Cert_));
1011 System.out.print("\nContent: ");
1012 System.out.println(new String(receivedMessage));
1013
1014 // rsaUser2
1015 System.out.println("\nVerify MAC for rsaUser2:");
1016 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
1017 message,
1018 rsaUser2PrivKey_,
1019 new SubjectKeyID(rsaUser2Cert_));
1020
1021 // ssdhUser1
1022 System.out.println("\nVerify MAC for ssdhUser1:");
1023 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
1024 message,
1025 ssdhUser1PrivKey_,
1026 new IssuerAndSerialNumber(ssdhUser1Cert_));
1027 System.out.print("\nContent: ");
1028 System.out.println(new String(receivedMessage));
1029 // ssdhUser2
1030 System.out.println("\nVerify MAC for ssdhUser2:");
1031 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
1032 message,
1033 ssdhUser2PrivKey_,
1034 new RecipientKeyIdentifier(ssdhUser2Cert_));
1035 // kekUser
1036 System.out.println("\nVerify MAC for kekUser:");
1037 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
1038 message,
1039 kek_,
1040 new KEKIdentifier(kekID_));
1041
1042 System.out.print("\nContent: ");
1043 System.out.println(new String(receivedMessage));
1044 }
1045 }
1046
1047 /**
1048 * Parses an AuthenticatedData and verifies the mac for all recipients
1049 * identified by their recipient certificate (or kek).
1050 *
1051 * @param stream whether to use AuthenticatedDataStream or AuthenticatedData
1052 * @param encodedAuthenticatedData the encoded AuthenticatedData object
1053 * @param message the content message, if transmitted by other means (explicit mode)
1054 *
1055 * @throws Exception if some error occurs during mac key decryption / mac verification
1056 */
1057 public void parseAuthenticatedDataWithRecipientCertOrKEKId(boolean stream,
1058 byte[] encodedAuthenticatedData,
1059 byte[] message)
1060 throws Exception {
1061
1062 byte[] receivedMessage;
1063 if (stream) {
1064
1065 // rsaUser1
1066 System.out.println("\nVerify MAC for rsaUser1:");
1067 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
1068 message,
1069 rsaUser1PrivKey_,
1070 rsaUser1Cert_,
1071 null);
1072 System.out.print("\nContent: ");
1073 System.out.println(new String(receivedMessage));
1074 // rsaUser2
1075 System.out.println("\nVerify MAC for rsaUser2:");
1076 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
1077 message,
1078 rsaUser2PrivKey_,
1079 rsaUser2Cert_,
1080 null);
1081
1082 // ssdhUser1
1083 System.out.println("\nVerify MAC for ssdhUser1:");
1084 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
1085 message,
1086 ssdhUser1PrivKey_,
1087 ssdhUser1Cert_,
1088 null);
1089 System.out.print("\nContent: ");
1090 System.out.println(new String(receivedMessage));
1091 // ssdhUser2
1092 System.out.println("\nVerify MAC for ssdhUser2:");
1093 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
1094 message,
1095 ssdhUser2PrivKey_,
1096 ssdhUser2Cert_,
1097 null);
1098 // kekUser
1099 System.out.println("\nVerify MAC for kekUser:");
1100 receivedMessage = getAuthenticatedDataStream(encodedAuthenticatedData,
1101 message,
1102 kek_,
1103 null,
1104 kekID_);
1105
1106 System.out.print("\nContent: ");
1107 System.out.println(new String(receivedMessage));
1108 } else {
1109 // rsaUser1
1110 System.out.println("\nVerify MAC for rsaUser1:");
1111 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
1112 message,
1113 rsaUser1PrivKey_,
1114 rsaUser1Cert_,
1115 null);
1116 System.out.print("\nContent: ");
1117 System.out.println(new String(receivedMessage));
1118 // rsaUser2
1119 System.out.println("\nVerify MAC for rsaUser2:");
1120 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
1121 message,
1122 rsaUser2PrivKey_,
1123 rsaUser2Cert_,
1124 null);
1125
1126 // ssdhUser1
1127 System.out.println("\nVerify MAC for ssdhUser1:");
1128 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
1129 message,
1130 ssdhUser1PrivKey_,
1131 ssdhUser1Cert_,
1132 null);
1133 System.out.print("\nContent: ");
1134 System.out.println(new String(receivedMessage));
1135 // ssdhUser2
1136 System.out.println("\nVerify MAC for ssdhUser2:");
1137 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
1138 message,
1139 ssdhUser2PrivKey_,
1140 ssdhUser2Cert_,
1141 null);
1142 // kekUser
1143 System.out.println("\nVerify MAC for kekUser:");
1144 receivedMessage = getAuthenticatedData(encodedAuthenticatedData,
1145 message,
1146 kek_,
1147 null,
1148 kekID_);
1149
1150 System.out.print("\nContent: ");
1151 System.out.println(new String(receivedMessage));
1152 }
1153 }
1154
1155 /**
1156 * Starts the test.
1157 */
1158 public void start() {
1159 // the test message
1160 String m = "This is the test message.";
1161 System.out.println("Test message: \""+m+"\"");
1162 System.out.println();
1163 byte[] message = m.getBytes();
1164
1165 try {
1166 byte[] encodedAuthenticatedData;
1167
1168 AlgorithmID macAlgorithm = (AlgorithmID)AlgorithmID.hMAC_SHA256.clone();
1169 int macKeyLength = 32;
1170 AlgorithmID digestAlgorithm = (AlgorithmID)AlgorithmID.sha256.clone();
1171
1172 System.out.println("Stream implementation demos");
1173 System.out.println("===========================");
1174
1175
1176 // the stream implementation
1177 //
1178 // test CMS AuthenticatedDataStream
1179 //
1180
1181 // implicit mode; with authenticated attributes
1182 System.out.println("\nCMS AuthenticatedDataStream demo with authenticated attributes [create, implicit mode]:\n");
1183 encodedAuthenticatedData = createAuthenticatedDataStream(message,
1184 macAlgorithm,
1185 macKeyLength,
1186 digestAlgorithm,
1187 AuthenticatedDataStream.IMPLICIT);
1188 // transmit data
1189 System.out.println("\nCMS AuthenticatedDataStream demo [parse, implicit mode]:\n");
1190 System.out.println("Decrypt and verify for the several recipients using their index into the recipientInfos field.");
1191 parseAuthenticatedDataWithRecipientInfoIndex(true, encodedAuthenticatedData, null);
1192 System.out.println("Decrypt and verify for the several recipients using their RecipientIdentifier.");
1193 parseAuthenticatedDataWithRecipientIdentifier(true, encodedAuthenticatedData, null);
1194 System.out.println("Decrypt and verify for the several recipients using their certificate or kek.");
1195 parseAuthenticatedDataWithRecipientCertOrKEKId(true, encodedAuthenticatedData, null);
1196
1197 // implicit mode; without authenticated attributes
1198 System.out.println("\nCMS AuthenticatedDataStream demo without authenticated attributes [create, implicit mode]:\n");
1199 encodedAuthenticatedData = createAuthenticatedDataStream(message,
1200 macAlgorithm,
1201 macKeyLength,
1202 null,
1203 AuthenticatedDataStream.IMPLICIT);
1204 // transmit data
1205 System.out.println("\nCMS AuthenticatedDataStream demo [parse, implicit mode]:\n");
1206 System.out.println("Decrypt and verify for the several recipients using their index into the recipientInfos field.");
1207 parseAuthenticatedDataWithRecipientInfoIndex(true, encodedAuthenticatedData, null);
1208 System.out.println("Decrypt and verify for the several recipients using their RecipientIdentifier.");
1209 parseAuthenticatedDataWithRecipientIdentifier(true, encodedAuthenticatedData, null);
1210 System.out.println("Decrypt and verify for the several recipients using their certificate or kek.");
1211 parseAuthenticatedDataWithRecipientCertOrKEKId(true, encodedAuthenticatedData, null);
1212
1213
1214 // explict mode; with authenticated attributes
1215 System.out.println("\nCMS AuthenticatedDataStream demo with authenticated attributes [create, explicit mode]:\n");
1216 encodedAuthenticatedData = createAuthenticatedDataStream(message,
1217 macAlgorithm,
1218 macKeyLength,
1219 digestAlgorithm,
1220 AuthenticatedDataStream.EXPLICIT);
1221 // transmit data
1222 System.out.println("\nCMS AuthenticatedDataStream demo [parse, explicit mode]:\n");
1223 System.out.println("Decrypt and verify for the several recipients using their index into the recipientInfos field.");
1224 parseAuthenticatedDataWithRecipientInfoIndex(true, encodedAuthenticatedData, message);
1225 System.out.println("Decrypt and verify for the several recipients using their RecipientIdentifier.");
1226 parseAuthenticatedDataWithRecipientIdentifier(true, encodedAuthenticatedData, message);
1227 System.out.println("Decrypt and verify for the several recipients using their certificate or kek.");
1228 parseAuthenticatedDataWithRecipientCertOrKEKId(true, encodedAuthenticatedData, message);
1229
1230 // explict mode; without authenticated attributes
1231 System.out.println("\nCMS AuthenticatedDataStream demo without authenticated attributes [create, explicit mode]:\n");
1232 encodedAuthenticatedData = createAuthenticatedDataStream(message,
1233 macAlgorithm,
1234 macKeyLength,
1235 null,
1236 AuthenticatedDataStream.EXPLICIT);
1237 // transmit data
1238 System.out.println("\nCMS AuthenticatedDataStream demo [parse, explicit mode]:\n");
1239 System.out.println("Decrypt and verify for the several recipients using their index into the recipientInfos field.");
1240 parseAuthenticatedDataWithRecipientInfoIndex(true, encodedAuthenticatedData, message);
1241 System.out.println("Decrypt and verify for the several recipients using their RecipientIdentifier.");
1242 parseAuthenticatedDataWithRecipientIdentifier(true, encodedAuthenticatedData, message);
1243 System.out.println("Decrypt and verify for the several recipients using their certificate or kek.");
1244 parseAuthenticatedDataWithRecipientCertOrKEKId(true, encodedAuthenticatedData, message);
1245
1246
1247
1248 // the non-stream implementation
1249 System.out.println("\nNon-stream implementation demos");
1250 System.out.println("===============================");
1251
1252
1253 //
1254 // test CMS AuthenticatedData
1255 //
1256
1257 // implict mode; with authenticated attributes
1258 System.out.println("\nCMS AuthenticatedData demo with authenticated attributes [create, implicit mode]:\n");
1259 encodedAuthenticatedData = createAuthenticatedData(message,
1260 macAlgorithm,
1261 macKeyLength,
1262 digestAlgorithm,
1263 AuthenticatedDataStream.IMPLICIT);
1264 // transmit data
1265 System.out.println("\nCMS AuthenticatedData demo [parse]:\n");
1266 System.out.println("Decrypt and verify for the several recipients using their index into the recipientInfos field.");
1267 parseAuthenticatedDataWithRecipientInfoIndex(false, encodedAuthenticatedData, null);
1268 System.out.println("Decrypt and verify for the several recipients using their RecipientIdentifier.");
1269 parseAuthenticatedDataWithRecipientIdentifier(false, encodedAuthenticatedData, null);
1270 System.out.println("Decrypt and verify for the several recipients using their certificate or kek.");
1271 parseAuthenticatedDataWithRecipientCertOrKEKId(false, encodedAuthenticatedData, null);
1272
1273 // implict mode; without authenticated attributes
1274 System.out.println("\nCMS AuthenticatedData demo without authenticated attributes [create, implicit mode]:\n");
1275 encodedAuthenticatedData = createAuthenticatedData(message,
1276 macAlgorithm,
1277 macKeyLength,
1278 null,
1279 AuthenticatedDataStream.IMPLICIT);
1280 // transmit data
1281 System.out.println("\nCMS AuthenticatedData demo [parse]:\n");
1282 System.out.println("Decrypt and verify for the several recipients using their index into the recipientInfos field.");
1283 parseAuthenticatedDataWithRecipientInfoIndex(false, encodedAuthenticatedData, null);
1284 System.out.println("Decrypt and verify for the several recipients using their RecipientIdentifier.");
1285 parseAuthenticatedDataWithRecipientIdentifier(false, encodedAuthenticatedData, null);
1286 System.out.println("Decrypt and verify for the several recipients using their certificate or kek.");
1287 parseAuthenticatedDataWithRecipientCertOrKEKId(false, encodedAuthenticatedData, null);
1288
1289
1290 // explict mode; with authenticated attributes
1291 System.out.println("\nCMS AuthenticatedData demo with authenticated attributes [create, explicit mode]:\n");
1292 encodedAuthenticatedData = createAuthenticatedData(message,
1293 macAlgorithm,
1294 macKeyLength,
1295 digestAlgorithm,
1296 AuthenticatedDataStream.EXPLICIT);
1297 // transmit data
1298 System.out.println("\nCMS AuthenticatedData demo [parse]:\n");
1299 System.out.println("Decrypt and verify for the several recipients using their index into the recipientInfos field.");
1300 parseAuthenticatedDataWithRecipientInfoIndex(false, encodedAuthenticatedData, message);
1301 System.out.println("Decrypt and verify for the several recipients using their RecipientIdentifier.");
1302 parseAuthenticatedDataWithRecipientIdentifier(false, encodedAuthenticatedData, message);
1303 System.out.println("Decrypt and verify for the several recipients using their certificate or kek.");
1304 parseAuthenticatedDataWithRecipientCertOrKEKId(false, encodedAuthenticatedData, message);
1305
1306 // explict mode; without authenticated attributes
1307 System.out.println("\nCMS AuthenticatedData demo without authenticated attributes [create, explicit mode]:\n");
1308 encodedAuthenticatedData = createAuthenticatedData(message,
1309 macAlgorithm,
1310 macKeyLength,
1311 null,
1312 AuthenticatedDataStream.EXPLICIT);
1313 // transmit data
1314 System.out.println("\nCMS AuthenticatedData demo [parse]:\n");
1315 System.out.println("Decrypt and verify for the several recipients using their index into the recipientInfos field.");
1316 parseAuthenticatedDataWithRecipientInfoIndex(false, encodedAuthenticatedData, message);
1317 System.out.println("Decrypt and verify for the several recipients using their RecipientIdentifier.");
1318 parseAuthenticatedDataWithRecipientIdentifier(false, encodedAuthenticatedData, message);
1319 System.out.println("Decrypt and verify for the several recipients using their certificate or kek.");
1320 parseAuthenticatedDataWithRecipientCertOrKEKId(false, encodedAuthenticatedData, message);
1321
1322
1323 } catch (Exception ex) {
1324 ex.printStackTrace();
1325 throw new RuntimeException(ex.toString());
1326 }
1327 }
1328
1329 /**
1330 * Main method.
1331 *
1332 * @throws IOException
1333 * if an I/O error occurs when reading required keys
1334 * and certificates from files
1335 */
1336 public static void main(String argv[]) throws Exception {
1337
1338 DemoUtil.initDemos();
1339 (new AuthenticatedDataDemo()).start();
1340 System.out.println("\nReady!");
1341 System.in.read();
1342 }
1343
1344 }