@@ -683,6 +683,50 @@ public void ConfigureEndpoint_ThrowsWhen_The_KeyIsPublic()
683683 Assert . IsAssignableFrom < CryptographicException > ( ex . InnerException ) ;
684684 }
685685
686+ #pragma warning disable SYSLIB5006
687+ private static readonly Dictionary < string , MLDsaAlgorithm > _mlDsaAlgorithms = ( ( IEnumerable < MLDsaAlgorithm > ) [
688+ MLDsaAlgorithm . MLDsa44 ,
689+ MLDsaAlgorithm . MLDsa65 ,
690+ MLDsaAlgorithm . MLDsa87 ,
691+ ] ) . ToDictionary ( a => a . Name ) ;
692+
693+ private static readonly Dictionary < string , SlhDsaAlgorithm > _slhDsaAlgorithms = ( ( IEnumerable < SlhDsaAlgorithm > ) [
694+ SlhDsaAlgorithm . SlhDsaSha2_128s ,
695+ SlhDsaAlgorithm . SlhDsaSha2_128f ,
696+ SlhDsaAlgorithm . SlhDsaSha2_192s ,
697+ SlhDsaAlgorithm . SlhDsaSha2_192f ,
698+ SlhDsaAlgorithm . SlhDsaSha2_256s ,
699+ SlhDsaAlgorithm . SlhDsaSha2_256f ,
700+ SlhDsaAlgorithm . SlhDsaShake128s ,
701+ SlhDsaAlgorithm . SlhDsaShake128f ,
702+ SlhDsaAlgorithm . SlhDsaShake192s ,
703+ SlhDsaAlgorithm . SlhDsaShake192f ,
704+ SlhDsaAlgorithm . SlhDsaShake256s ,
705+ SlhDsaAlgorithm . SlhDsaShake256f ,
706+ ] ) . ToDictionary ( a => a . Name ) ;
707+
708+ private static readonly Dictionary < string , CompositeMLDsaAlgorithm > _compositeMLDsaAlgorithms = ( ( IEnumerable < CompositeMLDsaAlgorithm > ) [
709+ CompositeMLDsaAlgorithm . MLDsa65WithECDsaP256 ,
710+ CompositeMLDsaAlgorithm . MLDsa65WithRSA3072Pkcs15 ,
711+ CompositeMLDsaAlgorithm . MLDsa65WithEd25519 ,
712+ CompositeMLDsaAlgorithm . MLDsa65WithECDsaP384 ,
713+ CompositeMLDsaAlgorithm . MLDsa87WithRSA4096Pss ,
714+ CompositeMLDsaAlgorithm . MLDsa65WithECDsaBrainpoolP256r1 ,
715+ CompositeMLDsaAlgorithm . MLDsa44WithRSA2048Pss ,
716+ CompositeMLDsaAlgorithm . MLDsa44WithRSA2048Pkcs15 ,
717+ CompositeMLDsaAlgorithm . MLDsa44WithEd25519 ,
718+ CompositeMLDsaAlgorithm . MLDsa44WithECDsaP256 ,
719+ CompositeMLDsaAlgorithm . MLDsa65WithRSA4096Pss ,
720+ CompositeMLDsaAlgorithm . MLDsa87WithECDsaBrainpoolP384r1 ,
721+ CompositeMLDsaAlgorithm . MLDsa87WithECDsaP384 ,
722+ CompositeMLDsaAlgorithm . MLDsa87WithECDsaP521 ,
723+ CompositeMLDsaAlgorithm . MLDsa87WithEd448 ,
724+ CompositeMLDsaAlgorithm . MLDsa87WithRSA3072Pss ,
725+ CompositeMLDsaAlgorithm . MLDsa65WithRSA3072Pss ,
726+ CompositeMLDsaAlgorithm . MLDsa65WithRSA4096Pkcs15 ,
727+ ] ) . ToDictionary ( a => a . Name ) ;
728+ #pragma warning restore SYSLIB5006
729+
686730 public static TheoryData < string , string , string > GetPemCertificateTestData ( )
687731 {
688732 var data = new TheoryData < string , string , string > ( ) ;
@@ -695,29 +739,24 @@ public static TheoryData<string, string, string> GetPemCertificateTestData()
695739#pragma warning disable SYSLIB5006
696740 if ( MLDsa . IsSupported )
697741 {
698- algorithms . AddRange ( [
699- "MLDsa44" ,
700- "MLDsa65" ,
701- "MLDsa87" ,
702- ] ) ;
742+ algorithms . AddRange ( _mlDsaAlgorithms . Keys ) ;
703743 }
704744
705745 if ( SlhDsa . IsSupported )
706746 {
707- algorithms . AddRange ( [
708- "SlhDsaSha2_128s" ,
709- "SlhDsaSha2_128f" ,
710- "SlhDsaSha2_192s" ,
711- "SlhDsaSha2_192f" ,
712- "SlhDsaSha2_256s" ,
713- "SlhDsaSha2_256f" ,
714- "SlhDsaShake_128s" ,
715- "SlhDsaShake_128f" ,
716- "SlhDsaShake_192s" ,
717- "SlhDsaShake_192f" ,
718- "SlhDsaShake_256s" ,
719- "SlhDsaShake_256f"
720- ] ) ;
747+ algorithms . AddRange ( _slhDsaAlgorithms . Keys ) ;
748+ }
749+
750+ // Composite ML-DSA certificate generation is not supported at the time
751+ // of writing, so we skip it.
752+ // When it gets implemented in the future, simply remove the SkipCompositeMLDsa
753+ // condition to include it in the tests.
754+ const bool SkipCompositeMLDsa = true ;
755+ if ( CompositeMLDsa . IsSupported && ! SkipCompositeMLDsa )
756+ {
757+ algorithms . AddRange ( _compositeMLDsaAlgorithms
758+ . Where ( kvp => CompositeMLDsa . IsAlgorithmSupported ( kvp . Value ) )
759+ . Select ( kvp => kvp . Key ) ) ;
721760 }
722761#pragma warning restore SYSLIB5006
723762
@@ -840,64 +879,35 @@ private static X509Certificate2 GenerateTestCertificateWithAlgorithm(string algo
840879 }
841880 break ;
842881
843- case "MLDsa44" :
844- case "MLDsa65" :
845- case "MLDsa87" :
846882#pragma warning disable SYSLIB5006
847- var mlDsaAlgorithm = algorithmType switch
848- {
849- "MLDsa44" => MLDsaAlgorithm . MLDsa44 ,
850- "MLDsa65" => MLDsaAlgorithm . MLDsa65 ,
851- "MLDsa87" => MLDsaAlgorithm . MLDsa87 ,
852- _ => throw new ArgumentException ( $ "Unknown ML-DSA variant: { algorithmType } ")
853- } ;
883+ case var x when _mlDsaAlgorithms . TryGetValue ( x , out var mlDsaAlgorithm ) :
854884 using ( var mlDsa = MLDsa . GenerateKey ( mlDsaAlgorithm ) )
855885 {
856886 var request = new CertificateRequest ( distinguishedName , mlDsa ) ;
857887 certificate = CreateTestCertificate ( request , sanBuilder ) ;
858888 keyPem = ExportMLDsaKeyToPem ( mlDsa , keyPassword ) ;
859889 }
860- #pragma warning restore SYSLIB5006
861890 break ;
862891
863- case "SlhDsaSha2_128s" :
864- case "SlhDsaSha2_128f" :
865- case "SlhDsaSha2_192s" :
866- case "SlhDsaSha2_192f" :
867- case "SlhDsaSha2_256s" :
868- case "SlhDsaSha2_256f" :
869- case "SlhDsaShake_128s" :
870- case "SlhDsaShake_128f" :
871- case "SlhDsaShake_192s" :
872- case "SlhDsaShake_192f" :
873- case "SlhDsaShake_256s" :
874- case "SlhDsaShake_256f" :
875- #pragma warning disable SYSLIB5006
876- var slhDsaAlgorithm = algorithmType switch
877- {
878- "SlhDsaSha2_128s" => SlhDsaAlgorithm . SlhDsaSha2_128s ,
879- "SlhDsaSha2_128f" => SlhDsaAlgorithm . SlhDsaSha2_128f ,
880- "SlhDsaSha2_192s" => SlhDsaAlgorithm . SlhDsaSha2_192s ,
881- "SlhDsaSha2_192f" => SlhDsaAlgorithm . SlhDsaSha2_192f ,
882- "SlhDsaSha2_256s" => SlhDsaAlgorithm . SlhDsaSha2_256s ,
883- "SlhDsaSha2_256f" => SlhDsaAlgorithm . SlhDsaSha2_256f ,
884- "SlhDsaShake_128s" => SlhDsaAlgorithm . SlhDsaShake128s ,
885- "SlhDsaShake_128f" => SlhDsaAlgorithm . SlhDsaShake128f ,
886- "SlhDsaShake_192s" => SlhDsaAlgorithm . SlhDsaShake192s ,
887- "SlhDsaShake_192f" => SlhDsaAlgorithm . SlhDsaShake192f ,
888- "SlhDsaShake_256s" => SlhDsaAlgorithm . SlhDsaShake256s ,
889- "SlhDsaShake_256f" => SlhDsaAlgorithm . SlhDsaShake256f ,
890- _ => throw new ArgumentException ( $ "Unknown SLH-DSA variant: { algorithmType } ")
891- } ;
892+ case var x when _slhDsaAlgorithms . TryGetValue ( x , out var slhDsaAlgorithm ) :
892893 using ( var slhDsa = SlhDsa . GenerateKey ( slhDsaAlgorithm ) )
893894 {
894895 var request = new CertificateRequest ( distinguishedName , slhDsa ) ;
895896 certificate = CreateTestCertificate ( request , sanBuilder ) ;
896897 keyPem = ExportSlhDsaKeyToPem ( slhDsa , keyPassword ) ;
897898 }
898- #pragma warning restore SYSLIB5006
899899 break ;
900900
901+ case var x when _compositeMLDsaAlgorithms . TryGetValue ( x , out var compositeMLDsaAlgorithm ) :
902+ using ( var compositeMLDsa = CompositeMLDsa . GenerateKey ( compositeMLDsaAlgorithm ) )
903+ {
904+ var request = new CertificateRequest ( distinguishedName , compositeMLDsa ) ;
905+ certificate = CreateTestCertificate ( request , sanBuilder ) ;
906+ keyPem = ExportCompositeMLDsaKeyToPem ( compositeMLDsa , keyPassword ) ;
907+ }
908+ break ;
909+ #pragma warning restore SYSLIB5006
910+
901911 default :
902912 throw new ArgumentException ( $ "Unknown algorithm type: { algorithmType } ") ;
903913 }
@@ -951,6 +961,14 @@ private static string ExportSlhDsaKeyToPem(SlhDsa slhDsa, string password)
951961 ? slhDsa . ExportPkcs8PrivateKeyPem ( )
952962 : slhDsa . ExportEncryptedPkcs8PrivateKeyPem ( password . AsSpan ( ) , new PbeParameters ( PbeEncryptionAlgorithm . Aes256Cbc , HashAlgorithmName . SHA256 , 100_000 ) ) ;
953963 }
964+
965+ private static string ExportCompositeMLDsaKeyToPem ( CompositeMLDsa compositeMLDsa , string password )
966+ {
967+ return password is null
968+ ? compositeMLDsa . ExportPkcs8PrivateKeyPem ( )
969+ : compositeMLDsa . ExportEncryptedPkcs8PrivateKeyPem ( password . AsSpan ( ) , new PbeParameters ( PbeEncryptionAlgorithm . Aes256Cbc , HashAlgorithmName . SHA256 , 100_000 ) ) ;
970+ }
971+
954972#pragma warning restore SYSLIB5006
955973
956974 [ Fact ]
0 commit comments