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.bc;
18  
19  import io.github.tonywasher.joceanus.gordianknot.api.base.GordianException;
20  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianKeyPair;
21  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianStateAwareKeyPair;
22  import io.github.tonywasher.joceanus.gordianknot.api.keypair.spec.GordianKeyPairSpec;
23  import io.github.tonywasher.joceanus.gordianknot.impl.core.exc.GordianDataException;
24  import io.github.tonywasher.joceanus.gordianknot.impl.core.keypair.GordianCoreKeyPair;
25  import io.github.tonywasher.joceanus.gordianknot.impl.core.keypair.GordianPrivateKey;
26  import io.github.tonywasher.joceanus.gordianknot.impl.core.keypair.GordianPrivateKey.GordianStateAwarePrivateKey;
27  import io.github.tonywasher.joceanus.gordianknot.impl.core.keypair.GordianPublicKey;
28  import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
29  
30  import java.util.Objects;
31  
32  /**
33   * BouncyCastle Asymmetric KeyPair.
34   */
35  public class BouncyKeyPair
36          extends GordianCoreKeyPair {
37      /**
38       * Constructor.
39       *
40       * @param pPublic the public key
41       */
42      protected BouncyKeyPair(final BouncyPublicKey<?> pPublic) {
43          this(pPublic, null);
44      }
45  
46      /**
47       * Constructor.
48       *
49       * @param pPublic  the public key
50       * @param pPrivate the private key
51       */
52      protected BouncyKeyPair(final BouncyPublicKey<?> pPublic,
53                              final BouncyPrivateKey<?> pPrivate) {
54          super(pPublic, pPrivate);
55      }
56  
57      @Override
58      public BouncyPublicKey<?> getPublicKey() {
59          return (BouncyPublicKey<?>) super.getPublicKey();
60      }
61  
62      @Override
63      public BouncyPrivateKey<?> getPrivateKey() {
64          return (BouncyPrivateKey<?>) super.getPrivateKey();
65      }
66  
67      @Override
68      public BouncyKeyPair getPublicOnly() {
69          return new BouncyKeyPair(getPublicKey());
70      }
71  
72      /**
73       * Check for bouncyKeyPair.
74       *
75       * @param pKeyPair the keyPair to check
76       * @throws GordianException on error
77       */
78      public static void checkKeyPair(final GordianKeyPair pKeyPair) throws GordianException {
79          /* Check that it is a BouncyKeyPair */
80          if (!(pKeyPair instanceof BouncyKeyPair)) {
81              /* Reject keyPair */
82              throw new GordianDataException("Invalid KeyPair");
83          }
84      }
85  
86      /**
87       * Check for bouncyKeyPair.
88       *
89       * @param pKeyPair the keyPair to check
90       * @param pSpec    the required keySpec
91       * @throws GordianException on error
92       */
93      public static void checkKeyPair(final GordianKeyPair pKeyPair,
94                                      final GordianKeyPairSpec pSpec) throws GordianException {
95          /* Check the keyPair */
96          checkKeyPair(pKeyPair);
97  
98          /* Check that it the correct key type */
99          if (!pSpec.equals(pKeyPair.getKeyPairSpec())) {
100             /* Reject keyPair */
101             throw new GordianDataException("Invalid KeyPairType");
102         }
103     }
104 
105     /**
106      * Bouncy PublicKey.
107      *
108      * @param <T> parameter type
109      */
110     public abstract static class BouncyPublicKey<T extends AsymmetricKeyParameter>
111             extends GordianPublicKey {
112         /**
113          * Public Key details.
114          */
115         private final T theKey;
116 
117         /**
118          * Constructor.
119          *
120          * @param pKeySpec the key spec
121          * @param pKey     the key
122          */
123         protected BouncyPublicKey(final GordianKeyPairSpec pKeySpec,
124                                   final T pKey) {
125             super(pKeySpec);
126             theKey = pKey;
127         }
128 
129         /**
130          * Obtain the public key.
131          *
132          * @return the key
133          */
134         public T getPublicKey() {
135             return theKey;
136         }
137 
138         /**
139          * matchKey.
140          *
141          * @param pThat the key to match
142          * @return true/false
143          */
144         protected abstract boolean matchKey(AsymmetricKeyParameter pThat);
145 
146         @Override
147         public boolean equals(final Object pThat) {
148             /* Handle the trivial cases */
149             if (pThat == this) {
150                 return true;
151             }
152             if (pThat == null) {
153                 return false;
154             }
155 
156             /* Make sure that the object is the same class */
157             if (!(pThat instanceof BouncyPublicKey<?> myThat)) {
158                 return false;
159             }
160 
161             /* Check differences */
162             return getKeySpec().equals(myThat.getKeySpec())
163                     && matchKey(myThat.getPublicKey());
164         }
165 
166         @Override
167         public int hashCode() {
168             return Objects.hash(getKeySpec().hashCode(), theKey);
169         }
170     }
171 
172     /**
173      * Bouncy PrivateKey.
174      *
175      * @param <T> parameter type
176      */
177     public abstract static class BouncyPrivateKey<T extends AsymmetricKeyParameter>
178             extends GordianPrivateKey {
179         /**
180          * Private Key details.
181          */
182         private final T theKey;
183 
184         /**
185          * Constructor.
186          *
187          * @param pKeySpec the key spec
188          * @param pKey     the key
189          */
190         protected BouncyPrivateKey(final GordianKeyPairSpec pKeySpec,
191                                    final T pKey) {
192             super(pKeySpec);
193             theKey = pKey;
194         }
195 
196         /**
197          * Obtain the private key.
198          *
199          * @return the key
200          */
201         public T getPrivateKey() {
202             return theKey;
203         }
204 
205         /**
206          * matchKey.
207          *
208          * @param pThat the key to match
209          * @return true/false
210          */
211         protected abstract boolean matchKey(AsymmetricKeyParameter pThat);
212 
213         @Override
214         public boolean equals(final Object pThat) {
215             /* Handle the trivial cases */
216             if (pThat == this) {
217                 return true;
218             }
219             if (pThat == null) {
220                 return false;
221             }
222 
223             /* Make sure that the object is the same class */
224             if (!(pThat instanceof BouncyPrivateKey<?> myThat)) {
225                 return false;
226             }
227 
228             /* Check differences */
229             return getKeySpec().equals(myThat.getKeySpec())
230                     && matchKey(myThat.getPrivateKey());
231         }
232 
233         @Override
234         public int hashCode() {
235             return Objects.hash(getKeySpec(), theKey);
236         }
237     }
238 
239     /**
240      * Bouncy StateAware PrivateKey.
241      *
242      * @param <T> parameter type
243      */
244     public abstract static class BouncyStateAwarePrivateKey<T extends AsymmetricKeyParameter>
245             extends BouncyPrivateKey<T>
246             implements GordianStateAwarePrivateKey {
247         /**
248          * The private key.
249          */
250         private final T thePrivateKey;
251 
252         /**
253          * Constructor.
254          *
255          * @param pKeySpec the key spec
256          * @param pKey     the key
257          */
258         protected BouncyStateAwarePrivateKey(final GordianKeyPairSpec pKeySpec,
259                                              final T pKey) {
260             super(pKeySpec, pKey);
261             thePrivateKey = pKey;
262         }
263 
264         @Override
265         public T getPrivateKey() {
266             return thePrivateKey;
267         }
268 
269         @Override
270         public abstract BouncyStateAwarePrivateKey<T> getKeyShard(int pNumUsages);
271 
272         @Override
273         public boolean equals(final Object pThat) {
274             /* Handle the trivial cases */
275             if (pThat == this) {
276                 return true;
277             }
278             if (pThat == null) {
279                 return false;
280             }
281 
282             /* Make sure that the object is the same class */
283             if (!(pThat instanceof BouncyStateAwarePrivateKey<?> myThat)) {
284                 return false;
285             }
286 
287             /* Check differences */
288             return getKeySpec().equals(myThat.getKeySpec())
289                     && matchKey(myThat.getPrivateKey());
290         }
291 
292         @Override
293         public int hashCode() {
294             return Objects.hash(getKeySpec(), thePrivateKey);
295         }
296     }
297 
298     /**
299      * Bouncy StateAware KeyPair.
300      */
301     public static class BouncyStateAwareKeyPair
302             extends BouncyKeyPair
303             implements GordianStateAwareKeyPair {
304         /**
305          * Constructor.
306          *
307          * @param pPublic  the public key
308          * @param pPrivate the private key
309          */
310         BouncyStateAwareKeyPair(final BouncyPublicKey<?> pPublic,
311                                 final BouncyStateAwarePrivateKey<?> pPrivate) {
312             super(pPublic, pPrivate);
313         }
314 
315         @Override
316         public BouncyStateAwarePrivateKey<?> getPrivateKey() {
317             return (BouncyStateAwarePrivateKey<?>) super.getPrivateKey();
318         }
319 
320         @Override
321         public long getUsagesRemaining() {
322             return getPrivateKey().getUsagesRemaining();
323         }
324 
325         @Override
326         public BouncyStateAwareKeyPair getKeyPairShard(final int pNumUsages) {
327             return new BouncyStateAwareKeyPair(getPublicKey(), getPrivateKey().getKeyShard(pNumUsages));
328         }
329     }
330 }