2525import org .junit .runner .RunWith ;
2626import org .junit .runners .JUnit4 ;
2727
28+ import java .io .ByteArrayInputStream ;
29+ import java .io .ByteArrayOutputStream ;
30+ import java .io .ObjectInputStream ;
31+ import java .io .ObjectOutputStream ;
2832import java .security .KeyFactory ;
2933import java .security .KeyPair ;
3034import java .security .KeyPairGenerator ;
@@ -122,6 +126,7 @@ public void mldsa65_works() throws Exception {
122126 ss .initSign (privateKey );
123127 ss .update (msg );
124128 byte [] sig = ss .sign ();
129+ assertEquals (3309 , sig .length );
125130
126131 Signature sv = Signature .getInstance ("ML-DSA-65" , conscryptProvider );
127132 sv .initVerify (publicKey );
@@ -145,6 +150,35 @@ public void getRawKey_works() throws Exception {
145150 EncodedKeySpec publicKeySpec = keyFactory .getKeySpec (keyPair .getPublic (), RawKeySpec .class );
146151 assertEquals ("raw" , publicKeySpec .getFormat ());
147152 assertEquals (1952 , publicKeySpec .getEncoded ().length );
153+
154+ PrivateKey privateKey = keyFactory .generatePrivate (privateKeySpec );
155+ PublicKey publicKey = keyFactory .generatePublic (publicKeySpec );
156+
157+ assertEquals (privateKey , keyPair .getPrivate ());
158+ assertEquals (publicKey , keyPair .getPublic ());
159+ }
160+
161+ @ Test
162+ public void mldsa65_getRawKey_works () throws Exception {
163+ KeyPairGenerator keyGen = KeyPairGenerator .getInstance ("ML-DSA-65" , conscryptProvider );
164+ KeyPair keyPair = keyGen .generateKeyPair ();
165+
166+ KeyFactory keyFactory = KeyFactory .getInstance ("ML-DSA-65" , conscryptProvider );
167+
168+ EncodedKeySpec privateKeySpec =
169+ keyFactory .getKeySpec (keyPair .getPrivate (), RawKeySpec .class );
170+ assertEquals ("raw" , privateKeySpec .getFormat ());
171+ assertEquals (32 , privateKeySpec .getEncoded ().length );
172+
173+ EncodedKeySpec publicKeySpec = keyFactory .getKeySpec (keyPair .getPublic (), RawKeySpec .class );
174+ assertEquals ("raw" , publicKeySpec .getFormat ());
175+ assertEquals (1952 , publicKeySpec .getEncoded ().length );
176+
177+ PrivateKey privateKey = keyFactory .generatePrivate (privateKeySpec );
178+ PublicKey publicKey = keyFactory .generatePublic (publicKeySpec );
179+
180+ assertEquals (privateKey , keyPair .getPrivate ());
181+ assertEquals (publicKey , keyPair .getPublic ());
148182 }
149183
150184 @ Test
@@ -172,23 +206,97 @@ public void testVectors() throws Exception {
172206 byte [] message = vector .getBytes ("message" );
173207 byte [] signature = vector .getBytes ("signature" );
174208
175- assertEquals (errMsg + ", algorithm:" , "ML-DSA-65" , algorithm );
209+ if (!algorithm .startsWith ("ML-DSA" )) {
210+ assertTrue (errMsg + ", algorithm must start with ML-DSA" , false );
211+ }
176212
177- KeyFactory keyFactory = KeyFactory .getInstance ("ML-DSA" , conscryptProvider );
213+ KeyFactory keyFactory = KeyFactory .getInstance (algorithm , conscryptProvider );
178214
179- Signature signer = Signature .getInstance ("ML-DSA" , conscryptProvider );
215+ Signature signer = Signature .getInstance (algorithm , conscryptProvider );
180216 signer .initSign (keyFactory .generatePrivate (new RawKeySpec (seed )));
181217 signer .update (message );
182218 byte [] sig = signer .sign ();
183219
184- Signature verifier = Signature .getInstance ("ML-DSA" , conscryptProvider );
220+ assertEquals (errMsg + ", signature length mismatch" , signature .length , sig .length );
221+
222+ Signature verifier = Signature .getInstance (algorithm , conscryptProvider );
185223 verifier .initVerify (keyFactory .generatePublic (new RawKeySpec (publicKey )));
186224 verifier .update (message );
187- assertTrue (verifier .verify (sig ));
225+ assertTrue (errMsg + ", new signature verification failed" , verifier .verify (sig ));
188226
189227 verifier .initVerify (keyFactory .generatePublic (new RawKeySpec (publicKey )));
190228 verifier .update (message );
191- assertTrue (verifier .verify (signature ));
229+ assertTrue (errMsg + ", testvector signature verification failed. how about: ["
230+ + TestUtils .encodeHex (sig ) + "]" ,
231+ verifier .verify (signature ));
192232 }
193233 }
234+
235+ @ Test
236+ public void serializeAndDeserialize_65_works () throws Exception {
237+ KeyPairGenerator keyGen = KeyPairGenerator .getInstance ("ML-DSA-65" , conscryptProvider );
238+ KeyPair keyPair = keyGen .generateKeyPair ();
239+
240+ ByteArrayOutputStream baos = new ByteArrayOutputStream (16384 );
241+ try (ObjectOutputStream oos = new ObjectOutputStream (baos )) {
242+ oos .writeObject (keyPair .getPrivate ());
243+ oos .writeObject (keyPair .getPublic ());
244+ }
245+
246+ ByteArrayInputStream bais = new ByteArrayInputStream (baos .toByteArray ());
247+ ObjectInputStream ois = new ObjectInputStream (bais );
248+ PrivateKey inflatedPrivateKey = (PrivateKey ) ois .readObject ();
249+ PublicKey inflatedPublicKey = (PublicKey ) ois .readObject ();
250+
251+ assertEquals (inflatedPrivateKey , keyPair .getPrivate ());
252+ assertEquals (inflatedPublicKey , keyPair .getPublic ());
253+ }
254+
255+ @ Test
256+ public void serializePrivateKey_65_isEqualToTestVector () throws Exception {
257+ byte [] rawPrivateKey = TestUtils .decodeHex (
258+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" );
259+
260+ KeyFactory keyFactory = KeyFactory .getInstance ("ML-DSA-65" , conscryptProvider );
261+ PrivateKey privateKey = keyFactory .generatePrivate (new RawKeySpec (rawPrivateKey ));
262+
263+ ByteArrayOutputStream baos = new ByteArrayOutputStream (16384 );
264+ try (ObjectOutputStream oos = new ObjectOutputStream (baos )) {
265+ oos .writeObject (privateKey );
266+ }
267+
268+ String expectedHexEncoding = "aced000573720024"
269+ + "6f72672e636f6e7363727970742e" // hex("org.conscrypt.")
270+ + "4f70656e53736c4d6c447361507269766174654b6579" // hex("OpenSslMldsaPrivateKey")
271+ + "3bacc385e8e106a3" // serialVersionUID
272+ + "0200015b0004"
273+ + "73656564" // hex("seed")
274+ + "7400025b427870757200025b42acf317f8060854e00200007870000000"
275+ + "20" // hex(32), size of the raw private key
276+ + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ; // rawPrivateKey
277+ assertEquals (expectedHexEncoding , TestUtils .encodeHex (baos .toByteArray ()));
278+ }
279+
280+ @ Test
281+ public void serializePublicKey_65_isEqualToTestVector () throws Exception {
282+ byte [] rawPublicKey = new byte [1952 ];
283+
284+ KeyFactory keyFactory = KeyFactory .getInstance ("ML-DSA-65" , conscryptProvider );
285+ PublicKey publicKey = keyFactory .generatePublic (new RawKeySpec (rawPublicKey ));
286+
287+ ByteArrayOutputStream baos = new ByteArrayOutputStream (16384 );
288+ try (ObjectOutputStream oos = new ObjectOutputStream (baos )) {
289+ oos .writeObject (publicKey );
290+ }
291+
292+ String expectedHexEncoding = "aced000573720023"
293+ + "6f72672e636f6e7363727970742e" // hex("org.conscrypt.")
294+ + "4f70656e53736c4d6c4473615075626c69634b6579" // hex("OpenSslMldsaPublicKey")
295+ + "064c7113d078e42d" // serialVersionUID
296+ + "0200015b0003"
297+ + "726177" // hex("raw")
298+ + "7400025b427870757200025b42acf317f8060854e002000078700000"
299+ + "07a0" + TestUtils .encodeHex (rawPublicKey );
300+ assertEquals (expectedHexEncoding , TestUtils .encodeHex (baos .toByteArray ()));
301+ }
194302}
0 commit comments