/* wolfCrypt-Test.cs * * Copyright (C) 2006-2026 wolfSSL Inc. * * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ /* Tests for the wolfCrypt C# wrapper */ using System; using System.Linq; using System.Text; using System.Security.Cryptography; using wolfSSL.CSharp; using System.Runtime.InteropServices; using static wolfSSL.CSharp.wolfcrypt; public class wolfCrypt_Test_CSharp { private static void random_test() { int ret, i, zeroCount = 0; Byte[] data = new Byte[128]; Console.WriteLine("Starting RNG test"); /* Random Test */ ret = wolfcrypt.Random(data, data.Length); if (ret == 0) { /* Check for 0's */ for (i = 0; i < (int)data.Length; i++) { if (data[i] == 0) { zeroCount++; } } if (zeroCount == data.Length) { Console.WriteLine("RNG zero check error"); } else { Console.WriteLine("RNG Test Passed"); } } else { Console.WriteLine("RNG Error" + wolfcrypt.GetError(ret)); } } /* END random_test */ private static void ecc_test(string hashAlgorithm, int keySize) { int ret; IntPtr rng = IntPtr.Zero; IntPtr PrivKey = IntPtr.Zero; IntPtr PubKey = IntPtr.Zero; IntPtr key = IntPtr.Zero; Console.WriteLine("\nStarting ECC" + (keySize*8) + " test for " + hashAlgorithm + "..."); /* Create a new RNG context */ rng = wolfcrypt.RandomNew(); if (rng == IntPtr.Zero) { throw new Exception("RNG initialization failed."); } /* Generate ECC Key Pair */ Console.WriteLine("Testing ECC Key Generation..."); key = wolfcrypt.EccMakeKey(keySize, rng); if (key == IntPtr.Zero) { throw new Exception("EccMakeKey failed"); } Console.WriteLine("ECC Key Generation test passed."); /* Export and Import Key */ Console.WriteLine("Testing ECC Key Export and Import..."); byte[] privateKeyDer; ret = wolfcrypt.EccExportPrivateKeyToDer(key, out privateKeyDer); if (ret < 0) { throw new Exception("ExportPrivateKeyToDer failed"); } byte[] publicKeyDer; ret = wolfcrypt.EccExportPublicKeyToDer(key, out publicKeyDer, true); if (ret < 0) { throw new Exception("ExportPublicKeyToDer failed"); } PrivKey = wolfcrypt.EccImportKey(privateKeyDer); if (PrivKey == IntPtr.Zero) { throw new Exception("EccImportKey Private failed"); } PubKey = wolfcrypt.EccImportPublicKeyFromDer(publicKeyDer); if (PubKey == IntPtr.Zero) { throw new Exception("ImportPublicKeyFromDer Public failed"); } Console.WriteLine("ECC Key Export and Import test passed."); /* Generate hash based on selected algorithm */ byte[] dataToHash = System.Text.Encoding.UTF8.GetBytes("This is some data to hash"); byte[] hash; switch (hashAlgorithm.ToUpper()) { case "SHA256": using (SHA256 sha256 = SHA256.Create()) { hash = sha256.ComputeHash(dataToHash); } break; case "SHA384": using (SHA384 sha384 = SHA384.Create()) { hash = sha384.ComputeHash(dataToHash); } break; case "SHA512": using (SHA512 sha512 = SHA512.Create()) { hash = sha512.ComputeHash(dataToHash); } break; default: throw new Exception("Unsupported hash algorithm"); } Console.WriteLine($"{hashAlgorithm} hash generated."); /* Sign Data */ Console.WriteLine("Testing ECC Signature Creation..."); byte[] signature = new byte[wolfcrypt.ECC_MAX_SIG_SIZE]; int signLength = wolfcrypt.EccSign(PrivKey, hash, signature); if (signLength <= 0) { throw new Exception("EccSign failed"); } byte[] actualSignature = new byte[signLength]; Array.Copy(signature, 0, actualSignature, 0, signLength); Console.WriteLine($"ECC Signature Creation test passed. Signature Length: {signLength}"); /* Verify Signature */ Console.WriteLine("Testing ECC Signature Verification..."); int verifyResult = wolfcrypt.EccVerify(PubKey, actualSignature, hash); if (verifyResult != 0) { throw new Exception("EccVerify failed"); } Console.WriteLine("ECC Signature Verification test passed."); /* Cleanup */ if (key != IntPtr.Zero) wolfcrypt.EccFreeKey(key); if (PubKey != IntPtr.Zero) wolfcrypt.EccFreeKey(PubKey); if (PrivKey != IntPtr.Zero) wolfcrypt.EccFreeKey(PrivKey); if (rng != IntPtr.Zero) wolfcrypt.RandomFree(rng); } /* END ecc_test */ private static void ecies_test(int keySize) { /* maximum encrypted message: * msgSz (14) + pad (2) + pubKeySz(1+66*2) + ivSz(16) + digestSz(32) = 197 */ int bufferSize = wolfcrypt.MAX_ECIES_TEST_SZ; const string message = "Hello wolfSSL!"; byte[] salt = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; IntPtr a = IntPtr.Zero; IntPtr b = IntPtr.Zero; IntPtr aCtx = IntPtr.Zero; IntPtr bCtx = IntPtr.Zero; IntPtr rng = IntPtr.Zero; IntPtr heap = IntPtr.Zero; byte[] plaintext = new byte[bufferSize]; byte[] encrypted = new byte[bufferSize]; byte[] decrypted = new byte[bufferSize]; try { Console.WriteLine($"\nStarting ECIES test for {keySize} byte key size..."); /* Create a new RNG context */ rng = wolfcrypt.RandomNew(); if (rng == IntPtr.Zero) { throw new Exception("RNG initialization failed."); } /* Initialize keys */ a = wolfcrypt.EccMakeKey(keySize, rng); b = wolfcrypt.EccMakeKey(keySize, rng); if (a == IntPtr.Zero || b == IntPtr.Zero) { throw new Exception("Key generation failed."); } Console.WriteLine("ECC key generation passed."); /* Create ECIES contexts for encryption and decryption */ aCtx = wolfcrypt.EciesNewCtx((int)wolfcrypt.ecFlags.REQ_RESP_CLIENT, rng, heap); bCtx = wolfcrypt.EciesNewCtx((int)wolfcrypt.ecFlags.REQ_RESP_SERVER, rng, heap); if (aCtx == IntPtr.Zero || bCtx == IntPtr.Zero) { throw new Exception("Context creation failed."); } Console.WriteLine("ECC context creation passed."); /* Set KDF salt */ if (wolfcrypt.EciesSetKdfSalt(aCtx, salt) != 0 || wolfcrypt.EciesSetKdfSalt(bCtx, salt) != 0) { throw new Exception("Failed to set KDF salt."); } Console.WriteLine("KDF salt setup passed."); /* Prepare plaintext */ Array.Clear(plaintext, 0, plaintext.Length); Array.Copy(Encoding.ASCII.GetBytes(message), plaintext, message.Length); /* Pad to block size */ int plaintextLen = ((message.Length + (wolfcrypt.AES_BLOCK_SIZE - 1)) / wolfcrypt.AES_BLOCK_SIZE) * wolfcrypt.AES_BLOCK_SIZE; /* Encrypt message */ int ret = wolfcrypt.EciesEncrypt(a, b, plaintext, (uint)plaintextLen, encrypted, aCtx); if (ret < 0) { throw new Exception("Encryption failed."); } int encryptedLen = ret; Console.WriteLine("ECC encryption passed."); /* Decrypt message */ ret = wolfcrypt.EciesDecrypt(b, a, encrypted, (uint)encryptedLen, decrypted, bCtx); if (ret < 0) { throw new Exception("Decryption failed."); } int decryptedLen = ret; Console.WriteLine("ECC decryption passed."); /* Compare decrypted text to original plaintext */ if (decryptedLen != plaintextLen || !wolfcrypt.ByteArrayVerify(plaintext, decrypted)) { throw new Exception("Decrypted text does not match original plaintext."); } Console.WriteLine("Decrypted text matches original plaintext."); } finally { /* Cleanup key and context */ if (a != IntPtr.Zero) wolfcrypt.EccFreeKey(a); if (b != IntPtr.Zero) wolfcrypt.EccFreeKey(b); if (aCtx != IntPtr.Zero) wolfcrypt.EciesFreeCtx(aCtx); if (bCtx != IntPtr.Zero) wolfcrypt.EciesFreeCtx(bCtx); if (rng != IntPtr.Zero) wolfcrypt.RandomFree(rng); } } /* END ecies_test */ private static void ecdhe_test(int keySize) { int ret; IntPtr rng = IntPtr.Zero; IntPtr keyA = IntPtr.Zero; IntPtr keyB = IntPtr.Zero; IntPtr publicKeyA = IntPtr.Zero; IntPtr publicKeyB = IntPtr.Zero; byte[] derKey; Console.WriteLine("\nStarting ECDHE shared secret test for " + keySize + " key size..."); /* Create RNG */ Console.WriteLine("Generating RNG..."); rng = RandomNew(); if (rng == IntPtr.Zero) { throw new Exception("Failed to generate RNG."); } Console.WriteLine("RNG generation test passed."); /* Generate Key Pair A */ Console.WriteLine("Generating Key Pair A..."); keyA = wolfcrypt.EccMakeKey(keySize, rng); if (keyA == IntPtr.Zero) { throw new Exception("Failed to generate key pair A."); } /* Generate Key Pair B */ Console.WriteLine("Generating Key Pair B..."); keyB = wolfcrypt.EccMakeKey(keySize, rng); if (keyB == IntPtr.Zero) { throw new Exception("Failed to generate key pair B."); } Console.WriteLine("ECC Key generation test passed."); /* Export Public Key B to DER format */ Console.WriteLine("Exporting Public Key B to DER format..."); ret = wolfcrypt.EccExportPublicKeyToDer(keyB, out derKey, true); if (ret < 0 || derKey == null) { throw new Exception("EccExportPublicKeyToDer failed"); } /* Decode Public Key B from DER format */ Console.WriteLine("Decoding Public Key B from DER format..."); publicKeyB = wolfcrypt.EccImportPublicKeyFromDer(derKey); if (publicKeyB == IntPtr.Zero) { throw new Exception("Failed to decode public key B from DER format."); } Console.WriteLine("ECC Export and Import test passed."); /* Compute Shared Secret using Private Key A and Public Key B */ Console.WriteLine("Computing Shared Secret using Private Key A and Public Key B..."); byte[] sharedSecretA = new byte[keySize]; int retA = wolfcrypt.EcdheSharedSecret(keyA, publicKeyB, sharedSecretA, rng); if (retA != 0) { throw new Exception("Failed to compute shared secret A. Error code: " + retA); } Console.WriteLine("ECC shared secret created using private Key A."); /* Export Public Key A to DER format */ Console.WriteLine("Exporting Public Key A to DER format..."); ret = wolfcrypt.EccExportPublicKeyToDer(keyA, out derKey, true); if (ret < 0 || derKey == null) { throw new Exception("EccExportPublicKeyToDer failed"); } /* Decode Public Key A from DER format */ Console.WriteLine("Decoding Public Key A from DER format..."); publicKeyA = wolfcrypt.EccImportPublicKeyFromDer(derKey); if (publicKeyA == IntPtr.Zero) { throw new Exception("Failed to decode public key A from DER format."); } /* Compute Shared Secret using Private Key B and Public Key A */ Console.WriteLine("Computing Shared Secret using Private Key B and Public Key A..."); byte[] sharedSecretB = new byte[keySize]; int retB = wolfcrypt.EcdheSharedSecret(keyB, publicKeyA, sharedSecretB, rng); if (retB != 0) { throw new Exception("Failed to compute shared secret B. Error code: " + retB); } Console.WriteLine("ECC shared secret created using private Key B."); /* Compare Shared Secrets */ Console.WriteLine("Comparing Shared Secrets..."); if (!wolfcrypt.ByteArrayVerify(sharedSecretA, sharedSecretB)) { throw new Exception("Shared secrets do not match."); } else { Console.WriteLine("ECC shared secret match."); } /* Cleanup */ if (keyA != IntPtr.Zero) wolfcrypt.EccFreeKey(keyA); if (keyB != IntPtr.Zero) wolfcrypt.EccFreeKey(keyB); if (publicKeyA != IntPtr.Zero) wolfcrypt.EccFreeKey(publicKeyA); if (publicKeyB != IntPtr.Zero) wolfcrypt.EccFreeKey(publicKeyB); if (rng != IntPtr.Zero) wolfcrypt.RandomFree(rng); } /* END ecdhe_test */ private static void rsa_test(string hashAlgorithm, int keySize) { IntPtr key = IntPtr.Zero; IntPtr heap = IntPtr.Zero; int devId = wolfcrypt.INVALID_DEVID; Console.WriteLine("\nStarting RSA" + keySize + " test for " + hashAlgorithm + "..."); /* Generate RSA Key Pair */ Console.WriteLine("Testing RSA Key Generation..."); key = wolfcrypt.RsaMakeKey(heap, devId, keySize); if (key == IntPtr.Zero) { throw new Exception("RsaMakeKey failed"); } Console.WriteLine("RSA Key Generation test passed."); /* Generate hash based on selected algorithm */ byte[] dataToHash = System.Text.Encoding.UTF8.GetBytes("This is some data to hash"); byte[] hash; switch (hashAlgorithm.ToUpper()) { case "SHA256": using (SHA256 sha256 = SHA256.Create()) { hash = sha256.ComputeHash(dataToHash); } break; case "SHA384": using (SHA384 sha384 = SHA384.Create()) { hash = sha384.ComputeHash(dataToHash); } break; case "SHA512": using (SHA512 sha512 = SHA512.Create()) { hash = sha512.ComputeHash(dataToHash); } break; default: throw new Exception("Unsupported hash algorithm"); } Console.WriteLine($"{hashAlgorithm} hash generated."); /* Sign Data */ Console.WriteLine("Testing RSA Signature Creation..."); byte[] signature = new byte[keySize / 8]; int signLength = wolfcrypt.RsaSignSSL(key, hash, signature); if (signLength <= 0) { throw new Exception("RsaSignSSL failed"); } byte[] actualSignature = new byte[signLength]; Array.Copy(signature, 0, actualSignature, 0, signLength); Console.WriteLine($"RSA Signature Creation test passed. Signature Length: {signLength}"); /* Verify Signature */ Console.WriteLine("Testing RSA Signature Verification..."); int verifyResult = wolfcrypt.RsaVerifySSL(key, actualSignature, hash); if (verifyResult != 0) { throw new Exception("RsaVerifySSL failed"); } Console.WriteLine("RSA Signature Verification test passed."); /* Cleanup */ if (key != IntPtr.Zero) wolfcrypt.RsaFreeKey(key); } /* END rsa_test */ private static void ed25519_test() { int ret; IntPtr key = IntPtr.Zero; byte[] privKey; byte[] pubKey; uint pubKeySz; Console.WriteLine("\nStarting ED25519 tests..."); IntPtr heap = IntPtr.Zero; int devId = wolfcrypt.INVALID_DEVID; /* Generate ED25519 Key Pair */ Console.WriteLine("Testing ED25519 Key Generation..."); key = wolfcrypt.Ed25519MakeKey(heap, devId); if (key == IntPtr.Zero) { throw new Exception("Ed25519MakeKey failed"); } Console.WriteLine("ED25519 Key Generation test passed."); /* Export and Import Key */ Console.WriteLine("Testing ED25519 Key Export and Import..."); /* Export Private */ ret = wolfcrypt.Ed25519ExportKeyToDer(key, out privKey); if (ret < 0 || privKey == null) { throw new Exception("Ed25519ExportKeyToDer failed"); } /* Export Public */ ret = wolfcrypt.Ed25519ExportPublicKeyToDer(key, out pubKey, true); if (ret < 0 || pubKey == null) { throw new Exception("Ed25519ExportKeyToDer failed"); } /* Import Private */ IntPtr importedPrivKey = wolfcrypt.Ed25519PrivateKeyDecode(privKey); if (importedPrivKey == IntPtr.Zero) { throw new Exception("Ed25519PrivateKeyDecode failed"); } /* Import Public */ IntPtr importedPubKey = wolfcrypt.Ed25519PublicKeyDecode(pubKey); if (importedPubKey == IntPtr.Zero) { throw new Exception("Ed25519PublicKeyDecode failed"); } Console.WriteLine("ED25519 Key Export and Import test passed."); /* Generate a hash */ byte[] dataToHash = System.Text.Encoding.UTF8.GetBytes("This is some data to hash"); /* Sign Data */ Console.WriteLine("Testing ED25519 Signature Creation..."); byte[] signature; ret = wolfcrypt.Ed25519SignMsg(dataToHash, out signature, key); if (ret != 0) { throw new Exception("Ed25519SignMsg failed"); } Console.WriteLine($"ED25519 Signature Creation test passed. Signature Length: {signature.Length}"); /* Verify Signature */ Console.WriteLine("Testing ED25519 Signature Verification..."); ret = wolfcrypt.Ed25519VerifyMsg(signature, dataToHash, key); if (ret != 0) { throw new Exception("Ed25519VerifyMsg failed"); } Console.WriteLine("ED25519 Signature Verification test passed."); /* test importing a raw public key */ ret = wolfcrypt.Ed25519ExportPublic(key, pubKey, out pubKeySz); if (ret < 0 || pubKey == null) { throw new Exception("Ed25519ExportPublic failed"); } Console.WriteLine("ED25519 Export Raw Public test passed."); if (importedPubKey != IntPtr.Zero) { wolfcrypt.Ed25519FreeKey(importedPubKey); } ret = wolfcrypt.Ed25519ImportPublic(pubKey, pubKeySz, out importedPubKey); if (importedPubKey == IntPtr.Zero) { throw new Exception("Ed25519ImportPublic failed"); } Console.WriteLine("ED25519 Import Raw Public test passed."); /* Cleanup */ if (key != IntPtr.Zero) { wolfcrypt.Ed25519FreeKey(key); } if (importedPubKey != IntPtr.Zero) { wolfcrypt.Ed25519FreeKey(importedPubKey); } if (importedPrivKey != IntPtr.Zero) { wolfcrypt.Ed25519FreeKey(importedPrivKey); } } /* END ed25519_test */ private static void curve25519_test() { int ret; IntPtr keyA = IntPtr.Zero; IntPtr keyB = IntPtr.Zero; IntPtr publicKeyA = IntPtr.Zero; IntPtr publicKeyB = IntPtr.Zero; byte[] rawPub, rawPrivate, derKey; Console.WriteLine("\nStarting Curve25519 shared secret test..."); /* Generate Key Pair A */ Console.WriteLine("Generating Key Pair A..."); keyA = wolfcrypt.Curve25519MakeKey(IntPtr.Zero, 0); if (keyA == IntPtr.Zero) { throw new Exception("Failed to generate key pair A."); } /* Generate Key Pair B */ Console.WriteLine("Generating Key Pair B..."); keyB = wolfcrypt.Curve25519MakeKey(IntPtr.Zero, 0); if (keyB == IntPtr.Zero) { throw new Exception("Failed to generate key pair B."); } Console.WriteLine("Curve25519 Key generation test passed."); /* Export Public Key A private and public to raw format */ wolfcrypt.Curve25519ExportKeyRaw(keyA, out rawPrivate, out rawPub); /* Export Public Key B public to raw format */ rawPub = wolfcrypt.Curve25519ExportPublicKey(keyB); /* rawPub / rawPrivate - not used */ /* Export Public Key B to DER format */ Console.WriteLine("Exporting Public Key B to DER format..."); ret = wolfcrypt.Curve25519ExportPublicKeyToDer(keyB, out derKey, true); if (ret < 0 || derKey == null) { throw new Exception("Curve25519ExportPublicKeyToDer failed"); } /* Decode Public Key B from DER format */ Console.WriteLine("Decoding Public Key B from DER format..."); publicKeyB = wolfcrypt.Curve25519PublicKeyDecode(derKey); if (publicKeyB == IntPtr.Zero) { throw new Exception("Failed to decode public key B from DER format."); } Console.WriteLine("Curve25519 Export and Import test passed."); /* Compute Shared Secret using Private Key A and Public Key B */ Console.WriteLine("Computing Shared Secret using Private Key A and Public Key B..."); byte[] sharedSecretA = new byte[wolfcrypt.ED25519_KEY_SIZE]; int retA = wolfcrypt.Curve25519SharedSecret(keyA, publicKeyB, sharedSecretA); if (retA != 0) { throw new Exception("Failed to compute shared secret A. Error code: " + retA); } Console.WriteLine("Curve25519 shared secret created using private Key A."); /* Export Public Key A to DER format */ Console.WriteLine("Exporting Public Key A to DER format..."); ret = wolfcrypt.Curve25519ExportPublicKeyToDer(keyA, out derKey, true); if (ret < 0 || derKey == null) { throw new Exception("Curve25519ExportPublicKeyToDer failed"); } /* Decode Public Key A from DER format */ Console.WriteLine("Decoding Public Key A from DER format..."); publicKeyA = wolfcrypt.Curve25519PublicKeyDecode(derKey); if (publicKeyA == IntPtr.Zero) { throw new Exception("Failed to decode public key A from DER format."); } /* Compute Shared Secret using Private Key B and Public Key A */ Console.WriteLine("Computing Shared Secret using Private Key B and Public Key A..."); byte[] sharedSecretB = new byte[wolfcrypt.ED25519_KEY_SIZE]; int retB = wolfcrypt.Curve25519SharedSecret(keyB, publicKeyA, sharedSecretB); if (retB != 0) { throw new Exception("Failed to compute shared secret B. Error code: " + retB); } Console.WriteLine("Curve25519 shared secret created using private Key B."); /* Compare Shared Secrets */ Console.WriteLine("Comparing Shared Secrets..."); if (!wolfcrypt.ByteArrayVerify(sharedSecretA, sharedSecretB)) { throw new Exception("Shared secrets do not match."); } else { Console.WriteLine("Curve25519 shared secret match."); } /* Cleanup */ if (keyA != IntPtr.Zero) wolfcrypt.Curve25519FreeKey(keyA); if (keyB != IntPtr.Zero) wolfcrypt.Curve25519FreeKey(keyB); if (publicKeyA != IntPtr.Zero) wolfcrypt.Curve25519FreeKey(publicKeyA); if (publicKeyB != IntPtr.Zero) wolfcrypt.Curve25519FreeKey(publicKeyB); } /* END curve25519_test */ private static void mlkem_test(wolfcrypt.MlKemTypes type) { int ret = 0; IntPtr keyA = IntPtr.Zero; IntPtr keyB = IntPtr.Zero; IntPtr heap = IntPtr.Zero; int devId = wolfcrypt.INVALID_DEVID; byte[] pubA = null; byte[] privA = null; byte[] cipherText = null; byte[] sharedSecretA = null; byte[] sharedSecretB = null; try { Console.WriteLine("\nStarting " + type + " shared secret test ..."); /* Generate Key Pair */ Console.WriteLine("Testing ML-KEM Key Generation..."); Console.WriteLine("Generate Key Pair A..."); keyA = wolfcrypt.MlKemMakeKey(type, heap, devId); if (keyA == IntPtr.Zero) { ret = -1; Console.Error.WriteLine("Failed to generate key pair A."); } if (ret == 0) { Console.WriteLine("Initialize Key B for decode..."); keyB = wolfcrypt.MlKemNew(type, heap, devId); if (keyB == IntPtr.Zero) { ret = -1; Console.Error.WriteLine("Failed to initialize key B for decode."); } } if (ret == 0) { Console.WriteLine("ML-KEM Key Generation test passed."); } /* Encode */ if (ret == 0) { Console.WriteLine("Testing ML-KEM Key Encode..."); ret = wolfcrypt.MlKemEncodePublicKey(keyA, out pubA); if (ret != 0) { Console.Error.WriteLine($"Failed to encode public key of A. Error code: {ret}"); } } if (ret == 0) { ret = wolfcrypt.MlKemEncodePrivateKey(keyA, out privA); if (ret != 0) { Console.Error.WriteLine($"Failed to encode private key of A. Error code: {ret}"); } } if (ret == 0) { Console.WriteLine("ML-KEM Key Encode test passed."); } /* Encapsulate */ if (ret == 0) { Console.WriteLine("Testing ML-KEM Encapsulation..."); ret = wolfcrypt.MlKemEncapsulate(keyA, out cipherText, out sharedSecretA); if (ret != 0) { Console.Error.WriteLine($"Failed to encapsulate. Error code: {ret}"); } } if (ret == 0) { Console.WriteLine("ML-KEM Encapsulation test passed."); } /* Decode */ if (ret == 0) { Console.WriteLine("Testing ML-KEM Decode..."); ret = wolfcrypt.MlKemDecodePrivateKey(keyB, privA); if (ret != 0) { Console.Error.WriteLine($"Failed to decode private key of A. Error code: {ret}"); } } if (ret == 0) { ret = wolfcrypt.MlKemDecodePublicKey(keyB, pubA); if (ret != 0) { Console.Error.WriteLine($"Failed to decode public key of A. Error code: {ret}"); } } if (ret == 0) { Console.WriteLine("ML-KEM Decode test passed."); } /* Decapsulate */ if (ret == 0) { Console.WriteLine("Testing ML-KEM Decapsulation..."); ret = wolfcrypt.MlKemDecapsulate(keyB, cipherText, out sharedSecretB); if (ret != 0) { Console.Error.WriteLine($"Failed to decapsulate. Error code: {ret}"); } } if (ret == 0) { Console.WriteLine("ML-KEM Decapsulation test passed."); } /* Check */ if (ret == 0) { Console.WriteLine("Comparing Shared Secrets..."); if (!wolfcrypt.ByteArrayVerify(sharedSecretA, sharedSecretB)) { ret = -1; Console.Error.WriteLine($"Shared secrets do not match. Error code: {ret}"); } } if (ret == 0) { Console.WriteLine("ML-KEM shared secret match."); } if (ret != 0) { throw new Exception("ML-KEM test failed."); } } catch (Exception ex) { Console.WriteLine($"ML-KEM test failed: {ex.Message}"); throw; } finally { /* Cleanup */ if (keyA != IntPtr.Zero) { ret = wolfcrypt.MlKemFreeKey(ref keyA); if (ret != 0) { Console.Error.WriteLine($"Failed to free MlKem key A. Error code: {ret}"); } } if (keyB != IntPtr.Zero) { ret = wolfcrypt.MlKemFreeKey(ref keyB); if (ret != 0) { Console.Error.WriteLine($"Failed to free MlKem key B. Error code: {ret}"); } } } } /* END mlkem_test */ private static void mldsa_test(wolfcrypt.MlDsaLevels level) { int ret = 0; IntPtr key = IntPtr.Zero; IntPtr importKey = IntPtr.Zero; IntPtr heap = IntPtr.Zero; int devId = wolfcrypt.INVALID_DEVID; byte[] privateKey = null; byte[] publicKey = null; byte[] message = Encoding.UTF8.GetBytes("This is some data to sign with ML-DSA"); byte[] signature = null; try { Console.WriteLine("\nStarting " + level + " key generation and signature test ..."); /* Generate Key */ Console.WriteLine("Testing ML-DSA Key Generation..."); key = wolfcrypt.MlDsaMakeKey(heap, devId, level); if (key == IntPtr.Zero) { ret = -1; Console.Error.WriteLine("Failed to generate keypair."); } if (ret == 0) { Console.WriteLine("ML-DSA Key Generation test passed."); } /* Export */ if (ret == 0) { Console.WriteLine("Testing ML-DSA Key Export..."); ret = wolfcrypt.MlDsaExportPrivateKey(key, out privateKey); if (ret != 0) { Console.Error.WriteLine($"Failed to export private key. Error code: {ret}"); } } if (ret == 0) { ret = wolfcrypt.MlDsaExportPublicKey(key, out publicKey); if (ret != 0) { Console.Error.WriteLine($"Failed to export public key. Error code: {ret}"); } } if (ret == 0) { Console.WriteLine("ML-DSA Key Export test passed."); } /* Import into a fresh key to test the full import workflow */ if (ret == 0) { Console.WriteLine("Testing ML-DSA Key Import..."); /* Free the keygen key and create a fresh one for import */ wolfcrypt.MlDsaFreeKey(ref key); importKey = wolfcrypt.MlDsaNew(heap, devId, level); if (importKey == IntPtr.Zero) { ret = -1; Console.Error.WriteLine("Failed to allocate key for import."); } } if (ret == 0) { ret = wolfcrypt.MlDsaImportPrivateKey(privateKey, importKey); if (ret != 0) { Console.Error.WriteLine($"Failed to import private key. Error code: {ret}"); } } if (ret == 0) { ret = wolfcrypt.MlDsaImportPublicKey(publicKey, importKey); if (ret != 0) { Console.Error.WriteLine($"Failed to import public key. Error code: {ret}"); } } if (ret == 0) { Console.WriteLine("ML-DSA Key Import test passed."); } /* Sign with imported key */ if (ret == 0) { Console.WriteLine("Testing ML-DSA Signature Creation..."); ret = wolfcrypt.MlDsaSignMsg(importKey, message, out signature); if (ret != 0) { Console.Error.WriteLine($"Failed to sign. Error code: {ret}"); } } if (ret == 0) { Console.WriteLine($"ML-DSA Signature Creation test passed. Signature Length: {signature.Length}"); } /* Verify with imported key */ if (ret == 0) { Console.WriteLine("Testing ML-DSA Signature Verification..."); ret = wolfcrypt.MlDsaVerifyMsg(importKey, message, signature); if (ret != 0) { Console.Error.WriteLine($"Failed to verify message. Error code: {ret}"); } } if (ret == 0) { Console.WriteLine("ML-DSA Signature Verification test passed."); } if (ret != 0) { throw new Exception("ML-DSA test failed."); } } catch (Exception ex) { Console.WriteLine($"ML-DSA test failed: {ex.Message}"); throw; } finally { if (key != IntPtr.Zero) { wolfcrypt.MlDsaFreeKey(ref key); } if (importKey != IntPtr.Zero) { wolfcrypt.MlDsaFreeKey(ref importKey); } } } /* END mldsa_test */ private static void aes_gcm_test() { IntPtr aes = IntPtr.Zero; byte[] key; byte[] iv; byte[] plaintext; byte[] ciphertext; byte[] addAuth; byte[] authTag; byte[] decrypted; int ret; try { Console.WriteLine("\nStarting AES-GCM tests..."); IntPtr heap = IntPtr.Zero; int devId = wolfcrypt.INVALID_DEVID; /* Initialize AES-GCM Context */ Console.WriteLine("Testing AES-GCM Initialization..."); /* * This is from the Test Case 16 from the document Galois/ * Counter Mode of Operation (GCM) by McGrew and * Viega. */ key = new byte[32] { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }; iv = new byte[12] { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }; plaintext = new byte[] { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39 }; ciphertext = new byte[] { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62 }; addAuth = new byte[] { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 }; authTag = new byte[16]; aes = wolfcrypt.AesNew(heap, devId); if (aes == IntPtr.Zero) { throw new Exception($"AesNew failed with error code {aes}"); } Console.WriteLine("AesNew test passed."); /* Set AES-GCM Key */ Console.WriteLine("Testing AES-GCM Key Setting..."); uint len = (uint)key.Length; ret = wolfcrypt.AesGcmSetKey(aes, key); if (ret != 0) { throw new Exception($"AesGcmSetKey failed with error code {ret}"); } Console.WriteLine("AES-GCM Key Setting test passed."); /* Encryption */ Console.WriteLine("Testing AES-GCM Encryption..."); ret = wolfcrypt.AesGcmEncrypt(aes, iv, plaintext, ciphertext, authTag, addAuth); if (ret != 0) { throw new Exception($"AesGcmEncrypt failed with error code {ret}"); } Console.WriteLine($"AES-GCM Encryption test passed. Ciphertext Length: {ciphertext.Length}"); /* Decryption */ Console.WriteLine("Testing AES-GCM Decryption..."); decrypted = new byte[plaintext.Length]; ret = wolfcrypt.AesGcmDecrypt(aes, iv, ciphertext, decrypted, authTag, addAuth); if (ret != 0) { throw new Exception($"AesGcmDecrypt failed with error code {ret}"); } /* Verify Decryption */ if (!plaintext.SequenceEqual(decrypted)) { throw new Exception("Decryption failed: decrypted data does not match original plaintext."); } Console.WriteLine("AES-GCM Decryption test passed."); } catch (Exception ex) { Console.WriteLine($"AES-GCM test failed: {ex.Message}"); } finally { /* Cleanup */ if (aes != IntPtr.Zero) { wolfcrypt.AesGcmFree(aes); } } } /* END aes_gcm_test */ private static void hash_test(uint hashType) { IntPtr hash = IntPtr.Zero; IntPtr heap = IntPtr.Zero; int devId = wolfcrypt.INVALID_DEVID; /* Get the enum name */ string hashTypeName = Enum.GetName(typeof(wolfcrypt.hashType), hashType); Console.WriteLine($"\nStarting hash test for {hashTypeName}..."); /* Allocate new hash context */ Console.WriteLine("Testing hash context allocation..."); hash = wolfcrypt.HashNew(hashType, heap, devId); if (hash == IntPtr.Zero) { Console.WriteLine($"HashNew failed for {hashTypeName}"); return; } Console.WriteLine("Hash context allocation test passed."); /* Initialize the hash context with the specified hash type */ Console.WriteLine("Testing hash initialization..."); int initResult = wolfcrypt.InitHash(hash, hashType); if (initResult != 0) { Console.WriteLine($"InitHash failed for {hashTypeName}"); wolfcrypt.HashFree(hash, hashType); return; } Console.WriteLine("Hash initialization test passed."); /* Update the hash with data */ byte[] dataToHash = Encoding.UTF8.GetBytes("This is some data to hash"); Console.WriteLine("Testing hash update..."); int updateResult = wolfcrypt.HashUpdate(hash, hashType, dataToHash); if (updateResult != 0) { Console.WriteLine($"HashUpdate failed for {hashTypeName}"); wolfcrypt.HashFree(hash, hashType); return; } Console.WriteLine("Hash update test passed."); /* Finalize the hash and get the result */ Console.WriteLine("Testing hash finalization..."); byte[] hashOutput; int finalResult = wolfcrypt.HashFinal(hash, hashType, out hashOutput); if (finalResult != 0) { Console.WriteLine($"HashFinal failed for {hashType}"); wolfcrypt.HashFree(hash, hashType); return; } Console.WriteLine($"Hash finalization test passed for {hashTypeName}. Hash Length: {hashOutput.Length}"); /* Output the hash result */ Console.WriteLine($"Hash Output ({hashTypeName}): {BitConverter.ToString(hashOutput).Replace("-", "")}"); /* Cleanup */ Console.WriteLine("Testing hash cleanup..."); int freeResult = wolfcrypt.HashFree(hash, hashType); if (freeResult != 0) { Console.WriteLine($"HashFree failed for {hashTypeName}"); } else { Console.WriteLine("Hash cleanup test passed."); } } /* END hash_test */ private static void hpke_test(wolfcrypt.HpkeKem kem, wolfcrypt.HpkeKdf kdf, wolfcrypt.HpkeAead aead) { IntPtr hpke = IntPtr.Zero; IntPtr receiverKey = IntPtr.Zero; IntPtr deserializedKey = IntPtr.Zero; IntPtr ephemeralKey = IntPtr.Zero; try { Console.WriteLine("\nStarting HPKE Base mode test..."); /* Initialize HPKE context */ Console.WriteLine("Initializing HPKE context..."); hpke = wolfcrypt.HpkeInit(kem, kdf, aead); if (hpke == IntPtr.Zero) { throw new Exception("HpkeInit failed"); } Console.WriteLine("HPKE context initialization passed."); /* Generate receiver keypair */ Console.WriteLine("Generating receiver keypair..."); receiverKey = wolfcrypt.HpkeGenerateKeyPair(hpke); if (receiverKey == IntPtr.Zero) { throw new Exception("HpkeGenerateKeyPair (receiver) failed"); } Console.WriteLine("Receiver keypair generation passed."); /* Serialize and deserialize public key (round-trip) */ Console.WriteLine("Testing public key serialize/deserialize round-trip..."); byte[] pubKeyBytes = wolfcrypt.HpkeSerializePublicKey(hpke, receiverKey); if (pubKeyBytes == null) { throw new Exception("HpkeSerializePublicKey failed"); } Console.WriteLine($"Serialized public key length: {pubKeyBytes.Length}"); deserializedKey = wolfcrypt.HpkeDeserializePublicKey(hpke, pubKeyBytes); if (deserializedKey == IntPtr.Zero) { throw new Exception("HpkeDeserializePublicKey failed"); } /* Verify round-trip by re-serializing */ byte[] pubKeyBytes2 = wolfcrypt.HpkeSerializePublicKey(hpke, deserializedKey); if (pubKeyBytes2 == null || !wolfcrypt.ByteArrayVerify(pubKeyBytes, pubKeyBytes2)) { throw new Exception("Public key round-trip verification failed"); } Console.WriteLine("Public key round-trip test passed."); /* Generate ephemeral keypair for sender */ Console.WriteLine("Generating ephemeral keypair..."); ephemeralKey = wolfcrypt.HpkeGenerateKeyPair(hpke); if (ephemeralKey == IntPtr.Zero) { throw new Exception("HpkeGenerateKeyPair (ephemeral) failed"); } Console.WriteLine("Ephemeral keypair generation passed."); /* Define test data */ byte[] info = Encoding.UTF8.GetBytes("HPKE .NET Test"); byte[] aad = Encoding.UTF8.GetBytes("additional data"); byte[] plaintext = Encoding.UTF8.GetBytes("Hello HPKE from wolfCrypt .NET!"); /* Seal (encrypt) */ Console.WriteLine("Testing HpkeSealBase..."); byte[] encCiphertext = wolfcrypt.HpkeSealBase(hpke, ephemeralKey, receiverKey, info, aad, plaintext); if (encCiphertext == null) { throw new Exception("HpkeSealBase failed"); } Console.WriteLine($"HpkeSealBase passed. Output length: {encCiphertext.Length}"); /* Open (decrypt) */ Console.WriteLine("Testing HpkeOpenBase..."); byte[] decrypted = wolfcrypt.HpkeOpenBase(hpke, receiverKey, encCiphertext, info, aad, plaintext.Length); if (decrypted == null) { throw new Exception("HpkeOpenBase failed"); } Console.WriteLine("HpkeOpenBase passed."); /* Compare plaintext and decrypted */ if (!wolfcrypt.ByteArrayVerify(plaintext, decrypted)) { throw new Exception("Decrypted text does not match original plaintext"); } Console.WriteLine("HPKE Base mode test PASSED."); /* Test convenience overload (no ephemeral key) */ Console.WriteLine("Testing HpkeSealBase convenience overload..."); byte[] encCiphertext2 = wolfcrypt.HpkeSealBase(hpke, receiverKey, info, aad, plaintext, kem); if (encCiphertext2 == null) { throw new Exception("HpkeSealBase (convenience) failed"); } Console.WriteLine($"HpkeSealBase convenience passed. Output length: {encCiphertext2.Length}"); byte[] decrypted2 = wolfcrypt.HpkeOpenBase(hpke, receiverKey, encCiphertext2, info, aad, kem); if (decrypted2 == null) { throw new Exception("HpkeOpenBase (convenience) failed"); } if (!wolfcrypt.ByteArrayVerify(plaintext, decrypted2)) { throw new Exception("Convenience seal/open: decrypted text does not match"); } Console.WriteLine("HPKE convenience overload test PASSED."); /* Empty plaintext round-trip - native API accepts ptSz == 0 */ Console.WriteLine("Testing HpkeSealBase/OpenBase with empty plaintext..."); byte[] emptyPt = new byte[0]; byte[] encEmpty = wolfcrypt.HpkeSealBase(hpke, receiverKey, info, aad, emptyPt, kem); if (encEmpty == null) { throw new Exception("HpkeSealBase with empty plaintext failed"); } byte[] decEmpty = wolfcrypt.HpkeOpenBase(hpke, receiverKey, encEmpty, info, aad, kem); if (decEmpty == null || decEmpty.Length != 0) { throw new Exception("HpkeOpenBase with empty plaintext: round-trip failed"); } Console.WriteLine("Empty plaintext round-trip test PASSED."); /* Negative test: tampered ciphertext should fail */ Console.WriteLine("Testing HpkeOpenBase with tampered ciphertext..."); byte[] tampered = (byte[])encCiphertext.Clone(); tampered[tampered.Length - 1] ^= 0xFF; /* flip last byte (in tag) */ byte[] badResult = wolfcrypt.HpkeOpenBase(hpke, receiverKey, tampered, info, aad, plaintext.Length); if (badResult != null) { throw new Exception("HpkeOpenBase should fail with tampered ciphertext"); } Console.WriteLine("Tampered ciphertext test PASSED (correctly rejected)."); /* Negative test: mismatched AAD should fail */ Console.WriteLine("Testing HpkeOpenBase with mismatched AAD..."); byte[] wrongAad = Encoding.UTF8.GetBytes("wrong aad"); badResult = wolfcrypt.HpkeOpenBase(hpke, receiverKey, encCiphertext, info, wrongAad, plaintext.Length); if (badResult != null) { throw new Exception("HpkeOpenBase should fail with mismatched AAD"); } Console.WriteLine("Mismatched AAD test PASSED (correctly rejected)."); /* Null info/aad round-trip - exercises the null-marshaling path through P/Invoke */ Console.WriteLine("Testing HpkeSealBase/OpenBase with null info and aad..."); byte[] encNull = wolfcrypt.HpkeSealBase(hpke, receiverKey, null, null, plaintext, kem); if (encNull == null) { throw new Exception("HpkeSealBase with null info/aad failed"); } byte[] decNull = wolfcrypt.HpkeOpenBase(hpke, receiverKey, encNull, null, null, kem); if (decNull == null || !wolfcrypt.ByteArrayVerify(plaintext, decNull)) { throw new Exception("HpkeOpenBase with null info/aad: round-trip failed"); } Console.WriteLine("Null info/aad round-trip test PASSED."); /* Negative test: invalid ptLen should fail */ Console.WriteLine("Testing HpkeOpenBase with invalid ptLen..."); badResult = wolfcrypt.HpkeOpenBase(hpke, receiverKey, encCiphertext, info, aad, plaintext.Length + 1); if (badResult != null) { throw new Exception("HpkeOpenBase should fail with incorrect ptLen"); } Console.WriteLine("Invalid ptLen test PASSED (correctly rejected)."); } finally { /* Cleanup */ if (ephemeralKey != IntPtr.Zero) wolfcrypt.HpkeFreeKey(hpke, ephemeralKey, kem); if (deserializedKey != IntPtr.Zero) wolfcrypt.HpkeFreeKey(hpke, deserializedKey, kem); if (receiverKey != IntPtr.Zero) wolfcrypt.HpkeFreeKey(hpke, receiverKey, kem); if (hpke != IntPtr.Zero) wolfcrypt.HpkeFree(hpke); } } /* END hpke_test */ public static void standard_log(int lvl, StringBuilder msg) { Console.WriteLine(msg); } public static void Main(string[] args) { try { Console.WriteLine("Starting Cryptographic Tests...\n"); wolfcrypt.Init(); /* setup logging to stdout */ wolfcrypt.SetLogging(standard_log); random_test(); Console.WriteLine("\nStarting ECC tests"); ecc_test("SHA256", 32); /* Uses SHA-256 (32 byte hash) */ ecc_test("SHA384", 32); /* Uses SHA-384 (32 byte hash) */ ecc_test("SHA512", 32); /* Uses SHA-512 (32 byte hash) */ Console.WriteLine("\nStarting ECIES tests"); ecies_test(32); /* ECIES test (32 byte key size) */ ecies_test(48); /* ECIES test (48 byte key size) */ ecies_test(66); /* ECIES test (66 byte key size) */ Console.WriteLine("\nStarting ECDHE tests"); ecdhe_test(32); /* ECDHE shared secret test (32 byte key size) */ ecdhe_test(48); /* ECDHE shared secret test (48 byte key size) */ ecdhe_test(66); /* ECDHE shared secret test (66 byte key size) */ Console.WriteLine("\nStarting RSA tests"); rsa_test("SHA256", 2048); /* Uses SHA-256 (2048 bit hash) */ rsa_test("SHA384", 2048); /* Uses SHA-384 (2048 bit hash) */ rsa_test("SHA512", 2048); /* Uses SHA-512 (2048 bit hash) */ Console.WriteLine("\nStarting ED25519 test"); ed25519_test(); /* ED25519 test */ Console.WriteLine("\nStarting curve25519 test"); curve25519_test(); /* curve25519 shared secret test */ Console.WriteLine("\nStarting ML-KEM test"); mlkem_test(wolfcrypt.MlKemTypes.ML_KEM_512); /* ML-KEM test */ mlkem_test(wolfcrypt.MlKemTypes.ML_KEM_768); /* ML-KEM test */ mlkem_test(wolfcrypt.MlKemTypes.ML_KEM_1024); /* ML-KEM test */ Console.WriteLine("\nStarting ML-DSA test"); mldsa_test(wolfcrypt.MlDsaLevels.ML_DSA_44); /* ML-DSA test */ mldsa_test(wolfcrypt.MlDsaLevels.ML_DSA_65); /* ML-DSA test */ mldsa_test(wolfcrypt.MlDsaLevels.ML_DSA_87); /* ML-DSA test */ Console.WriteLine("\nStarting AES-GCM test"); aes_gcm_test(); /* AES_GCM test */ Console.WriteLine("\nStarting HASH tests"); hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA256); /* SHA-256 HASH test */ hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA384); /* SHA-384 HASH test */ hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA512); /* SHA-512 HASH test */ hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA3_256); /* SHA3_256 HASH test */ Console.WriteLine("\nStarting HPKE tests"); hpke_test(wolfcrypt.HpkeKem.DHKEM_P256_HKDF_SHA256, wolfcrypt.HpkeKdf.HKDF_SHA256, wolfcrypt.HpkeAead.AES_128_GCM); hpke_test(wolfcrypt.HpkeKem.DHKEM_X25519_HKDF_SHA256, wolfcrypt.HpkeKdf.HKDF_SHA256, wolfcrypt.HpkeAead.AES_128_GCM); wolfcrypt.Cleanup(); Console.WriteLine("\nAll tests completed successfully"); } catch (Exception ex) { Console.WriteLine($"An error occurred: {ex.Message}"); Environment.Exit(-1); } } }