001    // Copyright (C) 2002 IAIK
002    // https://jce.iaik.tugraz.at
003    //
004    // Copyright (C) 2003 - 2025 Stiftung Secure Information and
005    //                           Communication Technologies SIC
006    // https://sic.tech
007    //
008    // All rights reserved.
009    //
010    // Redistribution and use in source and binary forms, with or without
011    // modification, are permitted provided that the following conditions
012    // are met:
013    // 1. Redistributions of source code must retain the above copyright
014    //    notice, this list of conditions and the following disclaimer.
015    // 2. Redistributions in binary form must reproduce the above copyright
016    //    notice, this list of conditions and the following disclaimer in the
017    //    documentation and/or other materials provided with the distribution.
018    //
019    // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
020    // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021    // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022    // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
023    // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
024    // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
025    // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026    // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
027    // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
028    // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
029    // SUCH DAMAGE.
030    
031    // Copyright (C) 2002 IAIK
032    // https://sic.tech/
033    //
034    // Copyright (C) 2003 - 2025 Stiftung Secure Information and 
035    //                           Communication Technologies SIC
036    // https://sic.tech/
037    //
038    // All rights reserved.
039    //
040    // This source is provided for inspection purposes and recompilation only,
041    // unless specified differently in a contract with IAIK. This source has to
042    // be kept in strict confidence and must not be disclosed to any third party
043    // under any circumstances. Redistribution in source and binary forms, with
044    // or without modification, are <not> permitted in any case!
045    //
046    // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
047    // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
048    // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
049    // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
050    // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
051    // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
052    // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
053    // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
054    // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
055    // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
056    // SUCH DAMAGE.
057    //
058    // $Header: /IAIK-CMS/current/src/demo/cms/ecc/ECDSASignedDataDemo.java 36    12.02.25 17:58 Dbratko $
059    // $Revision: 36 $
060    //
061    
062    package demo.cms.ecc;
063    
064    import iaik.asn1.ObjectID;
065    import iaik.asn1.structures.AlgorithmID;
066    import iaik.asn1.structures.Attribute;
067    import iaik.cms.CMSAlgorithmID;
068    import iaik.cms.CMSException;
069    import iaik.cms.ContentInfo;
070    import iaik.cms.ContentInfoStream;
071    import iaik.cms.IssuerAndSerialNumber;
072    import iaik.cms.SignedData;
073    import iaik.cms.SignedDataStream;
074    import iaik.cms.SignerInfo;
075    import iaik.cms.attributes.CMSContentType;
076    import iaik.cms.attributes.SigningTime;
077    import iaik.utils.KeyAndCertificate;
078    import iaik.utils.Util;
079    import iaik.x509.X509Certificate;
080    
081    import java.io.ByteArrayInputStream;
082    import java.io.ByteArrayOutputStream;
083    import java.io.IOException;
084    import java.io.InputStream;
085    import java.security.NoSuchAlgorithmException;
086    import java.security.PrivateKey;
087    import java.security.SignatureException;
088    
089    import demo.DemoUtil;
090    import demo.cms.ecc.keystore.CMSEccKeyStore;
091    
092    
093    /**
094     * This class demonstrates the IAIK-CMS SignedData(Stream) implementation
095     * with the ECDSA (with SHA1, SHA224, SHA256, SHA384, SHA512, RIPEMD160) signature algorithm. 
096     * <p>
097     * Any keys/certificates required for this demo are read from a keystore
098     * file "cmsecc.keystore" located in your current working directory. If
099     * the keystore file does not exist you can create it by running the
100     * {@link demo.cms.ecc.keystore.SetupCMSEccKeyStore SetupCMSEccKeyStore}
101     * program. 
102     * <p>
103     * Additionally to <code>iaik_cms.jar</code> you also must have 
104     * <code>iaik_jce_(full).jar</code> (IAIK-JCE, <a href =
105     * "https://sic.tech/products/core-crypto-toolkits/jca-jce/" target="_blank">
106     * https://sic.tech/products/core-crypto-toolkits/jca-jce/</a>),
107     * and <code>iaik_eccelarate.jar</code> (IAIK-ECCelerate<sup><small>TM</small></sup>, <a href =
108     * "https://sic.tech/products/core-crypto-toolkits/eccelerate/" target="_blank">
109     * https://sic.tech/products/core-crypto-toolkits/eccelerate/</a>)
110     * in your classpath.
111     */
112    public class ECDSASignedDataDemo {
113    
114      /**
115       * Default Constructor.
116       */
117      public ECDSASignedDataDemo() throws Exception {
118        System.out.println();
119        System.out.println("**********************************************************************************");
120        System.out.println("*                           ECDSASignedData demo                                 *");
121        System.out.println("*      (shows how to use the SignedData(Stream) implementation with ECDSA)       *");
122        System.out.println("**********************************************************************************");
123        System.out.println();
124        
125      }
126      
127      /**
128       * Creates an ECDSA signed CMS <code>SignedDataStream</code> object and wraps it by a
129       * CMS <code>ContentInfoStream</code>.
130       *
131       * @param message the message to be signed, as byte representation
132       * @param mode the transmission mode, either IMPLICIT or EXPLICIT
133       * @param hashAlgorithm the hash algorithm to be used
134       * @param signatureAlgorithm the signature algorithm to be used
135       * @param signerKey the private key of the signer
136       * @param certificates the certificate chain of the signer
137       * 
138       * @return the DER encoding of the <code>ContentInfo</code> object just created
139       * 
140       * @throws CMSException if the <code>SignedData</code>, <code>ContentInfo</code>
141       *            object cannot be created
142       * @throws IOException if an I/O related error occurs
143       */
144      public byte[] createSignedDataStream(byte[] message, 
145                                           int mode,
146                                           AlgorithmID hashAlgorithm,
147                                           AlgorithmID signatureAlgorithm,
148                                           PrivateKey signerKey,
149                                           X509Certificate[] certificates) 
150        throws CMSException, IOException  {
151        
152        System.out.print("Create a new message signed with " + signatureAlgorithm.getName());
153       
154        // we are testing the stream interface
155        ByteArrayInputStream is = new ByteArrayInputStream(message);
156        // create a new SignedData object which includes the data
157        SignedDataStream signed_data = new SignedDataStream(is, mode);
158        
159        // SignedData shall include the certificate chain for verifying
160        signed_data.setCertificates(certificates);
161    
162        // cert at index 0 is the user certificate
163        IssuerAndSerialNumber issuer = new IssuerAndSerialNumber(certificates[0]);
164    
165        // create a new SignerInfo
166        AlgorithmID ecdsaSig = (AlgorithmID)signatureAlgorithm.clone();
167        // CMS-ECDSA requires to encode the parameter field as NULL (see RFC 3278)
168        ecdsaSig.encodeAbsentParametersAsNull(true);
169        SignerInfo signer_info = new SignerInfo(issuer, (AlgorithmID)hashAlgorithm.clone(), ecdsaSig, signerKey);
170        
171        try {
172          // create some signed attributes
173          // the message digest attribute is automatically added
174          Attribute[] attributes = new Attribute[2];
175          // content type is data
176          CMSContentType contentType = new CMSContentType(ObjectID.cms_data);
177          attributes[0] = new Attribute(contentType);
178          // signing time is now
179          SigningTime signingTime = new SigningTime();
180          attributes[1] = new Attribute(signingTime);
181      
182          // set the attributes
183          signer_info.setSignedAttributes(attributes);
184        } catch (Exception ex) {
185          throw new CMSException("Error adding attributes: " + ex.toString());
186        }
187        
188        // finish the creation of SignerInfo by calling method addSigner
189        try {
190          signed_data.addSignerInfo(signer_info);
191        } catch (NoSuchAlgorithmException ex) {
192          throw new CMSException("No implementation for signature algorithm: "+ex.getMessage());
193        }
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    
205        signed_data.setBlockSize(2048);
206         // create the ContentInfo
207        ContentInfoStream cis = new ContentInfoStream(signed_data);
208        // return the SignedData as DER encoded byte array with block size 2048
209        ByteArrayOutputStream os = new ByteArrayOutputStream();
210        cis.writeTo(os);
211        return os.toByteArray();
212      }
213      
214      
215      /**
216       * Parses a CMS <code>ContentInfo</code> object holding a <code>SignedData</code> 
217       * object and verifies the signature.
218       *
219       * @param signedData the <code>ContentInfo</code> holding the <code>SignedData</code> 
220       *                   object as BER encoded byte array
221       * @param message the the message which was transmitted out-of-band (explicit signed)
222       * @param certificates the certificate of the signer (used for alternative signature verification)
223       * 
224       * @return the inherent message as byte array
225       * 
226       * @throws CMSException if any signature does not verify
227       * @throws IOException if an I/O related error occurs
228       */
229      public byte[] getSignedDataStream(byte[] signedData, byte[] message, X509Certificate[] certificates) 
230        throws CMSException, IOException {
231    
232        // we are testing the stream interface
233        ByteArrayInputStream is = new ByteArrayInputStream(signedData);
234    
235        SignedDataStream signed_data = new SignedDataStream(is);
236    
237        if (signed_data.getMode() == SignedDataStream.EXPLICIT) {
238          // in explicit mode explicitly supply the content for hash computation
239          signed_data.setInputStream(new ByteArrayInputStream(message));
240        }
241    
242        // get an InputStream for reading the signed content and update hash computation
243        InputStream data = signed_data.getInputStream();
244        ByteArrayOutputStream os = new ByteArrayOutputStream();
245        Util.copyStream(data, os, null);
246    
247        System.out.println("SignedData contains the following signer information:");
248        SignerInfo[] signer_infos = signed_data.getSignerInfos();
249        
250        int numberOfSignerInfos = signer_infos.length;
251        if (numberOfSignerInfos == 0) {
252          String warning = "Warning: Unsigned message (no SignerInfo included)!";  
253          System.err.println(warning);
254          throw new CMSException(warning);
255        } else {
256          for (int i = 0; i < numberOfSignerInfos; i++) {
257            try {
258              // verify the signed data using the SignerInfo at index i
259              X509Certificate signer_cert = signed_data.verify(i);
260              // if the signature is OK the certificate of the signer is returned
261              System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN());
262              // check for some included attributes
263              SigningTime signingTime = (SigningTime)signer_infos[i].getSignedAttributeValue(ObjectID.signingTime);
264              if (signingTime != null) {
265                System.out.println("This message has been signed at " + signingTime.get());
266              } 
267              CMSContentType contentType = (CMSContentType)signer_infos[i].getSignedAttributeValue(ObjectID.contentType);
268              if (contentType != null) {
269                System.out.println("The content has CMS content type " + contentType.get().getName());
270              }  
271            } catch (SignatureException ex) {
272              // if the signature is not OK a SignatureException is thrown
273              System.out.println("Signature ERROR from signer: "+signed_data.getCertificate(signer_infos[i].getSignerIdentifier()).getSubjectDN());
274              throw new CMSException(ex.toString());
275            }  
276          }  
277          // now check alternative signature verification
278          System.out.println("Now check the signature assuming that no certs have been included:");
279          try {
280            SignerInfo signer_info = signed_data.verify(certificates[0]);
281            // if the signature is OK the certificate of the signer is returned
282            System.out.println("Signature OK from signer: "+signed_data.getCertificate(signer_info.getSignerIdentifier()).getSubjectDN());
283          } catch (SignatureException ex) {
284            // if the signature is not OK a SignatureException is thrown
285            System.out.println("Signature ERROR from signer: "+certificates[0].getSubjectDN());
286            throw new CMSException(ex.toString());
287          }
288          // in practice we also would validate the signer certificate(s)  
289        }      
290        return os.toByteArray();
291      }
292      
293      
294      /**
295       * Creates an ECDSA signed CMS <code>SignedData</code> object and wraps it by a CMS
296       * <code>ContentInfo</code> object.
297       * <p>
298       *
299       * @param message the message to be signed, as byte representation
300       * @param mode the mode, either SignedData.IMPLICIT or SignedData.EXPLICIT
301       * @param hashAlgorithm the hash algorithm to be used
302       * @param signatureAlgorithm the signature algorithm to be used
303       * @param signerKey the private key of the signer
304       * @param certificates the certificate chain of the signer
305       * 
306       * @return the DER encoded <code>SignedData</code>-<code>ContentInfo</code> object
307       *  
308       * @throws CMSException if the <code>SignedData</code>-<code>ContentInfo</code> object cannot
309       *                          be created
310       * @throws IOException if an I/O related error occurs
311       */
312      public byte[] createSignedData(byte[] message, 
313                                     int mode,
314                                     AlgorithmID hashAlgorithm,
315                                     AlgorithmID signatureAlgorithm,
316                                     PrivateKey signerKey,
317                                     X509Certificate[] certificates) 
318        throws CMSException, IOException  {
319        
320        System.out.println("Create a new message signed with " + signatureAlgorithm.getName());
321      
322        // create a new SignedData object which includes the data
323        SignedData signed_data = new SignedData(message, mode);
324        
325        // SignedData shall include the certificate chain for verifying
326        signed_data.setCertificates(certificates);
327      
328        // cert at index 0 is the user certificate
329        IssuerAndSerialNumber issuer = new IssuerAndSerialNumber(certificates[0]);
330    
331        // create a new SignerInfo
332        AlgorithmID ecdsaSig = (AlgorithmID)signatureAlgorithm.clone();
333        // CMS-ECC requires that the parameters field is encoded as ASN.1 NULL object (see RFC 3278)
334        ecdsaSig.encodeAbsentParametersAsNull(true);
335        SignerInfo signer_info = new SignerInfo(issuer, (AlgorithmID)hashAlgorithm.clone(), ecdsaSig, signerKey);
336        
337        try {
338          // create some signed attributes
339          // the message digest attribute is automatically added
340          Attribute[] attributes = new Attribute[2];
341          // content type is data
342          CMSContentType contentType = new CMSContentType(ObjectID.cms_data);
343          attributes[0] = new Attribute(contentType);
344          // signing time is now
345          SigningTime signingTime = new SigningTime();
346          attributes[1] = new Attribute(signingTime);
347      
348          // set the attributes
349          signer_info.setSignedAttributes(attributes);
350        } catch (Exception ex) {
351          throw new CMSException("Error adding attributes: " + ex.toString());
352        }
353        
354        // finish the creation of SignerInfo by calling method addSigner
355        try {
356          signed_data.addSignerInfo(signer_info);
357        } catch (NoSuchAlgorithmException ex) {
358          throw new CMSException("No implementation for signature algorithm: "+ex.getMessage());
359        }
360    
361        ContentInfo ci = new ContentInfo(signed_data); 
362        return ci.getEncoded();
363      }
364      
365      
366      /**
367       * Parses a CMS <code>ContentInfo</code> holding a <code>SignedData</code> 
368       * object and verifies the signature.
369       *
370       * @param signedData the <code>ContentInfo</code> holding the <code>SignedData</code> 
371       *                   object as DER encoded byte array
372       * @param message the message which was transmitted out-of-band (explicit signed)
373       * @param certificates the certificate of the signer (used for alternative signature verification) 
374       * 
375       * @return the inherent message as byte array
376       * 
377       * @throws CMSException if any signature does not verify
378       * @throws IOException if an I/O related error occurs
379       */
380      public byte[] getSignedData(byte[] signedData, byte[] message, X509Certificate[] certificates) 
381        throws CMSException, IOException {
382        
383        ByteArrayInputStream is = new ByteArrayInputStream(signedData);
384        // create the SignedData object
385        SignedData signed_data = new SignedData(is);
386        
387        if (signed_data.getMode() == SignedData.EXPLICIT) {
388          // in explcit mode explictly supply the content data to do the hash calculation
389          signed_data.setContent(message);
390        }
391        
392        System.out.println("SignedData contains the following signer information:");
393        SignerInfo[] signer_infos = signed_data.getSignerInfos();
394        
395        int numberOfSignerInfos = signer_infos.length;
396        if (numberOfSignerInfos == 0) {
397          String warning = "Warning: Unsigned message (no SignerInfo included)!";  
398          System.err.println(warning);
399          throw new CMSException(warning);
400        } else {
401          for (int i = 0; i < numberOfSignerInfos; i++) {
402            try {
403              // verify the signed data using the SignerInfo at index i
404              X509Certificate signer_cert = signed_data.verify(i);
405              // if the signature is OK the certificate of the signer is returned
406              System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN());
407              // check some attributes
408              SigningTime signingTime = (SigningTime)signer_infos[i].getSignedAttributeValue(ObjectID.signingTime);
409              if (signingTime != null) {
410                System.out.println("This message has been signed at " + signingTime.get());
411              } 
412              CMSContentType contentType = (CMSContentType)signer_infos[i].getSignedAttributeValue(ObjectID.contentType);
413              if (contentType != null) {
414                System.out.println("The content has CMS content type " + contentType.get().getName());
415              }
416            } catch (SignatureException ex) {
417              // if the signature is not OK a SignatureException is thrown
418              System.out.println("Signature ERROR from signer: "+signed_data.getCertificate(signer_infos[i].getSignerIdentifier()).getSubjectDN());
419              throw new CMSException(ex.toString());
420            } 
421          }      
422        
423          // now check alternative signature verification
424          System.out.println("Now check the signature assuming that no certs have been included:");
425          try {
426            SignerInfo signer_info = signed_data.verify(certificates[0]);
427            // if the signature is OK the certificate of the signer is returned
428            System.out.println("Signature OK from signer: "+signed_data.getCertificate(signer_info.getSignerIdentifier()).getSubjectDN());
429          } catch (SignatureException ex) {
430            // if the signature is not OK a SignatureException is thrown
431            System.out.println("Signature ERROR from signer: "+certificates[0].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       * Runs the signing - verifying demo.
441       * 
442       * @param message the message to be signed
443       * @param hashAlgorithm the hash algorithm to be used
444       * @param signatureAlgorithm the signature algorithm to be used
445       * @param signerKeyAndCert private key and certificate chain of the signer
446       */
447      public void runDemo(byte[] message, 
448                          AlgorithmID hashAlgorithm,
449                          AlgorithmID signatureAlgorithm,
450                          KeyAndCertificate signerKeyAndCert) 
451        throws Exception {
452        
453        PrivateKey signerKey = signerKeyAndCert.getPrivateKey();
454        X509Certificate[] signerCerts = signerKeyAndCert.getCertificateChain();
455        
456        byte[] encodedSignedData;
457        byte[] received_message = null;
458        
459        System.out.println("\nRun demos for " + hashAlgorithm.getName() 
460                                              + " / " + signatureAlgorithm.getName() 
461                                              + " for " + signerCerts[0].getSubjectDN()
462                                              + "\n");
463          
464        System.out.println("Stream implementation demos");
465        System.out.println("===========================");
466        //
467        // test CMS Implicit SignedDataStream
468        //
469        System.out.println("\nImplicit SignedDataStream demo [create]:\n");
470        encodedSignedData = createSignedDataStream(message, 
471                                                   SignedDataStream.IMPLICIT,
472                                                   hashAlgorithm,
473                                                   signatureAlgorithm,
474                                                   signerKey,
475                                                   signerCerts);
476        System.out.println();
477       
478        // transmit data
479        System.out.println("\nImplicit SignedDataStream demo [parse]:\n");
480        received_message = getSignedDataStream(encodedSignedData, null, signerCerts);
481        System.out.print("\nSigned content: ");
482        System.out.println(new String(received_message));
483          
484        //
485        // test CMS Explicit SignedDataStream
486        //
487        System.out.println("\nExplicit SignedDataStream demo [create]:\n");
488        encodedSignedData = createSignedDataStream(message,
489                                                   SignedDataStream.EXPLICIT,
490                                                   hashAlgorithm,
491                                                   signatureAlgorithm,
492                                                   signerKey,
493                                                   signerCerts);
494        // transmit data
495        System.out.println("\nExplicit SignedDataStream demo [parse]:\n");
496        received_message = getSignedDataStream(encodedSignedData, message, signerCerts);
497        System.out.print("\nSigned content: ");
498        System.out.println(new String(received_message));
499          
500        // the non-stream implementation
501        System.out.println("\nNon-stream implementation demos");
502        System.out.println("===============================");
503    
504        //
505        // test CMS Implicit SignedData
506        //
507        System.out.println("\nImplicit CMS SignedData demo [create]:\n");
508        encodedSignedData = createSignedData(message, 
509                                             SignedData.IMPLICIT,
510                                             hashAlgorithm,
511                                             signatureAlgorithm,
512                                             signerKey,
513                                             signerCerts);
514        // transmit data
515        System.out.println("\nImplicit CMS SignedData demo [parse]:\n");
516        received_message = getSignedData(encodedSignedData, null, signerCerts);
517        System.out.print("\nSigned content: ");
518        System.out.println(new String(received_message));
519    
520        //
521        // test CMS Explicit SignedData
522        //
523        System.out.println("\nExplicit CMS SignedData demo [create]:\n");
524        encodedSignedData = createSignedData(message, 
525                                             SignedData.EXPLICIT,
526                                             hashAlgorithm,
527                                             signatureAlgorithm,
528                                             signerKey,
529                                             signerCerts);
530        // transmit data
531        System.out.println("\nExplicit CMS SignedData demo [parse]:\n");
532        received_message = getSignedData(encodedSignedData, message, signerCerts);
533        System.out.print("\nSigned content: ");
534        System.out.println(new String(received_message));
535            
536      }
537      
538      /**
539       * Tests the CMS SignedData implementation with the ECDSA signature
540       * algorithm and several hash algorithms.
541       */
542      public void start() throws Exception {
543        
544         // the test message
545        String m = "This is the test message.";
546        System.out.println("Test message: \""+m+"\"");
547        System.out.println();
548        byte[] message = m.getBytes();
549    
550        AlgorithmID[][] algorithms = new AlgorithmID[][] {
551                                       { CMSAlgorithmID.sha1, CMSAlgorithmID.ecdsa_With_SHA1 },
552                                       { CMSAlgorithmID.sha224, CMSAlgorithmID.ecdsa_With_SHA224 },
553                                       { CMSAlgorithmID.sha256, CMSAlgorithmID.ecdsa_With_SHA256 },
554                                       { CMSAlgorithmID.sha384, CMSAlgorithmID.ecdsa_With_SHA384 },
555                                       { CMSAlgorithmID.sha512, CMSAlgorithmID.ecdsa_With_SHA512 },
556                                       // ECDSA with RIPEMD-160 in plain format (BSI)
557                                       { CMSAlgorithmID.ripeMd160, CMSAlgorithmID.ecdsa_plain_With_RIPEMD160 },
558                                       
559                                     };
560    
561        // get signer key and certs                                 
562        KeyAndCertificate[] keyAndCerts = {
563          // P-192  
564          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_192_SIGN),
565                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_192_SIGN)),
566          // P-224  
567          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_224_SIGN),
568                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_224_SIGN)),
569          // P-256  
570          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_256_SIGN),
571                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_256_SIGN)),
572          // P-384                      
573          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_384_SIGN),
574                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_384_SIGN)),
575          // P-521                            
576          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_521_SIGN),
577                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_521_SIGN)),                                    
578          // (for ECDSA with RIPEMD-160 in plain format (BSI)  
579          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_192_SIGN),
580                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_192_SIGN)),
581        };  
582        
583        KeyAndCertificate[] brainpoolKeyAndCerts = { 
584          // Brainpool P-192  
585          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_192_BRAINPOOL_SIGN),
586                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_192_BRAINPOOL_SIGN)),
587          // Brainpool P-224  
588          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_224_BRAINPOOL_SIGN),
589                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_224_BRAINPOOL_SIGN)),
590          // Brainpool P-256  
591          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_256_BRAINPOOL_SIGN),
592                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_256_BRAINPOOL_SIGN)),
593          // Brainpool P-384                      
594          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_384_BRAINPOOL_SIGN),
595                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_384_BRAINPOOL_SIGN)),
596          // Brainpool P-512                            
597          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_512_BRAINPOOL_SIGN),
598                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_512_BRAINPOOL_SIGN)),   
599                                
600                                 
601        };
602                                     
603        final int HASH_ALG = 0;
604        final int SIGNATURE_ALG = 1;
605        for (int i = 0; i < keyAndCerts.length; i++) {
606          runDemo(message, algorithms[i][HASH_ALG], algorithms[i][SIGNATURE_ALG], keyAndCerts[i]);
607        }
608        // brainpool
609        for (int i = 0; i < brainpoolKeyAndCerts.length; i++) {
610          runDemo(message, algorithms[i][HASH_ALG], algorithms[i][SIGNATURE_ALG], brainpoolKeyAndCerts[i]);
611        }
612       
613      }  
614      
615      /**
616       * Starts the demo.
617       * 
618       * @throws Exception 
619       *            if an error occurs 
620       */
621      public static void main(String argv[]) throws Exception {
622    
623        DemoUtil.initDemos();
624        ECCDemoUtil.installIaikEccProvider();   
625        (new ECDSASignedDataDemo()).start();
626        System.out.println("\nReady!");
627        System.in.read();
628      }
629        
630    }