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.digest.spec.GordianDigestSpec;
22  import io.github.tonywasher.joceanus.gordianknot.api.digest.spec.GordianDigestType;
23  import io.github.tonywasher.joceanus.gordianknot.api.sign.GordianNewSignParams;
24  import io.github.tonywasher.joceanus.gordianknot.api.sign.spec.GordianSignatureSpec;
25  import io.github.tonywasher.joceanus.gordianknot.impl.bc.digest.BouncyDigest;
26  import io.github.tonywasher.joceanus.gordianknot.impl.bc.keypair.BouncyEllipticKeyPair.BouncyECPrivateKey;
27  import io.github.tonywasher.joceanus.gordianknot.impl.bc.keypair.BouncyEllipticKeyPair.BouncyECPublicKey;
28  import io.github.tonywasher.joceanus.gordianknot.impl.bc.keypair.BouncyKeyPair;
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.sign.GordianCoreSignature;
32  import io.github.tonywasher.joceanus.gordianknot.impl.core.spec.sign.GordianCoreSignatureSpec;
33  import org.bouncycastle.crypto.CryptoException;
34  import org.bouncycastle.crypto.params.ParametersWithRandom;
35  import org.bouncycastle.crypto.signers.SM2Signer;
36  
37  /**
38   * SM2 signature.
39   */
40  public class BouncySM2Signature
41          extends GordianCoreSignature {
42      /**
43       * The Signer.
44       */
45      private final SM2Signer theSigner;
46  
47      /**
48       * Constructor.
49       *
50       * @param pFactory the factory
51       * @param pSpec    the signatureSpec.
52       * @throws GordianException on error
53       */
54      BouncySM2Signature(final GordianBaseFactory pFactory,
55                         final GordianSignatureSpec pSpec) throws GordianException {
56          /* Initialise underlying class */
57          super(pFactory, pSpec);
58  
59          /* Create the signer */
60          final GordianDigestSpec mySpec = ((GordianCoreSignatureSpec) pSpec).getDigestSpec();
61          if (GordianDigestType.SM3.equals(mySpec.getDigestType())) {
62              theSigner = new SM2Signer();
63          } else {
64              final BouncyDigest myDigest = (BouncyDigest) pFactory.getDigestFactory().createDigest(mySpec);
65              theSigner = new SM2Signer(myDigest.getDigest());
66          }
67      }
68  
69      @Override
70      public void update(final byte[] pBytes,
71                         final int pOffset,
72                         final int pLength) {
73          theSigner.update(pBytes, pOffset, pLength);
74      }
75  
76      @Override
77      public void update(final byte pByte) {
78          theSigner.update(pByte);
79      }
80  
81      @Override
82      public void update(final byte[] pBytes) {
83          theSigner.update(pBytes, 0, pBytes.length);
84      }
85  
86      @Override
87      public void reset() {
88          theSigner.reset();
89      }
90  
91      @Override
92      protected BouncyKeyPair getKeyPair() {
93          return (BouncyKeyPair) super.getKeyPair();
94      }
95  
96      @Override
97      public void initForSigning(final GordianNewSignParams pParams) throws GordianException {
98          /* Initialise detail */
99          super.initForSigning(pParams);
100         final BouncyKeyPair myPair = getKeyPair();
101         BouncyKeyPair.checkKeyPair(myPair);
102 
103         /* Initialise and set the signer */
104         final BouncyECPrivateKey myPrivate = (BouncyECPrivateKey) myPair.getPrivateKey();
105         final ParametersWithRandom myParms = new ParametersWithRandom(myPrivate.getPrivateKey(), getRandom());
106         theSigner.init(true, myParms);
107     }
108 
109     @Override
110     public void initForVerify(final GordianNewSignParams pParams) throws GordianException {
111         /* Initialise detail */
112         super.initForVerify(pParams);
113         final BouncyKeyPair myPair = getKeyPair();
114         BouncyKeyPair.checkKeyPair(myPair);
115 
116         /* Initialise and set the signer */
117         final BouncyECPublicKey myPublic = (BouncyECPublicKey) myPair.getPublicKey();
118         theSigner.init(false, myPublic.getPublicKey());
119     }
120 
121     @Override
122     public byte[] sign() throws GordianException {
123         /* Check that we are in signing mode */
124         checkMode(GordianSignatureMode.SIGN);
125 
126         /* Sign the message */
127         try {
128             return theSigner.generateSignature();
129         } catch (CryptoException e) {
130             throw new GordianCryptoException(BouncySignature.ERROR_SIGGEN, e);
131         }
132     }
133 
134     @Override
135     public boolean verify(final byte[] pSignature) throws GordianException {
136         /* Check that we are in verify mode */
137         checkMode(GordianSignatureMode.VERIFY);
138 
139         /* Verify the message */
140         return theSigner.verifySignature(pSignature);
141     }
142 }