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