Inhaltsverzeichnis
5.1 P/Invoke - Vključitev DLL-jev
Ta stran prikazuje, kako uporabljate OpenSSL preko P/Invoke v .NET.
Kaj je P/Invoke?
P/Invoke (Platform Invoke) omogoča klic funkcij nativnih DLL-jev iz .NET:
.NET koda → P/Invoke → libcrypto-3-x64.dll → OpenSSL
Priprava DLL-jev
1. Kopiranje DLL-jev v projekt
cd MojProjekt copy "D:\Projects\openssl-3.6.0\bin\bin\libcrypto-3-x64.dll" .\ copy "D:\Projects\openssl-3.6.0\bin\bin\libssl-3-x64.dll" .\
2. Prilagoditev .csproj
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> </PropertyGroup> <ItemGroup> <!-- OpenSSL Native Libraries --> <None Update="libcrypto-3-x64.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> <None Update="libssl-3-x64.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> </Project>
Preprost primer P/Invoke
using System; using System.Runtime.InteropServices; namespace MojProjekt; /// <summary> /// OpenSSL P/Invoke Bindings /// </summary> public static class OpenSslInterop { private const string LIBCRYPTO = "libcrypto-3-x64.dll"; // Inicializacija [DllImport(LIBCRYPTO, CallingConvention = CallingConvention.Cdecl)] public static extern int OPENSSL_init_crypto(ulong opts, IntPtr settings); // Pridobitev različice [DllImport(LIBCRYPTO, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr OpenSSL_version(int type); // Konstante public const int OPENSSL_VERSION_STRING = 6; public const ulong OPENSSL_INIT_LOAD_CRYPTO_STRINGS = 0x00000002; public const ulong OPENSSL_INIT_ADD_ALL_CIPHERS = 0x00000004; public const ulong OPENSSL_INIT_ADD_ALL_DIGESTS = 0x00000008; /// <summary> /// Inicializira OpenSSL /// </summary> public static void Initialize() { OPENSSL_init_crypto( OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, IntPtr.Zero); } /// <summary> /// Vrne različico OpenSSL /// </summary> public static string GetVersion() { var ptr = OpenSSL_version(OPENSSL_VERSION_STRING); return Marshal.PtrToStringAnsi(ptr) ?? "Unknown"; } } // Uporaba: class Program { static void Main() { OpenSslInterop.Initialize(); Console.WriteLine($"OpenSSL Version: {OpenSslInterop.GetVersion()}"); } }
Generiranje ML-DSA ključev
public static class MlDsaInterop { private const string LIBCRYPTO = "libcrypto-3-x64.dll"; [DllImport(LIBCRYPTO)] private static extern IntPtr EVP_PKEY_CTX_new_from_name(IntPtr libctx, string name, IntPtr propq); [DllImport(LIBCRYPTO)] private static extern int EVP_PKEY_keygen_init(IntPtr ctx); [DllImport(LIBCRYPTO)] private static extern int EVP_PKEY_keygen(IntPtr ctx, out IntPtr pkey); [DllImport(LIBCRYPTO)] private static extern void EVP_PKEY_CTX_free(IntPtr ctx); [DllImport(LIBCRYPTO)] private static extern void EVP_PKEY_free(IntPtr pkey); [DllImport(LIBCRYPTO)] private static extern int i2d_PrivateKey(IntPtr pkey, ref IntPtr pp); [DllImport(LIBCRYPTO)] private static extern int i2d_PUBKEY(IntPtr pkey, ref IntPtr pp); [DllImport(LIBCRYPTO)] private static extern void OPENSSL_free(IntPtr ptr); /// <summary> /// Generira par ključev ML-DSA-65 /// </summary> public static (byte[] privateKey, byte[] publicKey) GenerateMlDsa65KeyPair() { IntPtr ctx = EVP_PKEY_CTX_new_from_name(IntPtr.Zero, "mldsa65", IntPtr.Zero); if (ctx == IntPtr.Zero) throw new Exception("Failed to create context"); try { if (EVP_PKEY_keygen_init(ctx) <= 0) throw new Exception("Failed to init keygen"); IntPtr pkey; if (EVP_PKEY_keygen(ctx, out pkey) <= 0) throw new Exception("Failed to generate key"); try { // Izvoz zasebnega ključa IntPtr privPtr = IntPtr.Zero; int privLen = i2d_PrivateKey(pkey, ref privPtr); byte[] privateKey = new byte[privLen]; Marshal.Copy(privPtr, privateKey, 0, privLen); OPENSSL_free(privPtr); // Izvoz javnega ključa IntPtr pubPtr = IntPtr.Zero; int pubLen = i2d_PUBKEY(pkey, ref pubPtr); byte[] publicKey = new byte[pubLen]; Marshal.Copy(pubPtr, publicKey, 0, pubLen); OPENSSL_free(pubPtr); return (privateKey, publicKey); } finally { EVP_PKEY_free(pkey); } } finally { EVP_PKEY_CTX_free(ctx); } } }
Popoln razred Interop
Za popolno implementacijo P/Invoke glejte:
→ WvdS.System.Security.Cryptography API
Ta knjižnica vsebuje:
- ML-DSA podpisovanje/preverjanje
- ML-KEM enkapsulacija/dekapsulacija
- X.509 certifikati s PQ algoritmi
- Hibridni podpisi
Pogoste napake
"DLL not found"
System.DllNotFoundException: Unable to load DLL 'libcrypto-3-x64.dll'
Rešitev:
- DLL-ji v izhodnem imeniku (bin/Debug/) prisotni?
- .csproj
CopyToOutputDirectorypravilno? - Platforma se ujema? (x64 vs x86)
"Entry point not found"
System.EntryPointNotFoundException: Unable to find entry point 'XYZ'
Rešitev:
- Ime funkcije pravilno napisano?
CallingConvention.Cdeclnastavljeno?- Različica OpenSSL podpira funkcijo?
Puščanje pomnilnika
Vedno sprostite vire!
EVP_PKEY_free(pkey)EVP_PKEY_CTX_free(ctx)OPENSSL_free(ptr)
Nasveti
LibraryImport namesto DllImport (od .NET 7)
// Sodoben pristop [LibraryImport("libcrypto-3-x64.dll")] public static partial int OPENSSL_init_crypto(ulong opts, IntPtr settings);
Naprej na
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional
Zuletzt geändert: dne 15.12.2025 ob 21:22