Skip to content

Commit 91bdcc2

Browse files
authored
Add ML-DSA private and public key serialization tests. (#1347)
* Add ML-DSA private and public key serialization tests. * Remove some stuff. * Remove tests with invalid keys. These tests do not work, as we don't yet validate the keys.
1 parent 4ef1df7 commit 91bdcc2

1 file changed

Lines changed: 114 additions & 6 deletions

File tree

common/src/test/java/org/conscrypt/MlDsaTest.java

Lines changed: 114 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
import org.junit.runner.RunWith;
2626
import 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;
2832
import java.security.KeyFactory;
2933
import java.security.KeyPair;
3034
import 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

Comments
 (0)