1- // Copyright 2020-2024 The NATS Authors
1+ // Copyright 2020-2025 The NATS Authors
22// Licensed under the Apache License, Version 2.0 (the "License");
33// you may not use this file except in compliance with the License.
44// You may obtain a copy of the License at:
1313
1414package io .nats .nkey ;
1515
16- import static io .nats .nkey .NKeyConstants .ED25519_PRIVATE_KEYSIZE ;
17- import static io .nats .nkey .NKeyConstants .ED25519_PUBLIC_KEYSIZE ;
18- import static io .nats .nkey .NKeyConstants .ED25519_SEED_SIZE ;
19- import static io .nats .nkey .NKeyConstants .ED_25519 ;
20- import static io .nats .nkey .NKeyConstants .PREFIX_BYTE_ACCOUNT ;
21- import static io .nats .nkey .NKeyConstants .PREFIX_BYTE_CLUSTER ;
22- import static io .nats .nkey .NKeyConstants .PREFIX_BYTE_OPERATOR ;
23- import static io .nats .nkey .NKeyConstants .PREFIX_BYTE_SEED ;
24- import static io .nats .nkey .NKeyConstants .PREFIX_BYTE_SERVER ;
25- import static io .nats .nkey .NKeyConstants .PREFIX_BYTE_USER ;
26- import static io .nats .nkey .NKeyUtils .PRAND ;
27- import static io .nats .nkey .NKeyUtils .SRAND ;
28- import static io .nats .nkey .NKeyUtils .base32Decode ;
29- import static io .nats .nkey .NKeyUtils .base32Encode ;
30- import static io .nats .nkey .NKeyUtils .crc16 ;
16+ import org .bouncycastle .crypto .params .Ed25519PrivateKeyParameters ;
17+ import org .bouncycastle .crypto .params .Ed25519PublicKeyParameters ;
18+ import org .bouncycastle .crypto .signers .Ed25519Signer ;
3119
3220import java .io .ByteArrayOutputStream ;
3321import java .io .IOException ;
3422import java .nio .ByteBuffer ;
3523import java .nio .ByteOrder ;
36- import java .security .GeneralSecurityException ;
37- import java .security .KeyPair ;
38- import java .security .MessageDigest ;
39- import java .security .NoSuchAlgorithmException ;
40- import java .security .NoSuchProviderException ;
41- import java .security .PrivateKey ;
42- import java .security .PublicKey ;
43- import java .security .SecureRandom ;
44- import java .security .Signature ;
24+ import java .security .*;
4525import java .util .Arrays ;
4626
47- import net .i2p .crypto .eddsa .EdDSAEngine ;
48- import net .i2p .crypto .eddsa .EdDSAPrivateKey ;
49- import net .i2p .crypto .eddsa .EdDSAPublicKey ;
50- import net .i2p .crypto .eddsa .spec .EdDSAPrivateKeySpec ;
51- import net .i2p .crypto .eddsa .spec .EdDSAPublicKeySpec ;
27+ import static io .nats .nkey .NKeyConstants .*;
28+ import static io .nats .nkey .NKeyUtils .*;
5229
5330public class NKey {
5431
@@ -173,23 +150,21 @@ static NKeyDecodedSeed decodeSeed(char[] seed) {
173150
174151 private static NKey createPair (NKeyType type , SecureRandom random )
175152 throws IOException , NoSuchProviderException , NoSuchAlgorithmException {
153+ byte [] seed = new byte [ED25519_SEED_SIZE ];
176154 if (random == null ) {
177- random = SRAND ;
155+ SRAND .nextBytes (seed );
156+ }
157+ else {
158+ random .nextBytes (seed );
178159 }
179-
180- byte [] seed = new byte [ED_25519 .getCurve ().getField ().getb () / 8 ];
181- random .nextBytes (seed );
182-
183160 return createPair (type , seed );
184161 }
185162
186- private static NKey createPair (NKeyType type , byte [] seed )
187- throws IOException , NoSuchProviderException , NoSuchAlgorithmException {
188- EdDSAPrivateKeySpec privKeySpec = new EdDSAPrivateKeySpec (seed , ED_25519 );
189- EdDSAPrivateKey privKey = new EdDSAPrivateKey (privKeySpec );
190- EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec (privKey .getA (), ED_25519 );
191- EdDSAPublicKey pubKey = new EdDSAPublicKey (pubKeySpec );
192- byte [] pubBytes = pubKey .getAbyte ();
163+ private static NKey createPair (NKeyType type , byte [] seed ) throws IOException {
164+ Ed25519PrivateKeyParameters privateKey = new Ed25519PrivateKeyParameters (seed );
165+ Ed25519PublicKeyParameters publicKey = privateKey .generatePublicKey ();
166+
167+ byte [] pubBytes = publicKey .getEncoded ();
193168
194169 byte [] bytes = new byte [pubBytes .length + seed .length ];
195170 System .arraycopy (seed , 0 , bytes , 0 , seed .length );
@@ -416,12 +391,7 @@ public char[] getPublicKey() throws GeneralSecurityException, IOException {
416391 if (publicKey != null ) {
417392 return publicKey ;
418393 }
419-
420- KeyPair keys = getKeyPair ();
421- EdDSAPublicKey pubKey = (EdDSAPublicKey ) keys .getPublic ();
422- byte [] pubBytes = pubKey .getAbyte ();
423-
424- return encode (this .type , pubBytes );
394+ return encode (this .type , getKeyPair ().getPublic ().getEncoded ());
425395 }
426396
427397 /**
@@ -458,12 +428,10 @@ public KeyPair getKeyPair() throws GeneralSecurityException, IOException {
458428 System .arraycopy (decoded .bytes , 0 , seedBytes , 0 , seedBytes .length );
459429 System .arraycopy (decoded .bytes , seedBytes .length , pubBytes , 0 , pubBytes .length );
460430
461- EdDSAPrivateKeySpec privKeySpec = new EdDSAPrivateKeySpec (seedBytes , ED_25519 );
462- EdDSAPrivateKey privKey = new EdDSAPrivateKey (privKeySpec );
463- EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec (pubBytes , ED_25519 );
464- EdDSAPublicKey pubKey = new EdDSAPublicKey (pubKeySpec );
431+ Ed25519PrivateKeyParameters privateKey = new Ed25519PrivateKeyParameters (seedBytes );
432+ Ed25519PublicKeyParameters publicKey = new Ed25519PublicKeyParameters (pubBytes );
465433
466- return new KeyPair (pubKey , privKey );
434+ return new KeyPair (new PublicKeyWrapper ( publicKey ), new PrivateKeyWrapper ( privateKey ) );
467435 }
468436
469437 /**
@@ -483,13 +451,11 @@ public NKeyType getType() {
483451 * @throws IOException if there is a problem reading the data
484452 */
485453 public byte [] sign (byte [] input ) throws GeneralSecurityException , IOException {
486- Signature sgr = new EdDSAEngine (MessageDigest .getInstance (ED_25519 .getHashAlgorithm ()));
487- PrivateKey sKey = getKeyPair ().getPrivate ();
488-
489- sgr .initSign (sKey );
490- sgr .update (input );
491-
492- return sgr .sign ();
454+ Ed25519PrivateKeyParameters privateKey = new Ed25519PrivateKeyParameters (getKeyPair ().getPrivate ().getEncoded ());
455+ Ed25519Signer signer = new Ed25519Signer ();
456+ signer .init (true , privateKey );
457+ signer .update (input , 0 , input .length );
458+ return signer .generateSignature ();
493459 }
494460
495461 /**
@@ -503,26 +469,20 @@ public byte[] sign(byte[] input) throws GeneralSecurityException, IOException {
503469 * @throws IOException if there is a problem reading the data
504470 */
505471 public boolean verify (byte [] input , byte [] signature ) throws GeneralSecurityException , IOException {
506- Signature sgr = new EdDSAEngine (MessageDigest .getInstance (ED_25519 .getHashAlgorithm ()));
507- PublicKey sKey ;
508-
472+ Ed25519PublicKeyParameters publicKey ;
509473 if (privateKeyAsSeed != null ) {
510- sKey = getKeyPair ().getPublic ();
511- }
512- else {
474+ publicKey = new Ed25519PublicKeyParameters (getKeyPair ().getPublic ().getEncoded ());
475+ } else {
513476 char [] encodedPublicKey = getPublicKey ();
514477 byte [] decodedPublicKey = decode (this .type , encodedPublicKey );
515- if (decodedPublicKey == null ) {
516- throw new IllegalArgumentException ("Unexpected type" );
517- }
518- EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec (decodedPublicKey , ED_25519 );
519- sKey = new EdDSAPublicKey (pubKeySpec );
478+ //noinspection DataFlowIssue // decode will throw instead of return null
479+ publicKey = new Ed25519PublicKeyParameters (decodedPublicKey );
520480 }
521481
522- sgr . initVerify ( sKey );
523- sgr . update ( input );
524-
525- return sgr . verify (signature );
482+ Ed25519Signer signer = new Ed25519Signer ( );
483+ signer . init ( false , publicKey );
484+ signer . update ( input , 0 , input . length );
485+ return signer . verifySignature (signature );
526486 }
527487
528488 @ Override
@@ -559,3 +519,4 @@ public int hashCode() {
559519 return result ;
560520 }
561521}
522+
0 commit comments