001// Copyright (C) 2002 IAIK 002// https://sic.tech/ 003// 004// Copyright (C) 2003 - 2025 Stiftung Secure Information and 005// Communication Technologies SIC 006// https://sic.tech/ 007// 008// All rights reserved. 009// 010// This source is provided for inspection purposes and recompilation only, 011// unless specified differently in a contract with IAIK. This source has to 012// be kept in strict confidence and must not be disclosed to any third party 013// under any circumstances. Redistribution in source and binary forms, with 014// or without modification, are <not> permitted in any case! 015// 016// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 017// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 018// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 019// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 020// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 021// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 022// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 023// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 024// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 025// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 026// SUCH DAMAGE. 027// 028// $Header: /IAIK-CMS/current/src/demo/smime/basic/CMSStreamDemo.java 31 12.02.25 17:58 Dbratko $ 029// $Revision: 31 $ 030// 031 032package demo.smime.basic; 033 034import java.io.ByteArrayInputStream; 035import java.io.ByteArrayOutputStream; 036import java.io.IOException; 037import java.io.InputStream; 038import java.io.OutputStream; 039import java.io.PipedInputStream; 040import java.io.PipedOutputStream; 041import java.security.PrivateKey; 042import java.util.Random; 043 044import demo.DemoSMimeUtil; 045import demo.DemoUtil; 046import demo.keystore.CMSKeyStore; 047import iaik.asn1.structures.AlgorithmID; 048import iaik.cms.IssuerAndSerialNumber; 049import iaik.smime.SMimeAuthEncrypted; 050import iaik.smime.SMimeEncrypted; 051import iaik.smime.SMimeSigned; 052import iaik.utils.CryptoUtils; 053import iaik.utils.Util; 054import iaik.x509.X509Certificate; 055 056/** 057 * This class shows the usage of the SMimeSigned and SMimeEncrypted classes. 058 * These classes can be used to create/parse signed and/or encrypted CMS messages. 059 * This demo does not use the Jakarta Mail API. 060 * 061 * @see iaik.smime.SMimeSigned 062 * @see iaik.smime.SMimeEncrypted 063 */ 064public class CMSStreamDemo { 065 066 // the signer private key 067 PrivateKey[] signerPrivateKeys; 068 // the signer certificate 069 X509Certificate rsaSignerCertificate; 070 // the signer certificate 071 X509Certificate dsaSignerCertificate; 072 // the recipient private key 073 PrivateKey[] recipientPrivateKeys; 074 // the recipient certificate 075 X509Certificate[] recipientCertificates; 076 // the certificate chain 077 X509Certificate[] signerCertificates; 078 // buffer with test data to sign and/or encrypt 079 byte[] buffer; 080 // size of the buffer 081 final static int BUF_SIZE = 10000; 082 083 /** 084 * Empty default constructor. 085 */ 086 public CMSStreamDemo() { 087 088 System.out.println(); 089 System.out.println("******************************************************************************************"); 090 System.out.println("* CMSStreamDemo *"); 091 System.out.println("* (shows the usage of the IAIK-CMS SMimeSigned and SMimeEncrypted classes) *"); 092 System.out.println("******************************************************************************************"); 093 System.out.println(); 094 095 // create some random data for the test 096 buffer = new byte[BUF_SIZE]; 097 Random rnd = new Random(); 098 rnd.nextBytes(buffer); 099 } 100 101 /** 102 * Reads the required keys and certificates from the demo keystore. 103 * 104 * @throws Exception if some error occurs when reading from the keystore 105 */ 106 public void setupCertificates() throws Exception { 107 // get the certificates from the KeyStore 108 // we use two signers just for demonstration 109 signerPrivateKeys = new PrivateKey[2]; 110 // RSA signer 111 X509Certificate[] rsaCerts = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1); 112 rsaSignerCertificate = rsaCerts[0]; 113 signerPrivateKeys[0] = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1); 114 // DSA signer 115 X509Certificate[] dsaCerts = CMSKeyStore.getCertificateChain(CMSKeyStore.DSA, CMSKeyStore.SZ_2048_SIGN_1); 116 dsaSignerCertificate = dsaCerts[0]; 117 signerPrivateKeys[1] = CMSKeyStore.getPrivateKey(CMSKeyStore.DSA, CMSKeyStore.SZ_2048_SIGN_1); 118 signerCertificates = new X509Certificate[rsaCerts.length + dsaCerts.length]; 119 System.arraycopy(rsaCerts, 0, signerCertificates, 0, dsaCerts.length); 120 System.arraycopy(dsaCerts, 0, signerCertificates, rsaCerts.length, dsaCerts.length); 121 122 // get the recipients keys and certificates 123 recipientPrivateKeys = new PrivateKey[2]; 124 recipientPrivateKeys[0] = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1); 125 recipientPrivateKeys[1] = CMSKeyStore.getPrivateKey(CMSKeyStore.ESDH, CMSKeyStore.SZ_2048_CRYPT_1); 126 recipientCertificates = new X509Certificate[2]; 127 recipientCertificates[0] = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1)[0]; 128 recipientCertificates[1] = CMSKeyStore.getCertificateChain(CMSKeyStore.ESDH, CMSKeyStore.SZ_2048_CRYPT_1)[0]; 129 } 130 131 /** 132 * Uses class {@link iaik.smime.SMimeEncrypted SMimeEncrypted} to encrypt some data, encode it, 133 * and finally parses the encoding to decrypt and recover the original content. 134 * 135 * @param contentEA the content encryption algorithm to be used 136 * @param keyWrapAlg the key wrap algorithm to be used for encrypting the temporary content encryption key 137 * @param keyLength the length of the content encryption key to be created and used 138 * @param recipientIndex the index into the recipientInfos field indicating for which recipient the message 139 * shall be decrypted 140 * 141 * @throws Exception if some error occurs 142 */ 143 public void testSMimeEncrypted(AlgorithmID contentEA, AlgorithmID keyWrapAlg, int keyLength, int recipientIndex) throws Exception { 144 145 // repository for the encrypted message 146 byte[] encrypted_message; 147 // the InputStream containing the data to encrypt 148 InputStream is = new ByteArrayInputStream(buffer); 149 // the OutputStream where the data shall be written to 150 ByteArrayOutputStream os = new ByteArrayOutputStream(); 151 152 // encrypt with DES/CBC and default key length 153 SMimeEncrypted encrypted = new SMimeEncrypted(is, contentEA, keyLength); 154 // add one RSA recipient 155 encrypted.addRecipient(recipientCertificates[0], (AlgorithmID)AlgorithmID.rsaEncryption.clone()); 156 // add one ESDH recipient 157 encrypted.addRecipient(recipientCertificates[1], (AlgorithmID)AlgorithmID.esdhKeyAgreement.clone(), keyWrapAlg, keyLength); 158 159 // encrypt and write the data to the output stream 160 encrypted.writeTo(os); 161 // finished 162 os.close(); 163 // get the encrypted message from the ByteArrayOutputStream 164 encrypted_message = os.toByteArray(); 165 166 // and now decrypt the data 167 is = new ByteArrayInputStream(encrypted_message); 168 encrypted = new SMimeEncrypted(is); 169 // use this private key to decrypt the symmetric key of recipient 0 170 encrypted.decryptSymmetricKey(recipientPrivateKeys[recipientIndex], recipientIndex); 171 // get the InputStream with the decrypted data 172 InputStream data = encrypted.getInputStream(); 173 174 // reset our output stream 175 os.reset(); 176 // write the decrypted data to an output stream 177 // copy the data 178 Util.copyStream(data, os, null); 179 os.close(); 180 181 // original and 'received' message must be the same 182 if (!CryptoUtils.equalsBlock(buffer, os.toByteArray())) 183 throw new RuntimeException("Error: messages are not equal!"); 184 } 185 186 /** 187 * Uses class {@link iaik.smime.SMimeSigned SMimeSigned} to sign some data, encode it, 188 * and finally parses the encoding to verify the signature. 189 * 190 * @param mode either {@link iaik.smime.SMimeSigned#IMPLICIT implicit} or 191 * {@link iaik.smime.SMimeSigned#EXPLICIT explicit} to indicate 192 * whether the content shall be included in the signature or 193 * transmitted out-of-band 194 * 195 * @throws Exception if some error occurs 196 */ 197 public void testSMimeSigned(int mode) throws Exception { 198 199 // repository for the signed message 200 byte[] signed_message = null; 201 // repository for the signature 202 byte[] signature; 203 // the InputStream containing the data to sign 204 InputStream is = new ByteArrayInputStream(buffer); 205 // the OutputStream where the data shall be written to 206 ByteArrayOutputStream os = new ByteArrayOutputStream(); 207 208 // create an implicitly/explicitly signed message 209 SMimeSigned signed = new SMimeSigned(is, mode); 210 // these certificates are sent within the signature 211 signed.setCertificates(signerCertificates); 212 // add two signers for testing 213 signed.addSigner(signerPrivateKeys[0], 214 new IssuerAndSerialNumber(rsaSignerCertificate)); 215 signed.addSigner(signerPrivateKeys[1], 216 new IssuerAndSerialNumber(dsaSignerCertificate), 217 (AlgorithmID)AlgorithmID.sha256.clone(), 218 (AlgorithmID)AlgorithmID.dsaWithSHA256.clone()); 219 220 221 if (mode == SMimeSigned.EXPLICIT) { 222 // write the data to the out-of-band file 223 ByteArrayOutputStream out_data = new ByteArrayOutputStream(); 224 Util.copyStream(signed.getInputStream(), out_data, null); 225 out_data.close(); 226 signed_message = out_data.toByteArray(); 227 } 228 229 // write the signature or the data+signature to the output stream 230 signed.writeTo(os); 231 os.close(); 232 signature = os.toByteArray(); 233 234 // and now verify the signature 235 is = new ByteArrayInputStream(signature); 236 signed = new SMimeSigned(is); 237 if (mode == SMimeSigned.EXPLICIT) { 238 // content data has been not included 239 signed.setInputStream(new ByteArrayInputStream(signed_message)); 240 } 241 242 // get the InputStream with the signed, plain data 243 InputStream data = signed.getInputStream(); 244 245 // reset our output stream 246 os.reset(); 247 // write the verified data to the output stream 248 // copy the data 249 Util.copyStream(data, os, null); 250 os.close(); 251 252 // now verify the signed data and print the certificate of the signer 253 // (verify() verifies signer at index 0) 254 X509Certificate cert = signed.verify(); 255 System.out.println("Signature OK from: "+cert.getSubjectDN()); 256 // verify our second test signer 257 cert = signed.verify(1); 258 System.out.println("Signature OK from: "+cert.getSubjectDN()); 259 260 // original and 'received' message must be the same 261 if (!CryptoUtils.equalsBlock(buffer, os.toByteArray())) 262 throw new RuntimeException("Error: messages are not equal!"); 263 } 264 265 /** 266 * Uses class {@link iaik.smime.SMimeAuthEncrypted SMimeAuthEncrypted} to 267 * authenticated encrypt some data, encode it, 268 * and finally parses the encoding to decrypt and recover the original content. 269 * 270 * @param contentEA the content-authenticated encryption algorithm to be used 271 * @param keyWrapAlg the key wrap algorithm to be used for encrypting the temporary content encryption key 272 * @param keyLength the length of the content encryption key to be created and used 273 * @param recipientIndex the index into the recipientInfos field indicating for which recipient the message 274 * shall be decrypted 275 * 276 * @throws Exception if some error occurs 277 */ 278 public void testSMimeAuthEncrypted(AlgorithmID contentEA, AlgorithmID keyWrapAlg, int keyLength, int recipientIndex) throws Exception { 279 280 // repository for the encrypted message 281 byte[] encrypted_message; 282 // the InputStream containing the data to encrypt 283 InputStream is = new ByteArrayInputStream(buffer); 284 // the OutputStream where the data shall be written to 285 ByteArrayOutputStream os = new ByteArrayOutputStream(); 286 287 // encrypt with DES/CBC and default key length 288 SMimeAuthEncrypted encrypted = new SMimeAuthEncrypted(is, contentEA, keyLength); 289 if (contentEA.equals(AlgorithmID.aes128_CCM) || 290 contentEA.equals(AlgorithmID.aes192_CCM) || 291 contentEA.equals(AlgorithmID.aes256_CCM)) { 292 // for aes-ccm we need to know the data input length in advance 293 encrypted.setInputLength(buffer.length); 294 } 295 296 // add one RSA recipient 297 encrypted.addRecipient(recipientCertificates[0], (AlgorithmID)AlgorithmID.rsaEncryption.clone()); 298 // add one ESDH recipient 299 encrypted.addRecipient(recipientCertificates[1], (AlgorithmID)AlgorithmID.esdhKeyAgreement.clone(), keyWrapAlg, keyLength); 300 301 // encrypt and write the data to the output stream 302 encrypted.writeTo(os); 303 // finished 304 os.close(); 305 // get the encrypted message from the ByteArrayOutputStream 306 encrypted_message = os.toByteArray(); 307 308 // and now decrypt the data 309 is = new ByteArrayInputStream(encrypted_message); 310 encrypted = new SMimeAuthEncrypted(is, (byte[])null, buffer.length); 311 // use this private key to decrypt the symmetric key of recipient 0 312 encrypted.decryptSymmetricKey(recipientPrivateKeys[recipientIndex], recipientIndex); 313 // get the InputStream with the decrypted data 314 InputStream data = encrypted.getInputStream(); 315 316 // reset our output stream 317 os.reset(); 318 // write the decrypted data to an output stream 319 // copy the data 320 Util.copyStream(data, os, null); 321 os.close(); 322 323 // original and 'received' message must be the same 324 if (!CryptoUtils.equalsBlock(buffer, os.toByteArray())) 325 throw new RuntimeException("Error: messages are not equal!"); 326 } 327 328 /** 329 * Uses class {@link iaik.smime.SMimeSigned SMimeSigned} and class {@link iaik.smime.SMimeEncrypted SMimeEncrypted} 330 * to sign and encrypt some data, encode it, and finally parses the encoding to decrypt and recover the original content 331 * and verify the signature. 332 * 333 * @param contentEA the content encryption algorithm to be used 334 * @param keyWrapAlg the key wrap algorithm to be used for encrypting the temporary content encryption key 335 * @param keyLength the length of the content encryption key to be created and used 336 * @param recipientIndex the index into the recipientInfos field indicating for which recipient the message 337 * shall be decrypted 338 * 339 * @throws Exception if some error occurs 340 */ 341 public void testSMimeSignedAndEncrypted(AlgorithmID contentEA, AlgorithmID keyWrapAlg, int keyLength, int recipientIndex) throws Exception { 342 343 // repository for the signed and encrypted message 344 byte[] signed_encrpyted_message; 345 // the InputStream containing the data to sign and encrypt 346 InputStream is = new ByteArrayInputStream(buffer); 347 // the OutputStream where the data shall be written to 348 ByteArrayOutputStream os = new ByteArrayOutputStream(); 349 350 // we have to sign and encrypt => connect 2 streams 351 PipedOutputStream piped_out = new PipedOutputStream(); 352 PipedInputStream piped_in = new PipedInputStream(piped_out); 353 354 // create an implicit signed message (signature contains message) 355 SMimeSigned signed = new SMimeSigned(is, SMimeSigned.IMPLICIT); 356 // these certificates are sent within the signature 357 signed.setCertificates(signerCertificates); 358 // add two signers for testing 359 signed.addSigner(signerPrivateKeys[0], 360 new IssuerAndSerialNumber(rsaSignerCertificate)); 361 signed.addSigner(signerPrivateKeys[1], new IssuerAndSerialNumber(dsaSignerCertificate), 362 (AlgorithmID)AlgorithmID.sha256.clone(), 363 (AlgorithmID)AlgorithmID.dsaWithSHA256.clone()); 364 365 366 // a new Thread between the 2 streams 367 Writer writer = new Writer(signed, piped_out); 368 writer.start(); 369 370 // encrypt with DES/CBC and default key length 371 SMimeEncrypted encrypted = new SMimeEncrypted(piped_in, contentEA, keyLength); 372 373 // add one RSA recipient 374 encrypted.addRecipient(recipientCertificates[0], 375 (AlgorithmID)AlgorithmID.rsaEncryption.clone()); 376 // add one ESDH recipient 377 encrypted.addRecipient(recipientCertificates[1], 378 (AlgorithmID)AlgorithmID.esdhKeyAgreement.clone(), 379 keyWrapAlg, 380 keyLength); 381 // encrypt and write the data to the output stream 382 encrypted.writeTo(os); 383 // finished 384 os.close(); 385 // get the signed and encrypted message from the ByteArrayOutputStream 386 signed_encrpyted_message = os.toByteArray(); 387 388 // and now decrypt the data and verify the signature 389 is = new ByteArrayInputStream(signed_encrpyted_message); 390 encrypted = new SMimeEncrypted(is); 391 // use this private key to decrypt the symmetric key 392 encrypted.decryptSymmetricKey(recipientPrivateKeys[recipientIndex], recipientIndex); 393 // get the InputStream with the decrypted data 394 InputStream data_dec = encrypted.getInputStream(); 395 396 // read the signed data from the derypted InputStream 397 signed = new SMimeSigned(data_dec); 398 399 // get the InputStream with the signed, plain data 400 InputStream data = signed.getInputStream(); 401 402 // reset our output stream 403 os.reset(); 404 // write the decrypted and verified data to the output stream 405 // copy the data 406 Util.copyStream(data, os, null); 407 os.close(); 408 409 // now verify the signed data and print the certificate of the signer 410 // (verify() verifies signer at index 0) 411 X509Certificate cert = signed.verify(); 412 System.out.println("Signature OK from: "+cert.getSubjectDN()); 413 // verify our second test signer 414 cert = signed.verify(1); 415 System.out.println("Signature OK from: "+cert.getSubjectDN()); 416 417 // original and 'received' message must be the same 418 if (!CryptoUtils.equalsBlock(buffer, os.toByteArray())) 419 throw new RuntimeException("Error: messages are not equal!"); 420 } 421 422 /** 423 * Uses class {@link iaik.smime.SMimeSigned SMimeSigned} and class {@link iaik.smime.SMimeAuthEncrypted SMimeAuthEncrypted} 424 * to sign and authenticated encrypt some data, encode it, and finally parses the encoding to decrypt and recover the original content 425 * and verify the signature. 426 * 427 * @param contentEA the content-authenticated encryption algorithm to be used 428 * @param keyWrapAlg the key wrap algorithm to be used for encrypting the temporary content encryption key 429 * @param keyLength the length of the content encryption key to be created and used 430 * @param recipientIndex the index into the recipientInfos field indicating for which recipient the message 431 * shall be decrypted 432 * 433 * @throws Exception if some error occurs 434 */ 435 public void testSMimeSignedAndAuthEncrypted(AlgorithmID contentEA, AlgorithmID keyWrapAlg, int keyLength, int recipientIndex) throws Exception { 436 437 // repository for the signed and encrypted message 438 byte[] signed_encrpyted_message; 439 // the InputStream containing the data to sign and encrypt 440 InputStream is = new ByteArrayInputStream(buffer); 441 // the OutputStream where the data shall be written to 442 ByteArrayOutputStream os = new ByteArrayOutputStream(); 443 444 // we have to sign and encrypt => connect 2 streams 445 PipedOutputStream piped_out = new PipedOutputStream(); 446 PipedInputStream piped_in = new PipedInputStream(piped_out); 447 448 // create an implicit signed message (signature contains message) 449 SMimeSigned signed = new SMimeSigned(is, SMimeSigned.IMPLICIT); 450 // these certificates are sent within the signature 451 signed.setCertificates(signerCertificates); 452 // add two signers for testing 453 signed.addSigner(signerPrivateKeys[0], 454 new IssuerAndSerialNumber(rsaSignerCertificate)); 455 signed.addSigner(signerPrivateKeys[1], new IssuerAndSerialNumber(dsaSignerCertificate), 456 (AlgorithmID)AlgorithmID.sha256.clone(), 457 (AlgorithmID)AlgorithmID.dsaWithSHA256.clone()); 458 459 460 // a new Thread between the 2 streams 461 Writer writer = new Writer(signed, piped_out); 462 writer.start(); 463 464 // encrypt with default key length 465 SMimeAuthEncrypted encrypted = new SMimeAuthEncrypted(piped_in, contentEA, keyLength); 466 467 // add one RSA recipient 468 encrypted.addRecipient(recipientCertificates[0], 469 (AlgorithmID)AlgorithmID.rsaEncryption.clone()); 470 // add one ESDH recipient 471 encrypted.addRecipient(recipientCertificates[1], 472 (AlgorithmID)AlgorithmID.esdhKeyAgreement.clone(), 473 keyWrapAlg, 474 keyLength); 475 // encrypt and write the data to the output stream 476 encrypted.writeTo(os); 477 // finished 478 os.close(); 479 // get the signed and encrypted message from the ByteArrayOutputStream 480 signed_encrpyted_message = os.toByteArray(); 481 482 // and now decrypt the data and verify the signature 483 is = new ByteArrayInputStream(signed_encrpyted_message); 484 encrypted = new SMimeAuthEncrypted(is, (byte[])null, -1); 485 486 // use this private key to decrypt the symmetric key 487 encrypted.decryptSymmetricKey(recipientPrivateKeys[recipientIndex], recipientIndex); 488 // get the InputStream with the decrypted data 489 InputStream decryptedIs = encrypted.getInputStream(); 490 491 // read the signed data from the derypted InputStream 492 signed = new SMimeSigned(decryptedIs); 493 494 // get the InputStream with the signed, plain data 495 InputStream data = signed.getInputStream(); 496 497 // reset our output stream 498 os.reset(); 499 // write the decrypted and verified data to the output stream 500 // copy the data 501 Util.copyStream(data, os, null); 502 os.close(); 503 504 // now verify the signed data and print the certificate of the signer 505 // (verify() verifies signer at index 0) 506 X509Certificate cert = signed.verify(); 507 System.out.println("Signature OK from: "+cert.getSubjectDN()); 508 // verify our second test signer 509 cert = signed.verify(1); 510 System.out.println("Signature OK from: "+cert.getSubjectDN()); 511 512 // original and 'received' message must be the same 513 if (!CryptoUtils.equalsBlock(buffer, os.toByteArray())) 514 throw new RuntimeException("Error: messages are not equal!"); 515 } 516 517 /** 518 * Starts the demo. 519 */ 520 public void start() { 521 try { 522 // read keys and certificates from demo keystore 523 setupCertificates(); 524 525 System.out.println("testing an implicit S/MIME signed message..."); 526 testSMimeSigned(SMimeSigned.IMPLICIT); 527 528 System.out.println("testing an explicit S/MIME signed message..."); 529 testSMimeSigned(SMimeSigned.EXPLICIT); 530 531 // DES EDE is deprecated; only demonstrated here 532 AlgorithmID contentEA = (AlgorithmID)AlgorithmID.des_EDE3_CBC.clone(); 533 AlgorithmID keyWrapAlg = (AlgorithmID)AlgorithmID.cms_3DES_wrap.clone(); 534 System.out.println("testing a S/MIME encrypted message for 3DES CBC; decrypting for RSA user..."); 535 testSMimeEncrypted(contentEA, keyWrapAlg, -1, 0); 536 System.out.println("testing a S/MIME encrypted message for 3DES CBC; decrypting for ESDH user..."); 537 testSMimeEncrypted(contentEA, keyWrapAlg, -1, 1); 538 539 // RC2 is deprecated; only demonstrated here 540 contentEA = (AlgorithmID)AlgorithmID.rc2_CBC.clone(); 541 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_rc2_wrap.clone(); 542 System.out.println("testing a S/MIME encrypted message for RC2 CBC; decrypting for RSA user..."); 543 testSMimeEncrypted(contentEA, keyWrapAlg, 128, 0); 544 System.out.println("testing a S/MIME encrypted message for RC2 CBC; decrypting for ESDH user..."); 545 testSMimeEncrypted(contentEA, keyWrapAlg, 128, 1); 546 547 // DES EDE is deprecated; only demonstrated here 548 contentEA = (AlgorithmID)AlgorithmID.des_EDE3_CBC.clone(); 549 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_3DES_wrap.clone(); 550 System.out.println("testing a S/MIME signed and encrypted message for 3DES CBC; decrypting for RSA user..."); 551 testSMimeSignedAndEncrypted(contentEA, keyWrapAlg, -1, 0); 552 System.out.println("testing a S/MIME signed and encrypted message for 3DES CBC; decrypting for ESDH user..."); 553 testSMimeSignedAndEncrypted(contentEA, keyWrapAlg, -1, 1); 554 555 // RC2 is deprecated; only demonstrated here 556 contentEA = (AlgorithmID)AlgorithmID.rc2_CBC.clone(); 557 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_rc2_wrap.clone(); 558 System.out.println("testing a S/MIME signed and encrypted message for RC2 CBC; decrypting for RSA user..."); 559 testSMimeSignedAndEncrypted(contentEA, keyWrapAlg, 128, 0); 560 System.out.println("testing a S/MIME signed and encrypted message for RC2 CBC; decrypting for ESDH user..."); 561 testSMimeSignedAndEncrypted(contentEA, keyWrapAlg, 128, 1); 562 563 contentEA = (AlgorithmID)AlgorithmID.aes128_CBC.clone(); 564 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes128_wrap.clone(); 565 System.out.println("testing a S/MIME encrypted message for AES-128-CBC; decrypting for RSA user..."); 566 testSMimeEncrypted(contentEA, keyWrapAlg, -1, 0); 567 System.out.println("testing a S/MIME encrypted message for AES-128-CBC; decrypting for ESDH user..."); 568 testSMimeEncrypted(contentEA, keyWrapAlg, -1, 1); 569 570 contentEA = (AlgorithmID)AlgorithmID.aes128_CBC.clone(); 571 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes128_wrap.clone(); 572 System.out.println("testing a S/MIME signed and encrypted message for AES-128-CBC; decrypting for RSA user..."); 573 testSMimeSignedAndEncrypted(contentEA, keyWrapAlg, -1, 0); 574 System.out.println("testing a S/MIME signed and encrypted message for AES-128-CBC; decrypting for ESDH user..."); 575 testSMimeSignedAndEncrypted(contentEA, keyWrapAlg, -1, 1); 576 577 contentEA = (AlgorithmID)AlgorithmID.aes192_CBC.clone(); 578 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes192_wrap.clone(); 579 System.out.println("testing a S/MIME encrypted message for AES-192-CBC; decrypting for RSA user..."); 580 testSMimeEncrypted(contentEA, keyWrapAlg, -1, 0); 581 System.out.println("testing a S/MIME encrypted message for AES-192-CBC; decrypting for ESDH user..."); 582 testSMimeEncrypted(contentEA, keyWrapAlg, -1, 1); 583 584 contentEA = (AlgorithmID)AlgorithmID.aes192_CBC.clone(); 585 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes192_wrap.clone(); 586 System.out.println("testing a S/MIME signed and encrypted message for AES-192-CBC; decrypting for RSA user..."); 587 testSMimeSignedAndEncrypted(contentEA, keyWrapAlg, -1, 0); 588 System.out.println("testing a S/MIME signed and encrypted message for AES-192-CBC; decrypting for ESDH user..."); 589 testSMimeSignedAndEncrypted(contentEA, keyWrapAlg, -1, 1); 590 591 contentEA = (AlgorithmID)AlgorithmID.aes256_CBC.clone(); 592 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes256_wrap.clone(); 593 System.out.println("testing a S/MIME encrypted message for AES-256-CBC; decrypting for RSA user..."); 594 testSMimeEncrypted(contentEA, keyWrapAlg, -1, 0); 595 System.out.println("testing a S/MIME encrypted message for AES-256-CBC; decrypting for ESDH user..."); 596 testSMimeEncrypted(contentEA, keyWrapAlg, -1, 1); 597 contentEA = (AlgorithmID)AlgorithmID.aes256_CBC.clone(); 598 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes256_wrap.clone(); 599 System.out.println("testing a S/MIME signed and encrypted message for AES-256-CBC; decrypting for RSA user..."); 600 testSMimeSignedAndEncrypted(contentEA, keyWrapAlg, -1, 0); 601 System.out.println("testing a S/MIME signed and encrypted message for AES-256-CBC; decrypting for ESDH user..."); 602 testSMimeSignedAndEncrypted(contentEA, keyWrapAlg, -1, 1); 603 604 contentEA = (AlgorithmID)AlgorithmID.aes128_GCM.clone(); 605 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes128_wrap.clone(); 606 System.out.println("testing a S/MIME auth encrypted message for AES-128-GCM; decrypting for RSA user..."); 607 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 0); 608 System.out.println("testing a S/MIME auth encrypted message for AES-128-GCM; decrypting for ESDH user..."); 609 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 1); 610 611 contentEA = (AlgorithmID)AlgorithmID.aes192_GCM.clone(); 612 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes192_wrap.clone(); 613 System.out.println("testing a S/MIME auth encrypted message for AES-192-GCM; decrypting for RSA user..."); 614 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 0); 615 System.out.println("testing a S/MIME auth encrypted message for AES-192-GCM; decrypting for ESDH user..."); 616 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 1); 617 618 contentEA = (AlgorithmID)AlgorithmID.aes256_GCM.clone(); 619 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes256_wrap.clone(); 620 System.out.println("testing a S/MIME auth encrypted message for AES-256-GCM; decrypting for RSA user..."); 621 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 0); 622 System.out.println("testing a S/MIME auth encrypted message for AES-256-GCM; decrypting for ESDH user..."); 623 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 1); 624 625 contentEA = (AlgorithmID)AlgorithmID.aes128_CCM.clone(); 626 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes128_wrap.clone(); 627 System.out.println("testing a S/MIME auth encrypted message for AES-128-CCM; decrypting for RSA user..."); 628 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 0); 629 System.out.println("testing a S/MIME auth encrypted message for AES-128-CCM; decrypting for ESDH user..."); 630 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 1); 631 632 contentEA = (AlgorithmID)AlgorithmID.aes192_CCM.clone(); 633 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes192_wrap.clone(); 634 System.out.println("testing a S/MIME auth encrypted message for AES-192-CCM; decrypting for RSA user..."); 635 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 0); 636 System.out.println("testing a S/MIME auth encrypted message for AES-192-CCM; decrypting for ESDH user..."); 637 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 1); 638 639 contentEA = (AlgorithmID)AlgorithmID.aes256_CCM.clone(); 640 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes256_wrap.clone(); 641 System.out.println("testing a S/MIME auth encrypted message for AES-256-CCM; decrypting for RSA user..."); 642 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 0); 643 System.out.println("testing a S/MIME auth encrypted message for AES-256-CCM; decrypting for ESDH user..."); 644 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 1); 645 646 contentEA = (AlgorithmID)AlgorithmID.chacha20Poly1305.clone(); 647 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes256_wrap.clone(); 648 System.out.println("testing a S/MIME auth encrypted message for ChaChaPoly1305; decrypting for RSA user..."); 649 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 0); 650 System.out.println("testing a S/MIME auth encrypted message for ChaChaPoly1305; decrypting for ESDH user..."); 651 testSMimeAuthEncrypted(contentEA, keyWrapAlg, -1, 1); 652 653 contentEA = (AlgorithmID)AlgorithmID.aes128_GCM.clone(); 654 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes128_wrap.clone(); 655 System.out.println("testing a S/MIME signed and auth encrypted message for AES-128-GCM; decrypting for RSA user..."); 656 testSMimeSignedAndAuthEncrypted(contentEA, keyWrapAlg, -1, 0); 657 System.out.println("testing a S/MIME signed and auth encrypted message for AES-128-GCM; decrypting for ESDH user..."); 658 testSMimeSignedAndAuthEncrypted(contentEA, keyWrapAlg, -1, 1); 659 660 contentEA = (AlgorithmID)AlgorithmID.aes192_GCM.clone(); 661 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes192_wrap.clone(); 662 System.out.println("testing a S/MIME signed and auth encrypted message for AES-192-GCM; decrypting for RSA user..."); 663 testSMimeSignedAndAuthEncrypted(contentEA, keyWrapAlg, -1, 0); 664 System.out.println("testing a S/MIME signed and auth encrypted message for AES-192-GCM; decrypting for ESDH user..."); 665 testSMimeSignedAndAuthEncrypted(contentEA, keyWrapAlg, -1, 1); 666 667 contentEA = (AlgorithmID)AlgorithmID.aes256_GCM.clone(); 668 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes256_wrap.clone(); 669 System.out.println("testing a S/MIME signed and auth encrypted message for AES-256-GCM; decrypting for RSA user..."); 670 testSMimeSignedAndAuthEncrypted(contentEA, keyWrapAlg, -1, 0); 671 System.out.println("testing a S/MIME signed and auth encrypted message for AES-256-GCM; decrypting for ESDH user..."); 672 testSMimeSignedAndAuthEncrypted(contentEA, keyWrapAlg, -1, 1); 673 674 contentEA = (AlgorithmID)AlgorithmID.chacha20Poly1305.clone(); 675 keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes256_wrap.clone(); 676 System.out.println("testing a S/MIME signed and auth encrypted message for ChaChaPoly1305; decrypting for RSA user..."); 677 testSMimeSignedAndAuthEncrypted(contentEA, keyWrapAlg, -1, 0); 678 System.out.println("testing a S/MIME signed and auth encrypted message for ChaChaPoly1305; decrypting for ESDH user..."); 679 testSMimeSignedAndAuthEncrypted(contentEA, keyWrapAlg, -1, 1); 680 681 682 } catch (Exception ex) { 683 ex.printStackTrace(); 684 throw new RuntimeException(ex.toString()); 685 } 686 } 687 688 /** 689 * The main method. 690 * Reads the certificates and the private key and then starts the demos. 691 */ 692 public static void main(String[] argv) throws IOException { 693 694 DemoSMimeUtil.initDemos(); 695 (new CMSStreamDemo()).start(); 696 697 System.out.println("\nReady!"); 698 DemoUtil.waitKey(); 699 } 700 701 /** 702 * Inner class for copying data between the 2 streams. 703 */ 704 static class Writer extends Thread { 705 706 SMimeSigned signed; 707 OutputStream os; 708 Exception exception; 709 710 public Writer(SMimeSigned signed, OutputStream os) { 711 super("Writer"); 712 this.signed = signed; 713 this.os = os; 714 } 715 716 /** 717 * Writes the SMimeSinged to the OutputStream. 718 */ 719 public void run() { 720 try { 721 signed.writeTo(os); 722 os.close(); 723 } catch (Exception ex) { 724 exception = ex; 725 System.out.println("Writer exception: "+exception); 726 } 727 } 728 729 /** 730 * Returns a possible exception. 731 */ 732 public Exception getException() { 733 return exception; 734 } 735 } 736}