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 }