11
11
import static org .junit .jupiter .api .Assertions .assertTrue ;
12
12
13
13
import com .amazon .corretto .crypto .provider .AmazonCorrettoCryptoProvider ;
14
+ import com .amazon .corretto .crypto .utils .MlDsaUtils ;
14
15
import java .security .InvalidKeyException ;
15
16
import java .security .KeyFactory ;
16
17
import java .security .KeyPair ;
24
25
import java .util .ArrayList ;
25
26
import java .util .Arrays ;
26
27
import java .util .List ;
28
+ import org .junit .jupiter .api .Disabled ;
27
29
import org .junit .jupiter .api .Test ;
28
30
import org .junit .jupiter .api .condition .DisabledIf ;
29
31
import org .junit .jupiter .api .extension .ExtendWith ;
@@ -88,7 +90,9 @@ private static List<TestParams> getParams() throws Exception {
88
90
// support non-Bouncy-Castle keys.
89
91
KeyFactory bcKf = KeyFactory .getInstance ("ML-DSA" , TestUtil .BC_PROVIDER );
90
92
PublicKey bcPub = bcKf .generatePublic (new X509EncodedKeySpec (nativePub .getEncoded ()));
91
- PrivateKey bcPriv = bcKf .generatePrivate (new PKCS8EncodedKeySpec (nativePriv .getEncoded ()));
93
+ // TODO uncomment below once BC supports CHOICE-encoded private keys
94
+ // PrivateKey bcPriv = bcKf.generatePrivate(new
95
+ // PKCS8EncodedKeySpec(nativePriv.getEncoded()));
92
96
93
97
Provider nativeProv = NATIVE_PROVIDER ;
94
98
Provider bcProv = TestUtil .BC_PROVIDER ;
@@ -98,8 +102,8 @@ private static List<TestParams> getParams() throws Exception {
98
102
99
103
params .add (new TestParams (nativeProv , nativeProv , nativePriv , nativePub , message ));
100
104
params .add (new TestParams (nativeProv , bcProv , nativePriv , bcPub , message ));
101
- params .add (new TestParams (bcProv , nativeProv , bcPriv , nativePub , message ));
102
- params .add (new TestParams (bcProv , bcProv , bcPriv , bcPub , message ));
105
+ // params.add(new TestParams(bcProv, nativeProv, bcPriv, nativePub, message));
106
+ // params.add(new TestParams(bcProv, bcProv, bcPriv, bcPub, message));
103
107
}
104
108
}
105
109
return params ;
@@ -200,47 +204,49 @@ public void testInvalidKeyInitialization() {
200
204
});
201
205
}
202
206
207
+ @ Disabled ("until BC updates to newer CHOICE priv key encoding format" )
203
208
@ Test
204
209
public void documentBouncyCastleDifferences () throws Exception {
205
- // ACCP and BouncyCastle both encode the public key in full form, but BC FIPS encodes the
206
- // private key as its 32 byte
207
- // seed while ACCP encodes the fully expanded key. Key sizes don't precisely match the spec's
208
- // sizes due to X509/PKCS9 ASN.1 encoding overhead.
209
- // https://openquantumsafe.org/liboqs/algorithms/sig/ml-dsa.html
210
+ // ACCP and BouncyCastle both encode ML-DSA public keys in "expanded "form and ML-DSA private
211
+ // keys in "seed" form.
212
+ KeyFactory bcKf = KeyFactory .getInstance ("ML-DSA" , TestUtil .BC_PROVIDER );
210
213
KeyPair nativePair =
211
214
KeyPairGenerator .getInstance ("ML-DSA-44" , NATIVE_PROVIDER ).generateKeyPair ();
212
- KeyPair bcPair =
213
- KeyPairGenerator .getInstance ("ML-DSA-44" , TestUtil .BC_PROVIDER ).generateKeyPair ();
214
- assertEquals (
215
- nativePair .getPublic ().getEncoded ().length , bcPair .getPublic ().getEncoded ().length );
216
- assertEquals (2584 , nativePair .getPrivate ().getEncoded ().length );
217
- assertEquals (52 , bcPair .getPrivate ().getEncoded ().length );
215
+ PublicKey nativePub = nativePair .getPublic ();
216
+ PrivateKey nativePriv = nativePair .getPrivate ();
217
+ PublicKey bcPub = bcKf .generatePublic (new X509EncodedKeySpec (nativePub .getEncoded ()));
218
+ PrivateKey bcPriv = bcKf .generatePrivate (new PKCS8EncodedKeySpec (nativePriv .getEncoded ()));
219
+ TestUtil .assertArraysHexEquals (bcPub .getEncoded (), nativePub .getEncoded ());
220
+ assertEquals (bcPriv .getEncoded ().length + 2 , nativePriv .getEncoded ().length );
221
+ TestUtil .assertArraysHexEquals (bcPriv .getEncoded (), nativePriv .getEncoded ());
218
222
219
223
nativePair = KeyPairGenerator .getInstance ("ML-DSA-65" , NATIVE_PROVIDER ).generateKeyPair ();
220
- bcPair = KeyPairGenerator .getInstance ("ML-DSA-65" , TestUtil .BC_PROVIDER ).generateKeyPair ();
221
- assertEquals (
222
- nativePair .getPublic ().getEncoded ().length , bcPair .getPublic ().getEncoded ().length );
223
- assertEquals (4056 , nativePair .getPrivate ().getEncoded ().length );
224
- assertEquals (52 , bcPair .getPrivate ().getEncoded ().length );
224
+ nativePub = nativePair .getPublic ();
225
+ nativePriv = nativePair .getPrivate ();
226
+ bcPub = bcKf .generatePublic (new X509EncodedKeySpec (nativePub .getEncoded ()));
227
+ bcPriv = bcKf .generatePrivate (new PKCS8EncodedKeySpec (nativePriv .getEncoded ()));
228
+ TestUtil .assertArraysHexEquals (bcPub .getEncoded (), nativePub .getEncoded ());
229
+ assertEquals (bcPriv .getEncoded ().length + 2 , nativePriv .getEncoded ().length );
230
+ TestUtil .assertArraysHexEquals (bcPriv .getEncoded (), nativePriv .getEncoded ());
225
231
226
232
nativePair = KeyPairGenerator .getInstance ("ML-DSA-87" , NATIVE_PROVIDER ).generateKeyPair ();
227
- bcPair = KeyPairGenerator .getInstance ("ML-DSA-87" , TestUtil .BC_PROVIDER ).generateKeyPair ();
228
- assertEquals (
229
- nativePair .getPublic ().getEncoded ().length , bcPair .getPublic ().getEncoded ().length );
230
- assertEquals (4920 , nativePair .getPrivate ().getEncoded ().length );
231
- assertEquals (52 , bcPair .getPrivate ().getEncoded ().length );
233
+ nativePub = nativePair .getPublic ();
234
+ nativePriv = nativePair .getPrivate ();
235
+ bcPub = bcKf .generatePublic (new X509EncodedKeySpec (nativePub .getEncoded ()));
236
+ bcPriv = bcKf .generatePrivate (new PKCS8EncodedKeySpec (nativePriv .getEncoded ()));
237
+ TestUtil .assertArraysHexEquals (bcPub .getEncoded (), nativePub .getEncoded ());
238
+ TestUtil .assertArraysHexEquals (bcPriv .getEncoded (), nativePriv .getEncoded ());
232
239
233
240
// BouncyCastle Signatures don't accept keys from other providers
234
241
Signature bcSignature = Signature .getInstance ("ML-DSA" , TestUtil .BC_PROVIDER );
235
- final KeyPair finalNativePair = nativePair ;
236
- assertThrows (
237
- InvalidKeyException .class , () -> bcSignature .initSign (finalNativePair .getPrivate ()));
242
+ final PrivateKey finalNativePriv = nativePriv ;
243
+ assertThrows (InvalidKeyException .class , () -> bcSignature .initSign (finalNativePriv ));
238
244
239
245
// However, ACCP can use BouncyCastle KeyPairs with seed-encoded PrivateKeys
240
246
Signature nativeSignature = Signature .getInstance ("ML-DSA" , NATIVE_PROVIDER );
241
- nativeSignature .initSign (bcPair . getPrivate () );
247
+ nativeSignature .initSign (bcPriv );
242
248
byte [] sigBytes = nativeSignature .sign ();
243
- nativeSignature .initVerify (bcPair . getPublic () );
249
+ nativeSignature .initVerify (bcPub );
244
250
assertTrue (nativeSignature .verify (sigBytes ));
245
251
}
246
252
@@ -258,7 +264,7 @@ public void testExtMu(TestParams params) throws Exception {
258
264
PublicKey pub = params .pub ;
259
265
260
266
byte [] message = Arrays .copyOf (params .message , params .message .length );
261
- byte [] mu = TestUtil . computeMLDSAMu (pub , message );
267
+ byte [] mu = MlDsaUtils . computeMu (pub , message );
262
268
assertEquals (64 , mu .length );
263
269
byte [] fakeMu = new byte [64 ];
264
270
Arrays .fill (fakeMu , (byte ) 0 );
@@ -304,22 +310,4 @@ public void testExtMu(TestParams params) throws Exception {
304
310
extMuVerifier .update (mu );
305
311
assertFalse (extMuVerifier .verify (signatureBytes ));
306
312
}
307
-
308
- @ ParameterizedTest
309
- @ ValueSource (strings = {"ML-DSA-44" , "ML-DSA-65" , "ML-DSA-87" })
310
- public void testComputeMLDSAExtMu (String algorithm ) throws Exception {
311
- KeyPair keyPair = KeyPairGenerator .getInstance (algorithm , NATIVE_PROVIDER ).generateKeyPair ();
312
- PublicKey nativePub = keyPair .getPublic ();
313
- KeyFactory bcKf = KeyFactory .getInstance ("ML-DSA" , TestUtil .BC_PROVIDER );
314
- PublicKey bcPub = bcKf .generatePublic (new X509EncodedKeySpec (nativePub .getEncoded ()));
315
-
316
- byte [] message = new byte [256 ];
317
- Arrays .fill (message , (byte ) 0x41 );
318
- byte [] mu = TestUtil .computeMLDSAMu (nativePub , message );
319
- assertEquals (64 , mu .length );
320
- // We don't have any other implementations of mu calculation to test against, so just assert
321
- // that mu is equivalent
322
- // generated from both ACCP and BouncyCastle keys.
323
- assertArrayEquals (mu , TestUtil .computeMLDSAMu (bcPub , message ));
324
- }
325
313
}
0 commit comments