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
SharedSecretSizeInBytes
The size, in bytes, of the shared secret produced by encapsulation and decapsulation.
public const int SharedSecretSizeInBytes = 32
Field Value
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
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
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
ciphertextReadOnlySpan<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
ciphertextdoes 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
ciphertextReadOnlySpan<byte>The ciphertext received from the encapsulating party.
sharedSecretSpan<byte>The span receiving the shared secret. Must be exactly 32 bytes.
Exceptions
- ObjectDisposedException
The instance has been disposed.
- ArgumentException
ciphertextdoes not have the exact parameter-set length, orsharedSecretis 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
ciphertextSpan<byte>The span receiving the ciphertext. Must be exactly CiphertextSizeInBytes bytes.
sharedSecretSpan<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
xmlStringstringThe 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
decapsulationKeyReadOnlySpan<byte>The encoded decapsulation key dk_PKE ‖ ek ‖ H(ek) ‖ z.
Exceptions
- ObjectDisposedException
The instance has been disposed.
- ArgumentException
decapsulationKeydoes 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
encapsulationKeyReadOnlySpan<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
encapsulationKeydoes 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
passwordBytesReadOnlySpan<byte>The bytes to use as a password when decrypting the key material.
sourceReadOnlySpan<byte>The bytes of a PKCS#8 EncryptedPrivateKeyInfo structure in the ASN.1-BER encoding.
bytesReadintWhen 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
sourceindicate the Key Derivation Function (KDF) to apply is the legacy PKCS#12 KDF, which requires char-based passwords.-or-
The contents of
sourcedo not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure.-or-
The contents of
sourceindicate the key is for an algorithm other than the algorithm represented by this instance.-or-
The contents of
sourcerepresent 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
passwordReadOnlySpan<char>The password to use for decrypting the key material.
sourceReadOnlySpan<byte>The bytes of a PKCS#8 EncryptedPrivateKeyInfo structure in the ASN.1-BER encoding.
bytesReadintWhen 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
sourcedo not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure.-or-
The contents of
sourceindicate the key is for an algorithm other than the algorithm represented by this instance.-or-
The contents of
sourcerepresent 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
sourceReadOnlySpan<byte>The bytes of a PKCS#8 PrivateKeyInfo structure in the ASN.1-BER encoding.
bytesReadintWhen 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
sourcedo not represent an ASN.1-BER-encoded PKCS#8 PrivateKeyInfo structure.-or-
The contents of
sourceindicate the key is for an algorithm other than the algorithm represented by this instance.-or-
The contents of
sourcerepresent 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
seedReadOnlySpan<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
seedis 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
sourceReadOnlySpan<byte>The bytes of an X.509 SubjectPublicKeyInfo structure in the ASN.1-DER encoding.
bytesReadintWhen 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
sourcedo not represent an ASN.1-DER-encoded X.509 SubjectPublicKeyInfo structure.-or-
The contents of
sourceindicate the key is for an algorithm other than the algorithm represented by this instance.-or-
The contents of
sourcerepresent 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
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
passwordBytesReadOnlySpan<byte>The bytes to use as a password when encrypting the key material.
pbeParametersPbeParametersThe password-based encryption (PBE) parameters to use when encrypting the key material.
destinationSpan<byte>The byte span to receive the PKCS#8 EncryptedPrivateKeyInfo data.
bytesWrittenintWhen this method returns, contains a value that indicates the number of bytes written to
destination. This parameter is treated as uninitialized.
Returns
Exceptions
- CryptographicException
The key could not be exported.
-or-
pbeParametersindicates 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
passwordReadOnlySpan<char>The password to use when encrypting the key material.
pbeParametersPbeParametersThe password-based encryption (PBE) parameters to use when encrypting the key material.
destinationSpan<byte>The byte span to receive the PKCS#8 EncryptedPrivateKeyInfo data.
bytesWrittenintWhen this method returns, contains a value that indicates the number of bytes written to
destination. This parameter is treated as uninitialized.
Returns
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
destinationSpan<byte>The byte span to receive the PKCS#8 PrivateKeyInfo data.
bytesWrittenintWhen this method returns, contains a value that indicates the number of bytes written to
destination. This parameter is treated as uninitialized.
Returns
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
destinationSpan<byte>The byte span to receive the X.509 SubjectPublicKeyInfo data.
bytesWrittenintWhen this method returns, contains a value that indicates the number of bytes written to
destination. This parameter is treated as uninitialized.
Returns
Exceptions
- CryptographicException
The key could not be exported.
- NotImplementedException
A derived type has not overriden this member.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |