====== 5.1 P/Invoke - Incorporare DLL ====== Questa pagina mostra come usare OpenSSL tramite P/Invoke in .NET. ---- ===== Cos'è P/Invoke? ===== **P/Invoke** (Platform Invoke) permette di chiamare funzioni DLL native da .NET: Codice .NET → P/Invoke → libcrypto-3-x64.dll → OpenSSL ---- ===== Preparare le DLL ===== ==== 1. Copiare le DLL nel Progetto ==== cd MioProjetto 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. Modificare .csproj ==== net8.0 PreserveNewest PreserveNewest ---- ===== Esempio Semplice P/Invoke ===== using System; using System.Runtime.InteropServices; namespace MioProjetto; /// /// Binding P/Invoke per OpenSSL /// public static class OpenSslInterop { private const string LIBCRYPTO = "libcrypto-3-x64.dll"; // Inizializzazione [DllImport(LIBCRYPTO, CallingConvention = CallingConvention.Cdecl)] public static extern int OPENSSL_init_crypto(ulong opts, IntPtr settings); // Ottenere versione [DllImport(LIBCRYPTO, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr OpenSSL_version(int type); // Costanti 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; /// /// Inizializza OpenSSL /// public static void Initialize() { OPENSSL_init_crypto( OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, IntPtr.Zero); } /// /// Restituisce la versione OpenSSL /// public static string GetVersion() { var ptr = OpenSSL_version(OPENSSL_VERSION_STRING); return Marshal.PtrToStringAnsi(ptr) ?? "Unknown"; } } // Utilizzo: class Program { static void Main() { OpenSslInterop.Initialize(); Console.WriteLine($"Versione OpenSSL: {OpenSslInterop.GetVersion()}"); } } ---- ===== Generazione Chiavi ML-DSA ===== 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); /// /// Genera una coppia di chiavi ML-DSA-65 /// 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("Impossibile creare il contesto"); try { if (EVP_PKEY_keygen_init(ctx) <= 0) throw new Exception("Impossibile inizializzare keygen"); IntPtr pkey; if (EVP_PKEY_keygen(ctx, out pkey) <= 0) throw new Exception("Impossibile generare la chiave"); try { // Esportare chiave privata 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); // Esportare chiave pubblica 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); } } } ---- ===== Classe Interop Completa ===== Per un'implementazione P/Invoke completa vedere: → [[..:..:api:start|API WvdS.System.Security.Cryptography]] Questa libreria contiene: * Firma/Verifica ML-DSA * Incapsulamento/Decapsulamento ML-KEM * Certificati X.509 con algoritmi PQ * Firme ibride ---- ===== Errori Comuni ===== ==== "DLL not found" ==== System.DllNotFoundException: Unable to load DLL 'libcrypto-3-x64.dll' **Soluzione:** - DLL presenti nella directory di output (bin/Debug/)? - ''CopyToOutputDirectory'' corretto in .csproj? - Piattaforma corretta? (x64 vs x86) ==== "Entry point not found" ==== System.EntryPointNotFoundException: Unable to find entry point 'XYZ' **Soluzione:** - Nome funzione scritto correttamente? - ''CallingConvention.Cdecl'' impostato? - Versione OpenSSL supporta la funzione? ==== Memory Leak ==== **Liberare sempre le risorse!** * ''EVP_PKEY_free(pkey)'' * ''EVP_PKEY_CTX_free(ctx)'' * ''OPENSSL_free(ptr)'' ---- ===== Suggerimenti ===== **LibraryImport invece di DllImport (da .NET 7)** // Approccio moderno [LibraryImport("libcrypto-3-x64.dll")] public static partial int OPENSSL_init_crypto(ulong opts, IntPtr settings); ---- ===== Continua con ===== * [[.:nuget-grundlagen|Creare pacchetto NuGet]] * [[.:blazor-wasm|Integrazione Blazor WASM]] * [[.:verteilung:start|6. Distribuzione]] ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//