Skip to content

Commit 7d1e654

Browse files
committed
add ML-KEM/ML-DSA support for C# wrapper
1 parent a1e2ba2 commit 7d1e654

File tree

4 files changed

+1070
-0
lines changed

4 files changed

+1070
-0
lines changed

wrapper/CSharp/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,12 @@ And run the server with the `-S` flag:
102102
```
103103
mono server.exe -S
104104
```
105+
106+
## PQC Suppport
107+
108+
To enable ML-KEM / ML-DSA API, add following options for `wolfssl` and `wolfCrypt-Test` projects:
109+
110+
```
111+
HAVE_MLKEM
112+
HAVE_MLDSA
113+
```

wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.cs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,174 @@ private static void curve25519_test()
648648
if (publicKeyB != IntPtr.Zero) wolfcrypt.Curve25519FreeKey(publicKeyB);
649649
} /* END curve25519_test */
650650

651+
#if HAVE_MLKEM
652+
private static void mlkem_test(wolfcrypt.MlKemTypes type)
653+
{
654+
int ret;
655+
IntPtr keyA = IntPtr.Zero;
656+
IntPtr keyB = IntPtr.Zero;
657+
IntPtr heap = IntPtr.Zero;
658+
int devId = wolfcrypt.INVALID_DEVID;
659+
byte[] pubA, privA, cipherText, sharedSecretA, sharedSecretB;
660+
661+
Console.WriteLine("\nStarting " + type + " shared secret test ...");
662+
663+
/* Generate Key Pair */
664+
Console.WriteLine("Testing ML-KEM Key Generation...");
665+
666+
Console.WriteLine("Generate Key Pair A...");
667+
keyA = wolfcrypt.MlKemMakeKey(type, heap, devId);
668+
if (keyA == IntPtr.Zero)
669+
{
670+
throw new Exception("Failed to generate key pair A.");
671+
}
672+
673+
Console.WriteLine("Generate Key Pair B...");
674+
keyB = wolfcrypt.MlKemMakeKey(type, heap, devId);
675+
if (keyB == IntPtr.Zero)
676+
{
677+
throw new Exception("Failed to generate key pair B.");
678+
}
679+
680+
Console.WriteLine("ML-KEM Key Generation test passed.");
681+
682+
/* Encode */
683+
Console.WriteLine("Testing ML-KEM Key Encode...");
684+
ret = wolfcrypt.MlKemEncodePublicKey(keyA, out pubA);
685+
if (ret != 0)
686+
{
687+
throw new Exception("Failed to encode public key of A.");
688+
}
689+
ret = wolfcrypt.MlKemEncodePrivateKey(keyA, out privA);
690+
if (ret != 0)
691+
{
692+
throw new Exception("Failed to encode private key of A.");
693+
}
694+
Console.WriteLine("ML-KEM Key Encode test passed.");
695+
696+
/* Encapsulate */
697+
Console.WriteLine("Testing ML-KEM Encapsulation...");
698+
ret = wolfcrypt.MlKemEncapsulate(keyA, out cipherText, out sharedSecretA);
699+
if (ret != 0)
700+
{
701+
throw new Exception("Failed to encapsulate.");
702+
}
703+
Console.WriteLine("ML-KEM Encapsulation test passed.");
704+
705+
/* Decode */
706+
Console.WriteLine("Testing ML-KEM Decode...");
707+
ret = wolfcrypt.MlKemDecodePrivateKey(keyB, privA);
708+
if (ret != 0)
709+
{
710+
throw new Exception("Failed to decode private key of A.");
711+
}
712+
ret = wolfcrypt.MlKemDecodePublicKey(keyB, pubA);
713+
if (ret != 0)
714+
{
715+
throw new Exception("Failed to decode public key of B.");
716+
}
717+
Console.WriteLine("ML-KEM Decode test passed.");
718+
719+
/* Decapsulate */
720+
Console.WriteLine("Testing ML-KEM Decapsulation...");
721+
ret = wolfcrypt.MlKemDecapsulate(keyB, cipherText, out sharedSecretB);
722+
if (ret != 0)
723+
{
724+
throw new Exception("Failed to decapsulate.");
725+
}
726+
Console.WriteLine("ML-KEM Decapsulation test passed.");
727+
728+
/* Check */
729+
Console.WriteLine("Comparing Shared Secrets...");
730+
if (!wolfcrypt.ByteArrayVerify(sharedSecretA, sharedSecretB))
731+
{
732+
throw new Exception("Shared secrets do not match.");
733+
}
734+
else
735+
{
736+
Console.WriteLine("ML-KEM shared secret match.");
737+
}
738+
739+
/* Cleanup */
740+
if (keyA != IntPtr.Zero) wolfcrypt.MlKemFreeKey(keyA);
741+
if (keyB != IntPtr.Zero) wolfcrypt.MlKemFreeKey(keyB);
742+
} /* END mlkem_test */
743+
#endif
744+
745+
#if HAVE_MLDSA
746+
private static void mldsa_test(wolfcrypt.MlDsaTypes type)
747+
{
748+
int ret;
749+
IntPtr key = IntPtr.Zero;
750+
IntPtr heap = IntPtr.Zero;
751+
int devId = wolfcrypt.INVALID_DEVID;
752+
byte[] privateKey;
753+
byte[] publicKey;
754+
byte[] message = Encoding.UTF8.GetBytes("This is some data to sign with ML-DSA");
755+
byte[] signature;
756+
757+
Console.WriteLine("\nStarting " + type + " shared secret test ...");
758+
759+
/* Generate Key Pair */
760+
Console.WriteLine("Testing ML-DSA Key Generation...");
761+
key = wolfcrypt.DilithiumMakeKey(heap, devId, type);
762+
if (key == IntPtr.Zero)
763+
{
764+
throw new Exception("DilithiumMakeKey failed");
765+
}
766+
Console.WriteLine("ML-DSA Key Generation test passed.");
767+
768+
/* Export */
769+
Console.WriteLine("Testing ML-DSA Key Export...");
770+
ret = DilithiumExportPrivateKey(key, out privateKey);
771+
if (ret != 0)
772+
{
773+
throw new Exception("DilithiumExportPrivateKey failed");
774+
}
775+
ret = DilithiumExportPublicKey(key, out publicKey);
776+
if (ret != 0)
777+
{
778+
throw new Exception("DilithiumExportPublicKey failed");
779+
}
780+
Console.WriteLine("ML-DSA Key Export test passed.");
781+
782+
/* Import */
783+
Console.WriteLine("Testing ML-DSA Key Import...");
784+
ret = DilithiumImportPrivateKey(privateKey, key);
785+
if (ret != 0)
786+
{
787+
throw new Exception("DilithiumImportPrivateKey failed");
788+
}
789+
ret = DilithiumImportPublicKey(publicKey, key);
790+
if (ret != 0)
791+
{
792+
throw new Exception("DilithiumImportPrivateKey failed");
793+
}
794+
Console.WriteLine("ML-DSA Key Import test passed.");
795+
796+
/* Sign */
797+
Console.WriteLine("Testing ML-DSA Signature Creation...");
798+
ret = wolfcrypt.DilithiumSignMsg(key, message, out signature);
799+
if (ret != 0)
800+
{
801+
throw new Exception("DilithiumSign failed");
802+
}
803+
Console.WriteLine($"ML-DSA Signature Creation test passed. Signature Length: {signature.Length}");
804+
805+
/* Verify */
806+
Console.WriteLine("Testing ML-DSA Signature Verification...");
807+
ret = wolfcrypt.DilithiumVerifyMsg(key, message, signature);
808+
if (ret != 0)
809+
{
810+
throw new Exception("DilithiumVerify failed");
811+
}
812+
Console.WriteLine("ML-DSA Signature Verification test passed.");
813+
814+
if (key != IntPtr.Zero) wolfcrypt.DilithiumFreeKey(key);
815+
816+
} /* END mldsa_test */
817+
#endif
818+
651819
private static void aes_gcm_test()
652820
{
653821
IntPtr aes = IntPtr.Zero;
@@ -904,6 +1072,22 @@ public static void Main(string[] args)
9041072

9051073
curve25519_test(); /* curve25519 shared secret test */
9061074

1075+
#if HAVE_MLKEM
1076+
Console.WriteLine("\nStarting ML-KEM test");
1077+
1078+
mlkem_test(wolfcrypt.MlKemTypes.ML_KEM_512); /* ML-KEM test */
1079+
mlkem_test(wolfcrypt.MlKemTypes.ML_KEM_768); /* ML-KEM test */
1080+
mlkem_test(wolfcrypt.MlKemTypes.ML_KEM_1024); /* ML-KEM test */
1081+
#endif
1082+
1083+
#if HAVE_MLDSA
1084+
Console.WriteLine("\nStarting ML-DSA test");
1085+
1086+
mldsa_test(wolfcrypt.MlDsaTypes.ML_DSA_44); /* ML-DSA test */
1087+
mldsa_test(wolfcrypt.MlDsaTypes.ML_DSA_65); /* ML-DSA test */
1088+
mldsa_test(wolfcrypt.MlDsaTypes.ML_DSA_87); /* ML-DSA test */
1089+
#endif
1090+
9071091
Console.WriteLine("\nStarting AES-GCM test");
9081092

9091093
aes_gcm_test(); /* AES_GCM test */

0 commit comments

Comments
 (0)