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/ess/SigningCertificateDemo.java 17 12.02.25 17:59 Dbratko $ 029// $Revision: 17 $ 030// 031 032package demo.smime.ess; 033 034import iaik.asn1.ASN1Object; 035import iaik.asn1.ObjectID; 036import iaik.asn1.SEQUENCE; 037import iaik.asn1.UTF8String; 038import iaik.asn1.structures.AlgorithmID; 039import iaik.asn1.structures.Attribute; 040import iaik.asn1.structures.GeneralName; 041import iaik.asn1.structures.GeneralNames; 042import iaik.asn1.structures.Name; 043import iaik.asn1.structures.PolicyInformation; 044import iaik.asn1.structures.PolicyQualifierInfo; 045import iaik.cms.CMSException; 046import iaik.cms.IssuerAndSerialNumber; 047import iaik.cms.SignedData; 048import iaik.cms.SignedDataStream; 049import iaik.cms.SignerInfo; 050import iaik.cms.attributes.CMSContentType; 051import iaik.cms.attributes.SigningTime; 052import iaik.smime.ess.SigningCertificate; 053import iaik.utils.Util; 054import iaik.x509.X509Certificate; 055import iaik.x509.attr.AttributeCertificate; 056import iaik.x509.attr.Holder; 057import iaik.x509.attr.V1Form; 058 059import java.io.ByteArrayInputStream; 060import java.io.ByteArrayOutputStream; 061import java.io.IOException; 062import java.io.InputStream; 063import java.math.BigInteger; 064import java.security.NoSuchAlgorithmException; 065import java.security.PrivateKey; 066import java.security.SignatureException; 067import java.security.cert.Certificate; 068import java.util.Calendar; 069import java.util.Date; 070import java.util.GregorianCalendar; 071 072import demo.DemoUtil; 073import demo.keystore.CMSKeyStore; 074 075 076/** 077 * Demonstrates how to add and parse a {@link iaik.smime.ess.SigningCertificate 078 * SigningCertificate} attribute to the SignerInfo of a {@link iaik.cms.SignedDataStream} or 079 * {@link iaik.cms.SignedData} object. The SigningCertificate attributes maybe used 080 * to include certificate identification information into the signed attributes of a 081 * CMS {@link iaik.cms.SignerInfo SignerInfo} object. 082 * 083 * @see iaik.smime.ess.SigningCertificate 084 * @see iaik.cms.SignerInfo 085 * @see iaik.cms.SignedDataStream 086 * @see iaik.cms.SignedData 087 */ 088public class SigningCertificateDemo { 089 090 // certificate of user 1 091 X509Certificate user1; 092 // private key of user 1 093 PrivateKey user1_pk; 094 095 // a certificate chain containing the user certs + CA 096 Certificate[] certs; 097 Certificate[] user1Certs; 098 099 // just for attribute certificate testing 100 PrivateKey issuer1_pk; 101 102 /** 103 * Setups the demo certificate chains. 104 * 105 * Keys and certificate are retrieved from the demo KeyStore. 106 * 107 * @throws IOException if an file read error occurs 108 */ 109 public SigningCertificateDemo() throws IOException { 110 111 System.out.println(); 112 System.out.println("**********************************************************************************"); 113 System.out.println("* SigningCertificateDemo demo *"); 114 System.out.println("* (shows the usage of the ESS SigningCertificate attribute) *"); 115 System.out.println("**********************************************************************************"); 116 System.out.println(); 117 118 // add all certificates to the list 119 user1Certs = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1); 120 user1 = (X509Certificate)user1Certs[0]; 121 user1_pk = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1); 122 123 certs = user1Certs; 124 try { 125 issuer1_pk = CMSKeyStore.getCaPrivateKey(CMSKeyStore.RSA); 126 AttributeCertificate attrCert = createAttributeCertificate(); 127 certs = new Certificate[user1Certs.length+1]; 128 System.arraycopy(user1Certs, 0, certs, 0, user1Certs.length); 129 certs[user1Certs.length] = attrCert; 130 } catch (CMSException ex) { 131 System.out.println("No attribute certificates!"); 132 } 133 } 134 135 /** 136 * Creates a CMS <code>SignedData</code> object. 137 * <p> 138 * 139 * @param message the message to be signed, as byte representation 140 * @param mode the transmission mode, either IMPLICIT or EXPLICIT 141 * @return the BER encoding of the <code>SignedData</code> object just created 142 * @throws CMSException if the <code>SignedData</code> object cannot 143 * be created 144 * @throws IOException if some stream I/O error occurs 145 */ 146 public byte[] createSignedDataStream(byte[] message, int mode) throws CMSException, IOException { 147 148 System.out.print("Create a new message signed by user 1 :"); 149 150 // we are testing the stream interface 151 ByteArrayInputStream is = new ByteArrayInputStream(message); 152 // create a new SignedData object which includes the data 153 SignedDataStream signed_data = new SignedDataStream(is, mode); 154 155 // SignedData shall include the certificate chain for verifying 156 signed_data.setCertificates(certs); 157 158 // cert at index 0 is the user certificate 159 IssuerAndSerialNumber issuer = new IssuerAndSerialNumber(user1); 160 161 // create a new SignerInfo 162 SignerInfo signer_info = new SignerInfo(issuer, (AlgorithmID)AlgorithmID.sha1.clone(), user1_pk); 163 // create some authenticated attributes 164 // the message digest attribute is automatically added 165 Attribute[] attributes = new Attribute[3]; 166 try { 167 // content type is data 168 CMSContentType contentType = new CMSContentType(ObjectID.cms_data); 169 attributes[0] = new Attribute(contentType); 170 // signing time is now 171 SigningTime signingTime = new SigningTime(); 172 attributes[1] = new Attribute(signingTime); 173 // signing certificate 174 SigningCertificate signingCertificate = createSigningCertificate(certs); 175 String explicitText = "This certificate only may be used for test purposes"; 176 PolicyQualifierInfo policyQualifier = new PolicyQualifierInfo(null, null, explicitText); 177 PolicyInformation[] policyInformations = 178 { new PolicyInformation(new ObjectID("1.3.6.1.4.1.2706.2.2.4.1.1.1.1"), 179 new PolicyQualifierInfo[] { policyQualifier }) }; 180 signingCertificate.setPolicies(policyInformations); 181 System.out.println("Include signingCertificate attribute:"); 182 System.out.println(signingCertificate); 183 attributes[2] = new Attribute(signingCertificate); 184 } catch (Exception ex) { 185 throw new CMSException("Error creating attribute: " + ex.toString()); 186 } 187 // set the attributes 188 signer_info.setSignedAttributes(attributes); 189 // finish the creation of SignerInfo by calling method addSigner 190 try { 191 signed_data.addSignerInfo(signer_info); 192 } catch (NoSuchAlgorithmException ex) { 193 throw new CMSException("No implementation for signature algorithm: "+ex.getMessage()); 194 } 195 // write the data through SignedData to any out-of-band place 196 if (mode == SignedDataStream.EXPLICIT) { 197 InputStream data_is = signed_data.getInputStream(); 198 byte[] buf = new byte[1024]; 199 int r; 200 while ((r = data_is.read(buf)) > 0) 201 ; // skip data 202 } 203 204 // return the SignedData as DER encoded byte array with block size 2048 205 ByteArrayOutputStream os = new ByteArrayOutputStream(); 206 signed_data.writeTo(os, 2048); 207 return os.toByteArray(); 208 } 209 210 211 /** 212 * Parses a CMS <code>SignedData</code> object and verifies the signatures 213 * for all participated signers. 214 * 215 * @param signedData <code>SignedData</code> object as BER encoded byte array 216 * @param message the the message which was transmitted out-of-band (explicit signed) 217 * 218 * @return the inherent message as byte array 219 * @throws CMSException if any signature does not verify 220 * @throws IOException if some stream I/O error occurs 221 */ 222 public byte[] getSignedDataStream(byte[] signedData, byte[] message) throws CMSException, IOException { 223 224 // we are testing the stream interface 225 ByteArrayInputStream is = new ByteArrayInputStream(signedData); 226 // create the SignedData object 227 SignedDataStream signed_data = new SignedDataStream(is); 228 229 if (signed_data.getMode() == SignedDataStream.EXPLICIT) { 230 // in explicit mode explicitly supply the content for hash computation 231 signed_data.setInputStream(new ByteArrayInputStream(message)); 232 } 233 234 // get an InputStream for reading the signed content 235 InputStream data = signed_data.getInputStream(); 236 ByteArrayOutputStream os = new ByteArrayOutputStream(); 237 Util.copyStream(data, os, null); 238 239 System.out.println("SignedData contains the following signer information:"); 240 SignerInfo[] signer_infos = signed_data.getSignerInfos(); 241 242 int numberOfSignerInfos = signer_infos.length; 243 if (numberOfSignerInfos == 0) { 244 String warning = "Warning: Unsigned message (no SignerInfo included)!"; 245 System.err.println(warning); 246 throw new CMSException(warning); 247 } else { 248 for (int i = 0; i < numberOfSignerInfos; i++) { 249 250 try { 251 // verify the signed data using the SignerInfo at index i 252 X509Certificate signer_cert = signed_data.verify(i); 253 // if the signature is OK the certificate of the signer is returned 254 System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN()); 255 SigningTime signingTime = (SigningTime)signer_infos[i].getSignedAttributeValue(ObjectID.signingTime); 256 if (signingTime != null) { 257 System.out.println("This message has been signed at " + signingTime.get()); 258 } 259 CMSContentType contentType = (CMSContentType)signer_infos[i].getSignedAttributeValue(ObjectID.contentType); 260 if (contentType != null) { 261 System.out.println("The content has CMS content type " + contentType.get().getName()); 262 } 263 // check SigningCertificate attribute 264 try { 265 SigningCertificate signingCertificate = getSigningCertificate(signer_infos[i]); 266 if (signingCertificate != null) { 267 checkSigningCertificate(signingCertificate, signer_cert, signed_data, i); 268 } 269 } catch (CMSException ex) { 270 throw new CMSException("Error parsing SigningCertificate attribute: " + ex.getMessage()); 271 } 272 273 } catch (SignatureException ex) { 274 // if the signature is not OK a SignatureException is thrown 275 System.out.println("Signature ERROR from signer: "+signed_data.getCertificate(signer_infos[i].getSignerIdentifier()).getSubjectDN()); 276 throw new CMSException(ex.toString()); 277 } 278 } 279 280 // now check alternative signature verification 281 System.out.println("Now check the signature assuming that no certs have been included:"); 282 try { 283 SignerInfo signer_info = signed_data.verify(user1); 284 // if the signature is OK the certificate of the signer is returned 285 System.out.println("Signature OK from signer: "+user1.getSubjectDN()); 286 287 } catch (SignatureException ex) { 288 // if the signature is not OK a SignatureException is thrown 289 System.out.println("Signature ERROR from signer: "+user1.getSubjectDN()); 290 throw new CMSException(ex.toString()); 291 } 292 // in practice we also would validate the signer certificate(s) 293 } 294 295 System.out.println("Included attribute certificates:"); 296 AttributeCertificate[] attributeCerts = signed_data.getAttributeCertificates(); 297 if (attributeCerts == null) { 298 System.out.println("No attribute certificates"); 299 } else { 300 for (int i = 0; i < attributeCerts.length; i++) { 301 System.out.println(attributeCerts[i].getHolder()); 302 } 303 } 304 305 return os.toByteArray(); 306 } 307 308 309 310 /** 311 * Creates a CMS <code>SignedData</code> object. 312 * <p> 313 * 314 * @param message the message to be signed, as byte representation 315 * @param mode the mode, either SignedData.IMPLICIT or SignedData.EXPLICIT 316 * @return the DER encoded <code>SignedData</code> object 317 * @throws CMSException if the <code>SignedData</code> object cannot 318 * be created 319 */ 320 public byte[] createSignedData(byte[] message, int mode) throws CMSException { 321 322 System.out.println("Create a new message signed by user 1 :"); 323 324 // create a new SignedData object which includes the data 325 SignedData signed_data = new SignedData(message, mode); 326 327 // SignedData shall include the certificate chain for verifying 328 signed_data.setCertificates(certs); 329 330 // cert at index 0 is the user certificate 331 IssuerAndSerialNumber issuer = new IssuerAndSerialNumber(user1); 332 333 // create a new SignerInfo 334 SignerInfo signer_info = new SignerInfo(issuer, (AlgorithmID)AlgorithmID.sha1.clone(), user1_pk); 335 // create some authenticated attributes 336 // the message digest attribute is automatically added 337 Attribute[] attributes = new Attribute[3]; 338 try { 339 // content type is data 340 CMSContentType contentType = new CMSContentType(ObjectID.cms_data); 341 attributes[0] = new Attribute(contentType); 342 // signing time is now 343 SigningTime signingTime = new SigningTime(); 344 attributes[1] = new Attribute(signingTime); 345 // signing certificate 346 SigningCertificate signingCertificate = createSigningCertificate(certs); 347 System.out.println("Include signingCertificate attribute:"); 348 System.out.println(signingCertificate); 349 attributes[2] = new Attribute(signingCertificate); 350 } catch (Exception ex) { 351 throw new CMSException("Error creating attribute: " + ex.toString()); 352 } 353 // set the attributes 354 signer_info.setSignedAttributes(attributes); 355 // finish the creation of SignerInfo by calling method addSigner 356 try { 357 signed_data.addSignerInfo(signer_info); 358 } catch (NoSuchAlgorithmException ex) { 359 throw new CMSException("No implementation for signature algorithm: "+ex.getMessage()); 360 } 361 return signed_data.getEncoded(); 362 } 363 364 365 /** 366 * Parses a CMS <code>SignedData</code> object and verifies the signatures 367 * for all participated signers. 368 * 369 * @param encoding the DER encoded <code>SignedData</code> object 370 * @param message the the message which was transmitted out-of-band (explicit signed) 371 * 372 * @return the inherent message as byte array 373 * @throws CMSException if any signature does not verify 374 * @throws IOException if some stream I/O error occurs 375 */ 376 public byte[] getSignedData(byte[] encoding, byte[] message) throws CMSException, IOException { 377 378 ByteArrayInputStream encodedStream = new ByteArrayInputStream(encoding); 379 // create the SignedData object 380 SignedData signed_data = new SignedData(encodedStream); 381 382 if (signed_data.getMode() == SignedData.EXPLICIT) { 383 // in explcit mode explictly supply the content data to do the hash calculation 384 signed_data.setContent(message); 385 } 386 387 System.out.println("SignedData contains the following signer information:"); 388 SignerInfo[] signer_infos = signed_data.getSignerInfos(); 389 390 int numberOfSignerInfos = signer_infos.length; 391 if (numberOfSignerInfos == 0) { 392 String warning = "Warning: Unsigned message (no SignerInfo included)!"; 393 System.err.println(warning); 394 throw new CMSException(warning); 395 } else { 396 for (int i = 0; i < numberOfSignerInfos; i++) { 397 try { 398 // verify the signed data using the SignerInfo at index i 399 X509Certificate signer_cert = signed_data.verify(i); 400 // if the signature is OK the certificate of the signer is returned 401 System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN()); 402 SigningTime signingTime = (SigningTime)signer_infos[i].getSignedAttributeValue(ObjectID.signingTime); 403 if (signingTime != null) { 404 System.out.println("This message has been signed at " + signingTime.get()); 405 } 406 CMSContentType contentType = (CMSContentType)signer_infos[i].getSignedAttributeValue(ObjectID.contentType); 407 if (contentType != null) { 408 System.out.println("The content has CMS content type " + contentType.get().getName()); 409 } 410 // check SigningCertificate attribute 411 SigningCertificate signingCertificate = getSigningCertificate(signer_infos[i]); 412 if (signingCertificate != null) { 413 checkSigningCertificate(signingCertificate, signer_cert, signed_data, i); 414 } 415 } catch (SignatureException ex) { 416 // if the signature is not OK a SignatureException is thrown 417 System.out.println("Signature ERROR from signer: "+signed_data.getCertificate(signer_infos[i].getSignerIdentifier()).getSubjectDN()); 418 throw new CMSException(ex.toString()); 419 } 420 } 421 422 // now check alternative signature verification 423 System.out.println("Now check the signature assuming that no certs have been included:"); 424 try { 425 SignerInfo signer_info = signed_data.verify(user1); 426 // if the signature is OK the certificate of the signer is returned 427 System.out.println("Signature OK from signer: "+signed_data.getCertificate(signer_info.getSignerIdentifier()).getSubjectDN()); 428 429 } catch (SignatureException ex) { 430 // if the signature is not OK a SignatureException is thrown 431 System.out.println("Signature ERROR from signer: "+user1.getSubjectDN()); 432 throw new CMSException(ex.toString()); 433 } 434 // in practice we also would validate the signer certificate(s) 435 } 436 return signed_data.getContent(); 437 } 438 439 /** 440 * Checks the SigningCertificate attribute. 441 * 442 * @param signingCertificate the SigningCertificate attribute 443 * @param signerCert the certificate of the signer 444 * @param signedData the SignedData containing the SignerInfo with the SigningCertificate 445 * attribute to be checked 446 * @param signerInfoIndex the index of the SignerInfo with the SigningCertificate 447 * attribute to be checked 448 * 449 * @throws CMSException if the SigningCertificate check fails 450 */ 451 private void checkSigningCertificate(SigningCertificate signingCertificate, 452 X509Certificate signerCert, 453 SignedDataStream signedData, 454 int signerInfoIndex) throws CMSException { 455 try { 456 if (signingCertificate != null) { 457 System.out.println("SigningCertificate attribute included!"); 458 if (!signingCertificate.isSignerCertificate(signerCert)) { 459 throw new CMSException("Cert ERROR!!! The certificate used for signing is not the one " + 460 "identified by the SignerCertificate attribute!"); 461 } else { 462 System.out.println("SigningCertificate attribute: Signer cert ok!"); 463 } 464 // get the authorization certs for this signerInfo 465 Certificate[] authCerts = 466 signingCertificate.getAuthorizedCertificates(signedData.getCertificates()); 467 if (authCerts != null) { 468 System.out.println("SignedData contains the following authorization certs for SignerInfo No " + (signerInfoIndex+1) +":"); 469 for (int j = 0; j < authCerts.length; j++) { 470 if (authCerts[j].getType().equalsIgnoreCase("X.509")) { 471 System.out.println("X.509 public key cert: " + ((X509Certificate)authCerts[j]).getSubjectDN()); 472 } else { 473 System.out.println("X.509 attribute cert: " + ((AttributeCertificate)authCerts[j]).getHolder()); 474 } 475 } 476 } 477 if (signingCertificate.countPolicies() > 0) { 478 // get the certs with PolicyInformations according to the SigningCertificate attribute: 479 Certificate[] policyCerts = 480 signingCertificate.getPolicyInformationCerts(signedData.getCertificates()); 481 if (policyCerts != null) { 482 System.out.println("SignedData contains the following certs corresponding to policy informations of SignerInfo No " 483 + (signerInfoIndex+1) +":"); 484 for (int j = 0; j < policyCerts.length; j++) { 485 if (policyCerts[j].getType().equalsIgnoreCase("X.509")) { 486 System.out.println("X.509 public key cert: " + ((X509Certificate)policyCerts[j]).getSubjectDN()); 487 } else { 488 System.out.println("X.509 attribute cert: " + ((AttributeCertificate)policyCerts[j]).getHolder()); 489 } 490 } 491 } 492 } 493 } 494 } catch (NoSuchAlgorithmException ex) { 495 throw new CMSException("Cannot check SigningCertificate attribute: Algorithm SHA not implemented!"); 496 } 497 } 498 499 /** 500 * Creates an attribute certificate just for testing. 501 * 502 * @return the attribute certificate created 503 * @throws CMSException if an error occurs when creating the attribute certificate 504 */ 505 public AttributeCertificate createAttributeCertificate() throws CMSException { 506 try { 507 508 Name issuer = (Name)user1.getIssuerDN(); 509 GeneralName genName = new GeneralName(GeneralName.directoryName, issuer); 510 GeneralNames genNames = new GeneralNames(genName); 511 V1Form v1Form = new V1Form(genNames); 512 Name subject = (Name)user1.getSubjectDN(); 513 GeneralName genName1 = new GeneralName(GeneralName.directoryName, subject); 514 GeneralNames genNames1 = new GeneralNames(genName1); 515 Holder holder = new Holder(); 516 holder.setEntityName(genNames1); 517 518 AttributeCertificate cert = new AttributeCertificate(); 519 cert.setHolder(holder); 520 cert.setIssuer(v1Form); 521 cert.setSerialNumber(new BigInteger("27")); 522 GregorianCalendar c = new GregorianCalendar(); 523 Date notBeforeTime = c.getTime(); 524 c.add(Calendar.MONTH, 1); 525 Date notAfterTime = c.getTime(); 526 cert.setNotBeforeTime(notBeforeTime); 527 cert.setNotAfterTime(notAfterTime); 528 Attribute[] attributes = new Attribute[1]; 529 // just for testing some abritrary attribute 530 SEQUENCE postalAddress = new SEQUENCE(); 531 postalAddress.addComponent(new UTF8String("A-8010 Graz, Austria")); 532 postalAddress.addComponent(new UTF8String("Inffeldgasse 16A")); 533 attributes[0] = new Attribute(ObjectID.postalAddress, new ASN1Object[] {postalAddress}); 534 cert.setAttributes(attributes); 535 cert.sign((AlgorithmID)AlgorithmID.sha1WithRSAEncryption_.clone(), issuer1_pk); 536 cert.verify(user1Certs[1].getPublicKey()); 537 return cert; 538 } catch (Exception ex) { 539 throw new CMSException("Error creating attribute certificate: " + ex.toString()); 540 } 541 542 } 543 544 /** 545 * Starts the demo. 546 */ 547 public void start() { 548 // the test message 549 String m = "This is the test message."; 550 System.out.println("Test message: \""+m+"\""); 551 System.out.println(); 552 byte[] message = m.getBytes(); 553 554 try { 555 byte[] encoding; 556 byte[] received_message = null; 557 System.out.println("Stream implementation demos"); 558 System.out.println("==========================="); 559 // 560 // test CMS Implicit SignedDataStream 561 // 562 System.out.println("\nImplicit SignedDataStream demo [create]:\n"); 563 encoding = createSignedDataStream(message, SignedDataStream.IMPLICIT); 564 // transmit data 565 System.out.println("\nImplicit SignedDataStream demo [parse]:\n"); 566 received_message = getSignedDataStream(encoding, null); 567 System.out.print("\nSigned content: "); 568 System.out.println(new String(received_message)); 569 570 // 571 // test CMS Explicit SignedDataStream 572 // 573 System.out.println("\nExplicit SignedDataStream demo [create]:\n"); 574 encoding = createSignedDataStream(message, SignedDataStream.EXPLICIT); 575 // transmit data 576 System.out.println("\nExplicit SignedDataStream demo [parse]:\n"); 577 received_message = getSignedDataStream(encoding, message); 578 System.out.print("\nSigned content: "); 579 System.out.println(new String(received_message)); 580 581 // the non-stream implementation 582 System.out.println("\nNon-stream implementation demos"); 583 System.out.println("==============================="); 584 585 // 586 // test CMS Implicit SignedData 587 // 588 System.out.println("\nImplicit CMS SignedData demo [create]:\n"); 589 encoding = createSignedData(message, SignedData.IMPLICIT); 590 // transmit data 591 System.out.println("\nImplicit CMS SignedData demo [parse]:\n"); 592 received_message = getSignedData(encoding, null); 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 CMS SignedData demo [create]:\n"); 600 encoding = createSignedData(message, SignedData.EXPLICIT); 601 // transmit data 602 System.out.println("\nExplicit CMS SignedData demo [parse]:\n"); 603 received_message = getSignedData(encoding, message); 604 System.out.print("\nSigned content: "); 605 System.out.println(new String(received_message)); 606 607 } catch (Exception ex) { 608 ex.printStackTrace(); 609 throw new RuntimeException(ex.toString()); 610 } 611 } 612 613 /** 614 * Creates a SigningCertificate attribute for the given certificates. 615 * 616 * @param certs the certificates for which to create the SigningCertificate 617 * attribute 618 * 619 * @return the SigningCertificate attribute just created 620 * 621 * @throws CMSException if an error occurs when creating the 622 * SigningCertificate attribute 623 */ 624 protected SigningCertificate createSigningCertificate(Certificate[] certs) 625 throws CMSException { 626 627 try { 628 return new SigningCertificate(certs, true); 629 } catch (Exception ex) { 630 throw new CMSException("Error creating SigningCertificate attribute: " + ex.toString()); 631 } 632 } 633 634 /** 635 * Gets the SigningCertificate attribute from the given SignerInfo. 636 * 637 * @param signerInfo the SignerInfo from which to get the 638 * SigningCertificate attribute 639 * 640 * @return the SigningCertificate attribute, or <code>null</code> 641 * if no SigningCertificate attribute is included 642 * 643 * @throws CMSException if an error occurs when getting the 644 * SigningCertificate attribute 645 */ 646 protected SigningCertificate getSigningCertificate(SignerInfo signerInfo) 647 throws CMSException { 648 649 return signerInfo.getSigningCertificateAttribute(); 650 } 651 652 /** 653 * Prints some header lines to System.out. 654 */ 655 protected void printHeader() { 656 System.out.println(); 657 System.out.println("**********************************************************************************"); 658 System.out.println("* SigningCertificateDemo demo *"); 659 System.out.println("* (shows the usage of the ESS SigningCertificate attribute) *"); 660 System.out.println("**********************************************************************************"); 661 System.out.println(); 662 } 663 664 665 /** 666 * The main method. 667 * 668 * @throws IOException 669 * if an I/O error occurs when reading required keys 670 * and certificates from files 671 */ 672 public static void main(String argv[]) throws Exception { 673 674 DemoUtil.initDemos(); 675 (new SigningCertificateDemo()).start(); 676 System.out.println("\nReady!"); 677 DemoUtil.waitKey(); 678 } 679}