11package io .opentdf .platform .sdk ;
22
3+ import org .bouncycastle .asn1 .ASN1ObjectIdentifier ;
34import org .bouncycastle .asn1 .pkcs .PrivateKeyInfo ;
45import org .bouncycastle .asn1 .x509 .SubjectPublicKeyInfo ;
5- import org .bouncycastle .cert .X509CertificateHolder ;
6+ import org .bouncycastle .asn1 .x9 .ECNamedCurveTable ;
7+ import org .bouncycastle .asn1 .x9 .X962Parameters ;
8+ import org .bouncycastle .asn1 .x9 .X9ECParameters ;
9+ import org .bouncycastle .asn1 .x9 .X9ECPoint ;
610import org .bouncycastle .crypto .digests .SHA256Digest ;
711import org .bouncycastle .crypto .generators .HKDFBytesGenerator ;
812import org .bouncycastle .crypto .params .HKDFParameters ;
913import org .bouncycastle .jcajce .provider .asymmetric .ec .KeyPairGeneratorSpi ;
10- import org .bouncycastle .jce .ECNamedCurveTable ;
11- import org .bouncycastle .jce .interfaces .ECPrivateKey ;
12- import org .bouncycastle .jce .interfaces .ECPublicKey ;
14+ import org .bouncycastle .jcajce .util .ECKeyUtil ;
1315import org .bouncycastle .jce .provider .BouncyCastleProvider ;
1416import org .bouncycastle .jce .spec .ECNamedCurveParameterSpec ;
17+ import org .bouncycastle .math .ec .ECCurve ;
1518import org .bouncycastle .math .ec .ECPoint ;
16- import org .bouncycastle .openssl .PEMException ;
1719import org .bouncycastle .openssl .PEMParser ;
1820import org .bouncycastle .openssl .jcajce .JcaPEMKeyConverter ;
21+ import org .bouncycastle .pqc .jcajce .provider .util .KeyUtil ;
1922import org .bouncycastle .util .io .pem .*;
2023import org .bouncycastle .util .io .pem .PemReader ;
21- import org .bouncycastle .jce .spec .ECPublicKeySpec ;
2224
2325import javax .crypto .KeyAgreement ;
26+ import java .security .interfaces .ECPrivateKey ;
27+ import java .security .interfaces .ECPublicKey ;
2428import java .io .*;
2529import java .security .*;
2630import java .security .spec .*;
@@ -31,14 +35,11 @@ public class ECKeyPair {
3135 static {
3236 Security .addProvider (new BouncyCastleProvider ());
3337 }
34-
3538 public enum ECAlgorithm {
3639 ECDH ,
3740 ECDSA
3841 }
3942
40- private static final BouncyCastleProvider BOUNCY_CASTLE_PROVIDER = new BouncyCastleProvider ();
41-
4243 public enum NanoTDFECCurve {
4344 SECP256R1 ("secp256r1" , KeyType .EC256Key ),
4445 PRIME256V1 ("prime256v1" , KeyType .EC256Key ),
@@ -63,8 +64,9 @@ public KeyType getKeyType() {
6364 }
6465 }
6566
66- private KeyPair keyPair ;
67- private String curveName ;
67+ private final ECPrivateKey privateKey ;
68+ private final ECPublicKey publicKey ;
69+ private final String curveName ;
6870
6971 public ECKeyPair () {
7072 this ("secp256r1" , ECAlgorithm .ECDH );
@@ -77,9 +79,9 @@ public ECKeyPair(String curveName, ECAlgorithm algorithm) {
7779 // Should this just use the algorithm vs use ECDH only for ECDH and ECDSA for
7880 // everything else.
7981 if (algorithm == ECAlgorithm .ECDH ) {
80- generator = KeyPairGeneratorSpi .getInstance (ECAlgorithm .ECDH .name (), BOUNCY_CASTLE_PROVIDER );
82+ generator = KeyPairGeneratorSpi .getInstance (ECAlgorithm .ECDH .name ());
8183 } else {
82- generator = KeyPairGeneratorSpi .getInstance (ECAlgorithm .ECDSA .name (), BOUNCY_CASTLE_PROVIDER );
84+ generator = KeyPairGeneratorSpi .getInstance (ECAlgorithm .ECDSA .name ());
8385 }
8486 } catch (NoSuchAlgorithmException e ) {
8587 throw new RuntimeException (e );
@@ -91,21 +93,24 @@ public ECKeyPair(String curveName, ECAlgorithm algorithm) {
9193 } catch (InvalidAlgorithmParameterException e ) {
9294 throw new RuntimeException (e );
9395 }
94- this .keyPair = generator .generateKeyPair ();
96+ KeyPair keyPair = generator .generateKeyPair ();
97+ this .publicKey = (ECPublicKey )keyPair .getPublic ();
98+ this .privateKey = (ECPrivateKey )keyPair .getPrivate ();
9599 this .curveName = curveName ;
96100 }
97101
98102 public ECKeyPair (ECPublicKey publicKey , ECPrivateKey privateKey , String curveName ) {
99- this .keyPair = new KeyPair (publicKey , privateKey );
103+ this .privateKey = privateKey ;
104+ this .publicKey = publicKey ;
100105 this .curveName = curveName ;
101106 }
102107
103108 public ECPublicKey getPublicKey () {
104- return ( ECPublicKey ) this .keyPair . getPublic () ;
109+ return this .publicKey ;
105110 }
106111
107112 public ECPrivateKey getPrivateKey () {
108- return ( ECPrivateKey ) this .keyPair . getPrivate () ;
113+ return this .privateKey ;
109114 }
110115
111116 public static int getECKeySize (String curveName ) {
@@ -126,7 +131,7 @@ public String publicKeyInPEMFormat() {
126131 PemWriter pemWriter = new PemWriter (writer );
127132
128133 try {
129- pemWriter .writeObject (new PemObject ("PUBLIC KEY" , this . keyPair . getPublic () .getEncoded ()));
134+ pemWriter .writeObject (new PemObject ("PUBLIC KEY" , publicKey .getEncoded ()));
130135 pemWriter .flush ();
131136 pemWriter .close ();
132137 } catch (IOException e ) {
@@ -141,7 +146,7 @@ public String privateKeyInPEMFormat() {
141146 PemWriter pemWriter = new PemWriter (writer );
142147
143148 try {
144- pemWriter .writeObject (new PemObject ("PRIVATE KEY" , this . keyPair . getPrivate () .getEncoded ()));
149+ pemWriter .writeObject (new PemObject ("PRIVATE KEY" , privateKey .getEncoded ()));
145150 pemWriter .flush ();
146151 pemWriter .close ();
147152 } catch (IOException e ) {
@@ -152,70 +157,55 @@ public String privateKeyInPEMFormat() {
152157 }
153158
154159 public int keySize () {
155- return this . keyPair . getPrivate () .getEncoded ().length * 8 ;
160+ return privateKey .getEncoded ().length * 8 ;
156161 }
157162
158163 public String curveName () {
159164 return this .curveName ;
160165 }
161166
162167 public byte [] compressECPublickey () {
163- return (( ECPublicKey ) this . keyPair . getPublic ()). getQ (). getEncoded ( true );
168+ return getCompressedECPublicKey ( publicKey );
164169 }
165170
166- public static String getPEMPublicKeyFromX509Cert (String pemInX509Format ) {
167- try {
168- PEMParser parser = new PEMParser (new StringReader (pemInX509Format ));
169- X509CertificateHolder x509CertificateHolder = (X509CertificateHolder ) parser .readObject ();
170- parser .close ();
171- SubjectPublicKeyInfo publicKeyInfo = x509CertificateHolder .getSubjectPublicKeyInfo ();
172- JcaPEMKeyConverter converter = new JcaPEMKeyConverter ().setProvider (BOUNCY_CASTLE_PROVIDER );
173- ECPublicKey publicKey = null ;
174- try {
175- publicKey = (ECPublicKey ) converter .getPublicKey (publicKeyInfo );
176- } catch (PEMException e ) {
177- throw new RuntimeException (e );
178- }
171+ private static byte [] getCompressedECPublicKey (PublicKey publicKey ) {
172+ SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo .getInstance (publicKey .getEncoded ());
173+ X962Parameters params = X962Parameters .getInstance (publicKeyInfo .getAlgorithm ().getParameters ());
174+ if (params .isImplicitlyCA ()) {
175+ throw new IllegalArgumentException ("Implicitly CA parameters are not supported." );
176+ }
179177
180- // EC public key to pem formated.
181- StringWriter writer = new StringWriter ();
182- PemWriter pemWriter = new PemWriter (writer );
178+ ECCurve curve = ECNamedCurveTable .getByOID ((ASN1ObjectIdentifier )params .getParameters ()).getCurve ();
179+ ECPoint p = curve .decodePoint (publicKeyInfo .getPublicKeyData ().getOctets ());
183180
184- pemWriter .writeObject (new PemObject ("PUBLIC KEY" , publicKey .getEncoded ()));
185- pemWriter .flush ();
186- pemWriter .close ();
187- return writer .toString ();
188- } catch (IOException e ) {
189- throw new RuntimeException (e );
190- }
181+ return new X9ECPoint (p , true ).getPointEncoding ();
191182 }
192183
193184 public static byte [] compressECPublickey (String pemECPubKey ) {
194185 try {
195- KeyFactory ecKeyFac = KeyFactory .getInstance ("EC" , "BC" );
186+ KeyFactory ecKeyFac = KeyFactory .getInstance ("EC" );
196187 PemReader pemReader = new PemReader (new StringReader (pemECPubKey ));
197188 PemObject pemObject = pemReader .readPemObject ();
198189 PublicKey pubKey = ecKeyFac .generatePublic (new X509EncodedKeySpec (pemObject .getContent ()));
199- return ((ECPublicKey ) pubKey ).getQ ().getEncoded (true );
200- } catch (NoSuchAlgorithmException e ) {
201- throw new RuntimeException (e );
202- } catch (IOException e ) {
203- throw new RuntimeException (e );
204- } catch (InvalidKeySpecException e ) {
205- throw new RuntimeException (e );
206- } catch (NoSuchProviderException e ) {
190+ return getCompressedECPublicKey (pubKey );
191+ } catch (NoSuchAlgorithmException | IOException | InvalidKeySpecException e ) {
207192 throw new RuntimeException (e );
208193 }
209194 }
210195
211196 public static String publicKeyFromECPoint (byte [] ecPoint , String curveName ) {
212197 try {
198+ ECPoint point = ECNamedCurveTable .getByName (curveName ).getCurve ().decodePoint (ecPoint );
199+ java .security .spec .ECPoint jpoint = new java .security .spec .ECPoint (point .getAffineXCoord ().toBigInteger (), point .getAffineYCoord ().toBigInteger ());
200+
213201 // Create EC Public key
214- ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable .getParameterSpec (curveName );
215- ECPoint point = ecSpec .getCurve ().decodePoint (ecPoint );
216- ECPublicKeySpec publicKeySpec = new ECPublicKeySpec (point , ecSpec );
217- KeyFactory keyFactory = KeyFactory .getInstance ("ECDSA" , "BC" );
218- PublicKey publicKey = keyFactory .generatePublic (publicKeySpec );
202+ AlgorithmParameters algorithmParameters = AlgorithmParameters .getInstance ("EC" );
203+ algorithmParameters .init (new ECGenParameterSpec (curveName ));
204+ ECParameterSpec ecParameterSpec = algorithmParameters .getParameterSpec (ECParameterSpec .class );
205+
206+ ECPublicKeySpec spec = new ECPublicKeySpec (jpoint , ecParameterSpec );
207+ KeyFactory keyFactory = KeyFactory .getInstance ("ECDSA" );
208+ PublicKey publicKey = keyFactory .generatePublic (spec );
219209
220210 // EC Public keu to pem format.
221211 StringWriter writer = new StringWriter ();
@@ -224,13 +214,7 @@ public static String publicKeyFromECPoint(byte[] ecPoint, String curveName) {
224214 pemWriter .flush ();
225215 pemWriter .close ();
226216 return writer .toString ();
227- } catch (InvalidKeySpecException e ) {
228- throw new RuntimeException (e );
229- } catch (NoSuchAlgorithmException e ) {
230- throw new RuntimeException (e );
231- } catch (NoSuchProviderException e ) {
232- throw new RuntimeException (e );
233- } catch (IOException e ) {
217+ } catch (InvalidKeySpecException | NoSuchAlgorithmException | IOException | InvalidParameterSpecException e ) {
234218 throw new RuntimeException (e );
235219 }
236220 }
@@ -241,7 +225,7 @@ public static ECPublicKey publicKeyFromPem(String pemEncoding) {
241225 SubjectPublicKeyInfo publicKeyInfo = (SubjectPublicKeyInfo ) parser .readObject ();
242226 parser .close ();
243227
244- JcaPEMKeyConverter converter = new JcaPEMKeyConverter (). setProvider ( BOUNCY_CASTLE_PROVIDER ) ;
228+ JcaPEMKeyConverter converter = new JcaPEMKeyConverter ();
245229 return (ECPublicKey ) converter .getPublicKey (publicKeyInfo );
246230 } catch (IOException e ) {
247231 throw new RuntimeException (e );
@@ -254,8 +238,7 @@ public static ECPrivateKey privateKeyFromPem(String pemEncoding) {
254238 PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo ) parser .readObject ();
255239 parser .close ();
256240
257- JcaPEMKeyConverter converter = new JcaPEMKeyConverter ().setProvider (BOUNCY_CASTLE_PROVIDER );
258- ;
241+ JcaPEMKeyConverter converter = new JcaPEMKeyConverter ();
259242 return (ECPrivateKey ) converter .getPrivateKey (privateKeyInfo );
260243 } catch (IOException e ) {
261244 throw new RuntimeException (e );
@@ -264,11 +247,11 @@ public static ECPrivateKey privateKeyFromPem(String pemEncoding) {
264247
265248 public static byte [] computeECDHKey (ECPublicKey publicKey , ECPrivateKey privateKey ) {
266249 try {
267- KeyAgreement aKeyAgree = KeyAgreement .getInstance ("ECDH" , "BC" );
250+ KeyAgreement aKeyAgree = KeyAgreement .getInstance ("ECDH" );
268251 aKeyAgree .init (privateKey );
269252 aKeyAgree .doPhase (publicKey , true );
270253 return aKeyAgree .generateSecret ();
271- } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException e ) {
254+ } catch (NoSuchAlgorithmException | InvalidKeyException e ) {
272255 throw new RuntimeException (e );
273256 }
274257 }
@@ -285,34 +268,22 @@ public static byte[] calculateHKDF(byte[] salt, byte[] secret) {
285268
286269 public static byte [] computeECDSASig (byte [] digest , ECPrivateKey privateKey ) {
287270 try {
288- Signature ecdsaSign = Signature .getInstance ("SHA256withECDSA" , "BC" );
271+ Signature ecdsaSign = Signature .getInstance ("SHA256withECDSA" );
289272 ecdsaSign .initSign (privateKey );
290273 ecdsaSign .update (digest );
291274 return ecdsaSign .sign ();
292- } catch (NoSuchAlgorithmException e ) {
293- throw new RuntimeException (e );
294- } catch (NoSuchProviderException e ) {
295- throw new RuntimeException (e );
296- } catch (InvalidKeyException e ) {
297- throw new RuntimeException (e );
298- } catch (SignatureException e ) {
275+ } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e ) {
299276 throw new RuntimeException (e );
300277 }
301278 }
302279
303280 public static Boolean verifyECDSAig (byte [] digest , byte [] signature , ECPublicKey publicKey ) {
304281 try {
305- Signature ecdsaVerify = Signature .getInstance ("SHA256withECDSA" , "BC" );
282+ Signature ecdsaVerify = Signature .getInstance ("SHA256withECDSA" );
306283 ecdsaVerify .initVerify (publicKey );
307284 ecdsaVerify .update (digest );
308285 return ecdsaVerify .verify (signature );
309- } catch (NoSuchAlgorithmException e ) {
310- throw new RuntimeException (e );
311- } catch (NoSuchProviderException e ) {
312- throw new RuntimeException (e );
313- } catch (InvalidKeyException e ) {
314- throw new RuntimeException (e );
315- } catch (SignatureException e ) {
286+ } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e ) {
316287 throw new RuntimeException (e );
317288 }
318289 }
0 commit comments