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/EdDSASignedDataDemo.java 4     12.02.25 17:58 Dbratko $
059    // $Revision: 4 $
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 EdDSA (Ed25519, Ed448) 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 EdDSASignedDataDemo {
113    
114      /**
115       * Default Constructor.
116       */
117      public EdDSASignedDataDemo() throws Exception {
118        System.out.println();
119        System.out.println("**********************************************************************************");
120        System.out.println("*                           EdDSASignedData demo                                 *");
121        System.out.println("*      (shows how to use the SignedData(Stream) implementation with EdDSA)       *");
122        System.out.println("**********************************************************************************");
123        System.out.println();
124        
125      }
126      
127      /**
128       * Creates an EdDSA 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 eddsaSig = (AlgorithmID)signatureAlgorithm.clone();
167        eddsaSig.encodeAbsentParametersAsNull(false);
168        SignerInfo signer_info = new SignerInfo(issuer, (AlgorithmID)hashAlgorithm.clone(), eddsaSig, signerKey);
169        
170        try {
171          // create some signed attributes
172          // the message digest attribute is automatically added
173          Attribute[] attributes = new Attribute[2];
174          // content type is data
175          CMSContentType contentType = new CMSContentType(ObjectID.cms_data);
176          attributes[0] = new Attribute(contentType);
177          // signing time is now
178          SigningTime signingTime = new SigningTime();
179          attributes[1] = new Attribute(signingTime);
180      
181          // set the attributes
182          signer_info.setSignedAttributes(attributes);
183        } catch (Exception ex) {
184          throw new CMSException("Error adding attributes: " + ex.toString());
185        }
186        
187        // finish the creation of SignerInfo by calling method addSigner
188        try {
189          signed_data.addSignerInfo(signer_info);
190        } catch (NoSuchAlgorithmException ex) {
191          throw new CMSException("No implementation for signature algorithm: "+ex.getMessage());
192        }
193    
194        // write the data through SignedData to any out-of-band place
195        if (mode == SignedDataStream.EXPLICIT) {
196          InputStream data_is = signed_data.getInputStream();
197          byte[] buf = new byte[1024];
198          int r;
199          while ((r = data_is.read(buf)) > 0) {
200            ;   // skip data
201          }  
202        }
203    
204        signed_data.setBlockSize(2048);
205         // create the ContentInfo
206        ContentInfoStream cis = new ContentInfoStream(signed_data);
207        // return the SignedData as DER encoded byte array with block size 2048
208        ByteArrayOutputStream os = new ByteArrayOutputStream();
209        cis.writeTo(os);
210        return os.toByteArray();
211      }
212      
213      
214      /**
215       * Parses a CMS <code>ContentInfo</code> object holding a <code>SignedData</code> 
216       * object and verifies the signature.
217       *
218       * @param signedData the <code>ContentInfo</code> holding the <code>SignedData</code> 
219       *                   object as BER encoded byte array
220       * @param message the the message which was transmitted out-of-band (explicit signed)
221       * @param certificates the certificate of the signer (used for alternative signature verification)
222       * 
223       * @return the inherent message as byte array
224       * 
225       * @throws CMSException if any signature does not verify
226       * @throws IOException if an I/O related error occurs
227       */
228      public byte[] getSignedDataStream(byte[] signedData, byte[] message, X509Certificate[] certificates) 
229        throws CMSException, IOException {
230    
231        // we are testing the stream interface
232        ByteArrayInputStream is = new ByteArrayInputStream(signedData);
233    
234        SignedDataStream signed_data = new SignedDataStream(is);
235    
236        if (signed_data.getMode() == SignedDataStream.EXPLICIT) {
237          // in explicit mode explicitly supply the content for hash computation
238          signed_data.setInputStream(new ByteArrayInputStream(message));
239        }
240    
241        // get an InputStream for reading the signed content and update hash computation
242        InputStream data = signed_data.getInputStream();
243        ByteArrayOutputStream os = new ByteArrayOutputStream();
244        Util.copyStream(data, os, null);
245    
246        System.out.println("SignedData contains the following signer information:");
247        SignerInfo[] signer_infos = signed_data.getSignerInfos();
248        
249        int numberOfSignerInfos = signer_infos.length;
250        if (numberOfSignerInfos == 0) {
251          String warning = "Warning: Unsigned message (no SignerInfo included)!";  
252          System.err.println(warning);
253          throw new CMSException(warning);
254        } else {
255          for (int i = 0; i < numberOfSignerInfos; i++) {
256            try {
257              // verify the signed data using the SignerInfo at index i
258              X509Certificate signer_cert = signed_data.verify(i);
259              // if the signature is OK the certificate of the signer is returned
260              System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN());
261              // check for some included attributes
262              SigningTime signingTime = (SigningTime)signer_infos[i].getSignedAttributeValue(ObjectID.signingTime);
263              if (signingTime != null) {
264                System.out.println("This message has been signed at " + signingTime.get());
265              } 
266              CMSContentType contentType = (CMSContentType)signer_infos[i].getSignedAttributeValue(ObjectID.contentType);
267              if (contentType != null) {
268                System.out.println("The content has CMS content type " + contentType.get().getName());
269              }  
270            } catch (SignatureException ex) {
271              // if the signature is not OK a SignatureException is thrown
272              System.out.println("Signature ERROR from signer: "+signed_data.getCertificate(signer_infos[i].getSignerIdentifier()).getSubjectDN());
273              throw new CMSException(ex.toString());
274            }  
275          }  
276          // now check alternative signature verification
277          System.out.println("Now check the signature assuming that no certs have been included:");
278          try {
279            SignerInfo signer_info = signed_data.verify(certificates[0]);
280            // if the signature is OK the certificate of the signer is returned
281            System.out.println("Signature OK from signer: "+signed_data.getCertificate(signer_info.getSignerIdentifier()).getSubjectDN());
282          } catch (SignatureException ex) {
283            // if the signature is not OK a SignatureException is thrown
284            System.out.println("Signature ERROR from signer: "+certificates[0].getSubjectDN());
285            throw new CMSException(ex.toString());
286          }
287          // in practice we also would validate the signer certificate(s)  
288        }      
289        return os.toByteArray();
290      }
291      
292      
293      /**
294       * Creates an EdDSA signed CMS <code>SignedData</code> object and wraps it by a CMS
295       * <code>ContentInfo</code> object.
296       * <p>
297       *
298       * @param message the message to be signed, as byte representation
299       * @param mode the mode, either SignedData.IMPLICIT or SignedData.EXPLICIT
300       * @param hashAlgorithm the hash algorithm to be used
301       * @param signatureAlgorithm the signature algorithm to be used
302       * @param signerKey the private key of the signer
303       * @param certificates the certificate chain of the signer
304       * 
305       * @return the DER encoded <code>SignedData</code>-<code>ContentInfo</code> object
306       *  
307       * @throws CMSException if the <code>SignedData</code>-<code>ContentInfo</code> object cannot
308       *                          be created
309       * @throws IOException if an I/O related error occurs
310       */
311      public byte[] createSignedData(byte[] message, 
312                                     int mode,
313                                     AlgorithmID hashAlgorithm,
314                                     AlgorithmID signatureAlgorithm,
315                                     PrivateKey signerKey,
316                                     X509Certificate[] certificates) 
317        throws CMSException, IOException  {
318        
319        System.out.println("Create a new message signed with " + signatureAlgorithm.getName());
320      
321        // create a new SignedData object which includes the data
322        SignedData signed_data = new SignedData(message, mode);
323        
324        // SignedData shall include the certificate chain for verifying
325        signed_data.setCertificates(certificates);
326      
327        // cert at index 0 is the user certificate
328        IssuerAndSerialNumber issuer = new IssuerAndSerialNumber(certificates[0]);
329    
330        // create a new SignerInfo
331        AlgorithmID eddsaSig = (AlgorithmID)signatureAlgorithm.clone();
332        eddsaSig.encodeAbsentParametersAsNull(false);
333        SignerInfo signer_info = new SignerInfo(issuer, (AlgorithmID)hashAlgorithm.clone(), eddsaSig, signerKey);
334        
335        try {
336          // create some signed attributes
337          // the message digest attribute is automatically added
338          Attribute[] attributes = new Attribute[2];
339          // content type is data
340          CMSContentType contentType = new CMSContentType(ObjectID.cms_data);
341          attributes[0] = new Attribute(contentType);
342          // signing time is now
343          SigningTime signingTime = new SigningTime();
344          attributes[1] = new Attribute(signingTime);
345      
346          // set the attributes
347          signer_info.setSignedAttributes(attributes);
348        } catch (Exception ex) {
349          throw new CMSException("Error adding attributes: " + ex.toString());
350        }
351        
352        // finish the creation of SignerInfo by calling method addSigner
353        try {
354          signed_data.addSignerInfo(signer_info);
355        } catch (NoSuchAlgorithmException ex) {
356          throw new CMSException("No implementation for signature algorithm: "+ex.getMessage());
357        }
358    
359        ContentInfo ci = new ContentInfo(signed_data); 
360        return ci.getEncoded();
361      }
362      
363      
364      /**
365       * Parses a CMS <code>ContentInfo</code> holding a <code>SignedData</code> 
366       * object and verifies the signature.
367       *
368       * @param signedData the <code>ContentInfo</code> holding the <code>SignedData</code> 
369       *                   object as DER encoded byte array
370       * @param message the message which was transmitted out-of-band (explicit signed)
371       * @param certificates the certificate of the signer (used for alternative signature verification) 
372       * 
373       * @return the inherent message as byte array
374       * 
375       * @throws CMSException if any signature does not verify
376       * @throws IOException if an I/O related error occurs
377       */
378      public byte[] getSignedData(byte[] signedData, byte[] message, X509Certificate[] certificates) 
379        throws CMSException, IOException {
380        
381        ByteArrayInputStream is = new ByteArrayInputStream(signedData);
382        // create the SignedData object
383        SignedData signed_data = new SignedData(is);
384        
385        if (signed_data.getMode() == SignedData.EXPLICIT) {
386          // in explcit mode explictly supply the content data to do the hash calculation
387          signed_data.setContent(message);
388        }
389        
390        System.out.println("SignedData contains the following signer information:");
391        SignerInfo[] signer_infos = signed_data.getSignerInfos();
392        
393        int numberOfSignerInfos = signer_infos.length;
394        if (numberOfSignerInfos == 0) {
395          String warning = "Warning: Unsigned message (no SignerInfo included)!";  
396          System.err.println(warning);
397          throw new CMSException(warning);
398        } else {
399          for (int i = 0; i < numberOfSignerInfos; i++) {
400            try {
401              // verify the signed data using the SignerInfo at index i
402              X509Certificate signer_cert = signed_data.verify(i);
403              // if the signature is OK the certificate of the signer is returned
404              System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN());
405              // check some attributes
406              SigningTime signingTime = (SigningTime)signer_infos[i].getSignedAttributeValue(ObjectID.signingTime);
407              if (signingTime != null) {
408                System.out.println("This message has been signed at " + signingTime.get());
409              } 
410              CMSContentType contentType = (CMSContentType)signer_infos[i].getSignedAttributeValue(ObjectID.contentType);
411              if (contentType != null) {
412                System.out.println("The content has CMS content type " + contentType.get().getName());
413              }
414            } catch (SignatureException ex) {
415              // if the signature is not OK a SignatureException is thrown
416              System.out.println("Signature ERROR from signer: "+signed_data.getCertificate(signer_infos[i].getSignerIdentifier()).getSubjectDN());
417              throw new CMSException(ex.toString());
418            } 
419          }      
420        
421          // now check alternative signature verification
422          System.out.println("Now check the signature assuming that no certs have been included:");
423          try {
424            SignerInfo signer_info = signed_data.verify(certificates[0]);
425            // if the signature is OK the certificate of the signer is returned
426            System.out.println("Signature OK from signer: "+signed_data.getCertificate(signer_info.getSignerIdentifier()).getSubjectDN());
427          } catch (SignatureException ex) {
428            // if the signature is not OK a SignatureException is thrown
429            System.out.println("Signature ERROR from signer: "+certificates[0].getSubjectDN());
430            throw new CMSException(ex.toString());
431          }
432          // in practice we also would validate the signer certificate(s)  
433        }      
434        return signed_data.getContent();
435      }
436    
437      /**
438       * Runs the signing - verifying demo.
439       * 
440       * @param message the message to be signed
441       * @param hashAlgorithm the hash algorithm to be used
442       * @param signatureAlgorithm the signature algorithm to be used
443       * @param signerKeyAndCert private key and certificate chain of the signer
444       */
445      public void runDemo(byte[] message, 
446                          AlgorithmID hashAlgorithm,
447                          AlgorithmID signatureAlgorithm,
448                          KeyAndCertificate signerKeyAndCert) 
449        throws Exception {
450        
451        PrivateKey signerKey = signerKeyAndCert.getPrivateKey();
452        X509Certificate[] signerCerts = signerKeyAndCert.getCertificateChain();
453        
454        byte[] encodedSignedData;
455        byte[] received_message = null;
456        
457        System.out.println("\nRun demos for " + hashAlgorithm.getName() + " / " + signatureAlgorithm.getName() + "\n");
458          
459        System.out.println("Stream implementation demos");
460        System.out.println("===========================");
461        //
462        // test CMS Implicit SignedDataStream
463        //
464        System.out.println("\nImplicit SignedDataStream demo [create]:\n");
465        encodedSignedData = createSignedDataStream(message, 
466                                                   SignedDataStream.IMPLICIT,
467                                                   hashAlgorithm,
468                                                   signatureAlgorithm,
469                                                   signerKey,
470                                                   signerCerts);
471        System.out.println();
472        // transmit data
473        System.out.println("\nImplicit SignedDataStream demo [parse]:\n");
474        received_message = getSignedDataStream(encodedSignedData, null, signerCerts);
475        System.out.print("\nSigned content: ");
476        System.out.println(new String(received_message));
477          
478        //
479        // test CMS Explicit SignedDataStream
480        //
481        System.out.println("\nExplicit SignedDataStream demo [create]:\n");
482        encodedSignedData = createSignedDataStream(message,
483                                                   SignedDataStream.EXPLICIT,
484                                                   hashAlgorithm,
485                                                   signatureAlgorithm,
486                                                   signerKey,
487                                                   signerCerts);
488        // transmit data
489        System.out.println("\nExplicit SignedDataStream demo [parse]:\n");
490        received_message = getSignedDataStream(encodedSignedData, message, signerCerts);
491        System.out.print("\nSigned content: ");
492        System.out.println(new String(received_message));
493          
494        // the non-stream implementation
495        System.out.println("\nNon-stream implementation demos");
496        System.out.println("===============================");
497    
498        //
499        // test CMS Implicit SignedData
500        //
501        System.out.println("\nImplicit CMS SignedData demo [create]:\n");
502        encodedSignedData = createSignedData(message, 
503                                             SignedData.IMPLICIT,
504                                             hashAlgorithm,
505                                             signatureAlgorithm,
506                                             signerKey,
507                                             signerCerts);
508        // transmit data
509        System.out.println("\nImplicit CMS SignedData demo [parse]:\n");
510        received_message = getSignedData(encodedSignedData, null, signerCerts);
511        System.out.print("\nSigned content: ");
512        System.out.println(new String(received_message));
513    
514        //
515        // test CMS Explicit SignedData
516        //
517        System.out.println("\nExplicit CMS SignedData demo [create]:\n");
518        encodedSignedData = createSignedData(message, 
519                                             SignedData.EXPLICIT,
520                                             hashAlgorithm,
521                                             signatureAlgorithm,
522                                             signerKey,
523                                             signerCerts);
524        // transmit data
525        System.out.println("\nExplicit CMS SignedData demo [parse]:\n");
526        received_message = getSignedData(encodedSignedData, message, signerCerts);
527        System.out.print("\nSigned content: ");
528        System.out.println(new String(received_message));
529            
530      }
531      
532      /**
533       * Tests the CMS SignedData implementation with the ECDSA signature
534       * algorithm and several hash algorithms.
535       */
536      public void start() throws Exception {
537        
538         // the test message
539        String m = "This is the test message.";
540        System.out.println("Test message: \""+m+"\"");
541        System.out.println();
542        byte[] message = m.getBytes();
543    
544        AlgorithmID[][] algorithms = new AlgorithmID[][] {
545                                       { CMSAlgorithmID.sha512, CMSAlgorithmID.ed25519},
546                                       { CMSAlgorithmID.shake256Len, CMSAlgorithmID.ed448 },
547                                     };
548    
549        // get signer key and certs                                 
550        KeyAndCertificate[] keyAndCerts = {
551          // ed25519  
552          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_ED25519),
553                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_ED25519)),
554          // ed448  
555          new KeyAndCertificate(CMSEccKeyStore.getPrivateKey(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_ED448),
556                                CMSEccKeyStore.getCertificateChain(CMSEccKeyStore.ECDSA, CMSEccKeyStore.SZ_ED448)),
557                                 
558        };
559                                     
560        final int HASH_ALG = 0;
561        final int SIGNATURE_ALG = 1;
562        for (int i = 0; i < algorithms.length; i++) {
563          runDemo(message, algorithms[i][HASH_ALG], algorithms[i][SIGNATURE_ALG], keyAndCerts[i]);
564        }
565       
566      }  
567      
568      /**
569       * Starts the demo.
570       * 
571       * @throws Exception 
572       *            if an error occurs 
573       */
574      public static void main(String argv[]) throws Exception {
575    
576        DemoUtil.initDemos();
577        ECCDemoUtil.installIaikEccelerateProvider();   
578        (new EdDSASignedDataDemo()).start();
579        System.out.println("\nReady!");
580        System.in.read();
581      }
582        
583    }