View Javadoc
1   /*
2    * GordianKnot: Security Suite
3    * Copyright 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  
18  package io.github.tonywasher.joceanus.gordianknot.impl.bc.sign;
19  
20  import io.github.tonywasher.joceanus.gordianknot.api.base.GordianException;
21  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianKeyPair;
22  import io.github.tonywasher.joceanus.gordianknot.api.sign.GordianNewSignParams;
23  import io.github.tonywasher.joceanus.gordianknot.api.sign.spec.GordianSignatureSpec;
24  import io.github.tonywasher.joceanus.gordianknot.impl.bc.keypair.BouncyKeyPair;
25  import io.github.tonywasher.joceanus.gordianknot.impl.bc.keypair.BouncyKeyPair.BouncyPrivateKey;
26  import io.github.tonywasher.joceanus.gordianknot.impl.bc.keypair.BouncyKeyPair.BouncyPublicKey;
27  import io.github.tonywasher.joceanus.gordianknot.impl.core.base.GordianBaseFactory;
28  import io.github.tonywasher.joceanus.gordianknot.impl.core.exc.GordianCryptoException;
29  import io.github.tonywasher.joceanus.gordianknot.impl.core.sign.GordianCoreSignature;
30  import io.github.tonywasher.joceanus.gordianknot.impl.core.spec.keypair.GordianCoreKeyPairSpec;
31  import org.bouncycastle.crypto.CryptoException;
32  import org.bouncycastle.crypto.Signer;
33  import org.bouncycastle.crypto.signers.Ed25519Signer;
34  import org.bouncycastle.crypto.signers.Ed448Signer;
35  
36  /**
37   * EdDSA signature.
38   */
39  public class BouncyEdDSASignature
40          extends GordianCoreSignature {
41      /**
42       * The Signer.
43       */
44      private Signer theSigner;
45  
46      /**
47       * Constructor.
48       *
49       * @param pFactory the factory
50       * @param pSpec    the signatureSpec.
51       */
52      BouncyEdDSASignature(final GordianBaseFactory pFactory,
53                           final GordianSignatureSpec pSpec) {
54          /* Initialise underlying class */
55          super(pFactory, pSpec);
56      }
57  
58      /**
59       * Create the signer according to the keyPair.
60       *
61       * @param pKeyPair the keyPair
62       * @return the signer
63       */
64      private static Signer createSigner(final GordianKeyPair pKeyPair) {
65          /* Determine the EdwardsCurve */
66          final GordianCoreKeyPairSpec myKeySpec = (GordianCoreKeyPairSpec) pKeyPair.getKeyPairSpec();
67          final boolean is25519 = myKeySpec.getEdwardsSpec().is25519();
68          final byte[] myContext = new byte[0];
69  
70          /* Create the internal digests */
71          return is25519
72                  ? new Ed25519Signer()
73                  : new Ed448Signer(myContext);
74      }
75  
76      @Override
77      public void initForSigning(final GordianNewSignParams pParams) throws GordianException {
78          /* Initialise detail */
79          super.initForSigning(pParams);
80          final GordianKeyPair myPair = getKeyPair();
81          BouncyKeyPair.checkKeyPair(myPair);
82  
83          /* Initialise and set the signer */
84          theSigner = createSigner(myPair);
85          final BouncyPrivateKey<?> myPrivate = getKeyPair().getPrivateKey();
86          theSigner.init(true, myPrivate.getPrivateKey());
87      }
88  
89      @Override
90      public void initForVerify(final GordianNewSignParams pParams) throws GordianException {
91          /* Initialise detail */
92          super.initForVerify(pParams);
93          final GordianKeyPair myPair = getKeyPair();
94          BouncyKeyPair.checkKeyPair(myPair);
95  
96          /* Initialise and set the signer */
97          theSigner = createSigner(myPair);
98          final BouncyPublicKey<?> myPublic = getKeyPair().getPublicKey();
99          theSigner.init(false, myPublic.getPublicKey());
100     }
101 
102     @Override
103     public void update(final byte[] pBytes,
104                        final int pOffset,
105                        final int pLength) {
106         theSigner.update(pBytes, pOffset, pLength);
107     }
108 
109     @Override
110     public void update(final byte pByte) {
111         theSigner.update(pByte);
112     }
113 
114     @Override
115     public void update(final byte[] pBytes) {
116         theSigner.update(pBytes, 0, pBytes.length);
117     }
118 
119     @Override
120     public void reset() {
121         theSigner.reset();
122     }
123 
124     @Override
125     protected BouncyKeyPair getKeyPair() {
126         return (BouncyKeyPair) super.getKeyPair();
127     }
128 
129     @Override
130     public byte[] sign() throws GordianException {
131         /* Check that we are in signing mode */
132         checkMode(GordianSignatureMode.SIGN);
133 
134         /* Sign the message */
135         try {
136             return theSigner.generateSignature();
137         } catch (CryptoException e) {
138             throw new GordianCryptoException(BouncySignature.ERROR_SIGGEN, e);
139         }
140     }
141 
142     @Override
143     public boolean verify(final byte[] pSignature) throws GordianException {
144         /* Check that we are in verify mode */
145         checkMode(GordianSignatureMode.VERIFY);
146 
147         /* Verify the message */
148         return theSigner.verifySignature(pSignature);
149     }
150 }