Table of Contents

MLKem Class

Definition

Namespace
Bodu.Security.Cryptography
Assembly
Bodu.Security.Cryptography.dll
Package
Bodu.Security.Cryptography 1.2.0
Source
MLKem.KeyFormats.cs

Provides the family base class for the ML-KEM module-lattice key-encapsulation mechanism standardized by NIST FIPS 203, exposed through the standard AsymmetricAlgorithm framework. Use the sealed MLKem512, MLKem768, or MLKem1024 parameter sets.

public abstract class MLKem : RawKeyAsymmetricAlgorithm, IDisposable
Inheritance
MLKem
Implements
Derived
Inherited Members
Extension Methods

Examples

using var receiver = MLKem768.Create();
receiver.GenerateKey();

using var sender = MLKem768.Create();
sender.ImportEncapsulationKey(receiver.ExportEncapsulationKey());
(byte[] ciphertext, byte[] senderSecret) = sender.Encapsulate();

byte[] receiverSecret = receiver.Decapsulate(ciphertext);
// senderSecret and receiverSecret are identical.

Remarks

ML-KEM is a key-encapsulation mechanism believed secure against quantum adversaries (its hardness rests on the Module-LWE problem). One party holds the decapsulation key; anyone with the encapsulation key can call Encapsulate() to produce a ciphertext together with a fresh 32-byte shared secret, which the key holder recovers via Decapsulate(ReadOnlySpan<byte>).

KeySize semantics. The reported key size is the FIPS 203 parameter-set designator (512, 768, or 1024) identifying the module rank and security category - it is not a key length in bits, because module-lattice keys have no meaningful single bit-length.

Implicit rejection. Decapsulate(ReadOnlySpan<byte>) never throws for a tampered ciphertext of the correct length: per FIPS 203 it silently returns the unrelated key J(z ‖ c), so an attacker cannot use decapsulation failures as an oracle. Only a wrong-length ciphertext throws ArgumentException.

Key formats. Only the FIPS 203 byte encodings are supported: the 64-byte private seed (d ‖ z) via ImportPrivateSeed(ReadOnlySpan<byte>), and the encoded decapsulation / encapsulation keys via ImportDecapsulationKey(ReadOnlySpan<byte>) and ImportEncapsulationKey(ReadOnlySpan<byte>), which apply the §7.3 hash and §7.2 modulus checks respectively. The PKCS#8 / SubjectPublicKeyInfo members inherited from AsymmetricAlgorithm are not implemented and retain their base (throwing) behavior.

Memory. When a key is generated or imported, the instance also keeps the values FIPS 203 derives from it on every operation - the matrix Â, the decoded vectors t̂ and ŝ, and H(ek) - so that encapsulation and decapsulation do not recompute them. Beside the encoded keys they take about 8, 15 and 24 KiB for ML-KEM-512, 768 and 1024, or 6, 12 and 20 KiB for an instance holding only an encapsulation key.

The decapsulation re-encryption comparison and key selection are constant-time, and private key material, the cached secret vector included, is zeroed on dispose. This implementation offers best-effort side-channel resistance and has not been independently audited.

Fields

PrivateSeedSizeInBytes

The size, in bytes, of the private seed d ‖ z accepted by ImportPrivateSeed(ReadOnlySpan<byte>).

public const int PrivateSeedSizeInBytes = 64

Field Value

int

SharedSecretSizeInBytes

The size, in bytes, of the shared secret produced by encapsulation and decapsulation.

public const int SharedSecretSizeInBytes = 32

Field Value

int

Properties

AlgorithmName

Gets the FIPS 203 parameter-set name, such as "ML-KEM-768".

public string AlgorithmName { get; }

Property Value

string

The parameter-set name selected when the instance was created.

Remarks

Unlike the inherited KeySize, which reports a fixed parameter-set designator rather than a meaningful bit length for a post-quantum scheme, this property names the parameter set directly.

CiphertextSizeInBytes

Gets the size, in bytes, of the ciphertext produced by encapsulation.

public int CiphertextSizeInBytes { get; }

Property Value

int

768, 1088, or 1568 depending on the parameter set.

Exceptions

ObjectDisposedException

The instance has been disposed.

DecapsulationKeySizeInBytes

Gets the size, in bytes, of the encoded decapsulation (private) key.

public int DecapsulationKeySizeInBytes { get; }

Property Value

int

1632, 2400, or 3168 depending on the parameter set.

Exceptions

ObjectDisposedException

The instance has been disposed.

EncapsulationKeySizeInBytes

Gets the size, in bytes, of the encoded encapsulation (public) key.

public int EncapsulationKeySizeInBytes { get; }

Property Value

int

800, 1184, or 1568 depending on the parameter set.

Exceptions

ObjectDisposedException

The instance has been disposed.

HasDecapsulationKey

Gets a value indicating whether the instance currently holds a decapsulation key.

public bool HasDecapsulationKey { get; }

Property Value

bool

true when decapsulation key material is present; otherwise, false.

Exceptions

ObjectDisposedException

The instance has been disposed.

HasEncapsulationKey

Gets a value indicating whether the instance currently holds an encapsulation key.

public bool HasEncapsulationKey { get; }

Property Value

bool

true when encapsulation key material is present; otherwise, false.

Exceptions

ObjectDisposedException

The instance has been disposed.

KeyExchangeAlgorithm

When overridden in a derived class, gets the name of the key exchange algorithm. Otherwise, throws an NotImplementedException.

public override string? KeyExchangeAlgorithm { get; }

Property Value

string

The name of the key exchange algorithm.

SecurityStrengthBits

Gets the claimed security strength of the selected parameter set, in bits (128, 192, or 256 for ML-KEM-512, ML-KEM-768, and ML-KEM-1024 respectively, corresponding to NIST security categories 1, 3, and 5).

public int SecurityStrengthBits { get; }

Property Value

int

The security strength in bits.

SignatureAlgorithm

When implemented in a derived class, gets the name of the signature algorithm. Otherwise, always throws a NotImplementedException.

public override string? SignatureAlgorithm { get; }

Property Value

string

The name of the signature algorithm.

Methods

Decapsulate(ReadOnlySpan<byte>)

Recovers the shared secret from a ciphertext using the instance's decapsulation key.

public byte[] Decapsulate(ReadOnlySpan<byte> ciphertext)

Parameters

ciphertext ReadOnlySpan<byte>

The ciphertext received from the encapsulating party.

Returns

byte[]

The 32-byte shared secret.

Remarks

A tampered ciphertext of the correct length does not throw: implicit rejection silently yields a key unrelated to the encapsulating party's, per FIPS 203.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

ciphertext does not have the exact parameter-set length.

CryptographicException

The instance does not hold a decapsulation key.

Decapsulate(ReadOnlySpan<byte>, Span<byte>)

Recovers the shared secret from a ciphertext using the instance's decapsulation key, writing it into the supplied span.

public void Decapsulate(ReadOnlySpan<byte> ciphertext, Span<byte> sharedSecret)

Parameters

ciphertext ReadOnlySpan<byte>

The ciphertext received from the encapsulating party.

sharedSecret Span<byte>

The span receiving the shared secret. Must be exactly 32 bytes.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

ciphertext does not have the exact parameter-set length, or sharedSecret is not exactly 32 bytes.

CryptographicException

The instance does not hold a decapsulation key.

Encapsulate()

Encapsulates a fresh shared secret to the instance's encapsulation key.

public (byte[] Ciphertext, byte[] SharedSecret) Encapsulate()

Returns

(byte[] Encapsulation, byte[] Ciphertext)

The ciphertext to transmit and the 32-byte shared secret to keep.

Exceptions

ObjectDisposedException

The instance has been disposed.

CryptographicException

The instance does not hold an encapsulation key.

Encapsulate(Span<byte>, Span<byte>)

Encapsulates a fresh shared secret to the instance's encapsulation key, writing the ciphertext and secret into the supplied spans.

public void Encapsulate(Span<byte> ciphertext, Span<byte> sharedSecret)

Parameters

ciphertext Span<byte>

The span receiving the ciphertext. Must be exactly CiphertextSizeInBytes bytes.

sharedSecret Span<byte>

The span receiving the shared secret. Must be exactly 32 bytes.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

A span does not have its exact required length.

CryptographicException

The instance does not hold an encapsulation key.

ExportDecapsulationKey()

Exports the encoded FIPS 203 decapsulation key.

public byte[] ExportDecapsulationKey()

Returns

byte[]

A fresh copy of the encoded decapsulation key.

Exceptions

ObjectDisposedException

The instance has been disposed.

CryptographicException

The instance does not hold a decapsulation key.

ExportEncapsulationKey()

Exports the encoded FIPS 203 encapsulation key.

public byte[] ExportEncapsulationKey()

Returns

byte[]

A fresh copy of the encoded encapsulation key.

Exceptions

ObjectDisposedException

The instance has been disposed.

CryptographicException

The instance does not hold an encapsulation key.

FromXmlString(string)

When overridden in a derived class, reconstructs an AsymmetricAlgorithm object from an XML string. Otherwise, throws a NotImplementedException.

public override void FromXmlString(string xmlString)

Parameters

xmlString string

The XML string to use to reconstruct the AsymmetricAlgorithm object.

GenerateKey()

Generates a fresh random key pair, replacing any existing key material on the instance.

public void GenerateKey()

Remarks

The two 32-byte seeds (d for key derivation, z for implicit rejection) are drawn from a cryptographically secure random source. Any previously held decapsulation key is zeroed before being replaced.

Exceptions

ObjectDisposedException

The instance has been disposed.

ImportDecapsulationKey(ReadOnlySpan<byte>)

Imports an encoded FIPS 203 decapsulation key, replacing any existing key material on the instance.

public void ImportDecapsulationKey(ReadOnlySpan<byte> decapsulationKey)

Parameters

decapsulationKey ReadOnlySpan<byte>

The encoded decapsulation key dk_PKE ‖ ek ‖ H(ek) ‖ z.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

decapsulationKey does not have the exact parameter-set length, or fails the FIPS 203 §7.3 hash-consistency and embedded-key checks.

ImportEncapsulationKey(ReadOnlySpan<byte>)

Imports an encoded FIPS 203 encapsulation key, replacing any existing key material on the instance.

public void ImportEncapsulationKey(ReadOnlySpan<byte> encapsulationKey)

Parameters

encapsulationKey ReadOnlySpan<byte>

The encoded encapsulation key ByteEncode₁₂(t̂) ‖ ρ.

Remarks

Any decapsulation key previously held by the instance is zeroed and discarded, leaving an encapsulate-only instance.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

encapsulationKey does not have the exact parameter-set length, or fails the FIPS 203 §7.2 modulus check.

ImportEncryptedPkcs8PrivateKey(ReadOnlySpan<byte>, ReadOnlySpan<byte>, out int)

When overridden in a derived class, imports the public/private keypair from a PKCS#8 EncryptedPrivateKeyInfo structure after decrypting with a byte-based password, replacing the keys for this object.

public override void ImportEncryptedPkcs8PrivateKey(ReadOnlySpan<byte> passwordBytes, ReadOnlySpan<byte> source, out int bytesRead)

Parameters

passwordBytes ReadOnlySpan<byte>

The bytes to use as a password when decrypting the key material.

source ReadOnlySpan<byte>

The bytes of a PKCS#8 EncryptedPrivateKeyInfo structure in the ASN.1-BER encoding.

bytesRead int

When this method returns, contains a value that indicates the number of bytes read from source. This parameter is treated as uninitialized.

Exceptions

CryptographicException

The password is incorrect.

-or-

The contents of source indicate the Key Derivation Function (KDF) to apply is the legacy PKCS#12 KDF, which requires char-based passwords.

-or-

The contents of source do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure.

-or-

The contents of source indicate the key is for an algorithm other than the algorithm represented by this instance.

-or-

The contents of source represent the key in a format that is not supported.

-or-

The algorithm-specific key import failed.

NotImplementedException

A derived type has not overriden this member.

ImportEncryptedPkcs8PrivateKey(ReadOnlySpan<char>, ReadOnlySpan<byte>, out int)

When overridden in a derived class, imports the public/private keypair from a PKCS#8 EncryptedPrivateKeyInfo structure after decrypting with a char-based password, replacing the keys for this object.

public override void ImportEncryptedPkcs8PrivateKey(ReadOnlySpan<char> password, ReadOnlySpan<byte> source, out int bytesRead)

Parameters

password ReadOnlySpan<char>

The password to use for decrypting the key material.

source ReadOnlySpan<byte>

The bytes of a PKCS#8 EncryptedPrivateKeyInfo structure in the ASN.1-BER encoding.

bytesRead int

When this method returns, contains a value that indicates the number of bytes read from source. This parameter is treated as uninitialized.

Exceptions

CryptographicException

The password is incorrect.

-or-

The contents of source do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure.

-or-

The contents of source indicate the key is for an algorithm other than the algorithm represented by this instance.

-or-

The contents of source represent the key in a format that is not supported.

-or-

The algorithm-specific key import failed.

NotImplementedException

A derived type has not overriden this member.

ImportPkcs8PrivateKey(ReadOnlySpan<byte>, out int)

When overriden in a derived class, imports the public/private keypair from a PKCS#8 PrivateKeyInfo structure after decryption, replacing the keys for this object.

public override void ImportPkcs8PrivateKey(ReadOnlySpan<byte> source, out int bytesRead)

Parameters

source ReadOnlySpan<byte>

The bytes of a PKCS#8 PrivateKeyInfo structure in the ASN.1-BER encoding.

bytesRead int

When this method returns, contains a value that indicates the number of bytes read from source. This parameter is treated as uninitialized.

Exceptions

CryptographicException

The contents of source do not represent an ASN.1-BER-encoded PKCS#8 PrivateKeyInfo structure.

-or-

The contents of source indicate the key is for an algorithm other than the algorithm represented by this instance.

-or-

The contents of source represent the key in a format that is not supported.

-or-

The algorithm-specific key import failed.

NotImplementedException

A derived type has not overriden this member.

ImportPrivateSeed(ReadOnlySpan<byte>)

Imports the FIPS 203 64-byte private seed d ‖ z and regenerates the full key pair from it, replacing any existing key material on the instance.

public void ImportPrivateSeed(ReadOnlySpan<byte> seed)

Parameters

seed ReadOnlySpan<byte>

The 64-byte concatenation of the key-derivation seed d and the implicit-rejection seed z.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

seed is not exactly 64 bytes long.

ImportSubjectPublicKeyInfo(ReadOnlySpan<byte>, out int)

When overriden in a derived class, imports the public key from an X.509 SubjectPublicKeyInfo structure after decryption, replacing the keys for this object.

public override void ImportSubjectPublicKeyInfo(ReadOnlySpan<byte> source, out int bytesRead)

Parameters

source ReadOnlySpan<byte>

The bytes of an X.509 SubjectPublicKeyInfo structure in the ASN.1-DER encoding.

bytesRead int

When this method returns, contains a value that indicates the number of bytes read from source. This parameter is treated as uninitialized.

Exceptions

CryptographicException

The contents of source do not represent an ASN.1-DER-encoded X.509 SubjectPublicKeyInfo structure.

-or-

The contents of source indicate the key is for an algorithm other than the algorithm represented by this instance.

-or-

The contents of source represent the key in a format that is not supported.

-or-

The algorithm-specific key import failed.

NotImplementedException

A derived type has not overriden this member.

ToXmlString(bool)

When overridden in a derived class, creates and returns an XML string representation of the current AsymmetricAlgorithm object. Otherwise, throws a NotImplementedException.

public override string ToXmlString(bool includePrivateParameters)

Parameters

includePrivateParameters bool

true to include private parameters; otherwise, false.

Returns

string

An XML string encoding of the current AsymmetricAlgorithm object.

TryExportEncryptedPkcs8PrivateKey(ReadOnlySpan<byte>, PbeParameters, Span<byte>, out int)

When overridden in a derived class, attempts to export the current key in the PKCS#8 EncryptedPrivateKeyInfo format into a provided buffer, using a byte-based password.

public override bool TryExportEncryptedPkcs8PrivateKey(ReadOnlySpan<byte> passwordBytes, PbeParameters pbeParameters, Span<byte> destination, out int bytesWritten)

Parameters

passwordBytes ReadOnlySpan<byte>

The bytes to use as a password when encrypting the key material.

pbeParameters PbeParameters

The password-based encryption (PBE) parameters to use when encrypting the key material.

destination Span<byte>

The byte span to receive the PKCS#8 EncryptedPrivateKeyInfo data.

bytesWritten int

When this method returns, contains a value that indicates the number of bytes written to destination. This parameter is treated as uninitialized.

Returns

bool

true if destination is big enough to receive the output; otherwise, false.

Exceptions

CryptographicException

The key could not be exported.

-or-

pbeParameters indicates that TripleDes3KeyPkcs12 should be used, which requires char-based passwords.

NotImplementedException

A derived type has not overriden this member.

TryExportEncryptedPkcs8PrivateKey(ReadOnlySpan<char>, PbeParameters, Span<byte>, out int)

When overriden in a derived class, attempts to export the current key in the PKCS#8 EncryptedPrivateKeyInfo format into a provided buffer, using a char-based password.

public override bool TryExportEncryptedPkcs8PrivateKey(ReadOnlySpan<char> password, PbeParameters pbeParameters, Span<byte> destination, out int bytesWritten)

Parameters

password ReadOnlySpan<char>

The password to use when encrypting the key material.

pbeParameters PbeParameters

The password-based encryption (PBE) parameters to use when encrypting the key material.

destination Span<byte>

The byte span to receive the PKCS#8 EncryptedPrivateKeyInfo data.

bytesWritten int

When this method returns, contains a value that indicates the number of bytes written to destination. This parameter is treated as uninitialized.

Returns

bool

true if destination is big enough to receive the output; otherwise, false.

Exceptions

CryptographicException

The key could not be exported.

NotImplementedException

A derived type has not overriden this member.

TryExportPkcs8PrivateKey(Span<byte>, out int)

When overridden in a derived class, attempts to export the current key in the PKCS#8 PrivateKeyInfo format into a provided buffer.

public override bool TryExportPkcs8PrivateKey(Span<byte> destination, out int bytesWritten)

Parameters

destination Span<byte>

The byte span to receive the PKCS#8 PrivateKeyInfo data.

bytesWritten int

When this method returns, contains a value that indicates the number of bytes written to destination. This parameter is treated as uninitialized.

Returns

bool

true if destination is big enough to receive the output; otherwise, false.

Exceptions

CryptographicException

The key could not be exported.

NotImplementedException

A derived type has not overriden this member.

TryExportSubjectPublicKeyInfo(Span<byte>, out int)

When overridden in a derived class, attempts to export the current key in the X.509 SubjectPublicKeyInfo format into a provided buffer.

public override bool TryExportSubjectPublicKeyInfo(Span<byte> destination, out int bytesWritten)

Parameters

destination Span<byte>

The byte span to receive the X.509 SubjectPublicKeyInfo data.

bytesWritten int

When this method returns, contains a value that indicates the number of bytes written to destination. This parameter is treated as uninitialized.

Returns

bool

true if destination is big enough to receive the output; otherwise, false.

Exceptions

CryptographicException

The key could not be exported.

NotImplementedException

A derived type has not overriden this member.

Applies to

ProductVersions
.NET8, 10