@@ -85,6 +85,7 @@ import java.security.interfaces.RSAPublicKey
8585import java .security .spec .ECGenParameterSpec
8686import java .security .spec .ECPoint
8787import java .security .spec .ECPublicKeySpec
88+ import java .security .spec .NamedParameterSpec
8889import java .security .spec .PKCS8EncodedKeySpec
8990import java .security .spec .X509EncodedKeySpec
9091import java .time .Instant
@@ -416,6 +417,8 @@ object TestAuthenticator {
416417 case pub : BCEdDSAPublicKey => WebAuthnTestCodecs .eddsaPublicKeyToCose(pub)
417418 case pub : RSAPublicKey =>
418419 WebAuthnTestCodecs .rsaPublicKeyToCose(pub, keyAlgorithm)
420+ case pub if pub.getAlgorithm == " ML-DSA" =>
421+ WebAuthnTestCodecs .mlDsaPublicKeyToCose(pub, keyAlgorithm)
419422 }
420423
421424 val authDataBytes : ByteArray = makeAuthDataBytes(
@@ -1098,8 +1101,15 @@ object TestAuthenticator {
10981101 ): ByteArray = {
10991102 val jAlg = WebAuthnCodecs .getJavaAlgorithmName(alg)
11001103
1101- // Need to use BouncyCastle provider here because JDK15 standard providers do not support secp256k1
1102- val sig = Signature .getInstance(jAlg, new BouncyCastleProvider ())
1104+ val sig = alg match {
1105+ case COSEAlgorithmIdentifier .ML_DSA_44 |
1106+ COSEAlgorithmIdentifier .ML_DSA_65 |
1107+ COSEAlgorithmIdentifier .ML_DSA_87 =>
1108+ Signature .getInstance(jAlg)
1109+ case _ =>
1110+ // Need to use BouncyCastle provider here because JDK15 standard providers do not support secp256k1
1111+ Signature .getInstance(jAlg, new BouncyCastleProvider ())
1112+ }
11031113
11041114 sig.initSign(key)
11051115 sig.update(data.getBytes)
@@ -1117,6 +1127,10 @@ object TestAuthenticator {
11171127 case COSEAlgorithmIdentifier .RS256 | COSEAlgorithmIdentifier .RS384 |
11181128 COSEAlgorithmIdentifier .RS512 | COSEAlgorithmIdentifier .RS1 =>
11191129 generateRsaKeypair()
1130+ case COSEAlgorithmIdentifier .ML_DSA_44 |
1131+ COSEAlgorithmIdentifier .ML_DSA_65 |
1132+ COSEAlgorithmIdentifier .ML_DSA_87 =>
1133+ generateMlDsaKeypair(algorithm)
11201134 }
11211135
11221136 def generateEcKeypair (curve : String = " secp256r1" ): KeyPair = {
@@ -1138,6 +1152,15 @@ object TestAuthenticator {
11381152 keyPairGenerator.generateKeyPair()
11391153 }
11401154
1155+ def generateMlDsaKeypair (
1156+ algorithm : COSEAlgorithmIdentifier
1157+ ): KeyPair = {
1158+ val alg = WebAuthnCodecs .getJavaAlgorithmName(algorithm)
1159+ val keyPairGenerator = KeyPairGenerator .getInstance(" ML-DSA" )
1160+ keyPairGenerator.initialize(new NamedParameterSpec (alg))
1161+ keyPairGenerator.generateKeyPair()
1162+ }
1163+
11411164 def importEcKeypair (
11421165 privateBytes : ByteArray ,
11431166 publicBytes : ByteArray ,
@@ -1312,9 +1335,15 @@ object TestAuthenticator {
13121335 val signerBuilder = new JcaContentSignerBuilder (
13131336 WebAuthnCodecs .getJavaAlgorithmName(signingAlg)
13141337 )
1315- .setProvider(
1316- new BouncyCastleProvider ()
1317- ) // Needed because JDK15 standard providers do not support secp256k1
1338+ signingAlg match {
1339+ case COSEAlgorithmIdentifier .ML_DSA_44 |
1340+ COSEAlgorithmIdentifier .ML_DSA_65 |
1341+ COSEAlgorithmIdentifier .ML_DSA_87 =>
1342+ case _ =>
1343+ signerBuilder.setProvider(
1344+ new BouncyCastleProvider ()
1345+ ) // Needed because JDK15 standard providers do not support secp256k1
1346+ }
13181347
13191348 builder.build(signerBuilder.build(signingKey)).getEncoded
13201349 })
0 commit comments