====== 5.1 P/Invoke - DLLs einbinden ======
Diese Seite zeigt, wie Sie OpenSSL über P/Invoke in .NET nutzen.
----
===== Was ist P/Invoke? =====
**P/Invoke** (Platform Invoke) ermöglicht den Aufruf von nativen DLL-Funktionen aus .NET:
.NET Code → P/Invoke → libcrypto-3-x64.dll → OpenSSL
----
===== DLLs vorbereiten =====
==== 1. DLLs in Projekt kopieren ====
cd MeinProjekt
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. .csproj anpassen ====
net8.0
PreserveNewest
PreserveNewest
----
===== Einfaches P/Invoke Beispiel =====
using System;
using System.Runtime.InteropServices;
namespace MeinProjekt;
///
/// OpenSSL P/Invoke Bindings
///
public static class OpenSslInterop
{
private const string LIBCRYPTO = "libcrypto-3-x64.dll";
// Initialisierung
[DllImport(LIBCRYPTO, CallingConvention = CallingConvention.Cdecl)]
public static extern int OPENSSL_init_crypto(ulong opts, IntPtr settings);
// Version abrufen
[DllImport(LIBCRYPTO, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr OpenSSL_version(int type);
// Konstanten
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;
///
/// Initialisiert 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);
}
///
/// Gibt die OpenSSL-Version zurück
///
public static string GetVersion()
{
var ptr = OpenSSL_version(OPENSSL_VERSION_STRING);
return Marshal.PtrToStringAnsi(ptr) ?? "Unknown";
}
}
// Verwendung:
class Program
{
static void Main()
{
OpenSslInterop.Initialize();
Console.WriteLine($"OpenSSL Version: {OpenSslInterop.GetVersion()}");
}
}
----
===== ML-DSA Schlüsselgenerierung =====
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);
///
/// Generiert ein ML-DSA-65 Schlüsselpaar
///
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
{
// Private Key exportieren
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);
// Public Key exportieren
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);
}
}
}
----
===== Vollständige Interop-Klasse =====
Für eine vollständige P/Invoke-Implementierung siehe:
→ [[de:int:pqcrypt:api:start|WvdS.System.Security.Cryptography API]]
Diese Bibliothek enthält:
* ML-DSA Signieren/Verifizieren
* ML-KEM Encapsulation/Decapsulation
* X.509-Zertifikate mit PQ-Algorithmen
* Hybride Signaturen
----
===== Häufige Fehler =====
==== "DLL not found" ====
System.DllNotFoundException: Unable to load DLL 'libcrypto-3-x64.dll'
**Lösung:**
- DLLs im Ausgabeverzeichnis (bin/Debug/) vorhanden?
- .csproj ''CopyToOutputDirectory'' korrekt?
- Plattform stimmt? (x64 vs x86)
==== "Entry point not found" ====
System.EntryPointNotFoundException: Unable to find entry point 'XYZ'
**Lösung:**
- Funktionsname korrekt geschrieben?
- ''CallingConvention.Cdecl'' gesetzt?
- OpenSSL-Version unterstützt die Funktion?
==== Speicherlecks ====
**Immer Ressourcen freigeben!**
* ''EVP_PKEY_free(pkey)''
* ''EVP_PKEY_CTX_free(ctx)''
* ''OPENSSL_free(ptr)''
----
===== Tipps =====
**LibraryImport statt DllImport (ab .NET 7)**
// Moderner Ansatz
[LibraryImport("libcrypto-3-x64.dll")]
public static partial int OPENSSL_init_crypto(ulong opts, IntPtr settings);
----
===== Weiter zu =====
* [[.:nuget-grundlagen|NuGet-Paket erstellen]]
* [[.:blazor-wasm|Blazor WASM Integration]]
* [[.:verteilung:start|6. Verteilung]]
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//