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 }