ML-KEM.NetCore
1.0.0
dotnet add package ML-KEM.NetCore --version 1.0.0
NuGet\Install-Package ML-KEM.NetCore -Version 1.0.0
<PackageReference Include="ML-KEM.NetCore" Version="1.0.0" />
<PackageVersion Include="ML-KEM.NetCore" Version="1.0.0" />
<PackageReference Include="ML-KEM.NetCore" />
paket add ML-KEM.NetCore --version 1.0.0
#r "nuget: ML-KEM.NetCore, 1.0.0"
#:package ML-KEM.NetCore@1.0.0
#addin nuget:?package=ML-KEM.NetCore&version=1.0.0
#tool nuget:?package=ML-KEM.NetCore&version=1.0.0
ML-KEM.NetCore
ML-KEM.NetCore is a pure managed .NET implementation of the NIST-standardized ML-KEM (Kyber) post-quantum key encapsulation mechanism.
The library targets .NET 8 and uses PinnedMemory for secret key and shared secret material to improve lifecycle control.
Table of contents
- Requirements
- Installation
- Quick start
- API reference
- Parameter sizes
- Best practices
- Validation and testing
- Development
- Security notes
- License
Requirements
- .NET 8 SDK for building and running tests.
- Project target framework:
net8.0.
Installation
From source
Clone the repository and reference the MLKEM.NetCore project from your solution.
NuGet (when published)
dotnet add package ML-KEM.NetCore
Quick start
Pinned-memory encapsulation flow
using MLKEM.NetCore;
var kem = new MLKem(MLKemParameterSet.MLKem768);
var keyPair = kem.GenerateKeyPair();
using (keyPair.SecretKey)
{
var encapsulation = kem.Encapsulate(keyPair.PublicKey);
using (encapsulation.SharedSecret)
{
var secretKey = keyPair.SecretKey.Read().AsSpan(0, kem.SecretKeyBytes);
using var sharedSecretBob = kem.Decapsulate(secretKey, encapsulation.CipherText);
// Compare or use shared secrets, then dispose to scrub.
}
}
API reference
MLKemParameterSet
enum MLKemParameterSet
{
MLKem512,
MLKem768,
MLKem1024
}
Selects the NIST parameter set used by an MLKem instance.
MLKem
Constructor
MLKem(MLKemParameterSet parameterSet)
Size properties
int PublicKeyBytes { get; }
int SecretKeyBytes { get; }
int CipherTextBytes { get; }
int SharedSecretBytes { get; } // always 32
Key generation
SecureKeyPair GenerateKeyPair()
SecureKeyPair GenerateKeyPair(ReadOnlySpan<byte> d, ReadOnlySpan<byte> z)
- Deterministic generation requires
dandzto be exactly 32 bytes each.
Encapsulation
EncapsulationResult Encapsulate(ReadOnlySpan<byte> publicKey)
EncapsulationResult EncapsulateDeterministic(ReadOnlySpan<byte> publicKey, ReadOnlySpan<byte> m)
EncapsulateDeterministic(...)requiresmto be exactly 32 bytes.
Decapsulation
PinnedMemory<byte> Decapsulate(ReadOnlySpan<byte> secretKey, ReadOnlySpan<byte> cipherText)
- Input lengths are validated and must match the selected parameter set sizes.
Result types
sealed class SecureKeyPair
{
byte[] PublicKey { get; }
PinnedMemory<byte> SecretKey { get; }
}
sealed class EncapsulationResult
{
byte[] CipherText { get; }
PinnedMemory<byte> SharedSecret { get; }
}
Parameter sizes
Per instantiated MLKem object:
MLKem512- Public key: 800 bytes
- Secret key: 1632 bytes
- Ciphertext: 768 bytes
- Shared secret: 32 bytes
MLKem768- Public key: 1184 bytes
- Secret key: 2400 bytes
- Ciphertext: 1088 bytes
- Shared secret: 32 bytes
MLKem1024- Public key: 1568 bytes
- Secret key: 3168 bytes
- Ciphertext: 1568 bytes
- Shared secret: 32 bytes
Best practices
Use secure APIs for secret-bearing values
- Use
GenerateKeyPair,Encapsulate, andDecapsulateto keep key material inPinnedMemory<byte>. - Dispose
PinnedMemory<byte>instances promptly.
- Use
Treat parameter sets as protocol constants
- Do not mix parameter sets between peers.
- Validate all serialized key/ciphertext lengths before use.
Prefer deterministic APIs only for tests/vectors
- In production, use randomized
GenerateKeyPair()andEncapsulate().
- In production, use randomized
Keep secret data lifetime short
- Zero and dispose sensitive buffers as soon as possible.
Validation and testing
The test suite includes:
- Deterministic known-answer-style vector checks
- Encapsulation/decapsulation round-trip checks across parameter sets
- Ciphertext tamper rejection behavior
- Secure API behavior and memory handling coverage
Run all tests:
dotnet test MLKEM.sln
Development
Build
dotnet build MLKEM.sln
Test
dotnet test MLKEM.sln
Security notes
This implementation follows ML-KEM constructions in RFC 9936, including a rejection-sampling path that continues SHAKE output generation until enough coefficients are produced.
Current hardening in this repository:
- Decapsulation uses constant-time ciphertext validation with fallback to
zon invalid ciphertext. - Sensitive intermediates in decapsulation are explicitly zeroed before returning.
- All secret key and shared secret APIs expose
PinnedMemory<byte>for deterministic cleanup of secret-bearing values. - Public keys and ciphertext remain
byte[]for interoperability, while key material is pinned.
License
MIT License. See LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- PinnedMemory (>= 2.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 36 | 3/13/2026 |