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/pkcs7cms/PKCS7CMSEncryptedContentInfoDemo.java 25 12.02.25 17:58 Dbratko $ 059 // $Revision: 25 $ 060 // 061 062 package demo.cms.pkcs7cms; 063 064 import iaik.asn1.ASN; 065 import iaik.asn1.ASN1Object; 066 import iaik.asn1.INTEGER; 067 import iaik.asn1.OCTET_STRING; 068 import iaik.asn1.ObjectID; 069 import iaik.asn1.SEQUENCE; 070 import iaik.asn1.structures.AlgorithmID; 071 import iaik.cms.EncryptedContentInfoStream; 072 import iaik.cms.EnvelopedDataStream; 073 import iaik.cms.KeyTransRecipientInfo; 074 import iaik.cms.RecipientInfo; 075 import iaik.cms.SecurityProvider; 076 import iaik.security.random.SecRandom; 077 import iaik.utils.Util; 078 import iaik.x509.X509Certificate; 079 080 import java.io.ByteArrayInputStream; 081 import java.io.ByteArrayOutputStream; 082 import java.io.IOException; 083 import java.io.InputStream; 084 import java.math.BigInteger; 085 import java.security.PrivateKey; 086 import java.security.SecureRandom; 087 import java.security.spec.AlgorithmParameterSpec; 088 089 import javax.crypto.KeyGenerator; 090 import javax.crypto.SecretKey; 091 import javax.crypto.spec.IvParameterSpec; 092 import javax.crypto.spec.RC2ParameterSpec; 093 094 import demo.DemoUtil; 095 import demo.keystore.CMSKeyStore; 096 097 /** 098 * This class demonstrates the EnvelopedDataStream/EncryptedContentInfoStream usages 099 * for algorithms that may require a specific parameter handling. 100 * <p> 101 * This class shows the compatibility to PKCS#7. 102 * <p> 103 * All keys and certificates are read from a keystore created by the 104 * SetupCMSKeyStore program. 105 * <p> 106 * The following algorithms are demonstrated: 107 * <ul> 108 * <li>ARCFOUR: Variable-key-size stream cipher; no parameters to be sent 109 * <li>RC2_CBC: Variable-key-size block cipher; parameters as used by S/MIME: 110 * rc2ParamterVersion and IV; encoded as SEQUENCE: 111 * <pre> 112 * RC2-CBC parameter ::= SEQUENCE { 113 * rc2ParameterVersion INTEGER, 114 * iv OCTET STRING (8)} 115 * 116 * For the effective-key-bits of 40, 64, and 128, the 117 * rc2ParameterVersion values are 160, 120, 58 respectively. 118 * </pre> 119 * <li>CAST5_CBC: Feistel type block cipher with key sizes of 40-128 bit in 8 bit 120 * increments; parameters (RFC 2144): 121 * <pre> 122 * Parameters ::= SEQUENCE { 123 * iv OCTET STRING DEFAULT 0, 124 * keyLength INTEGER } 125 * 126 * </pre> 127 * </ul> 128 * This class shows how an EncryptedContentInfo is explicit created for encrypt�ng 129 * the content and supplying it to an EnvelopedDataStream object. Note that IAIK-CMS 130 * also allows to use EnvelopedData(Stream) for algorithms like RC2, ARCFOUR or CAST in 131 * without having the necessity of explicit key/parameter handling, see {@link 132 * demo.cms.envelopedData.RC2EnvelopedDataDemo RC2EnvelopedDataDemo} for an example. 133 * <p> 134 * Note that the usage of algorithms like RC2 is deprecated but used here for this 135 * demo since it requires a specific parameter handling. 136 */ 137 public class PKCS7CMSEncryptedContentInfoDemo { 138 139 // certificate of user 1 140 X509Certificate user1; 141 // private key of user 1 142 PrivateKey user1_pk; 143 // certificate of user 2 144 X509Certificate user2; 145 // private key of user 2 146 PrivateKey user2_pk; 147 // secure random number generator 148 SecureRandom random; 149 150 /** 151 * Setup the demo certificate chains. 152 * 153 * Keys and certificate are retrieved from the demo KeyStore. 154 * 155 * @throws IOException if an file read error occurs 156 */ 157 public PKCS7CMSEncryptedContentInfoDemo() throws IOException { 158 159 System.out.println(); 160 System.out.println("********************************************************************************************************"); 161 System.out.println("* PKCS7CMSEncryptedContentInfoDemo *"); 162 System.out.println("* (tests the CMS EncryptedContentInfo against the IAIK-JCE PKCS#7 EncryptedContentInfo implementation) *"); 163 System.out.println("********************************************************************************************************"); 164 System.out.println(); 165 166 // add all certificates to the list 167 X509Certificate[] certs = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1); 168 user1 = certs[0]; 169 user1_pk = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_1); 170 user2 = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2)[0]; 171 user2_pk = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_CRYPT_2); 172 173 random = SecRandom.getDefault(); 174 175 176 177 } 178 179 180 /** 181 * Creates a CMS <code>EnvelopedDataStream</code> message. 182 * 183 * @param message the message to be enveloped, as byte representation 184 * @param contentEA the content encryption algorithm 185 * @param keyLength the key length for the symmetric key 186 * @return the DER encoding of the <code>EnvelopedData</code> object just created 187 * @throws Exception if the <code>EnvelopedData</code> object cannot be created 188 */ 189 public byte[] createEnvelopedDataStream(byte[] message, AlgorithmID contentEA, int keyLength) throws Exception { 190 191 SecurityProvider provider = SecurityProvider.getSecurityProvider(); 192 ByteArrayInputStream is = new ByteArrayInputStream(message); 193 194 AlgorithmParameterSpec params = null; 195 SecretKey secretKey = null; 196 197 // create iv 198 byte[] iv = new byte[8]; 199 random.nextBytes(iv); 200 201 int rc2_param = 58; 202 if (contentEA.equals(AlgorithmID.rc2_CBC)) { 203 204 switch (keyLength) { 205 case 40: 206 rc2_param = 160; 207 break; 208 case 64: 209 rc2_param = 120; 210 break; 211 default: // 128 212 rc2_param = 58; 213 keyLength = 128; 214 } 215 // create the paramters (SEQUENCE) to be sent 216 SEQUENCE parameter = new SEQUENCE(); 217 parameter.addComponent(new INTEGER(rc2_param)); 218 parameter.addComponent(new OCTET_STRING(iv)); 219 contentEA.setParameter(parameter); 220 params = new RC2ParameterSpec(keyLength,iv); 221 } else if (contentEA.equals(AlgorithmID.arcfour)){ 222 // no params for ARCFOUR 223 params = null; 224 } else if (contentEA.equals(AlgorithmID.cast5_CBC)) { 225 SEQUENCE parameter = new SEQUENCE(); 226 parameter.addComponent(new OCTET_STRING(iv)); 227 parameter.addComponent(new INTEGER(keyLength)); 228 contentEA.setParameter(parameter); 229 params = new IvParameterSpec(iv); 230 231 } else { 232 throw new Exception("Algorithm " + contentEA + " not supportted for this test!"); 233 } 234 235 KeyGenerator keyGen = provider.getKeyGenerator(contentEA, keyLength); 236 // generate a new key 237 secretKey = keyGen.generateKey(); 238 239 // create the EncryptedContentInfo for the content to be encrypted 240 EncryptedContentInfoStream eci = new EncryptedContentInfoStream(ObjectID.pkcs7_data, is); 241 // setup the cipher for encryption 242 eci.setupCipher(contentEA, secretKey, params); 243 244 // create the recipient infos 245 RecipientInfo[] recipients = new RecipientInfo[2]; 246 // user1 is the first receiver 247 recipients[0] = new KeyTransRecipientInfo(user1, (AlgorithmID)AlgorithmID.rsaEncryption.clone()); 248 // encrypt the secret key for recipient 1 249 recipients[0].encryptKey(secretKey); 250 // user2 is the second receiver 251 recipients[1] = new KeyTransRecipientInfo(user2, (AlgorithmID)AlgorithmID.rsaEncryption.clone()); 252 // encrypt the secret key for recipient 2 253 recipients[1].encryptKey(secretKey); 254 // now create the EnvelopedDataStream 255 EnvelopedDataStream enveloped_data = new EnvelopedDataStream(recipients, eci); 256 257 // return the EnvelopedDate as DER encoded byte array with block size 2048 258 ByteArrayOutputStream os = new ByteArrayOutputStream(); 259 enveloped_data.writeTo(os, 2048); 260 byte[] enc = os.toByteArray(); 261 return enc; 262 263 } 264 265 /** 266 * Decrypts the encrypted content of the given CMS <code>EnvelopedData</code> object for the 267 * specified recipient and returns the decrypted (= original) message. 268 * 269 * @param encoding the <code>EnvelopedData</code> object as DER encoded byte array 270 * @param privateKey the private key to decrypt the message 271 * @param recipientInfoIndex the index into the <code>RecipientInfo</code> array 272 * to which the specified private key belongs 273 * 274 * @return the recovered message, as byte array 275 * @throws Exception if the message cannot be recovered 276 */ 277 public byte[] getEnvelopedDataStream(byte[] encoding, PrivateKey privateKey, int recipientInfoIndex) throws Exception { 278 279 // create the EnvelopedData object from a DER encoded byte array 280 // we are testing the stream interface 281 ByteArrayInputStream is = new ByteArrayInputStream(encoding); 282 EnvelopedDataStream enveloped_data = new EnvelopedDataStream(is); 283 284 AlgorithmParameterSpec params = null; 285 // get the recipient infos 286 RecipientInfo[] recipients = enveloped_data.getRecipientInfos(); 287 288 System.out.println("\nThis message can be decrypted by the owners of the following certificates:"); 289 290 for (int i=0; i<recipients.length; i++) { 291 System.out.println("Recipient "+(i+1)+":"); 292 System.out.println(recipients[i].getRecipientIdentifiers()[0]); 293 } 294 // decrypt symmetric content encryption key, e.g.: 295 SecretKey secretKey = recipients[recipientInfoIndex].decryptKey(user1_pk); 296 297 //get the ECI from the enveloped data: 298 EncryptedContentInfoStream eci = (EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo(); 299 //get the content encryption algorithm: 300 AlgorithmID contentEA = eci.getContentEncryptionAlgorithm(); 301 System.out.println("Content Encryption Algorithm: " + contentEA); 302 if (contentEA.equals(AlgorithmID.rc2_CBC)) { 303 // get the parameters as SEQUENCE 304 SEQUENCE seq = (SEQUENCE)contentEA.getParameter(); 305 // the iv is the second component 306 OCTET_STRING oct = (OCTET_STRING)seq.getComponentAt(1); 307 // create an IvParameterSpec: 308 //params = new IvParameterSpec((byte[])oct.getValue()); 309 int rc2ParameterVersion = ((BigInteger)seq.getComponentAt(0).getValue()).intValue(); 310 int effective_key_bits = 32; 311 switch (rc2ParameterVersion) { 312 case 160: 313 effective_key_bits = 40; 314 break; 315 case 120: 316 effective_key_bits = 64; 317 break; 318 case 58: 319 effective_key_bits = 128; 320 break; 321 default: 322 throw new Exception("Invalid rc2ParameterVersion " + rc2ParameterVersion + "!"); 323 324 } 325 params = new RC2ParameterSpec(effective_key_bits,(byte[])seq.getComponentAt(1).getValue()); 326 327 } 328 else if (contentEA.equals(AlgorithmID.rc5_CBC)) { 329 OCTET_STRING oct = (OCTET_STRING)contentEA.getParameter(); 330 // create an IvParameterSpec: 331 params = new IvParameterSpec((byte[])oct.getValue()); 332 } else if (contentEA.equals(AlgorithmID.arcfour)) { 333 params = null; 334 } else if (contentEA.equals(AlgorithmID.cast5_CBC)) { 335 // get the parameters 336 ASN1Object asn1Params = contentEA.getParameter(); 337 if (asn1Params.isA(ASN.SEQUENCE)) { 338 // the iv is the first component 339 params = new IvParameterSpec((byte[])asn1Params.getComponentAt(0).getValue()); 340 } else { 341 // to be compatible with (invalid) CAST AlgorithmIDs only using the IV as parameters 342 params = new IvParameterSpec((byte[])asn1Params.getValue()); 343 } 344 } else { 345 throw new Exception("Algorithm " + contentEA + " not supportted for this test!"); 346 } 347 348 349 //now setup the cipher with previously decrypted recipient key amd params 350 eci.setupCipher(secretKey, params); 351 //get and read the data thereby actually performing the decryption 352 InputStream data_is = eci.getInputStream(); 353 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 354 Util.copyStream(data_is, baos, null); 355 byte[] decrypted = baos.toByteArray(); 356 return decrypted; 357 358 } 359 360 // PKCS#7 361 362 363 /** 364 * Creates a PKCS#7 <code>EnvelopedDataStream</code> message. 365 * <p> 366 * The enveloped-data content type consists of encrypted content of any 367 * type and encrypted content-encryption keys for one or more recipients. 368 * The combination of encrypted content and encrypted content-encryption 369 * key for a recipient is a "digital envelope" for that recipient. Any type 370 * of content can be enveloped for any number of recipients in parallel. 371 * 372 * @param message the message to be enveloped, as byte representation 373 * @param cea the content encryption algorithm 374 * @param keyLength the key length for the symmetric key 375 * @return the DER encoding of the <code>EnvelopedData</code> object just created 376 * @throws Exception if the <code>EnvelopedData</code> object cannot 377 * be created 378 */ 379 public byte[] createPKCS7EnvelopedDataStream(byte[] message, AlgorithmID cea, int keyLength) throws Exception { 380 381 SecurityProvider provider = SecurityProvider.getSecurityProvider(); 382 ByteArrayInputStream is = new ByteArrayInputStream(message); 383 AlgorithmID contentEA = (AlgorithmID)cea.clone(); 384 AlgorithmParameterSpec params = null; 385 KeyGenerator key_gen = null; 386 SecretKey secretKey = null; 387 388 // create iv 389 byte[] iv = new byte[8]; 390 random.nextBytes(iv); 391 392 int rc2_param = 58; 393 if (contentEA.equals(AlgorithmID.rc2_CBC)) { 394 switch (keyLength) { 395 case 40: 396 rc2_param = 160; 397 break; 398 case 64: 399 rc2_param = 120; 400 break; 401 default: // 128 402 rc2_param = 58; 403 keyLength = 128; 404 } 405 // create the paramters (SEQUENCE) to be sent 406 SEQUENCE parameter = new SEQUENCE(); 407 parameter.addComponent(new INTEGER(rc2_param)); 408 parameter.addComponent(new OCTET_STRING(iv)); 409 contentEA.setParameter(parameter); 410 params = new RC2ParameterSpec(keyLength,iv); 411 } else if (contentEA.equals(AlgorithmID.arcfour)){ 412 // no params for ARCFOUR 413 params = null; 414 } else if (contentEA.equals(AlgorithmID.cast5_CBC)) { 415 416 SEQUENCE parameter = new SEQUENCE(); 417 parameter.addComponent(new OCTET_STRING(iv)); 418 parameter.addComponent(new INTEGER(keyLength)); 419 contentEA.setParameter(parameter); 420 params = new IvParameterSpec(iv); 421 422 } else { 423 throw new Exception("Algorithm " + contentEA + " not supportted for this test!"); 424 } 425 426 KeyGenerator keyGen = provider.getKeyGenerator(contentEA, keyLength); 427 // generate a new key 428 secretKey = keyGen.generateKey(); 429 430 // create the EncryptedContentInfo for the content to be encrypted 431 iaik.pkcs.pkcs7.EncryptedContentInfoStream eci = new iaik.pkcs.pkcs7.EncryptedContentInfoStream(ObjectID.pkcs7_data, is); 432 // setup the cipher for encryption 433 eci.setupCipher(contentEA, secretKey, params); 434 435 // create the recipient infos 436 iaik.pkcs.pkcs7.RecipientInfo[] recipients = new iaik.pkcs.pkcs7.RecipientInfo[2]; 437 // user1 is the first receiver 438 recipients[0] = new iaik.pkcs.pkcs7.RecipientInfo(user1, (AlgorithmID)AlgorithmID.rsaEncryption.clone()); 439 // encrypt the secret key for recipient 1 440 recipients[0].encryptKey(secretKey); 441 // user2 is the second receiver 442 recipients[1] = new iaik.pkcs.pkcs7.RecipientInfo(user2, (AlgorithmID)AlgorithmID.rsaEncryption.clone()); 443 // encrypt the secret key for recipient 2 444 recipients[1].encryptKey(secretKey); 445 // now create the EnvelopedDataStream 446 iaik.pkcs.pkcs7.EnvelopedDataStream enveloped_data = 447 new iaik.pkcs.pkcs7.EnvelopedDataStream(recipients, eci); 448 449 // return the EnvelopedDate as DER encoded byte array with block size 2048 450 ByteArrayOutputStream os = new ByteArrayOutputStream(); 451 enveloped_data.writeTo(os, 2048); 452 byte[] enc = os.toByteArray(); 453 return enc; 454 455 } 456 457 /** 458 * Decrypts the encrypted content of the given PKCS#7 <code>EnvelopedData</code> object for the 459 * specified recipient and returns the decrypted (= original) message. 460 * 461 * @param encoding the <code>EnvelopedData</code> object as DER encoded byte array 462 * @param privateKey the private key to decrypt the message 463 * @param recipientInfoIndex the index into the <code>RecipientInfo</code> array 464 * to which the specified private key belongs 465 * 466 * @return the recovered message, as byte array 467 * @throws Exception if the message cannot be recovered 468 */ 469 public byte[] getPKCS7EnvelopedDataStream(byte[] encoding, PrivateKey privateKey, int recipientInfoIndex) throws Exception { 470 471 // create the EnvelopedData object from a DER encoded byte array 472 // we are testing the stream interface 473 ByteArrayInputStream is = new ByteArrayInputStream(encoding); 474 iaik.pkcs.pkcs7.EnvelopedDataStream enveloped_data = new iaik.pkcs.pkcs7.EnvelopedDataStream(is); 475 476 AlgorithmParameterSpec params = null; 477 // get the recipient infos 478 iaik.pkcs.pkcs7.RecipientInfo[] recipients = enveloped_data.getRecipientInfos(); 479 480 System.out.println("\nThis message can be decrypted by the owners of the following certificates:"); 481 482 for (int i=0; i<recipients.length; i++) { 483 System.out.println("Recipient "+(i+1)+":"); 484 System.out.println(recipients[i].getIssuerAndSerialNumber()); 485 } 486 // decrypt symmetric content encryption key, e.g.: 487 SecretKey secretKey = recipients[recipientInfoIndex].decryptKey(user1_pk); 488 489 //get the ECI from the enveloped data: 490 iaik.pkcs.pkcs7.EncryptedContentInfoStream eci = (iaik.pkcs.pkcs7.EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo(); 491 //get the content encryption algorithm: 492 AlgorithmID contentEA = eci.getContentEncryptionAlgorithm(); 493 System.out.println("Content Encryption Algorithm: " + contentEA); 494 if (contentEA.equals(AlgorithmID.rc2_CBC)) { 495 // get the parameters as SEQUENCE 496 SEQUENCE seq = (SEQUENCE)contentEA.getParameter(); 497 // the iv is the second component 498 OCTET_STRING oct = (OCTET_STRING)seq.getComponentAt(1); 499 // create an IvParameterSpec: 500 //params = new IvParameterSpec((byte[])oct.getValue()); 501 int rc2ParameterVersion = ((BigInteger)seq.getComponentAt(0).getValue()).intValue(); 502 int effective_key_bits = 32; 503 switch (rc2ParameterVersion) { 504 case 160: 505 effective_key_bits = 40; 506 break; 507 case 120: 508 effective_key_bits = 64; 509 break; 510 case 58: 511 effective_key_bits = 128; 512 break; 513 default: 514 throw new Exception("Invalid rc2ParameterVersion " + rc2ParameterVersion + "!"); 515 516 } 517 params = new RC2ParameterSpec(effective_key_bits,(byte[])seq.getComponentAt(1).getValue()); 518 519 } 520 else if (contentEA.equals(AlgorithmID.rc5_CBC)) { 521 OCTET_STRING oct = (OCTET_STRING)contentEA.getParameter(); 522 // create an IvParameterSpec: 523 params = new IvParameterSpec((byte[])oct.getValue()); 524 } else if (contentEA.equals(AlgorithmID.arcfour)) { 525 params = null; 526 } else if (contentEA.equals(AlgorithmID.cast5_CBC)) { 527 // get the parameters 528 ASN1Object asn1Params = contentEA.getParameter(); 529 if (asn1Params.isA(ASN.SEQUENCE)) { 530 // the iv is the first component 531 params = new IvParameterSpec((byte[])asn1Params.getComponentAt(0).getValue()); 532 } else { 533 // to be compatible with (invalid) CAST AlgorithmIDs only using the IV as parameters 534 params = new IvParameterSpec((byte[])asn1Params.getValue()); 535 } 536 } else { 537 throw new Exception("Algorithm " + contentEA + " not supportted for this test!"); 538 } 539 540 541 //now setup the cipher with previously decrypted recipient key amd params 542 eci.setupCipher(secretKey, params); 543 //get and read the data thereby actually performing the decryption 544 InputStream data_is = eci.getInputStream(); 545 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 546 Util.copyStream(data_is, baos, null); 547 byte[] decrypted = baos.toByteArray(); 548 return decrypted; 549 550 } 551 552 553 554 /** 555 * Starts the test. 556 */ 557 public void start() { 558 // the test message 559 String m = "This is the test message."; 560 System.out.println("Test message: \""+m+"\""); 561 System.out.println(); 562 byte[] message = m.getBytes(); 563 564 try { 565 byte[] data; 566 byte[] received_message = null; 567 568 569 // the stream implementation 570 // 571 // test CMS EnvelopedDataStream 572 // 573 574 // ARCFOUR 575 System.out.println("\nEnvelopedDataStream demo for algorithm ARCFOUR [create]:\n"); 576 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.arcfour.clone(), 128); 577 // transmit data 578 System.out.println("\nEnvelopedDataStream demo [parse]:\n"); 579 // user1 means index 0 (hardcoded for this demo) 580 received_message = getEnvelopedDataStream(data, user1_pk, 0); 581 System.out.print("\nDecrypted content: "); 582 System.out.println(new String(received_message)); 583 584 // RC2 585 System.out.println("\nEnvelopedDataStream demo for algorithm RC2 [create]:\n"); 586 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.rc2_CBC.clone(), 128); 587 // transmit data 588 System.out.println("\nEnvelopedDataStream demo [parse]:\n"); 589 // user1 means index 0 (hardcoded for this demo) 590 received_message = getEnvelopedDataStream(data, user1_pk, 0); 591 System.out.print("\nDecrypted content: "); 592 System.out.println(new String(received_message)); 593 594 // CAST5_CBC 595 System.out.println("\nEnvelopedDataStream demo for algorithm CAST5_CBC [create]:\n"); 596 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.cast5_CBC.clone(), 128); 597 // transmit data 598 System.out.println("\nEnvelopedDataStream demo [parse]:\n"); 599 // user1 means index 0 (hardcoded for this demo) 600 received_message = getEnvelopedDataStream(data, user1_pk, 0); 601 System.out.print("\nDecrypted content: "); 602 System.out.println(new String(received_message)); 603 604 // CMS <---> PKCS#7 605 606 System.out.println("Test compatibility to PKCS#7...."); 607 608 // ARCFOUR 609 System.out.println("\nCMS EnvelopedDataStream demo for algorithm ARCFOUR [create]:\n"); 610 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.arcfour.clone(), 128); 611 // transmit data 612 System.out.println("\nPKCS#7 EnvelopedDataStream demo [parse]:\n"); 613 // user1 means index 0 (hardcoded for this demo) 614 received_message = getPKCS7EnvelopedDataStream(data, user1_pk, 0); 615 System.out.print("\nDecrypted content: "); 616 System.out.println(new String(received_message)); 617 618 System.out.println("\nPKCS#7 EnvelopedDataStream demo for algorithm ARCFOUR [create]:\n"); 619 data = createPKCS7EnvelopedDataStream(message, (AlgorithmID)AlgorithmID.arcfour.clone(), 128); 620 // transmit data 621 System.out.println("\nCMS EnvelopedDataStream demo [parse]:\n"); 622 // user1 means index 0 (hardcoded for this demo) 623 received_message = getEnvelopedDataStream(data, user1_pk, 0); 624 System.out.print("\nDecrypted content: "); 625 System.out.println(new String(received_message)); 626 627 628 // RC2 629 System.out.println("\nCMS EnvelopedDataStream demo for algorithm RC2 [create]:\n"); 630 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.rc2_CBC.clone(), 128); 631 // transmit data 632 System.out.println("\nPKCS#7 EnvelopedDataStream demo [parse]:\n"); 633 // user1 means index 0 (hardcoded for this demo) 634 received_message = getPKCS7EnvelopedDataStream(data, user1_pk, 0); 635 System.out.print("\nDecrypted content: "); 636 System.out.println(new String(received_message)); 637 638 System.out.println("\nPKCS#7 EnvelopedDataStream demo for algorithm RC2 [create]:\n"); 639 data = createPKCS7EnvelopedDataStream(message, (AlgorithmID)AlgorithmID.rc2_CBC.clone(), 128); 640 // transmit data 641 System.out.println("\nCMS EnvelopedDataStream demo [parse]:\n"); 642 // user1 means index 0 (hardcoded for this demo) 643 received_message = getEnvelopedDataStream(data, user1_pk, 0); 644 System.out.print("\nDecrypted content: "); 645 System.out.println(new String(received_message)); 646 647 // CAST5_CBC 648 System.out.println("\nCMS EnvelopedDataStream demo for algorithm CAST5_CBC [create]:\n"); 649 data = createEnvelopedDataStream(message, (AlgorithmID)AlgorithmID.cast5_CBC.clone(), 128); 650 // transmit data 651 System.out.println("\nPKCS#7 EnvelopedDataStream demo [parse]:\n"); 652 // user1 means index 0 (hardcoded for this demo) 653 received_message = getPKCS7EnvelopedDataStream(data, user1_pk, 0); 654 System.out.print("\nDecrypted content: "); 655 System.out.println(new String(received_message)); 656 657 System.out.println("\nPKCS#7 EnvelopedDataStream demo for algorithm CAST5_CBC [create]:\n"); 658 data = createPKCS7EnvelopedDataStream(message, (AlgorithmID)AlgorithmID.cast5_CBC.clone(), 128); 659 // transmit data 660 System.out.println("\nCMS EnvelopedDataStream demo [parse]:\n"); 661 // user1 means index 0 (hardcoded for this demo) 662 received_message = getEnvelopedDataStream(data, user1_pk, 0); 663 System.out.print("\nDecrypted content: "); 664 System.out.println(new String(received_message)); 665 666 } catch (Exception ex) { 667 ex.printStackTrace(); 668 throw new RuntimeException(ex.toString()); 669 } 670 } 671 672 /** 673 * The main method. 674 * 675 * @throws IOException 676 * if an I/O error occurs when reading required keys 677 * and certificates from files 678 */ 679 public static void main(String argv[]) throws Exception { 680 681 DemoUtil.initDemos(); 682 683 (new PKCS7CMSEncryptedContentInfoDemo()).start(); 684 System.out.println("\nReady!"); 685 DemoUtil.waitKey(); 686 } 687 }