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.GordianKeyPairSpec;
22  import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianStateAwareKeyPair;
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)) {
158                 return false;
159             }
160 
161             /* Access the target field */
162             final BouncyPublicKey<?> myThat = (BouncyPublicKey<?>) pThat;
163 
164             /* Check differences */
165             return getKeySpec().equals(myThat.getKeySpec())
166                     && matchKey(myThat.getPublicKey());
167         }
168 
169         @Override
170         public int hashCode() {
171             return Objects.hash(getKeySpec().hashCode(), theKey);
172         }
173     }
174 
175     /**
176      * Bouncy PrivateKey.
177      *
178      * @param <T> parameter type
179      */
180     public abstract static class BouncyPrivateKey<T extends AsymmetricKeyParameter>
181             extends GordianPrivateKey {
182         /**
183          * Private Key details.
184          */
185         private final T theKey;
186 
187         /**
188          * Constructor.
189          *
190          * @param pKeySpec the key spec
191          * @param pKey     the key
192          */
193         protected BouncyPrivateKey(final GordianKeyPairSpec pKeySpec,
194                                    final T pKey) {
195             super(pKeySpec);
196             theKey = pKey;
197         }
198 
199         /**
200          * Obtain the private key.
201          *
202          * @return the key
203          */
204         public T getPrivateKey() {
205             return theKey;
206         }
207 
208         /**
209          * matchKey.
210          *
211          * @param pThat the key to match
212          * @return true/false
213          */
214         protected abstract boolean matchKey(AsymmetricKeyParameter pThat);
215 
216         @Override
217         public boolean equals(final Object pThat) {
218             /* Handle the trivial cases */
219             if (pThat == this) {
220                 return true;
221             }
222             if (pThat == null) {
223                 return false;
224             }
225 
226             /* Make sure that the object is the same class */
227             if (!(pThat instanceof BouncyPrivateKey)) {
228                 return false;
229             }
230 
231             /* Access the target field */
232             final BouncyPrivateKey<?> myThat = (BouncyPrivateKey<?>) pThat;
233 
234             /* Check differences */
235             return getKeySpec().equals(myThat.getKeySpec())
236                     && matchKey(myThat.getPrivateKey());
237         }
238 
239         @Override
240         public int hashCode() {
241             return Objects.hash(getKeySpec(), theKey);
242         }
243     }
244 
245     /**
246      * Bouncy StateAware PrivateKey.
247      *
248      * @param <T> parameter type
249      */
250     public abstract static class BouncyStateAwarePrivateKey<T extends AsymmetricKeyParameter>
251             extends BouncyPrivateKey<T>
252             implements GordianStateAwarePrivateKey {
253         /**
254          * The private key.
255          */
256         private final T thePrivateKey;
257 
258         /**
259          * Constructor.
260          *
261          * @param pKeySpec the key spec
262          * @param pKey     the key
263          */
264         protected BouncyStateAwarePrivateKey(final GordianKeyPairSpec pKeySpec,
265                                              final T pKey) {
266             super(pKeySpec, pKey);
267             thePrivateKey = pKey;
268         }
269 
270         @Override
271         public T getPrivateKey() {
272             return thePrivateKey;
273         }
274 
275         @Override
276         public abstract BouncyStateAwarePrivateKey<T> getKeyShard(int pNumUsages);
277 
278         @Override
279         public boolean equals(final Object pThat) {
280             /* Handle the trivial cases */
281             if (pThat == this) {
282                 return true;
283             }
284             if (pThat == null) {
285                 return false;
286             }
287 
288             /* Make sure that the object is the same class */
289             if (!(pThat instanceof BouncyStateAwarePrivateKey)) {
290                 return false;
291             }
292 
293             /* Access the target field */
294             final BouncyStateAwarePrivateKey<?> myThat = (BouncyStateAwarePrivateKey<?>) pThat;
295 
296             /* Check differences */
297             return getKeySpec().equals(myThat.getKeySpec())
298                     && matchKey(myThat.getPrivateKey());
299         }
300 
301         @Override
302         public int hashCode() {
303             return Objects.hash(getKeySpec(), thePrivateKey);
304         }
305     }
306 
307     /**
308      * Bouncy StateAware KeyPair.
309      */
310     public static class BouncyStateAwareKeyPair
311             extends BouncyKeyPair
312             implements GordianStateAwareKeyPair {
313         /**
314          * Constructor.
315          *
316          * @param pPublic  the public key
317          * @param pPrivate the private key
318          */
319         BouncyStateAwareKeyPair(final BouncyPublicKey<?> pPublic,
320                                 final BouncyStateAwarePrivateKey<?> pPrivate) {
321             super(pPublic, pPrivate);
322         }
323 
324         @Override
325         public BouncyStateAwarePrivateKey<?> getPrivateKey() {
326             return (BouncyStateAwarePrivateKey<?>) super.getPrivateKey();
327         }
328 
329         @Override
330         public long getUsagesRemaining() {
331             return getPrivateKey().getUsagesRemaining();
332         }
333 
334         @Override
335         public BouncyStateAwareKeyPair getKeyPairShard(final int pNumUsages) {
336             return new BouncyStateAwareKeyPair(getPublicKey(), getPrivateKey().getKeyShard(pNumUsages));
337         }
338     }
339 }