====== 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//