View Javadoc
1   /*
2    * GordianKnot: Security Suite
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  package io.github.tonywasher.joceanus.gordianknot.impl.jca;
18  
19  import io.github.tonywasher.joceanus.gordianknot.api.base.GordianException;
20  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianDHGroup;
21  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianDSAKeyType;
22  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianKeyPair;
23  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianKeyPairSpec;
24  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianLMSKeySpec;
25  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianLMSKeySpec.GordianHSSKeySpec;
26  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianRSAModulus;
27  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianXMSSKeySpec;
28  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianXMSSKeySpec.GordianXMSSDigestType;
29  import io.github.tonywasher.joceanus.gordianknot.impl.core.base.GordianBaseFactory;
30  import io.github.tonywasher.joceanus.gordianknot.impl.core.exc.GordianCryptoException;
31  import io.github.tonywasher.joceanus.gordianknot.impl.core.exc.GordianLogicException;
32  import io.github.tonywasher.joceanus.gordianknot.impl.core.keypair.GordianCoreKeyPairGenerator;
33  import io.github.tonywasher.joceanus.gordianknot.impl.core.keypair.GordianKeyPairValidity;
34  import io.github.tonywasher.joceanus.gordianknot.impl.jca.JcaKeyPair.JcaDHPrivateKey;
35  import io.github.tonywasher.joceanus.gordianknot.impl.jca.JcaKeyPair.JcaDHPublicKey;
36  import io.github.tonywasher.joceanus.gordianknot.impl.jca.JcaKeyPair.JcaPrivateKey;
37  import io.github.tonywasher.joceanus.gordianknot.impl.jca.JcaKeyPair.JcaPublicKey;
38  import io.github.tonywasher.joceanus.gordianknot.impl.jca.JcaKeyPair.JcaStateAwareKeyPair;
39  import io.github.tonywasher.joceanus.gordianknot.impl.jca.JcaKeyPair.JcaStateAwarePrivateKey;
40  import org.bouncycastle.crypto.params.DHParameters;
41  import org.bouncycastle.jcajce.provider.asymmetric.dh.BCDHPrivateKey;
42  import org.bouncycastle.jcajce.provider.asymmetric.dh.BCDHPublicKey;
43  import org.bouncycastle.jcajce.spec.DHDomainParameterSpec;
44  import org.bouncycastle.jcajce.spec.EdDSAParameterSpec;
45  import org.bouncycastle.jcajce.spec.MLDSAParameterSpec;
46  import org.bouncycastle.jcajce.spec.MLKEMParameterSpec;
47  import org.bouncycastle.jcajce.spec.SLHDSAParameterSpec;
48  import org.bouncycastle.jcajce.spec.XDHParameterSpec;
49  import org.bouncycastle.jce.spec.ElGamalParameterSpec;
50  import org.bouncycastle.pqc.crypto.lms.LMSParameters;
51  import org.bouncycastle.pqc.jcajce.spec.BIKEParameterSpec;
52  import org.bouncycastle.pqc.jcajce.spec.CMCEParameterSpec;
53  import org.bouncycastle.pqc.jcajce.spec.FalconParameterSpec;
54  import org.bouncycastle.pqc.jcajce.spec.FrodoParameterSpec;
55  import org.bouncycastle.pqc.jcajce.spec.HQCParameterSpec;
56  import org.bouncycastle.pqc.jcajce.spec.LMSHSSKeyGenParameterSpec;
57  import org.bouncycastle.pqc.jcajce.spec.LMSKeyGenParameterSpec;
58  import org.bouncycastle.pqc.jcajce.spec.MayoParameterSpec;
59  import org.bouncycastle.pqc.jcajce.spec.NTRULPRimeParameterSpec;
60  import org.bouncycastle.pqc.jcajce.spec.NTRUParameterSpec;
61  import org.bouncycastle.pqc.jcajce.spec.PicnicParameterSpec;
62  import org.bouncycastle.pqc.jcajce.spec.SABERParameterSpec;
63  import org.bouncycastle.pqc.jcajce.spec.SNTRUPrimeParameterSpec;
64  import org.bouncycastle.pqc.jcajce.spec.SnovaParameterSpec;
65  import org.bouncycastle.pqc.jcajce.spec.XMSSMTParameterSpec;
66  import org.bouncycastle.pqc.jcajce.spec.XMSSParameterSpec;
67  
68  import java.security.InvalidAlgorithmParameterException;
69  import java.security.KeyFactory;
70  import java.security.KeyPair;
71  import java.security.KeyPairGenerator;
72  import java.security.NoSuchAlgorithmException;
73  import java.security.PrivateKey;
74  import java.security.PublicKey;
75  import java.security.spec.AlgorithmParameterSpec;
76  import java.security.spec.ECGenParameterSpec;
77  import java.security.spec.InvalidKeySpecException;
78  import java.security.spec.PKCS8EncodedKeySpec;
79  import java.security.spec.X509EncodedKeySpec;
80  import java.util.Arrays;
81  
82  /**
83   * Jca KeyPair generator.
84   */
85  public abstract class JcaKeyPairGenerator
86          extends GordianCoreKeyPairGenerator {
87      /**
88       * Parse error.
89       */
90      private static final String PARSE_ERROR = "Failed to parse encoding";
91  
92      /**
93       * Factory.
94       */
95      private KeyFactory theFactory;
96  
97      /**
98       * Constructor.
99       *
100      * @param pFactory the Security Factory
101      * @param pKeySpec the keySpec
102      */
103     JcaKeyPairGenerator(final GordianBaseFactory pFactory,
104                         final GordianKeyPairSpec pKeySpec) {
105         super(pFactory, pKeySpec);
106     }
107 
108     /**
109      * Obtain Set the key factory.
110      *
111      * @return the keyFactory
112      */
113     KeyFactory getKeyFactory() {
114         return theFactory;
115     }
116 
117     /**
118      * Set the key factory.
119      *
120      * @param pFactory the keyFactory
121      */
122     void setKeyFactory(final KeyFactory pFactory) {
123         theFactory = pFactory;
124     }
125 
126     @Override
127     public PKCS8EncodedKeySpec getPKCS8Encoding(final GordianKeyPair pKeyPair) throws GordianException {
128         /* Check the keyPair */
129         JcaKeyPair.checkKeyPair(pKeyPair);
130 
131         /* derive the encoding */
132         final JcaPrivateKey myPrivateKey = (JcaPrivateKey) getPrivateKey(pKeyPair);
133         return new PKCS8EncodedKeySpec(myPrivateKey.getPrivateKey().getEncoded());
134     }
135 
136     @Override
137     public X509EncodedKeySpec getX509Encoding(final GordianKeyPair pKeyPair) throws GordianException {
138         /* Check the keyPair */
139         JcaKeyPair.checkKeyPair(pKeyPair);
140 
141         /* derive the encoding */
142         final JcaPublicKey myPublicKey = (JcaPublicKey) getPublicKey(pKeyPair);
143         return new X509EncodedKeySpec(myPublicKey.getPublicKey().getEncoded());
144     }
145 
146     @Override
147     public JcaKeyPair deriveKeyPair(final X509EncodedKeySpec pPublicKey,
148                                     final PKCS8EncodedKeySpec pPrivateKey) throws GordianException {
149         /* Protect against exceptions */
150         try {
151             /* Check the keySpec */
152             checkKeySpec(pPrivateKey);
153 
154             /* derive the keyPair */
155             final JcaPublicKey myPublic = derivePublicKey(pPublicKey);
156             final JcaPrivateKey myPrivate = createPrivate(theFactory.generatePrivate(pPrivateKey));
157             final JcaKeyPair myPair = new JcaKeyPair(myPublic, myPrivate);
158 
159             /* Check that we have a matching pair */
160             GordianKeyPairValidity.checkValidity(getFactory(), myPair);
161 
162             /* Return the keyPair */
163             return myPair;
164 
165         } catch (InvalidKeySpecException e) {
166             throw new GordianCryptoException(PARSE_ERROR, e);
167         }
168     }
169 
170     /**
171      * Create private key.
172      *
173      * @param pPrivateKey the private key
174      * @return the private key
175      */
176     protected JcaPrivateKey createPrivate(final PrivateKey pPrivateKey) {
177         return new JcaPrivateKey(getKeySpec(), pPrivateKey);
178     }
179 
180     /**
181      * Create public key.
182      *
183      * @param pPublicKey the public key
184      * @return the public key
185      */
186     protected JcaPublicKey createPublic(final PublicKey pPublicKey) {
187         return new JcaPublicKey(getKeySpec(), pPublicKey);
188     }
189 
190     @Override
191     public JcaKeyPair derivePublicOnlyKeyPair(final X509EncodedKeySpec pPublicKey) throws GordianException {
192         final JcaPublicKey myPublic = derivePublicKey(pPublicKey);
193         return new JcaKeyPair(myPublic);
194     }
195 
196     /**
197      * Derive the public key.
198      *
199      * @param pEncodedKey the encoded public key
200      * @return the public key
201      * @throws GordianException on error
202      */
203     protected JcaPublicKey derivePublicKey(final X509EncodedKeySpec pEncodedKey) throws GordianException {
204         /* Protect against exceptions */
205         try {
206             /* Check the keySpec */
207             checkKeySpec(pEncodedKey);
208 
209             /* derive the key */
210             return createPublic(theFactory.generatePublic(pEncodedKey));
211 
212         } catch (InvalidKeySpecException e) {
213             throw new GordianCryptoException(PARSE_ERROR, e);
214         }
215     }
216 
217     /**
218      * Jca RSA KeyPair generator.
219      */
220     public static class JcaRSAKeyPairGenerator
221             extends JcaKeyPairGenerator {
222         /**
223          * RSA algorithm.
224          */
225         private static final String RSA_ALGO = "RSA";
226 
227         /**
228          * Generator.
229          */
230         private final KeyPairGenerator theGenerator;
231 
232         /**
233          * Constructor.
234          *
235          * @param pFactory the Security Factory
236          * @param pKeySpec the keySpec
237          * @throws GordianException on error
238          */
239         JcaRSAKeyPairGenerator(final GordianBaseFactory pFactory,
240                                final GordianKeyPairSpec pKeySpec) throws GordianException {
241             /* initialize underlying class */
242             super(pFactory, pKeySpec);
243 
244             /* Create and initialize the generator */
245             theGenerator = getJavaKeyPairGenerator(RSA_ALGO, false);
246             theGenerator.initialize(pKeySpec.getRSAModulus().getLength(), getRandom());
247 
248             /* Create the factory */
249             setKeyFactory(getJavaKeyFactory(RSA_ALGO, false));
250         }
251 
252         @Override
253         public JcaKeyPair generateKeyPair() {
254             /* Generate and return the keyPair */
255             final KeyPair myPair = theGenerator.generateKeyPair();
256             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
257             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
258             return new JcaKeyPair(myPublic, myPrivate);
259         }
260     }
261 
262     /**
263      * Jca ElGamal KeyPair generator.
264      */
265     public static class JcaElGamalKeyPairGenerator
266             extends JcaKeyPairGenerator {
267         /**
268          * RSA algorithm.
269          */
270         private static final String ELGAMAL_ALGO = "ELGAMAL";
271 
272         /**
273          * Generator.
274          */
275         private final KeyPairGenerator theGenerator;
276 
277         /**
278          * Constructor.
279          *
280          * @param pFactory the Security Factory
281          * @param pKeySpec the keySpec
282          * @throws GordianException on error
283          */
284         JcaElGamalKeyPairGenerator(final GordianBaseFactory pFactory,
285                                    final GordianKeyPairSpec pKeySpec) throws GordianException {
286             /* initialize underlying class */
287             super(pFactory, pKeySpec);
288 
289             /* Protect against exceptions */
290             try {
291                 /* Create the parameter generator */
292                 final GordianDHGroup myGroup = pKeySpec.getDHGroup();
293                 final DHParameters myParms = myGroup.getParameters();
294                 final ElGamalParameterSpec mySpec = new ElGamalParameterSpec(myParms.getP(), myParms.getQ());
295 
296                 /* Create and initialize the generator */
297                 theGenerator = getJavaKeyPairGenerator(ELGAMAL_ALGO, false);
298                 theGenerator.initialize(mySpec, getRandom());
299 
300                 /* Create the factory */
301                 setKeyFactory(getJavaKeyFactory(ELGAMAL_ALGO, false));
302 
303             } catch (InvalidAlgorithmParameterException e) {
304                 throw new GordianCryptoException("Failed to create ElGamalGenerator", e);
305             }
306         }
307 
308         @Override
309         public JcaKeyPair generateKeyPair() {
310             /* Generate and return the keyPair */
311             final KeyPair myPair = theGenerator.generateKeyPair();
312             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
313             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
314             return new JcaKeyPair(myPublic, myPrivate);
315         }
316     }
317 
318     /**
319      * Jca Elliptic KeyPair generator.
320      */
321     public static class JcaECKeyPairGenerator
322             extends JcaKeyPairGenerator {
323         /**
324          * Generator.
325          */
326         private final KeyPairGenerator theGenerator;
327 
328         /**
329          * Constructor.
330          *
331          * @param pFactory the Security Factory
332          * @param pKeySpec the keySpec
333          * @throws GordianException on error
334          */
335         JcaECKeyPairGenerator(final GordianBaseFactory pFactory,
336                               final GordianKeyPairSpec pKeySpec) throws GordianException {
337             /* initialize underlying class */
338             super(pFactory, pKeySpec);
339 
340             /* Protect against exceptions */
341             try {
342                 /* Create and initialize the generator */
343                 final String myAlgo = getAlgorithm();
344                 theGenerator = getJavaKeyPairGenerator(myAlgo, false);
345                 final ECGenParameterSpec myParms = new ECGenParameterSpec(pKeySpec.getElliptic().getCurveName());
346                 theGenerator.initialize(myParms, getRandom());
347 
348                 /* Create the factory */
349                 setKeyFactory(getJavaKeyFactory(myAlgo, false));
350 
351             } catch (InvalidAlgorithmParameterException e) {
352                 throw new GordianCryptoException("Failed to create ECgenerator for:  " + pKeySpec, e);
353             }
354         }
355 
356         @Override
357         public JcaKeyPair generateKeyPair() {
358             /* Generate and return the keyPair */
359             final KeyPair myPair = theGenerator.generateKeyPair();
360             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
361             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
362             return new JcaKeyPair(myPublic, myPrivate);
363         }
364 
365         /**
366          * Obtain algorithm for keySpec.
367          *
368          * @return the algorithm
369          */
370         private String getAlgorithm() {
371             switch (this.getKeySpec().getKeyPairType()) {
372                 case DSTU4145:
373                     return "DSTU4145";
374                 case GOST2012:
375                     return "ECGOST3410-2012";
376                 default:
377                     return "EC";
378             }
379         }
380     }
381 
382     /**
383      * Jca DSA KeyPair generator.
384      */
385     public static class JcaDSAKeyPairGenerator
386             extends JcaKeyPairGenerator {
387         /**
388          * DSA algorithm.
389          */
390         private static final String DSA_ALGO = "DSA";
391 
392         /**
393          * Generator.
394          */
395         private final KeyPairGenerator theGenerator;
396 
397         /**
398          * Constructor.
399          *
400          * @param pFactory the Security Factory
401          * @param pKeySpec the keySpec
402          * @throws GordianException on error
403          */
404         JcaDSAKeyPairGenerator(final GordianBaseFactory pFactory,
405                                final GordianKeyPairSpec pKeySpec) throws GordianException {
406             /* initialize underlying class */
407             super(pFactory, pKeySpec);
408 
409             /* Create and initialize the generator */
410             final GordianDSAKeyType myKeyType = pKeySpec.getDSAKeyType();
411             theGenerator = getJavaKeyPairGenerator(DSA_ALGO, false);
412             theGenerator.initialize(myKeyType.getKeySize(), getRandom());
413 
414             /* Create the factory */
415             setKeyFactory(getJavaKeyFactory(DSA_ALGO, false));
416         }
417 
418         @Override
419         public JcaKeyPair generateKeyPair() {
420             /* Generate and return the keyPair */
421             final KeyPair myPair = theGenerator.generateKeyPair();
422             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
423             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
424             return new JcaKeyPair(myPublic, myPrivate);
425         }
426     }
427 
428     /**
429      * Jca DiffieHellman KeyPair generator.
430      */
431     public static class JcaDHKeyPairGenerator
432             extends JcaKeyPairGenerator {
433         /**
434          * DH algorithm.
435          */
436         private static final String DH_ALGO = "DH";
437 
438         /**
439          * Generator.
440          */
441         private final KeyPairGenerator theGenerator;
442 
443         /**
444          * Constructor.
445          *
446          * @param pFactory the Security Factory
447          * @param pKeySpec the keySpec
448          * @throws GordianException on error
449          */
450         JcaDHKeyPairGenerator(final GordianBaseFactory pFactory,
451                               final GordianKeyPairSpec pKeySpec) throws GordianException {
452             /* initialize underlying class */
453             super(pFactory, pKeySpec);
454 
455             /* Protect against exceptions */
456             try {
457                 /* Create the parameter generator */
458                 final GordianDHGroup myGroup = pKeySpec.getDHGroup();
459                 final DHParameters myParms = myGroup.getParameters();
460                 final DHDomainParameterSpec mySpec = new DHDomainParameterSpec(myParms);
461 
462                 /* Create and initialize the generator */
463                 theGenerator = getJavaKeyPairGenerator(DH_ALGO, false);
464                 theGenerator.initialize(mySpec, getRandom());
465 
466                 /* Create the factory */
467                 setKeyFactory(getJavaKeyFactory(DH_ALGO, false));
468 
469             } catch (InvalidAlgorithmParameterException e) {
470                 throw new GordianCryptoException("Failed to create DHgenerator", e);
471             }
472         }
473 
474         @Override
475         public JcaKeyPair generateKeyPair() {
476             /* Generate and return the keyPair */
477             final KeyPair myPair = theGenerator.generateKeyPair();
478             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
479             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
480             return new JcaKeyPair(myPublic, myPrivate);
481         }
482 
483         @Override
484         protected JcaPrivateKey createPrivate(final PrivateKey pPrivateKey) {
485             return new JcaDHPrivateKey(getKeySpec(), (BCDHPrivateKey) pPrivateKey);
486         }
487 
488         @Override
489         protected JcaPublicKey createPublic(final PublicKey pPublicKey) {
490             return new JcaDHPublicKey(getKeySpec(), (BCDHPublicKey) pPublicKey);
491         }
492     }
493 
494     /**
495      * Jca SLHDSA KeyPair generator.
496      */
497     public static class JcaSLHDSAKeyPairGenerator
498             extends JcaKeyPairGenerator {
499         /**
500          * SLHDSA algorithm.
501          */
502         private static final String SLHDSA_ALGO = "SLH-DSA";
503 
504         /**
505          * HASH indication.
506          */
507         private static final String SLHDSA_HASH = "HASH-" + SLHDSA_ALGO;
508 
509         /**
510          * Generator.
511          */
512         private final KeyPairGenerator theGenerator;
513 
514         /**
515          * Constructor.
516          *
517          * @param pFactory the Security Factory
518          * @param pKeySpec the keySpec
519          * @throws GordianException on error
520          */
521         JcaSLHDSAKeyPairGenerator(final GordianBaseFactory pFactory,
522                                   final GordianKeyPairSpec pKeySpec) throws GordianException {
523             /* initialize underlying class */
524             super(pFactory, pKeySpec);
525 
526             /* Protect against exceptions */
527             try {
528                 /* Determine algorithm */
529                 final String myAlgo = pKeySpec.getSLHDSAKeySpec().isHash() ? SLHDSA_HASH : SLHDSA_ALGO;
530 
531                 /* Create and initialize the generator */
532                 theGenerator = getJavaKeyPairGenerator(myAlgo, false);
533                 final SLHDSAParameterSpec myParms = pKeySpec.getSLHDSAKeySpec().getParameterSpec();
534                 theGenerator.initialize(myParms, getRandom());
535 
536                 /* Create the factory */
537                 setKeyFactory(getJavaKeyFactory(myAlgo, false));
538 
539             } catch (InvalidAlgorithmParameterException e) {
540                 throw new GordianCryptoException("Failed to create SLHDSAgenerator", e);
541             }
542         }
543 
544         @Override
545         public JcaKeyPair generateKeyPair() {
546             /* Generate and return the keyPair */
547             final KeyPair myPair = theGenerator.generateKeyPair();
548             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
549             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
550             return new JcaKeyPair(myPublic, myPrivate);
551         }
552     }
553 
554     /**
555      * Jca CMCE KeyPair generator.
556      */
557     public static class JcaCMCEKeyPairGenerator
558             extends JcaKeyPairGenerator {
559         /**
560          * FRODO algorithm.
561          */
562         private static final String CMCE_ALGO = "CMCE";
563 
564         /**
565          * Generator.
566          */
567         private final KeyPairGenerator theGenerator;
568 
569         /**
570          * Constructor.
571          *
572          * @param pFactory the Security Factory
573          * @param pKeySpec the keySpec
574          * @throws GordianException on error
575          */
576         JcaCMCEKeyPairGenerator(final GordianBaseFactory pFactory,
577                                 final GordianKeyPairSpec pKeySpec) throws GordianException {
578             /* initialize underlying class */
579             super(pFactory, pKeySpec);
580 
581             /* Protect against exceptions */
582             try {
583                 /* Create and initialize the generator */
584                 theGenerator = getJavaKeyPairGenerator(CMCE_ALGO, true);
585                 final CMCEParameterSpec myParms = pKeySpec.getCMCEKeySpec().getParameterSpec();
586                 theGenerator.initialize(myParms, getRandom());
587 
588                 /* Create the factory */
589                 setKeyFactory(getJavaKeyFactory(CMCE_ALGO, true));
590 
591             } catch (InvalidAlgorithmParameterException e) {
592                 throw new GordianCryptoException("Failed to create CMCEgenerator", e);
593             }
594         }
595 
596         @Override
597         public JcaKeyPair generateKeyPair() {
598             /* Generate and return the keyPair */
599             final KeyPair myPair = theGenerator.generateKeyPair();
600             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
601             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
602             return new JcaKeyPair(myPublic, myPrivate);
603         }
604     }
605 
606     /**
607      * Jca Frodo KeyPair generator.
608      */
609     public static class JcaFrodoKeyPairGenerator
610             extends JcaKeyPairGenerator {
611         /**
612          * FRODO algorithm.
613          */
614         private static final String FRODO_ALGO = "FRODO";
615 
616         /**
617          * Generator.
618          */
619         private final KeyPairGenerator theGenerator;
620 
621         /**
622          * Constructor.
623          *
624          * @param pFactory the Security Factory
625          * @param pKeySpec the keySpec
626          * @throws GordianException on error
627          */
628         JcaFrodoKeyPairGenerator(final GordianBaseFactory pFactory,
629                                  final GordianKeyPairSpec pKeySpec) throws GordianException {
630             /* initialize underlying class */
631             super(pFactory, pKeySpec);
632 
633             /* Protect against exceptions */
634             try {
635                 /* Create and initialize the generator */
636                 theGenerator = getJavaKeyPairGenerator(FRODO_ALGO, true);
637                 final FrodoParameterSpec myParms = pKeySpec.getFRODOKeySpec().getParameterSpec();
638                 theGenerator.initialize(myParms, getRandom());
639 
640                 /* Create the factory */
641                 setKeyFactory(getJavaKeyFactory(FRODO_ALGO, true));
642 
643             } catch (InvalidAlgorithmParameterException e) {
644                 throw new GordianCryptoException("Failed to create FRODOgenerator", e);
645             }
646         }
647 
648         @Override
649         public JcaKeyPair generateKeyPair() {
650             /* Generate and return the keyPair */
651             final KeyPair myPair = theGenerator.generateKeyPair();
652             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
653             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
654             return new JcaKeyPair(myPublic, myPrivate);
655         }
656     }
657 
658     /**
659      * Jca SABER KeyPair generator.
660      */
661     public static class JcaSABERKeyPairGenerator
662             extends JcaKeyPairGenerator {
663         /**
664          * SABER algorithm.
665          */
666         private static final String SABER_ALGO = "SABER";
667 
668         /**
669          * Generator.
670          */
671         private final KeyPairGenerator theGenerator;
672 
673         /**
674          * Constructor.
675          *
676          * @param pFactory the Security Factory
677          * @param pKeySpec the keySpec
678          * @throws GordianException on error
679          */
680         JcaSABERKeyPairGenerator(final GordianBaseFactory pFactory,
681                                  final GordianKeyPairSpec pKeySpec) throws GordianException {
682             /* initialize underlying class */
683             super(pFactory, pKeySpec);
684 
685             /* Protect against exceptions */
686             try {
687                 /* Create and initialize the generator */
688                 theGenerator = getJavaKeyPairGenerator(SABER_ALGO, true);
689                 final SABERParameterSpec myParms = pKeySpec.getSABERKeySpec().getParameterSpec();
690                 theGenerator.initialize(myParms, getRandom());
691 
692                 /* Create the factory */
693                 setKeyFactory(getJavaKeyFactory(SABER_ALGO, true));
694 
695             } catch (InvalidAlgorithmParameterException e) {
696                 throw new GordianCryptoException("Failed to create SABERgenerator", e);
697             }
698         }
699 
700         @Override
701         public JcaKeyPair generateKeyPair() {
702             /* Generate and return the keyPair */
703             final KeyPair myPair = theGenerator.generateKeyPair();
704             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
705             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
706             return new JcaKeyPair(myPublic, myPrivate);
707         }
708     }
709 
710     /**
711      * Jca MLKEM KeyPair generator.
712      */
713     public static class JcaMLKEMKeyPairGenerator
714             extends JcaKeyPairGenerator {
715         /**
716          * MLKEM algorithm.
717          */
718         private static final String MLKEM_ALGO = "MLKEM";
719 
720         /**
721          * Generator.
722          */
723         private final KeyPairGenerator theGenerator;
724 
725         /**
726          * Constructor.
727          *
728          * @param pFactory the Security Factory
729          * @param pKeySpec the keySpec
730          * @throws GordianException on error
731          */
732         JcaMLKEMKeyPairGenerator(final GordianBaseFactory pFactory,
733                                  final GordianKeyPairSpec pKeySpec) throws GordianException {
734             /* initialize underlying class */
735             super(pFactory, pKeySpec);
736 
737             /* Protect against exceptions */
738             try {
739                 /* Create and initialize the generator */
740                 theGenerator = getJavaKeyPairGenerator(MLKEM_ALGO, false);
741                 final MLKEMParameterSpec myParms = pKeySpec.getMLKEMKeySpec().getParameterSpec();
742                 theGenerator.initialize(myParms, getRandom());
743 
744                 /* Create the factory */
745                 setKeyFactory(getJavaKeyFactory(MLKEM_ALGO, false));
746 
747             } catch (InvalidAlgorithmParameterException e) {
748                 throw new GordianCryptoException("Failed to create MLKEMgenerator", e);
749             }
750         }
751 
752         @Override
753         public JcaKeyPair generateKeyPair() {
754             /* Generate and return the keyPair */
755             final KeyPair myPair = theGenerator.generateKeyPair();
756             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
757             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
758             return new JcaKeyPair(myPublic, myPrivate);
759         }
760     }
761 
762     /**
763      * Jca MLDSA KeyPair generator.
764      */
765     public static class JcaMLDSAKeyPairGenerator
766             extends JcaKeyPairGenerator {
767         /**
768          * MLDSA algorithm.
769          */
770         private static final String MLDSA_ALGO = "ML-DSA";
771 
772         /**
773          * HASH indication.
774          */
775         private static final String MLDSA_HASH = "HASH-" + MLDSA_ALGO;
776 
777         /**
778          * Generator.
779          */
780         private final KeyPairGenerator theGenerator;
781 
782         /**
783          * Constructor.
784          *
785          * @param pFactory the Security Factory
786          * @param pKeySpec the keySpec
787          * @throws GordianException on error
788          */
789         JcaMLDSAKeyPairGenerator(final GordianBaseFactory pFactory,
790                                  final GordianKeyPairSpec pKeySpec) throws GordianException {
791             /* initialize underlying class */
792             super(pFactory, pKeySpec);
793 
794             /* Protect against exceptions */
795             try {
796                 /* Determine algorithm */
797                 final String myAlgo = pKeySpec.getMLDSAKeySpec().isHash() ? MLDSA_HASH : MLDSA_ALGO;
798 
799                 /* Create and initialize the generator */
800                 theGenerator = getJavaKeyPairGenerator(myAlgo, false);
801                 final MLDSAParameterSpec myParms = pKeySpec.getMLDSAKeySpec().getParameterSpec();
802                 theGenerator.initialize(myParms, getRandom());
803 
804                 /* Create the factory */
805                 setKeyFactory(getJavaKeyFactory(myAlgo, false));
806 
807             } catch (InvalidAlgorithmParameterException e) {
808                 throw new GordianCryptoException("Failed to create MLDSAGenerator", e);
809             }
810         }
811 
812         @Override
813         public JcaKeyPair generateKeyPair() {
814             /* Generate and return the keyPair */
815             final KeyPair myPair = theGenerator.generateKeyPair();
816             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
817             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
818             return new JcaKeyPair(myPublic, myPrivate);
819         }
820     }
821 
822     /**
823      * Jca HQC KeyPair generator.
824      */
825     public static class JcaHQCKeyPairGenerator
826             extends JcaKeyPairGenerator {
827         /**
828          * BIKE algorithm.
829          */
830         private static final String HQC_ALGO = "HQC";
831 
832         /**
833          * Generator.
834          */
835         private final KeyPairGenerator theGenerator;
836 
837         /**
838          * Constructor.
839          *
840          * @param pFactory the Security Factory
841          * @param pKeySpec the keySpec
842          * @throws GordianException on error
843          */
844         JcaHQCKeyPairGenerator(final GordianBaseFactory pFactory,
845                                final GordianKeyPairSpec pKeySpec) throws GordianException {
846             /* initialize underlying class */
847             super(pFactory, pKeySpec);
848 
849             /* Protect against exceptions */
850             try {
851                 /* Create and initialize the generator */
852                 theGenerator = getJavaKeyPairGenerator(HQC_ALGO, true);
853                 final HQCParameterSpec myParms = pKeySpec.getHQCKeySpec().getParameterSpec();
854                 theGenerator.initialize(myParms, getRandom());
855 
856                 /* Create the factory */
857                 setKeyFactory(getJavaKeyFactory(HQC_ALGO, true));
858 
859             } catch (InvalidAlgorithmParameterException e) {
860                 throw new GordianCryptoException("Failed to create HQCgenerator", e);
861             }
862         }
863 
864         @Override
865         public JcaKeyPair generateKeyPair() {
866             /* Generate and return the keyPair */
867             final KeyPair myPair = theGenerator.generateKeyPair();
868             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
869             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
870             return new JcaKeyPair(myPublic, myPrivate);
871         }
872     }
873 
874 
875     /**
876      * Jca BIKE KeyPair generator.
877      */
878     public static class JcaBIKEKeyPairGenerator
879             extends JcaKeyPairGenerator {
880         /**
881          * BIKE algorithm.
882          */
883         private static final String BIKE_ALGO = "BIKE";
884 
885         /**
886          * Generator.
887          */
888         private final KeyPairGenerator theGenerator;
889 
890         /**
891          * Constructor.
892          *
893          * @param pFactory the Security Factory
894          * @param pKeySpec the keySpec
895          * @throws GordianException on error
896          */
897         JcaBIKEKeyPairGenerator(final GordianBaseFactory pFactory,
898                                 final GordianKeyPairSpec pKeySpec) throws GordianException {
899             /* initialize underlying class */
900             super(pFactory, pKeySpec);
901 
902             /* Protect against exceptions */
903             try {
904                 /* Create and initialize the generator */
905                 theGenerator = getJavaKeyPairGenerator(BIKE_ALGO, true);
906                 final BIKEParameterSpec myParms = pKeySpec.getBIKEKeySpec().getParameterSpec();
907                 theGenerator.initialize(myParms, getRandom());
908 
909                 /* Create the factory */
910                 setKeyFactory(getJavaKeyFactory(BIKE_ALGO, true));
911 
912             } catch (InvalidAlgorithmParameterException e) {
913                 throw new GordianCryptoException("Failed to create BIKEgenerator", e);
914             }
915         }
916 
917         @Override
918         public JcaKeyPair generateKeyPair() {
919             /* Generate and return the keyPair */
920             final KeyPair myPair = theGenerator.generateKeyPair();
921             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
922             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
923             return new JcaKeyPair(myPublic, myPrivate);
924         }
925     }
926 
927     /**
928      * Jca NTRU KeyPair generator.
929      */
930     public static class JcaNTRUKeyPairGenerator
931             extends JcaKeyPairGenerator {
932         /**
933          * NTRU algorithm.
934          */
935         private static final String NTRU_ALGO = "NTRU";
936 
937         /**
938          * Generator.
939          */
940         private final KeyPairGenerator theGenerator;
941 
942         /**
943          * Constructor.
944          *
945          * @param pFactory the Security Factory
946          * @param pKeySpec the keySpec
947          * @throws GordianException on error
948          */
949         JcaNTRUKeyPairGenerator(final GordianBaseFactory pFactory,
950                                 final GordianKeyPairSpec pKeySpec) throws GordianException {
951             /* initialize underlying class */
952             super(pFactory, pKeySpec);
953 
954             /* Protect against exceptions */
955             try {
956                 /* Create and initialize the generator */
957                 theGenerator = getJavaKeyPairGenerator(NTRU_ALGO, true);
958                 final NTRUParameterSpec myParms = pKeySpec.getNTRUKeySpec().getParameterSpec();
959                 theGenerator.initialize(myParms, getRandom());
960 
961                 /* Create the factory */
962                 setKeyFactory(getJavaKeyFactory(NTRU_ALGO, true));
963 
964             } catch (InvalidAlgorithmParameterException e) {
965                 throw new GordianCryptoException("Failed to create NTRUgenerator", e);
966             }
967         }
968 
969         @Override
970         public JcaKeyPair generateKeyPair() {
971             /* Generate and return the keyPair */
972             final KeyPair myPair = theGenerator.generateKeyPair();
973             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
974             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
975             return new JcaKeyPair(myPublic, myPrivate);
976         }
977     }
978 
979     /**
980      * Jca Falcon KeyPair generator.
981      */
982     public static class JcaFalconKeyPairGenerator
983             extends JcaKeyPairGenerator {
984         /**
985          * FALCON algorithm.
986          */
987         private static final String FALCON_ALGO = "FALCON";
988 
989         /**
990          * Generator.
991          */
992         private final KeyPairGenerator theGenerator;
993 
994         /**
995          * Constructor.
996          *
997          * @param pFactory the Security Factory
998          * @param pKeySpec the keySpec
999          * @throws GordianException on error
1000          */
1001         JcaFalconKeyPairGenerator(final GordianBaseFactory pFactory,
1002                                   final GordianKeyPairSpec pKeySpec) throws GordianException {
1003             /* initialize underlying class */
1004             super(pFactory, pKeySpec);
1005 
1006             /* Protect against exceptions */
1007             try {
1008                 /* Create and initialize the generator */
1009                 theGenerator = getJavaKeyPairGenerator(FALCON_ALGO, true);
1010                 final FalconParameterSpec myParms = pKeySpec.getFalconKeySpec().getParameterSpec();
1011                 theGenerator.initialize(myParms, getRandom());
1012 
1013                 /* Create the factory */
1014                 setKeyFactory(getJavaKeyFactory(FALCON_ALGO, true));
1015 
1016             } catch (InvalidAlgorithmParameterException e) {
1017                 throw new GordianCryptoException("Failed to create FALCONgenerator", e);
1018             }
1019         }
1020 
1021         @Override
1022         public JcaKeyPair generateKeyPair() {
1023             /* Generate and return the keyPair */
1024             final KeyPair myPair = theGenerator.generateKeyPair();
1025             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
1026             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
1027             return new JcaKeyPair(myPublic, myPrivate);
1028         }
1029     }
1030 
1031     /**
1032      * Jca Mayo KeyPair generator.
1033      */
1034     public static class JcaMayoKeyPairGenerator
1035             extends JcaKeyPairGenerator {
1036         /**
1037          * Mayo algorithm.
1038          */
1039         private static final String MAYO_ALGO = "MAYO";
1040 
1041         /**
1042          * Generator.
1043          */
1044         private final KeyPairGenerator theGenerator;
1045 
1046         /**
1047          * Constructor.
1048          *
1049          * @param pFactory the Security Factory
1050          * @param pKeySpec the keySpec
1051          * @throws GordianException on error
1052          */
1053         JcaMayoKeyPairGenerator(final GordianBaseFactory pFactory,
1054                                 final GordianKeyPairSpec pKeySpec) throws GordianException {
1055             /* initialize underlying class */
1056             super(pFactory, pKeySpec);
1057 
1058             /* Protect against exceptions */
1059             try {
1060                 /* Create and initialize the generator */
1061                 theGenerator = getJavaKeyPairGenerator(MAYO_ALGO, true);
1062                 final MayoParameterSpec myParms = pKeySpec.getMayoKeySpec().getParameterSpec();
1063                 theGenerator.initialize(myParms, getRandom());
1064 
1065                 /* Create the factory */
1066                 setKeyFactory(getJavaKeyFactory(MAYO_ALGO, true));
1067 
1068             } catch (InvalidAlgorithmParameterException e) {
1069                 throw new GordianCryptoException("Failed to create MayoGenerator", e);
1070             }
1071         }
1072 
1073         @Override
1074         public JcaKeyPair generateKeyPair() {
1075             /* Generate and return the keyPair */
1076             final KeyPair myPair = theGenerator.generateKeyPair();
1077             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
1078             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
1079             return new JcaKeyPair(myPublic, myPrivate);
1080         }
1081     }
1082 
1083     /**
1084      * Jca Snova KeyPair generator.
1085      */
1086     public static class JcaSnovaKeyPairGenerator
1087             extends JcaKeyPairGenerator {
1088         /**
1089          * Snova algorithm.
1090          */
1091         private static final String SNOVA_ALGO = "SNOVA";
1092 
1093         /**
1094          * Generator.
1095          */
1096         private final KeyPairGenerator theGenerator;
1097 
1098         /**
1099          * Constructor.
1100          *
1101          * @param pFactory the Security Factory
1102          * @param pKeySpec the keySpec
1103          * @throws GordianException on error
1104          */
1105         JcaSnovaKeyPairGenerator(final GordianBaseFactory pFactory,
1106                                  final GordianKeyPairSpec pKeySpec) throws GordianException {
1107             /* initialize underlying class */
1108             super(pFactory, pKeySpec);
1109 
1110             /* Protect against exceptions */
1111             try {
1112                 /* Create and initialize the generator */
1113                 theGenerator = getJavaKeyPairGenerator(SNOVA_ALGO, true);
1114                 final SnovaParameterSpec myParms = pKeySpec.getSnovaKeySpec().getParameterSpec();
1115                 theGenerator.initialize(myParms, getRandom());
1116 
1117                 /* Create the factory */
1118                 setKeyFactory(getJavaKeyFactory(SNOVA_ALGO, true));
1119 
1120             } catch (InvalidAlgorithmParameterException e) {
1121                 throw new GordianCryptoException("Failed to create SnovaGenerator", e);
1122             }
1123         }
1124 
1125         @Override
1126         public JcaKeyPair generateKeyPair() {
1127             /* Generate and return the keyPair */
1128             final KeyPair myPair = theGenerator.generateKeyPair();
1129             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
1130             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
1131             return new JcaKeyPair(myPublic, myPrivate);
1132         }
1133     }
1134 
1135     /**
1136      * Jca NTRULPrime KeyPair generator.
1137      */
1138     public static class JcaNTRULPrimeKeyPairGenerator
1139             extends JcaKeyPairGenerator {
1140         /**
1141          * NTRULPrime algorithm.
1142          */
1143         private static final String NTRU_ALGO = "NTRULPRIME";
1144 
1145         /**
1146          * Generator.
1147          */
1148         private final KeyPairGenerator theGenerator;
1149 
1150         /**
1151          * Constructor.
1152          *
1153          * @param pFactory the Security Factory
1154          * @param pKeySpec the keySpec
1155          * @throws GordianException on error
1156          */
1157         JcaNTRULPrimeKeyPairGenerator(final GordianBaseFactory pFactory,
1158                                       final GordianKeyPairSpec pKeySpec) throws GordianException {
1159             /* initialize underlying class */
1160             super(pFactory, pKeySpec);
1161 
1162             /* Protect against exceptions */
1163             try {
1164                 /* Create and initialize the generator */
1165                 theGenerator = getJavaKeyPairGenerator(NTRU_ALGO, true);
1166                 final NTRULPRimeParameterSpec myParms = pKeySpec.getNTRUPrimeKeySpec().getParams().getNTRULParameterSpec();
1167                 theGenerator.initialize(myParms, getRandom());
1168 
1169                 /* Create the factory */
1170                 setKeyFactory(getJavaKeyFactory(NTRU_ALGO, true));
1171 
1172             } catch (InvalidAlgorithmParameterException e) {
1173                 throw new GordianCryptoException("Failed to create NTRULPrimeGenerator", e);
1174             }
1175         }
1176 
1177         @Override
1178         public JcaKeyPair generateKeyPair() {
1179             /* Generate and return the keyPair */
1180             final KeyPair myPair = theGenerator.generateKeyPair();
1181             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
1182             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
1183             return new JcaKeyPair(myPublic, myPrivate);
1184         }
1185     }
1186 
1187     /**
1188      * Jca SNTRUPrime KeyPair generator.
1189      */
1190     public static class JcaSNTRUPrimeKeyPairGenerator
1191             extends JcaKeyPairGenerator {
1192         /**
1193          * NTRULPrime algorithm.
1194          */
1195         private static final String NTRU_ALGO = "SNTRUPRIME";
1196 
1197         /**
1198          * Generator.
1199          */
1200         private final KeyPairGenerator theGenerator;
1201 
1202         /**
1203          * Constructor.
1204          *
1205          * @param pFactory the Security Factory
1206          * @param pKeySpec the keySpec
1207          * @throws GordianException on error
1208          */
1209         JcaSNTRUPrimeKeyPairGenerator(final GordianBaseFactory pFactory,
1210                                       final GordianKeyPairSpec pKeySpec) throws GordianException {
1211             /* initialize underlying class */
1212             super(pFactory, pKeySpec);
1213 
1214             /* Protect against exceptions */
1215             try {
1216                 /* Create and initialize the generator */
1217                 theGenerator = getJavaKeyPairGenerator(NTRU_ALGO, true);
1218                 final SNTRUPrimeParameterSpec myParms = pKeySpec.getNTRUPrimeKeySpec().getParams().getSNTRUParameterSpec();
1219                 theGenerator.initialize(myParms, getRandom());
1220 
1221                 /* Create the factory */
1222                 setKeyFactory(getJavaKeyFactory(NTRU_ALGO, true));
1223 
1224             } catch (InvalidAlgorithmParameterException e) {
1225                 throw new GordianCryptoException("Failed to create SNTRUPrimeGenerator", e);
1226             }
1227         }
1228 
1229         @Override
1230         public JcaKeyPair generateKeyPair() {
1231             /* Generate and return the keyPair */
1232             final KeyPair myPair = theGenerator.generateKeyPair();
1233             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
1234             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
1235             return new JcaKeyPair(myPublic, myPrivate);
1236         }
1237     }
1238 
1239     /**
1240      * Jca Picnic KeyPair generator.
1241      */
1242     public static class JcaPicnicKeyPairGenerator
1243             extends JcaKeyPairGenerator {
1244         /**
1245          * Picnic algorithm.
1246          */
1247         private static final String PICNIC_ALGO = "PICNIC";
1248 
1249         /**
1250          * Generator.
1251          */
1252         private final KeyPairGenerator theGenerator;
1253 
1254         /**
1255          * Constructor.
1256          *
1257          * @param pFactory the Security Factory
1258          * @param pKeySpec the keySpec
1259          * @throws GordianException on error
1260          */
1261         JcaPicnicKeyPairGenerator(final GordianBaseFactory pFactory,
1262                                   final GordianKeyPairSpec pKeySpec) throws GordianException {
1263             /* initialize underlying class */
1264             super(pFactory, pKeySpec);
1265 
1266             /* Protect against exceptions */
1267             try {
1268                 /* Create and initialize the generator */
1269                 theGenerator = getJavaKeyPairGenerator(PICNIC_ALGO, true);
1270                 final PicnicParameterSpec myParms = pKeySpec.getPicnicKeySpec().getParameterSpec();
1271                 theGenerator.initialize(myParms, getRandom());
1272 
1273                 /* Create the factory */
1274                 setKeyFactory(getJavaKeyFactory(PICNIC_ALGO, true));
1275 
1276             } catch (InvalidAlgorithmParameterException e) {
1277                 throw new GordianCryptoException("Failed to create PICNICgenerator", e);
1278             }
1279         }
1280 
1281         @Override
1282         public JcaKeyPair generateKeyPair() {
1283             /* Generate and return the keyPair */
1284             final KeyPair myPair = theGenerator.generateKeyPair();
1285             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
1286             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
1287             return new JcaKeyPair(myPublic, myPrivate);
1288         }
1289     }
1290 
1291     /**
1292      * Jca XMSS KeyPair generator.
1293      */
1294     public static class JcaXMSSKeyPairGenerator
1295             extends JcaKeyPairGenerator {
1296         /**
1297          * Generator.
1298          */
1299         private final KeyPairGenerator theGenerator;
1300 
1301         /**
1302          * Constructor.
1303          *
1304          * @param pFactory the Security Factory
1305          * @param pKeySpec the keySpec
1306          * @throws GordianException on error
1307          */
1308         JcaXMSSKeyPairGenerator(final GordianBaseFactory pFactory,
1309                                 final GordianKeyPairSpec pKeySpec) throws GordianException {
1310             /* initialize underlying class */
1311             super(pFactory, pKeySpec);
1312 
1313             /* Protect against exceptions */
1314             try {
1315                 /* Access the algorithm */
1316                 final GordianXMSSKeySpec myXMSSKeySpec = pKeySpec.getXMSSKeySpec();
1317                 final boolean isXMSSMT = myXMSSKeySpec.isMT();
1318                 final GordianXMSSDigestType myType = myXMSSKeySpec.getDigestType();
1319 
1320                 /* Create the parameters */
1321                 final AlgorithmParameterSpec myAlgo = isXMSSMT
1322                         ? new XMSSMTParameterSpec(myXMSSKeySpec.getHeight().getHeight(),
1323                         myXMSSKeySpec.getLayers().getLayers(), myType.name())
1324                         : new XMSSParameterSpec(myXMSSKeySpec.getHeight().getHeight(), myType.name());
1325 
1326                 /* Create and initialize the generator */
1327                 final String myJavaType = myXMSSKeySpec.getKeyType().name();
1328                 theGenerator = getJavaKeyPairGenerator(myJavaType, true);
1329                 theGenerator.initialize(myAlgo, getRandom());
1330 
1331                 /* Create the factory */
1332                 setKeyFactory(getJavaKeyFactory(myJavaType, true));
1333 
1334             } catch (InvalidAlgorithmParameterException e) {
1335                 throw new GordianCryptoException("Failed to create XMSSgenerator", e);
1336             }
1337         }
1338 
1339         @Override
1340         public JcaKeyPair generateKeyPair() {
1341             /* Generate and return the keyPair */
1342             final KeyPair myPair = theGenerator.generateKeyPair();
1343             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
1344             final JcaStateAwarePrivateKey myPrivate = createPrivate(myPair.getPrivate());
1345             return new JcaStateAwareKeyPair(myPublic, myPrivate);
1346         }
1347 
1348         @Override
1349         protected JcaStateAwarePrivateKey createPrivate(final PrivateKey pPrivateKey) {
1350             return new JcaStateAwarePrivateKey(getKeySpec(), pPrivateKey);
1351         }
1352 
1353         @Override
1354         public JcaKeyPair deriveKeyPair(final X509EncodedKeySpec pPublicKey,
1355                                         final PKCS8EncodedKeySpec pPrivateKey) throws GordianException {
1356             /* Protect against exceptions */
1357             try {
1358                 /* Check the keySpecs */
1359                 checkKeySpec(pPrivateKey);
1360 
1361                 /* derive keyPair */
1362                 final JcaPublicKey myPublic = derivePublicKey(pPublicKey);
1363                 JcaStateAwarePrivateKey myPrivate = createPrivate(getKeyFactory().generatePrivate(pPrivateKey));
1364                 final JcaKeyPair myPair = new JcaStateAwareKeyPair(myPublic, myPrivate);
1365 
1366                 /* Check that we have a matching pair */
1367                 GordianKeyPairValidity.checkValidity(getFactory(), myPair);
1368 
1369                 /* Rebuild and return the keyPair to avoid incrementing usage count */
1370                 myPrivate = createPrivate(getKeyFactory().generatePrivate(pPrivateKey));
1371                 return new JcaStateAwareKeyPair(myPublic, myPrivate);
1372 
1373             } catch (InvalidKeySpecException e) {
1374                 throw new GordianCryptoException(PARSE_ERROR, e);
1375             }
1376         }
1377     }
1378 
1379     /**
1380      * Jca Edwards KeyPair generator.
1381      */
1382     public static class JcaEdKeyPairGenerator
1383             extends JcaKeyPairGenerator {
1384         /**
1385          * Generator.
1386          */
1387         private final KeyPairGenerator theGenerator;
1388 
1389         /**
1390          * Constructor.
1391          *
1392          * @param pFactory the Security Factory
1393          * @param pKeySpec the keySpec
1394          * @throws GordianException on error
1395          */
1396         protected JcaEdKeyPairGenerator(final GordianBaseFactory pFactory,
1397                                         final GordianKeyPairSpec pKeySpec) throws GordianException {
1398             /* initialize underlying class */
1399             super(pFactory, pKeySpec);
1400 
1401             /* Protect against exceptions */
1402             try {
1403                 /* Create the parameters */
1404                 final AlgorithmParameterSpec myAlgo;
1405                 final boolean is25519 = pKeySpec.getEdwardsElliptic().is25519();
1406                 switch (pKeySpec.getKeyPairType()) {
1407                     case XDH:
1408                         myAlgo = is25519
1409                                 ? new XDHParameterSpec(XDHParameterSpec.X25519)
1410                                 : new XDHParameterSpec(XDHParameterSpec.X448);
1411                         break;
1412                     case EDDSA:
1413                         myAlgo = is25519
1414                                 ? new EdDSAParameterSpec(EdDSAParameterSpec.Ed25519)
1415                                 : new EdDSAParameterSpec(EdDSAParameterSpec.Ed448);
1416                         break;
1417                     default:
1418                         throw new GordianLogicException("Invalid KeySpec" + pKeySpec);
1419                 }
1420 
1421                 /* Create and initialize the generator */
1422                 final String myJavaType = pKeySpec.toString();
1423                 theGenerator = getJavaKeyPairGenerator(myJavaType, false);
1424                 theGenerator.initialize(myAlgo, getRandom());
1425 
1426                 /* Create the factory */
1427                 setKeyFactory(getJavaKeyFactory(myJavaType, false));
1428 
1429             } catch (InvalidAlgorithmParameterException e) {
1430                 throw new GordianCryptoException("Failed to create EdwardsGenerator", e);
1431             }
1432         }
1433 
1434         @Override
1435         public JcaKeyPair generateKeyPair() {
1436             /* Generate and return the keyPair */
1437             final KeyPair myPair = theGenerator.generateKeyPair();
1438             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
1439             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
1440             return new JcaKeyPair(myPublic, myPrivate);
1441         }
1442     }
1443 
1444     /**
1445      * Jca NewHope KeyPair generator.
1446      */
1447     public static class JcaNewHopeKeyPairGenerator
1448             extends JcaKeyPairGenerator {
1449         /**
1450          * NewHope algorithm.
1451          */
1452         private static final String NEWHOPE_ALGO = "NH";
1453 
1454         /**
1455          * Generator.
1456          */
1457         private final KeyPairGenerator theGenerator;
1458 
1459         /**
1460          * Constructor.
1461          *
1462          * @param pFactory the Security Factory
1463          * @param pKeySpec the keySpec
1464          * @throws GordianException on error
1465          */
1466         JcaNewHopeKeyPairGenerator(final GordianBaseFactory pFactory,
1467                                    final GordianKeyPairSpec pKeySpec) throws GordianException {
1468             /* initialize underlying class */
1469             super(pFactory, pKeySpec);
1470 
1471             /* Create and initialize the generator */
1472             theGenerator = getJavaKeyPairGenerator(NEWHOPE_ALGO, true);
1473             theGenerator.initialize(GordianRSAModulus.MOD1024.getLength(), getRandom());
1474 
1475             /* Create the factory */
1476             setKeyFactory(getJavaKeyFactory(NEWHOPE_ALGO, true));
1477         }
1478 
1479         @Override
1480         public JcaKeyPair generateKeyPair() {
1481             /* Generate and return the keyPair */
1482             final KeyPair myPair = theGenerator.generateKeyPair();
1483             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
1484             final JcaPrivateKey myPrivate = createPrivate(myPair.getPrivate());
1485             return new JcaKeyPair(myPublic, myPrivate);
1486         }
1487     }
1488 
1489     /**
1490      * Jca LMS KeyPair generator.
1491      */
1492     public static class JcaLMSKeyPairGenerator
1493             extends JcaKeyPairGenerator {
1494         /**
1495          * Generator.
1496          */
1497         private final KeyPairGenerator theGenerator;
1498 
1499         /**
1500          * Constructor.
1501          *
1502          * @param pFactory the Security Factory
1503          * @param pKeySpec the keySpec
1504          * @throws GordianException on error
1505          */
1506         JcaLMSKeyPairGenerator(final GordianBaseFactory pFactory,
1507                                final GordianKeyPairSpec pKeySpec) throws GordianException {
1508             /* initialize underlying class */
1509             super(pFactory, pKeySpec);
1510 
1511             /* Create and initialize the generator */
1512             final String myJavaType = pKeySpec.getKeyPairType().toString();
1513             theGenerator = getJavaKeyPairGenerator(myJavaType, true);
1514 
1515             /* Protect against exceptions */
1516             try {
1517                 final AlgorithmParameterSpec myParms = pKeySpec.getSubKeyType() instanceof GordianHSSKeySpec
1518                         ? deriveParameters(pKeySpec.getHSSKeySpec())
1519                         : deriveParameters(pKeySpec.getLMSKeySpec());
1520                 theGenerator.initialize(myParms, getRandom());
1521 
1522             } catch (InvalidAlgorithmParameterException e) {
1523                 throw new GordianCryptoException("Failed to initialize generator", e);
1524             }
1525 
1526             /* Create the factory */
1527             setKeyFactory(getJavaKeyFactory(myJavaType, true));
1528         }
1529 
1530         /**
1531          * Derive the parameters.
1532          *
1533          * @param pKeySpec the keySPec
1534          * @return the parameters.
1535          */
1536         private static LMSHSSKeyGenParameterSpec deriveParameters(final GordianHSSKeySpec pKeySpec) {
1537             /* Generate and return the keyPair */
1538             final GordianLMSKeySpec myKeySpec = pKeySpec.getKeySpec();
1539             final LMSKeyGenParameterSpec[] myParams = new LMSKeyGenParameterSpec[pKeySpec.getTreeDepth()];
1540             Arrays.fill(myParams, deriveParameters(myKeySpec));
1541             return new LMSHSSKeyGenParameterSpec(myParams);
1542         }
1543 
1544         /**
1545          * Derive the parameters.
1546          *
1547          * @param pKeySpec the keySpec
1548          * @return the parameters.
1549          */
1550         private static LMSKeyGenParameterSpec deriveParameters(final GordianLMSKeySpec pKeySpec) {
1551             final LMSParameters myParms = pKeySpec.getParameters();
1552             return new LMSKeyGenParameterSpec(myParms.getLMSigParam(), myParms.getLMOTSParam());
1553         }
1554 
1555         @Override
1556         public JcaKeyPair generateKeyPair() {
1557             /* Generate and return the keyPair */
1558             final KeyPair myPair = theGenerator.generateKeyPair();
1559             final JcaPublicKey myPublic = createPublic(myPair.getPublic());
1560             final JcaStateAwarePrivateKey myPrivate = createPrivate(myPair.getPrivate());
1561             return new JcaStateAwareKeyPair(myPublic, myPrivate);
1562         }
1563 
1564         @Override
1565         protected JcaStateAwarePrivateKey createPrivate(final PrivateKey pPrivateKey) {
1566             return new JcaStateAwarePrivateKey(getKeySpec(), pPrivateKey);
1567         }
1568 
1569         @Override
1570         public JcaKeyPair deriveKeyPair(final X509EncodedKeySpec pPublicKey,
1571                                         final PKCS8EncodedKeySpec pPrivateKey) throws GordianException {
1572             /* Protect against exceptions */
1573             try {
1574                 /* Check the keySpecs */
1575                 checkKeySpec(pPrivateKey);
1576 
1577                 /* derive keyPair */
1578                 final JcaPublicKey myPublic = derivePublicKey(pPublicKey);
1579                 JcaStateAwarePrivateKey myPrivate = createPrivate(getKeyFactory().generatePrivate(pPrivateKey));
1580                 final JcaKeyPair myPair = new JcaStateAwareKeyPair(myPublic, myPrivate);
1581 
1582                 /* Check that we have a matching pair */
1583                 GordianKeyPairValidity.checkValidity(getFactory(), myPair);
1584 
1585                 /* Rebuild and return the keyPair to avoid incrementing usage count */
1586                 myPrivate = createPrivate(getKeyFactory().generatePrivate(pPrivateKey));
1587                 return new JcaStateAwareKeyPair(myPublic, myPrivate);
1588 
1589             } catch (InvalidKeySpecException e) {
1590                 throw new GordianCryptoException(PARSE_ERROR, e);
1591             }
1592         }
1593     }
1594 
1595     /**
1596      * Create the BouncyCastle KeyFactory via JCA.
1597      *
1598      * @param pAlgorithm  the Algorithm
1599      * @param postQuantum is this a postQuantum algorithm?
1600      * @return the KeyFactory
1601      * @throws GordianException on error
1602      */
1603     static KeyFactory getJavaKeyFactory(final String pAlgorithm,
1604                                         final boolean postQuantum) throws GordianException {
1605         /* Protect against exceptions */
1606         try {
1607             /* Return a KeyFactory for the algorithm */
1608             return KeyFactory.getInstance(pAlgorithm, postQuantum
1609                     ? JcaProvider.BCPQPROV
1610                     : JcaProvider.BCPROV);
1611 
1612             /* Catch exceptions */
1613         } catch (NoSuchAlgorithmException e) {
1614             /* Throw the exception */
1615             throw new GordianCryptoException("Failed to create KeyFactory", e);
1616         }
1617     }
1618 
1619     /**
1620      * Create the BouncyCastle KeyPairGenerator via JCA.
1621      *
1622      * @param pAlgorithm  the Algorithm
1623      * @param postQuantum is this a postQuantum algorithm?
1624      * @return the KeyPairGenerator
1625      * @throws GordianException on error
1626      */
1627     static KeyPairGenerator getJavaKeyPairGenerator(final String pAlgorithm,
1628                                                     final boolean postQuantum) throws GordianException {
1629         /* Protect against exceptions */
1630         try {
1631             /* Return a KeyPairGenerator for the algorithm */
1632             return KeyPairGenerator.getInstance(pAlgorithm, postQuantum
1633                     ? JcaProvider.BCPQPROV
1634                     : JcaProvider.BCPROV);
1635 
1636             /* Catch exceptions */
1637         } catch (NoSuchAlgorithmException e) {
1638             /* Throw the exception */
1639             throw new GordianCryptoException("Failed to create KeyPairGenerator", e);
1640         }
1641     }
1642 }