@@ -34,6 +34,17 @@ public class MLDsaTest
3434 { "sigVer_ML-DSA-87.txt" , MLDsaParameters . ml_dsa_87 } ,
3535 } ;
3636
37+ private static readonly Dictionary < string , MLDsaParameters > ContextFileParameters =
38+ new Dictionary < string , MLDsaParameters > ( )
39+ {
40+ { "mldsa44.rsp" , MLDsaParameters . ml_dsa_44 } ,
41+ { "mldsa65.rsp" , MLDsaParameters . ml_dsa_65 } ,
42+ { "mldsa87.rsp" , MLDsaParameters . ml_dsa_87 } ,
43+ { "mldsa44Sha512.rsp" , MLDsaParameters . ml_dsa_44_with_sha512 } ,
44+ { "mldsa65Sha512.rsp" , MLDsaParameters . ml_dsa_65_with_sha512 } ,
45+ { "mldsa87Sha512.rsp" , MLDsaParameters . ml_dsa_87_with_sha512 } ,
46+ } ;
47+
3748 private static readonly Dictionary < string , MLDsaParameters > Parameters =
3849 new Dictionary < string , MLDsaParameters > ( )
3950 {
@@ -51,6 +62,8 @@ public class MLDsaTest
5162 "keyGen_ML-DSA-87.txt" ,
5263 } ;
5364
65+ private static readonly IEnumerable < string > ContextFiles = ContextFileParameters . Keys ;
66+
5467 private static readonly string [ ] SigGenAcvpFiles =
5568 {
5669 "sigGen_ML-DSA-44.txt" ,
@@ -107,6 +120,14 @@ public void Consistency(MLDsaParameters parameters)
107120 while ( msgLen <= 2048 ) ;
108121 }
109122
123+ [ TestCaseSource ( nameof ( ContextFiles ) ) ]
124+ [ Parallelizable ]
125+ public void Context ( string fileName )
126+ {
127+ RunTestVectors ( "pqc/crypto/mldsa" , fileName ,
128+ ( name , data ) => ImplContext ( name , data , ContextFileParameters [ name ] ) ) ;
129+ }
130+
110131 [ Test ]
111132 [ Parallelizable ]
112133 public void KeyGen ( )
@@ -155,6 +176,77 @@ public void KeyGenAcvp(string fileName)
155176 // (name, data) => ImplSigVer(name, data, AcvpFileParameters[name]));
156177 //}
157178
179+ private static void ImplContext ( string name , Dictionary < string , string > data , MLDsaParameters parameters )
180+ {
181+ string count = data [ "count" ] ;
182+ byte [ ] seed = Hex . Decode ( data [ "seed" ] ) ;
183+ byte [ ] msg = Hex . Decode ( data [ "msg" ] ) ;
184+ byte [ ] pk = Hex . Decode ( data [ "pk" ] ) ;
185+ byte [ ] sk = Hex . Decode ( data [ "sk" ] ) ;
186+ byte [ ] sm = Hex . Decode ( data [ "sm" ] ) ;
187+
188+ byte [ ] context = null ;
189+ if ( data . TryGetValue ( "context" , out var contextValue ) )
190+ {
191+ context = Hex . Decode ( contextValue ) ;
192+ }
193+
194+ var random = FixedSecureRandom . From ( seed ) ;
195+
196+ var kpg = new MLDsaKeyPairGenerator ( ) ;
197+ kpg . Init ( new MLDsaKeyGenerationParameters ( random , parameters ) ) ;
198+
199+ var kp = kpg . GenerateKeyPair ( ) ;
200+
201+ var publicKey = ( MLDsaPublicKeyParameters ) kp . Public ;
202+ var privateKey = ( MLDsaPrivateKeyParameters ) kp . Private ;
203+
204+ Assert . True ( Arrays . AreEqual ( pk , publicKey . GetEncoded ( ) ) , $ "{ name } { count } : public key") ;
205+ Assert . True ( Arrays . AreEqual ( sk , privateKey . GetEncoded ( ) ) , $ "{ name } { count } : secret key") ;
206+
207+ var publicKeyRT = ( MLDsaPublicKeyParameters ) PublicKeyFactory . CreateKey (
208+ SubjectPublicKeyInfoFactory . CreateSubjectPublicKeyInfo ( publicKey ) ) ;
209+ var privateKeyRT = ( MLDsaPrivateKeyParameters ) PrivateKeyFactory . CreateKey (
210+ PrivateKeyInfoFactory . CreatePrivateKeyInfo ( privateKey ) ) ;
211+
212+ Assert . True ( Arrays . AreEqual ( pk , publicKeyRT . GetEncoded ( ) ) , $ "{ name } { count } : public key (round-trip)") ;
213+ Assert . True ( Arrays . AreEqual ( sk , privateKeyRT . GetEncoded ( ) ) , $ "{ name } { count } : secret key (round-trip)") ;
214+
215+ // Note that this is a deterministic signature test, since we are not given "rnd"
216+ ISigner sig ;
217+ if ( parameters . IsPreHash )
218+ {
219+ sig = new HashMLDsaSigner ( parameters , deterministic : true ) ;
220+ }
221+ else
222+ {
223+ sig = new MLDsaSigner ( parameters , deterministic : true ) ;
224+ }
225+
226+ // The current test data is a bit weird and uses internal signing when no explicit context provided.
227+ if ( context == null )
228+ {
229+ //var rnd = new byte[32]; // Deterministic
230+ //byte[] generated = privateKey.SignInternal(rnd, msg, 0, msg.Length);
231+ //Assert.True(Arrays.AreEqual(sm, generated), $"{name} {count}: SignInternal");
232+
233+ //bool shouldVerify = publicKey.VerifyInternal(msg, 0, msg.Length, sm);
234+ //Assert.True(shouldVerify, $"{name} {count}: VerifyInternal");
235+ }
236+ else
237+ {
238+ sig . Init ( forSigning : true , ParameterUtilities . WithContext ( privateKey , context ) ) ;
239+ sig . BlockUpdate ( msg , 0 , msg . Length ) ;
240+ byte [ ] generated = sig . GenerateSignature ( ) ;
241+ Assert . True ( Arrays . AreEqual ( sm , generated ) , $ "{ name } { count } : GenerateSignature") ;
242+
243+ sig . Init ( forSigning : false , ParameterUtilities . WithContext ( publicKey , context ) ) ;
244+ sig . BlockUpdate ( msg , 0 , msg . Length ) ;
245+ bool shouldVerify = sig . VerifySignature ( sm ) ;
246+ Assert . True ( shouldVerify , $ "{ name } { count } : VerifySignature") ;
247+ }
248+ }
249+
158250 private static void ImplKeyGen ( string name , Dictionary < string , string > data , MLDsaParameters parameters )
159251 {
160252 byte [ ] seed = Hex . Decode ( data [ "seed" ] ) ;
@@ -195,7 +287,7 @@ private static void ImplKeyGen(string name, Dictionary<string, string> data, MLD
195287 // rnd = Hex.Decode(data["rnd"]);
196288 // }
197289
198- // var privateKey = new MLDsaPrivateKeyParameters(parameters, sk);
290+ // var privateKey = MLDsaPrivateKeyParameters.FromEncoding (parameters, sk);
199291
200292 // byte[] generated = privateKey.SignInternal(rnd, message, 0, message.Length);
201293
@@ -209,7 +301,7 @@ private static void ImplKeyGen(string name, Dictionary<string, string> data, MLD
209301 // byte[] message = Hex.Decode(data["message"]);
210302 // byte[] signature = Hex.Decode(data["signature"]);
211303
212- // var publicKey = new MLDsaPublicKeyParameters(parameters, pk);
304+ // var publicKey = MLDsaPublicKeyParameters.FromEncoding (parameters, pk);
213305
214306 // bool verified = publicKey.VerifyInternal(message, 0, message.Length, signature);
215307
0 commit comments