Skip to content

Commit 5179440

Browse files
authored
Accept foreign ML-DSA keys for sign and verify. (#1442)
Currently, we use OpenSSLKey.fromPublicKey(publicKey). But that doesn't work for ML-DSA, because it used an old parse function that doesn't support ML-DSA. It is better to use engineTranslateKey.
1 parent fb995d8 commit 5179440

File tree

2 files changed

+86
-51
lines changed

2 files changed

+86
-51
lines changed

common/src/main/java/org/conscrypt/OpenSslSignatureMlDsa.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@
2828
*/
2929
@Internal
3030
public abstract class OpenSslSignatureMlDsa extends SignatureSpi {
31+
private static OpenSslMlDsaKeyFactory keyFactory = new OpenSslMlDsaKeyFactory.MlDsa();
32+
3133
/**
3234
* The current OpenSSL key we're operating on.
3335
*/
34-
3536
private OpenSSLKey key;
3637
private NativeRef.EVP_MD_CTX ctx;
3738

@@ -94,7 +95,9 @@ protected Object engineGetParameter(String param) throws InvalidParameterExcepti
9495

9596
@Override
9697
protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
97-
key = OpenSSLKey.fromPrivateKey(privateKey);
98+
OpenSslMlDsaPrivateKey conscryptPrivateKey =
99+
(OpenSslMlDsaPrivateKey) keyFactory.engineTranslateKey(privateKey);
100+
key = conscryptPrivateKey.getOpenSSLKey();
98101
MlDsaAlgorithm algorithm = OpenSslMlDsaKeyFactory.getMlDsaAlgorithm(key);
99102
if (!supportsAlgorithm(algorithm)) {
100103
throw new InvalidKeyException("Key version mismatch: " + algorithm);
@@ -107,7 +110,9 @@ protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException
107110

108111
@Override
109112
protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
110-
key = OpenSSLKey.fromPublicKey(publicKey);
113+
OpenSslMlDsaPublicKey conscryptPublicKey =
114+
(OpenSslMlDsaPublicKey) keyFactory.engineTranslateKey(publicKey);
115+
key = conscryptPublicKey.getOpenSSLKey();
111116
MlDsaAlgorithm algorithm = OpenSslMlDsaKeyFactory.getMlDsaAlgorithm(key);
112117
if (!supportsAlgorithm(algorithm)) {
113118
throw new InvalidKeyException("Key version mismatch: " + algorithm);

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

Lines changed: 78 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,54 @@ public void emptyMessage_works() throws Exception {
124124
assertTrue(signature.verify(sig2));
125125
}
126126

127+
/** Helper class to test KeyFactory.translateKey. */
128+
static class TestPublicKey implements PublicKey {
129+
public TestPublicKey(byte[] x509encoded) {
130+
this.x509encoded = x509encoded;
131+
}
132+
133+
private final byte[] x509encoded;
134+
135+
@Override
136+
public String getAlgorithm() {
137+
return "ML-DSA";
138+
}
139+
140+
@Override
141+
public String getFormat() {
142+
return "X.509";
143+
}
144+
145+
@Override
146+
public byte[] getEncoded() {
147+
return x509encoded;
148+
}
149+
}
150+
151+
/** Helper class to test KeyFactory.translateKey. */
152+
static class TestPrivateKey implements PrivateKey {
153+
public TestPrivateKey(byte[] pkcs8encoded) {
154+
this.pkcs8encoded = pkcs8encoded;
155+
}
156+
157+
private final byte[] pkcs8encoded;
158+
159+
@Override
160+
public String getAlgorithm() {
161+
return "ML-DSA";
162+
}
163+
164+
@Override
165+
public String getFormat() {
166+
return "PKCS#8";
167+
}
168+
169+
@Override
170+
public byte[] getEncoded() {
171+
return pkcs8encoded;
172+
}
173+
}
174+
127175
@Test
128176
public void mldsa65KeyPair_signVerify_works() throws Exception {
129177
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ML-DSA-65", conscryptProvider);
@@ -190,6 +238,36 @@ public void mldsa87KeyPair_signVerify_works() throws Exception {
190238
assertThrows(InvalidKeyException.class, () -> s65.initVerify(publicKey));
191239
}
192240

241+
@Test
242+
public void foreignMldsa65KeyPair_signVerify_works() throws Exception {
243+
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ML-DSA-65", conscryptProvider);
244+
KeyPair keyPair = keyGen.generateKeyPair();
245+
PrivateKey privateKey = new TestPrivateKey(keyPair.getPrivate().getEncoded());
246+
PublicKey publicKey = new TestPublicKey(keyPair.getPublic().getEncoded());
247+
248+
for (String signAlgorithm : new String[] {"ML-DSA-65", "ML-DSA"}) {
249+
byte[] msg = new byte[123];
250+
Signature ss = Signature.getInstance(signAlgorithm, conscryptProvider);
251+
ss.initSign(privateKey);
252+
ss.update(msg);
253+
byte[] sig = ss.sign();
254+
assertEquals(3309, sig.length);
255+
256+
for (String verifyAlgorithm : new String[] {"ML-DSA-65", "ML-DSA"}) {
257+
Signature sv = Signature.getInstance(verifyAlgorithm, conscryptProvider);
258+
sv.initVerify(publicKey);
259+
sv.update(msg);
260+
boolean verified = sv.verify(sig);
261+
assertTrue(verified);
262+
}
263+
}
264+
265+
// ML-DSA-87 does not support ML-DSA-65 keys.
266+
Signature s87 = Signature.getInstance("ML-DSA-87", conscryptProvider);
267+
assertThrows(InvalidKeyException.class, () -> s87.initSign(privateKey));
268+
assertThrows(InvalidKeyException.class, () -> s87.initVerify(publicKey));
269+
}
270+
193271
@Test
194272
public void mldsa65KeyPair_toAndFromRaw_works() throws Exception {
195273
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ML-DSA-65", conscryptProvider);
@@ -296,54 +374,6 @@ public void generateFromInvalidRawKey_throws() throws Exception {
296374
}
297375
}
298376

299-
/** Helper class to test KeyFactory.translateKey. */
300-
static class TestPublicKey implements PublicKey {
301-
public TestPublicKey(byte[] x509encoded) {
302-
this.x509encoded = x509encoded;
303-
}
304-
305-
private final byte[] x509encoded;
306-
307-
@Override
308-
public String getAlgorithm() {
309-
return "ML-DSA";
310-
}
311-
312-
@Override
313-
public String getFormat() {
314-
return "X.509";
315-
}
316-
317-
@Override
318-
public byte[] getEncoded() {
319-
return x509encoded;
320-
}
321-
}
322-
323-
/** Helper class to test KeyFactory.translateKey. */
324-
static class TestPrivateKey implements PrivateKey {
325-
public TestPrivateKey(byte[] pkcs8encoded) {
326-
this.pkcs8encoded = pkcs8encoded;
327-
}
328-
329-
private final byte[] pkcs8encoded;
330-
331-
@Override
332-
public String getAlgorithm() {
333-
return "ML-DSA";
334-
}
335-
336-
@Override
337-
public String getFormat() {
338-
return "PKCS#8";
339-
}
340-
341-
@Override
342-
public byte[] getEncoded() {
343-
return pkcs8encoded;
344-
}
345-
}
346-
347377
@Test
348378
public void mldsa65KeyPair_x509AndPkcs8() throws Exception {
349379
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ML-DSA-65", conscryptProvider);

0 commit comments

Comments
 (0)