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/signedData/CounterSignatureDemo.java 30 12.02.25 17:58 Dbratko $ 059 // $Revision: 30 $ 060 // 061 062 package demo.cms.signedData; 063 064 import iaik.asn1.CodingException; 065 import iaik.asn1.ObjectID; 066 import iaik.asn1.structures.AlgorithmID; 067 import iaik.asn1.structures.Attribute; 068 import iaik.asn1.structures.AttributeValue; 069 import iaik.cms.CMSException; 070 import iaik.cms.ContentInfo; 071 import iaik.cms.ContentInfoStream; 072 import iaik.cms.IssuerAndSerialNumber; 073 import iaik.cms.SignedData; 074 import iaik.cms.SignedDataStream; 075 import iaik.cms.SignerInfo; 076 import iaik.cms.attributes.CMSContentType; 077 import iaik.cms.attributes.CounterSignature; 078 import iaik.cms.attributes.SigningTime; 079 import iaik.utils.Util; 080 import iaik.x509.X509Certificate; 081 082 import java.io.ByteArrayInputStream; 083 import java.io.ByteArrayOutputStream; 084 import java.io.IOException; 085 import java.io.InputStream; 086 import java.security.NoSuchAlgorithmException; 087 import java.security.PrivateKey; 088 import java.security.SignatureException; 089 090 import demo.DemoUtil; 091 import demo.keystore.CMSKeyStore; 092 093 /** 094 * This class demonstrates the usage of the CounterSignature attribute. 095 * <p> 096 * A {@link iaik.cms.attributes.CounterSignature CounterSignature} attribute may be included 097 * as an unsigned attribute into a {@link iaik.cms.SignerInfo SignerInfo} for counter signing 098 * (signing in serial) the signature value of a SignerInfo included in a SignedData. The value 099 * of a CounterSignature attribute itself is a SignerInfo. 100 * <p> 101 * This demo shows how a CounterSignature attribute may be added to some SignerInfo that belongs 102 * to a SignedData object just parsed/verified. This class demonstrates adding/verifying of a 103 * CounterSignature attribute to both the {@link iaik.cms.SignedDataStream stream} and the 104 * {@link iaik.cms.SignedData non-stream} implementations of the SignedData type. Since when 105 * parsing an implicit -- where the content is included -- SignedData object, SignerInfos 106 * can not accessed before the data has been processed, adding a counter signature to 107 * a {@link iaik.cms.SignedDataStream SignedDataStream} may require a different proceeding 108 * than adding it to a {@link iaik.cms.SignedData SignedData} object. For that reason a 109 * {@link CounterSignatureListener CounterSignatureListener} is used for the 110 * stream demos to listen on and add the counter signature during the encoding process. 111 * 112 * @see CounterSignatureListener 113 * @see iaik.cms.attributes.CounterSignature 114 * @see iaik.cms.SDSEncodeListener 115 * @see iaik.cms.SignedDataStream 116 * @see iaik.cms.SignerInfo 117 */ 118 public class CounterSignatureDemo { 119 120 byte[] message; 121 122 // signing certificate of user 1 123 X509Certificate user1_sign; 124 // signing private key of user 1 125 PrivateKey user1_sign_pk; 126 // signing certificate of user 2 (counter signer) 127 X509Certificate user2_sign; 128 // signing private key of user 2 (counter signer) 129 PrivateKey user2_sign_pk; 130 131 // a certificate chain containing the user certs + CA 132 X509Certificate[] certificates; 133 134 /** 135 * Constructor. 136 * Reads required keys/certs from the demo keystore. 137 */ 138 public CounterSignatureDemo() { 139 140 System.out.println(); 141 System.out.println("**********************************************************************************"); 142 System.out.println("* CounterSignatureDemo demo *"); 143 System.out.println("* (shows the usage of the CounterSignature attribute implementation) *"); 144 System.out.println("**********************************************************************************"); 145 System.out.println(); 146 147 message = "This is a test of the CMS implementation!".getBytes(); 148 // signing certs 149 certificates = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1); 150 user1_sign = certificates[0]; 151 user1_sign_pk = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1); 152 user2_sign = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1)[0]; 153 user2_sign_pk = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1); 154 } 155 156 /** 157 * Creates a CMS <code>SignedData</code> object. 158 * <p> 159 * 160 * @param message the message to be signed, as byte representation 161 * @param mode the mode indicating whether to include the content 162 * (SignedDataStream.IMPLICIT) or not (SignedDataStream.EXPLICIT) 163 * @return the encoding of the <code>SignedData</code> object just created 164 * @throws Exception if the <code>SignedData</code> object cannot 165 * be created for some reason 166 */ 167 public byte[] createSignedDataStream(byte[] message, int mode) throws Exception { 168 169 System.out.println("Create a new message signed by user 1:"); 170 171 // we are testing the stream interface 172 ByteArrayInputStream is = new ByteArrayInputStream(message); 173 // create a new SignedData object which includes the data 174 SignedDataStream signed_data = new SignedDataStream(is, mode); 175 176 // SignedData shall include the certificate chain for verifying 177 signed_data.setCertificates(certificates); 178 179 // cert at index 0 is the user certificate 180 IssuerAndSerialNumber issuer = new IssuerAndSerialNumber(user1_sign); 181 182 // create a new SignerInfo 183 SignerInfo signer_info = new SignerInfo(issuer, (AlgorithmID)AlgorithmID.sha256.clone(), user1_sign_pk); 184 // create some authenticated attributes 185 // the message digest attribute is automatically added 186 Attribute[] attributes = new Attribute[2]; 187 // content type is data 188 attributes[0] = new Attribute(new CMSContentType(ObjectID.cms_data)); 189 // signing time is now 190 attributes[1] = new Attribute(new SigningTime()); 191 // set the attributes 192 signer_info.setSignedAttributes(attributes); 193 // finish the creation of SignerInfo by calling method addSigner 194 try { 195 signed_data.addSignerInfo(signer_info); 196 197 } catch (NoSuchAlgorithmException ex) { 198 throw new CMSException("No implementation for signature algorithm: "+ex.getMessage()); 199 } 200 // ensure block encoding 201 signed_data.setBlockSize(2048); 202 203 // write the data through SignedData to any out-of-band place 204 if (mode == SignedDataStream.EXPLICIT) { 205 InputStream data_is = signed_data.getInputStream(); 206 byte[] buf = new byte[1024]; 207 int r; 208 while ((r = data_is.read(buf)) > 0) { 209 ; // skip data 210 } 211 } 212 213 // return the SignedData as encoded byte array with block size 2048 214 ByteArrayOutputStream os = new ByteArrayOutputStream(); 215 // wrap into ContentInfo 216 ContentInfoStream ci = new ContentInfoStream(signed_data); 217 ci.writeTo(os); 218 return os.toByteArray(); 219 } 220 221 /** 222 * Parses a CMS <code>SignedData</code> object and verifies the signatures 223 * for all participated signers. 224 * 225 * @param signedData the SignedData, as BER encoded byte array 226 * @param message the the message which was transmitted out-of-band (explicit signed) 227 * @param counterSign whether to use a SDSEncodeListener to add a SignerInfo 228 * and encode the SignedData again 229 * 230 * @return the inherent message as byte array, or the BER encoded SignedData if 231 * it shall be encoded again (counter signing phase) 232 * @throws Exception if an error occurs 233 */ 234 public byte[] getSignedDataStream(byte[] signedData, byte[] message, boolean counterSign) 235 throws Exception { 236 237 // we are testing the stream interface 238 ByteArrayInputStream is = new ByteArrayInputStream(signedData); 239 240 // the ByteArrayOutputStream to which to write the content 241 ByteArrayOutputStream os = new ByteArrayOutputStream(); 242 243 SignedDataStream signed_data = new SignedDataStream(is); 244 245 // content included (implicit mode)? 246 boolean implicit = (signed_data.getMode() == SignedDataStream.IMPLICIT); 247 248 if (implicit == false) { 249 // in explicit mode explicitly supply the content for hash computation 250 signed_data.setInputStream(new ByteArrayInputStream(message)); 251 } 252 253 254 if (counterSign) { 255 // we want to write the SignedData again 256 // we add a counter signature attribute to the first signer 257 258 // add the CounterSignature via SDSEncodeListener 259 CounterSignatureListener csl = 260 new CounterSignatureListener(new IssuerAndSerialNumber(user2_sign), 261 (AlgorithmID)AlgorithmID.sha256.clone(), 262 user2_sign_pk); 263 // we only want to counter sign some specific signer 264 csl.setCertOfSignerToBeCounterSigned(user1_sign); 265 266 if (implicit) { 267 // in implicit mode copy data to os 268 csl.setOutputStream(os); 269 signed_data.setSDSEncodeListener(csl); 270 271 } else { 272 signed_data.setSDSEncodeListener(csl); 273 // get an InputStream for reading the signed content 274 InputStream data = signed_data.getInputStream(); 275 Util.copyStream(data, os, null); 276 } 277 278 // ensure block encoding 279 signed_data.setBlockSize(2048); 280 // return the SignedData as encoded byte array with block size 2048 281 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 282 // wrap into ContentInfo 283 ContentInfoStream ci = new ContentInfoStream(signed_data); 284 ci.writeTo(baos); 285 286 // we read the content 287 byte[] content = os.toByteArray(); 288 System.out.println("Content: " + new String(content)); 289 290 // return encoded SignedData 291 return baos.toByteArray(); 292 293 } else { 294 295 // get an InputStream for reading the signed content 296 InputStream data = signed_data.getInputStream(); 297 os = new ByteArrayOutputStream(); 298 Util.copyStream(data, os, null); 299 300 System.out.println("SignedData contains the following signer information:"); 301 SignerInfo[] signer_infos = signed_data.getSignerInfos(); 302 303 int numberOfSignerInfos = signer_infos.length; 304 if (numberOfSignerInfos == 0) { 305 String warning = "Warning: Unsigned message (no SignerInfo included)!"; 306 System.err.println(warning); 307 throw new CMSException(warning); 308 } else { 309 for (int i = 0; i < numberOfSignerInfos; i++) { 310 try { 311 // verify the signed data using the SignerInfo at index i 312 X509Certificate signer_cert = signed_data.verify(i); 313 // if the signature is OK the certificate of the signer is returned 314 System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN()); 315 // get signed attributes 316 // signing time 317 SigningTime signingTime = (SigningTime)signer_infos[i].getSignedAttributeValue(ObjectID.signingTime); 318 if (signingTime != null) { 319 System.out.println("This message has been signed at " + signingTime.get()); 320 } 321 // content type 322 CMSContentType contentType = (CMSContentType)signer_infos[i].getSignedAttributeValue(ObjectID.contentType); 323 if (contentType != null) { 324 System.out.println("The content has CMS content type " + contentType.get().getName()); 325 } 326 // counter signature? 327 Attribute counterSignatureAttribute = signer_infos[i].getUnsignedAttribute(ObjectID.countersignature); 328 if (counterSignatureAttribute != null) { 329 AttributeValue[] counterSignatures = counterSignatureAttribute.getAttributeValues(); 330 System.out.println("This SignerInfo is counter signed from: "); 331 for (int j = 0; j < counterSignatures.length; j++) { 332 CounterSignature counterSignature = (CounterSignature)counterSignatures[j]; 333 try { 334 if (counterSignature.verify(user2_sign.getPublicKey(), signer_infos[i])) { 335 System.out.println("Signature OK from counter signer: "+counterSignature.getSignerIdentifier()); 336 } else { 337 System.out.println("Signature ERROR from counter signer: "+counterSignature.getSignerIdentifier()); 338 } 339 } catch (SignatureException ex) { 340 System.out.println("Signature ERROR from counter signer: "+counterSignature.getSignerIdentifier()); 341 throw new CMSException(ex.toString()); 342 } 343 signingTime = (SigningTime)counterSignature.getSignedAttributeValue(ObjectID.signingTime); 344 if (signingTime != null) { 345 System.out.println("Counter signature has been created " + signingTime.get()); 346 } 347 } 348 } 349 350 } catch (SignatureException ex) { 351 // if the signature is not OK a SignatureException is thrown 352 System.err.println("Signature ERROR from signer: "+signed_data.getCertificate((signer_infos[i].getSignerIdentifier())).getSubjectDN()); 353 throw new CMSException(ex.toString()); 354 } catch (CodingException ex) { 355 throw new CMSException("Attribute decoding error: " + ex.toString()); 356 } 357 } 358 // in practice we also would validate the signer certificate(s) 359 } 360 361 // return content 362 return os.toByteArray(); 363 } 364 } 365 366 367 /** 368 * Creates a CMS <code>SignedData</code> object. 369 * <p> 370 * 371 * @param message the message to be signed, as byte representation 372 * @param mode the mode indicating whether to include the content 373 * (SignedDataStream.IMPLICIT) or not (SignedDataStream.EXPLICIT) 374 * @return the encoding of the <code>SignedData</code> object just created 375 * @throws CMSException if the <code>SignedData</code> object cannot 376 * be created 377 * @throws Exception if an error occurs 378 */ 379 public byte[] createSignedData(byte[] message, int mode) throws Exception { 380 381 System.out.println("Create a new message signed by user 1:"); 382 383 // create a new SignedData object 384 SignedData signed_data = new SignedData(message, mode); 385 386 // SignedData shall include the certificate chain for verifying 387 signed_data.setCertificates(certificates); 388 389 // cert at index 0 is the user certificate 390 IssuerAndSerialNumber issuer = new IssuerAndSerialNumber(user1_sign); 391 392 // create a new SignerInfo 393 SignerInfo signer_info = new SignerInfo(issuer, (AlgorithmID)AlgorithmID.sha256.clone(), user1_sign_pk); 394 // create some authenticated attributes 395 // the message digest attribute is automatically added 396 Attribute[] attributes = new Attribute[2]; 397 // content type is data 398 attributes[0] = new Attribute(new CMSContentType(ObjectID.cms_data)); 399 // signing time is now 400 attributes[1] = new Attribute(new SigningTime()); 401 // set the attributes 402 signer_info.setSignedAttributes(attributes); 403 // finish the creation of SignerInfo by calling method addSigner 404 try { 405 signed_data.addSignerInfo(signer_info); 406 407 } catch (NoSuchAlgorithmException ex) { 408 throw new CMSException("No implementation for signature algorithm: "+ex.getMessage()); 409 } 410 411 // return the SignedData as encoded byte array with block size 2048 412 ByteArrayOutputStream os = new ByteArrayOutputStream(); 413 // wrap into ContentInfo 414 ContentInfo ci = new ContentInfo(signed_data); 415 ci.writeTo(os); 416 return os.toByteArray(); 417 } 418 419 /** 420 * Parses a CMS <code>SignedData</code> object and verifies the signatures 421 * for all participated signers. 422 * 423 * @param signedData the SignedData, as BER encoded byte array 424 * @param message the the message which was transmitted out-of-band (explicit signed) 425 * @param counterSign whether to use a SDSEncodeListener to add a SignerInfo 426 * and encode the SignedData again 427 * 428 * @return the inherent message as byte array, or the BER encoded SignedData if 429 * it shall be encoded again (counter signing phase) 430 * @throws Exception if any error occurs 431 */ 432 public byte[] getSignedData(byte[] signedData, byte[] message, boolean counterSign) 433 throws Exception { 434 435 // we are testing the stream interface 436 ByteArrayInputStream is = new ByteArrayInputStream(signedData); 437 438 SignedData signed_data = new SignedData(is); 439 440 // content included (implicit mode)? 441 boolean implicit = (signed_data.getMode() == SignedData.IMPLICIT); 442 if (implicit == false) { 443 // in explcit mode explictly supply the content data to do the hash calculation 444 signed_data.setContent(message); 445 } 446 447 System.out.println("SignedData contains the following signer information:"); 448 SignerInfo[] signer_infos = signed_data.getSignerInfos(); 449 450 int numberOfSignerInfos = signer_infos.length; 451 if (numberOfSignerInfos == 0) { 452 String warning = "Warning: Unsigned message (no SignerInfo included)!"; 453 System.err.println(warning); 454 throw new CMSException(warning); 455 } else { 456 for (int i = 0; i < numberOfSignerInfos; i++) { 457 try { 458 // verify the signed data using the SignerInfo at index i 459 X509Certificate signer_cert = signed_data.verify(i); 460 // if the signature is OK the certificate of the signer is returned 461 System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN()); 462 // get signed attributes 463 // signing time 464 SigningTime signingTime = (SigningTime)signer_infos[i].getSignedAttributeValue(ObjectID.signingTime); 465 if (signingTime != null) { 466 System.out.println("This message has been signed at " + signingTime.get()); 467 } 468 // content type 469 CMSContentType contentType = (CMSContentType)signer_infos[i].getSignedAttributeValue(ObjectID.contentType); 470 if (contentType != null) { 471 System.out.println("The content has CMS content type " + contentType.get().getName()); 472 } 473 // counter signature? 474 Attribute counterSignatureAttribute = signer_infos[i].getUnsignedAttribute(ObjectID.countersignature); 475 if (counterSignatureAttribute != null) { 476 AttributeValue[] counterSignatures = counterSignatureAttribute.getAttributeValues(); 477 System.out.println("This SignerInfo is counter signed from: "); 478 for (int j = 0; j < counterSignatures.length; j++) { 479 CounterSignature counterSignature = (CounterSignature)counterSignatures[j]; 480 try { 481 if (counterSignature.verify(user2_sign.getPublicKey(), signer_infos[i])) { 482 System.out.println("Signature OK from counter signer: "+counterSignature.getSignerIdentifier()); 483 } else { 484 System.out.println("Signature ERROR from counter signer: "+counterSignature.getSignerIdentifier()); 485 } 486 } catch (SignatureException ex) { 487 System.out.println("Signature ERROR from counter signer: "+counterSignature.getSignerIdentifier()); 488 throw new CMSException(ex.toString()); 489 } 490 signingTime = (SigningTime)counterSignature.getSignedAttributeValue(ObjectID.signingTime); 491 if (signingTime != null) { 492 System.out.println("Counter signature has been created " + signingTime.get()); 493 } 494 } 495 } 496 497 } catch (SignatureException ex) { 498 // if the signature is not OK a SignatureException is thrown 499 System.out.println("Signature ERROR from signer: "+signed_data.getCertificate((signer_infos[i].getSignerIdentifier())).getSubjectDN()); 500 throw new CMSException(ex.toString()); 501 } catch (CodingException ex) { 502 throw new CMSException("Attribute decoding error: " + ex.toString()); 503 } 504 } 505 // in practice we also would validate the signer certificate(s) 506 } 507 508 if (counterSign) { 509 // we want to write the SignedData again 510 // we add a counter signature attribute to the first signer 511 CounterSignature counterSignature = new CounterSignature(new IssuerAndSerialNumber(user2_sign), 512 (AlgorithmID)AlgorithmID.sha256.clone(), user2_sign_pk); 513 // create some authenticated attributes 514 // the message digest attribute is automatically added 515 // signing time is now 516 SigningTime signingTime = new SigningTime(); 517 Attribute[] attributes = { new Attribute(signingTime) }; 518 // set the attributes 519 counterSignature.setSignedAttributes(attributes); 520 // now counter sign first SignerInfo 521 counterSignature.counterSign(signer_infos[0]); 522 // and add the counter signature as unsigned attribute 523 Attribute[] usignedAttributes = { new Attribute(counterSignature) }; 524 signer_infos[0].addUnsignedAttributes(usignedAttributes); 525 526 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 527 ContentInfo ci = new ContentInfo(signed_data); 528 ci.writeTo(baos); 529 signed_data.writeTo(baos); 530 531 // we read the content 532 System.out.println("Content: " + new String(signed_data.getContent())); 533 534 return baos.toByteArray(); 535 536 } else { 537 // return the content 538 return signed_data.getContent(); 539 } 540 541 542 } 543 544 /** 545 * Starts the demo. 546 */ 547 public void start() { 548 549 try { 550 551 byte[] data; 552 byte[] received_message = null; 553 554 // 555 // test CMS Implicit SignedDataStream 556 // 557 System.out.println("\nImplicit SignedDataStream demo [create]:\n"); 558 data = createSignedDataStream(message, SignedDataStream.IMPLICIT); 559 // parse and encode again 560 System.out.println("\nImplicit SignedDataStream demo [counter sign]:\n"); 561 data = getSignedDataStream(data, null, true); 562 // parse 563 System.out.println("\nImplicit SignedDataStream demo [parse]:\n"); 564 received_message = getSignedDataStream(data, null, false); 565 System.out.print("\nSigned content: "); 566 System.out.println(new String(received_message)); 567 568 // 569 // test CMS Explicit SignedDataStream 570 // 571 System.out.println("\nExplicit SignedDataStream demo [create]:\n"); 572 data = createSignedDataStream(message, SignedDataStream.EXPLICIT); 573 // parse and encode again 574 System.out.println("\nExplicit SignedDataStream demo [counter sign]:\n"); 575 data = getSignedDataStream(data, message, true); 576 577 System.out.println("\nExplicit SignedDataStream demo [parse]:\n"); 578 received_message = getSignedDataStream(data, message, false); 579 System.out.print("\nSigned content: "); 580 System.out.println(new String(received_message)); 581 582 // 583 // test CMS Implicit SignedData 584 // 585 System.out.println("\nImplicit SignedData demo [create]:\n"); 586 data = createSignedData(message, SignedData.IMPLICIT); 587 // parse and encode again 588 System.out.println("\nImplicit SignedData demo [counter sign]:\n"); 589 data = getSignedData(data, null, true); 590 // parse 591 System.out.println("\nImplicit SignedData demo [parse]:\n"); 592 received_message = getSignedData(data, null, false); 593 System.out.print("\nSigned content: "); 594 System.out.println(new String(received_message)); 595 596 // 597 // test CMS Explicit SignedData 598 // 599 System.out.println("\nExplicit SignedData demo [create]:\n"); 600 data = createSignedData(message, SignedData.EXPLICIT); 601 // parse and encode again 602 System.out.println("\nExplicit SignedData demo [counter sign]:\n"); 603 data = getSignedData(data, message, true); 604 605 System.out.println("\nExplicit SignedData demo [parse]:\n"); 606 received_message = getSignedData(data, message, false); 607 System.out.print("\nSigned content: "); 608 System.out.println(new String(received_message)); 609 610 } catch (Exception ex) { 611 ex.printStackTrace(); 612 throw new RuntimeException(ex.toString()); 613 } 614 } 615 616 617 /** 618 * Main method. 619 * 620 * @throws IOException 621 * if an I/O error occurs when reading required keys 622 * and certificates from files 623 */ 624 public static void main(String argv[]) throws IOException { 625 try { 626 DemoUtil.initDemos(); 627 (new CounterSignatureDemo()).start(); 628 System.out.println("\nReady!"); 629 } catch (Exception ex) { 630 ex.printStackTrace(); 631 } 632 DemoUtil.waitKey(); 633 } 634 }