Skip to content

Commit 78f7ad4

Browse files
committed
Add HPKE (RFC 9180) C# wrapper and test
1 parent 1d363f3 commit 78f7ad4

3 files changed

Lines changed: 530 additions & 0 deletions

File tree

wrapper/CSharp/user_settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
#define WOLFSSL_SHA512
7171

7272
#define HAVE_HKDF
73+
#define HAVE_HPKE
7374

7475
#undef NO_DH
7576
#define HAVE_PUBLIC_FFDHE

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

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,117 @@ private static void hash_test(uint hashType)
880880
}
881881
} /* END hash_test */
882882

883+
private static void hpke_test()
884+
{
885+
IntPtr hpke = IntPtr.Zero;
886+
IntPtr receiverKey = IntPtr.Zero;
887+
IntPtr deserializedKey = IntPtr.Zero;
888+
IntPtr ephemeralKey = IntPtr.Zero;
889+
890+
wolfcrypt.HpkeKem kem = wolfcrypt.HpkeKem.DHKEM_P256_HKDF_SHA256;
891+
wolfcrypt.HpkeKdf kdf = wolfcrypt.HpkeKdf.HKDF_SHA256;
892+
wolfcrypt.HpkeAead aead = wolfcrypt.HpkeAead.AES_128_GCM;
893+
894+
try
895+
{
896+
Console.WriteLine("\nStarting HPKE Base mode test...");
897+
898+
/* Initialize HPKE context */
899+
Console.WriteLine("Initializing HPKE context...");
900+
hpke = wolfcrypt.HpkeInit(kem, kdf, aead);
901+
if (hpke == IntPtr.Zero)
902+
{
903+
throw new Exception("HpkeInit failed");
904+
}
905+
Console.WriteLine("HPKE context initialization passed.");
906+
907+
/* Generate receiver keypair */
908+
Console.WriteLine("Generating receiver keypair...");
909+
receiverKey = wolfcrypt.HpkeGenerateKeyPair(hpke);
910+
if (receiverKey == IntPtr.Zero)
911+
{
912+
throw new Exception("HpkeGenerateKeyPair (receiver) failed");
913+
}
914+
Console.WriteLine("Receiver keypair generation passed.");
915+
916+
/* Serialize and deserialize public key (round-trip) */
917+
Console.WriteLine("Testing public key serialize/deserialize round-trip...");
918+
byte[] pubKeyBytes = wolfcrypt.HpkeSerializePublicKey(hpke, receiverKey);
919+
if (pubKeyBytes == null)
920+
{
921+
throw new Exception("HpkeSerializePublicKey failed");
922+
}
923+
Console.WriteLine($"Serialized public key length: {pubKeyBytes.Length}");
924+
925+
deserializedKey = wolfcrypt.HpkeDeserializePublicKey(hpke, pubKeyBytes);
926+
if (deserializedKey == IntPtr.Zero)
927+
{
928+
throw new Exception("HpkeDeserializePublicKey failed");
929+
}
930+
931+
/* Verify round-trip by re-serializing */
932+
byte[] pubKeyBytes2 = wolfcrypt.HpkeSerializePublicKey(hpke, deserializedKey);
933+
if (pubKeyBytes2 == null || !wolfcrypt.ByteArrayVerify(pubKeyBytes, pubKeyBytes2))
934+
{
935+
throw new Exception("Public key round-trip verification failed");
936+
}
937+
Console.WriteLine("Public key round-trip test passed.");
938+
939+
/* Generate ephemeral keypair for sender */
940+
Console.WriteLine("Generating ephemeral keypair...");
941+
ephemeralKey = wolfcrypt.HpkeGenerateKeyPair(hpke);
942+
if (ephemeralKey == IntPtr.Zero)
943+
{
944+
throw new Exception("HpkeGenerateKeyPair (ephemeral) failed");
945+
}
946+
Console.WriteLine("Ephemeral keypair generation passed.");
947+
948+
/* Define test data */
949+
byte[] info = Encoding.UTF8.GetBytes("HPKE .NET Test");
950+
byte[] aad = Encoding.UTF8.GetBytes("additional data");
951+
byte[] plaintext = Encoding.UTF8.GetBytes("Hello HPKE from wolfCrypt .NET!");
952+
953+
/* Seal (encrypt) */
954+
Console.WriteLine("Testing HpkeSealBase...");
955+
byte[] encCiphertext = wolfcrypt.HpkeSealBase(hpke, ephemeralKey,
956+
receiverKey, info, aad, plaintext);
957+
if (encCiphertext == null)
958+
{
959+
throw new Exception("HpkeSealBase failed");
960+
}
961+
Console.WriteLine($"HpkeSealBase passed. Output length: {encCiphertext.Length}");
962+
963+
/* Open (decrypt) */
964+
Console.WriteLine("Testing HpkeOpenBase...");
965+
byte[] decrypted = wolfcrypt.HpkeOpenBase(hpke, receiverKey,
966+
encCiphertext, info, aad, plaintext.Length);
967+
if (decrypted == null)
968+
{
969+
throw new Exception("HpkeOpenBase failed");
970+
}
971+
Console.WriteLine("HpkeOpenBase passed.");
972+
973+
/* Compare plaintext and decrypted */
974+
if (!wolfcrypt.ByteArrayVerify(plaintext, decrypted))
975+
{
976+
throw new Exception("Decrypted text does not match original plaintext");
977+
}
978+
Console.WriteLine("HPKE Base mode test PASSED.");
979+
}
980+
finally
981+
{
982+
/* Cleanup */
983+
if (ephemeralKey != IntPtr.Zero)
984+
wolfcrypt.HpkeFreeKey(hpke, ephemeralKey, kem);
985+
if (deserializedKey != IntPtr.Zero)
986+
wolfcrypt.HpkeFreeKey(hpke, deserializedKey, kem);
987+
if (receiverKey != IntPtr.Zero)
988+
wolfcrypt.HpkeFreeKey(hpke, receiverKey, kem);
989+
if (hpke != IntPtr.Zero)
990+
wolfcrypt.HpkeFree(hpke);
991+
}
992+
} /* END hpke_test */
993+
883994
public static void standard_log(int lvl, StringBuilder msg)
884995
{
885996
Console.WriteLine(msg);
@@ -941,6 +1052,10 @@ public static void Main(string[] args)
9411052
hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA512); /* SHA-512 HASH test */
9421053
hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA3_256); /* SHA3_256 HASH test */
9431054

1055+
Console.WriteLine("\nStarting HPKE tests");
1056+
1057+
hpke_test(); /* HPKE Base mode test */
1058+
9441059
wolfcrypt.Cleanup();
9451060

9461061
Console.WriteLine("\nAll tests completed successfully");

0 commit comments

Comments
 (0)