LibOQS.NET provides .NET wrapper/bindings for the Open Quantum Safe liboqs C library, which is a C library for quantum-resistant cryptographic algorithms.
This project offers two .NET packages:
- The
LibOQS.NET.Nativepackage provides low-level P/Invoke bindings to the liboqs C library - The
LibOQS.NETpackage offers a high-level, type-safe .NET API for the quantum-resistant algorithms
Both packages are self-contained and include all necessary native dependencies - no manual compilation or native library installation is required.
Install from NuGet - no additional dependencies or native compilation required:
<PackageReference Include="LibOQS.NET" Version="...version..." />Or via the .NET CLI:
dotnet add package LibOQS.NETusing LibOQS.NET;
// LibOQS initializes automatically - no manual Initialize() call needed
try
{
// Key Encapsulation Mechanism example
using var kem = new KemInstance(KemAlgorithm.MlKem512);
// Generate keypair
var (publicKey, secretKey) = kem.GenerateKeypair();
// Encapsulate a shared secret
var (ciphertext, sharedSecret1) = kem.Encapsulate(publicKey);
// Decapsulate the shared secret
var sharedSecret2 = kem.Decapsulate(secretKey, ciphertext);
// Verify they match
Console.WriteLine($"Shared secrets match: {sharedSecret1.SequenceEqual(sharedSecret2)}");
// Digital signature example
using var sig = new SigInstance(SigAlgorithm.MlDsa44);
// Generate signature keypair
var (sigPublicKey, sigSecretKey) = sig.GenerateKeypair();
// Sign a message
var message = System.Text.Encoding.UTF8.GetBytes("Hello, post-quantum world!");
var signature = sig.Sign(message, sigSecretKey);
// Verify the signature
var isValid = sig.Verify(message, signature, sigPublicKey);
Console.WriteLine($"Signature valid: {isValid}");
}
finally
{
// Optional cleanup - called automatically at app shutdown
LibOqs.Cleanup();
}using LibOQS.NET;
try
{
using var sigAlg = new SigInstance(SigAlgorithm.MlDsa44);
using var kemAlg = new KemInstance(KemAlgorithm.MlKem512);
// A's long-term secrets
var (aSigPk, aSigSk) = sigAlg.GenerateKeypair();
// B's long-term secrets
var (bSigPk, bSigSk) = sigAlg.GenerateKeypair();
// A -> B: kem_pk, signature
var (kemPk, kemSk) = kemAlg.GenerateKeypair();
var signature1 = sigAlg.Sign(kemPk, aSigSk);
// B -> A: kem_ct, signature
if (!sigAlg.Verify(kemPk, signature1, aSigPk))
throw new Exception("Failed to verify A's signature");
var (kemCt, bKemSs) = kemAlg.Encapsulate(kemPk);
var signature2 = sigAlg.Sign(kemCt, bSigSk);
// A verifies, decapsulates, now both have kem_ss
if (!sigAlg.Verify(kemCt, signature2, bSigPk))
throw new Exception("Failed to verify B's signature");
var aKemSs = kemAlg.Decapsulate(kemSk, kemCt);
// Verify shared secrets match
if (aKemSs.SequenceEqual(bKemSs))
Console.WriteLine("Key exchange successful!");
}
finally
{
LibOqs.Cleanup();
}- Key Encapsulation Mechanisms (KEMs): ML-KEM, Kyber, BIKE, HQC, NTRU, Classic McEliece, NTRU Prime, FrodoKEM
- Digital Signatures: ML-DSA, SLH-DSA, Falcon, SPHINCS+, MAYO, CROSS, UOV, SNOVA
- New Features: Support for context strings in signatures and derandomized (deterministic) operations in KEM.
- Type-safe API: Strong typing with enums for algorithms and proper resource management
- Memory management: Automatic cleanup of native resources using IDisposable pattern
- Cross-platform: Supports Windows x64, Windows ARM64, macOS ARM64, Linux x64, and Linux ARM64
- Self-contained: No manual native library installation or compilation required
- ML-KEM (NIST standardized): ML-KEM-512, ML-KEM-768, ML-KEM-1024
- Kyber: Kyber512, Kyber768, Kyber1024
- BIKE: BIKE-L1, BIKE-L3, BIKE-L5
- HQC: HQC-128, HQC-192, HQC-256
- NTRU: NTRU-HPS-2048-509, NTRU-HPS-2048-677, NTRU-HPS-4096-821, NTRU-HPS-4096-1229, NTRU-HRSS-701, NTRU-HRSS-1373
- Classic McEliece: All 10 variants (e.g., 348864, 460896, 6688128, 6960119, 8192128 with fast variants)
- NTRU Prime: sntrup761
- FrodoKEM: FrodoKEM-640-AES, FrodoKEM-640-SHAKE, FrodoKEM-976-AES, FrodoKEM-976-SHAKE, FrodoKEM-1344-AES, FrodoKEM-1344-SHAKE
- ML-DSA (NIST standardized): ML-DSA-44, ML-DSA-65, ML-DSA-87
- SLH-DSA (NIST standardized): All 12 pure variants (SHA2 and SHAKE, 128/192/256, fast/small)
- Falcon: Falcon-512, Falcon-1024, Falcon-Padded-512, Falcon-Padded-1024
- SPHINCS+: All "simple" variants (SHA2 and SHAKE, 128/192/256, fast/small)
- MAYO: MAYO-1, MAYO-2, MAYO-3, MAYO-5
- CROSS: All 18 variants (RSDP/RSDPG, Balanced/Fast/Small)
- UOV: All 12 variants (Ip, Is, III, V; with pkc/skc variants)
- SNOVA: All 12 variants
Not all algorithms may be available in every build of liboqs. You can check if an algorithm is enabled:
if (KemAlgorithm.MlKem512.IsEnabled())
{
// Use ML-KEM-512
using var kem = new KemInstance(KemAlgorithm.MlKem512);
// ...
}The library properly manages native resources:
- Automatic initialization: LibOQS initializes automatically via static constructor
- Automatic cleanup: Use
usingstatements withKemInstanceandSigInstance - Optional manual cleanup: Call
LibOqs.Cleanup()when completely done with the library
The native liboqs library is generally thread-safe for read operations but may not be thread-safe for initialization. It's recommended to:
- Use separate instances of
KemInstanceandSigInstanceper thread - The automatic initialization is thread-safe
- Call
LibOqs.Cleanup()once at application shutdown if needed
The library throws specific exceptions:
OqsException: General OQS operation failuresAlgorithmNotSupportedException: When an algorithm is not enabledArgumentException: Invalid parametersObjectDisposedException: Using disposed objects
The NuGet packages are self-contained and don't require building from source. This section is only for developers who want to contribute or modify the library.
- .NET 9.0 SDK or later
- CMake 3.5 or later
- C/C++ compiler (Visual Studio Build Tools on Windows, GCC/Clang on Linux/macOS)
- Git with submodule support
This repository uses git submodules to include the liboqs library. Clone with submodules:
git clone --recursive https://github.com/filipw/maybe-liboqs-dotnet.git
cd maybe-liboqs-dotnetIf you already cloned without --recursive, initialize the submodules:
git submodule init
git submodule update-
Build the native liboqs library:
On Windows, run the PowerShell script:
.\build-dotnet-liboqs.ps1
On Linux, run the bash script:
./build-dotnet-liboqs-linux.sh
On Mac, use:
./build-dotnet-liboqs-macos.sh
This will:
- Configure and build liboqs as a shared library
- Copy the resulting DLL/so/dylib to the appropriate directories
- Enable all common quantum-resistant algorithms (ML-KEM, ML-DSA, SLH-DSA, Kyber, Falcon, FrodoKEM, BIKE, HQC, SPHINCS+, NTRU, SNOVA, etc.)
-
Build the .NET libraries:
dotnet build
-
Run tests:
dotnet test -
Run examples:
cd src/Examples dotnet run
This project uses liboqs v0.15.0 as a git submodule.
Update to latest liboqs version:
cd liboqs
git fetch
git checkout <new-tag>
cd ..
git add liboqs
git commit -m "Update liboqs to <new-tag>"Working with submodules:
# Initialize submodules after cloning
git submodule init
git submodule update
# Update all submodules to latest commits
git submodule update --remote
# Clone with all submodules
git clone --recursive <repo-url>LibOQS.NET supports the following platforms out of the box with no additional setup required:
- Windows x64
- Windows ARM64
- Linux x64
- Linux ARM64
- macOS ARM64
Note
Platform Limitations:
- Windows:
SLH-DSA(Pure variants) are currently disabled due to a known bug inliboqs0.15.0 that causes verification failures on Windows.BIKEis also disabled on Windows.
The NuGet packages include all necessary native libraries for these platforms.
This means the algorithm you're trying to use was not enabled when liboqs was compiled. You can:
- Check which algorithms are enabled using the
.IsEnabled()method - Use a different algorithm that is available
If you encounter issues:
- Ensure you're using a supported platform (see Platform Support above)
- Check that your .NET runtime version is compatible (.NET 9.0 or later)
- Verify the algorithm you're trying to use is enabled with
.IsEnabled()
- Fork the repository
- Create a feature branch
- Make your changes
- Ensure tests pass:
dotnet test - Submit a pull request
When working with submodules:
- Keep liboqs submodule updates in separate commits
- Test thoroughly after submodule updates
- Update documentation if API changes occur
LibOQS.NET is licensed under the MIT license.
The included liboqs library is covered by its own license.
- Open Quantum Safe project
- liboqs C library
- The quantum cryptography research community