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 }