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 }