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