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