Table of Contents

MLDsa Class

Definition

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

Provides the family base class for the ML-DSA module-lattice digital signature algorithm standardized by NIST FIPS 204, exposed through the standard AsymmetricAlgorithm framework. Use the sealed MLDsa44, MLDsa65, or MLDsa87 parameter sets.

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

Examples

using var signer = MLDsa65.Create();
signer.GenerateKey();
byte[] signature = signer.SignData(message);

using var verifier = MLDsa65.Create();
verifier.ImportPublicKey(signer.ExportPublicKey());
bool valid = verifier.VerifyData(message, signature);

Remarks

ML-DSA is a digital signature scheme believed secure against quantum adversaries (its hardness rests on the Module-LWE and SelfTargetMSIS problems). Signing accepts an optional context string of at most 255 bytes that domain-separates signatures across applications; a signature created with a context verifies only with the same context.

Hedged versus deterministic signing. By default signing is hedged: each signature mixes 32 fresh random bytes into the nonce derivation, which is the FIPS 204 default and protects against fault-injection and randomness-disclosure attacks. Setting DeterministicSigning to true substitutes the all-zero string, making signatures reproducible for a fixed key and message. Both variants are standard; verification is unaffected.

KeySize semantics. The reported key size is the FIPS 204 parameter-set designator (44, 65, or 87) identifying the matrix dimensions and security category - it is not a key length in bits.

Scope. This type implements pure ML-DSA (the ML-DSA.Sign / ML-DSA.Verify external functions). The pre-hash variant HashML-DSA is deliberately out of scope for this version. Only the raw FIPS 204 byte encodings are supported: the 32-byte seed ξ via ImportPrivateSeed(ReadOnlySpan<byte>) and the encoded keys via ImportPrivateKey(ReadOnlySpan<byte>) (which cross-checks the embedded public-key hash) and ImportPublicKey(ReadOnlySpan<byte>) . 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 204 derives from it on every operation - the matrix Â, the hash tr, and the key's vectors in the form the arithmetic uses - so that signing and verification do not recompute them. Beside the encoded keys they take about 32, 53 and 87 KiB for ML-DSA-44, 65 and 87, or 20, 36 and 64 KiB for an instance holding only a public key.

Verification returns false (never throws) for malformed, non-canonical, or wrong-length signatures. Private key material, the cached secret vectors included, is zeroed on dispose. This implementation offers best-effort side-channel resistance and has not been independently audited.

Fields

MaxContextSizeInBytes

The maximum length, in bytes, of the signature context string.

public const int MaxContextSizeInBytes = 255

Field Value

int

PrivateSeedSizeInBytes

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

public const int PrivateSeedSizeInBytes = 32

Field Value

int

Properties

AlgorithmName

Gets the FIPS 204 parameter-set name, such as "ML-DSA-65".

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.

DeterministicSigning

Gets or sets a value indicating whether signing is deterministic instead of hedged.

public bool DeterministicSigning { get; set; }

Property Value

bool

false (the default) to mix 32 fresh random bytes into every signature per the FIPS 204 hedged variant; true to use the all-zero string, making signatures reproducible.

HasPrivateKey

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

public bool HasPrivateKey { get; }

Property Value

bool

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

Exceptions

ObjectDisposedException

The instance has been disposed.

HasPublicKey

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

public bool HasPublicKey { get; }

Property Value

bool

true when public 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.

PrivateKeySizeInBytes

Gets the size, in bytes, of the encoded private key.

public int PrivateKeySizeInBytes { get; }

Property Value

int

2560, 4032, or 4896 depending on the parameter set.

Exceptions

ObjectDisposedException

The instance has been disposed.

PublicKeySizeInBytes

Gets the size, in bytes, of the encoded public key.

public int PublicKeySizeInBytes { get; }

Property Value

int

1312, 1952, or 2592 depending on the parameter set.

Exceptions

ObjectDisposedException

The instance has been disposed.

SecurityStrengthBits

Gets the claimed security strength of the selected parameter set, in bits (128, 192, or 256 for ML-DSA-44, ML-DSA-65, and ML-DSA-87 respectively, corresponding to NIST security categories 2, 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.

SignatureSizeInBytes

Gets the size, in bytes, of an encoded signature.

public int SignatureSizeInBytes { get; }

Property Value

int

2420, 3309, or 4627 depending on the parameter set.

Exceptions

ObjectDisposedException

The instance has been disposed.

Methods

ExportPrivateKey()

Exports the encoded FIPS 204 private key.

public byte[] ExportPrivateKey()

Returns

byte[]

A fresh copy of the encoded private key.

Exceptions

ObjectDisposedException

The instance has been disposed.

CryptographicException

The instance does not hold a private key.

ExportPublicKey()

Exports the encoded FIPS 204 public key.

public byte[] ExportPublicKey()

Returns

byte[]

A fresh copy of the encoded public key.

Exceptions

ObjectDisposedException

The instance has been disposed.

CryptographicException

The instance does not hold a public 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 32-byte seed ξ is drawn from a cryptographically secure random source. Any previously held private key is zeroed before being replaced.

Exceptions

ObjectDisposedException

The instance has been disposed.

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.

ImportPrivateKey(ReadOnlySpan<byte>)

Imports an encoded FIPS 204 private key, recomputing and caching the matching public key, and replacing any existing key material on the instance.

public void ImportPrivateKey(ReadOnlySpan<byte> privateKey)

Parameters

privateKey ReadOnlySpan<byte>

The encoded private key ρ ‖ K ‖ tr ‖ s₁ ‖ s₂ ‖ t₀.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

privateKey does not have the exact parameter-set length; encodes an s₁ or s₂ coefficient outside its canonical [−η, η] range; carries a t₀ vector inconsistent with the low bits recomputed from the secret vectors; or its embedded tr hash does not match the public key recomputed from those vectors.

ImportPrivateSeed(ReadOnlySpan<byte>)

Imports the FIPS 204 32-byte private seed ξ 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 32-byte key-generation seed ξ.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

seed is not exactly 32 bytes long.

ImportPublicKey(ReadOnlySpan<byte>)

Imports an encoded FIPS 204 public key, replacing any existing key material on the instance.

public void ImportPublicKey(ReadOnlySpan<byte> publicKey)

Parameters

publicKey ReadOnlySpan<byte>

The encoded public key ρ ‖ t₁.

Remarks

Any private key previously held by the instance is zeroed and discarded, leaving a verify-only instance.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

publicKey does not have the exact parameter-set length.

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.

SignData(ReadOnlySpan<byte>)

Signs the supplied data with an empty context string.

public byte[] SignData(ReadOnlySpan<byte> data)

Parameters

data ReadOnlySpan<byte>

The message bytes to sign. May be empty.

Returns

byte[]

The encoded signature.

Exceptions

ObjectDisposedException

The instance has been disposed.

CryptographicException

The instance does not hold a private key.

SignData(ReadOnlySpan<byte>, ReadOnlySpan<byte>)

Signs the supplied data under a context string.

public byte[] SignData(ReadOnlySpan<byte> data, ReadOnlySpan<byte> context)

Parameters

data ReadOnlySpan<byte>

The message bytes to sign. May be empty.

context ReadOnlySpan<byte>

The domain-separation context string of at most 255 bytes. May be empty.

Returns

byte[]

The encoded signature.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

context is longer than 255 bytes.

CryptographicException

The instance does not hold a private key.

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

Signs the supplied data under a context string, writing the encoded signature into destination.

public void SignData(ReadOnlySpan<byte> data, ReadOnlySpan<byte> context, Span<byte> destination)

Parameters

data ReadOnlySpan<byte>

The message bytes to sign. May be empty.

context ReadOnlySpan<byte>

The domain-separation context string of at most 255 bytes. May be empty.

destination Span<byte>

The span receiving the signature. Must be exactly SignatureSizeInBytes bytes.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

context is longer than 255 bytes, or destination does not have the exact signature length.

CryptographicException

The instance does not hold a private key.

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.

VerifyData(ReadOnlySpan<byte>, ReadOnlySpan<byte>)

Verifies a signature over the supplied data with an empty context string.

public bool VerifyData(ReadOnlySpan<byte> data, ReadOnlySpan<byte> signature)

Parameters

data ReadOnlySpan<byte>

The message bytes that were signed. May be empty.

signature ReadOnlySpan<byte>

The candidate encoded signature.

Returns

bool

true when the signature is valid; false for any invalid, malformed, or wrong-length signature.

Exceptions

ObjectDisposedException

The instance has been disposed.

CryptographicException

The instance does not hold a public key.

VerifyData(ReadOnlySpan<byte>, ReadOnlySpan<byte>, ReadOnlySpan<byte>)

Verifies a signature over the supplied data under a context string.

public bool VerifyData(ReadOnlySpan<byte> data, ReadOnlySpan<byte> signature, ReadOnlySpan<byte> context)

Parameters

data ReadOnlySpan<byte>

The message bytes that were signed. May be empty.

signature ReadOnlySpan<byte>

The candidate encoded signature.

context ReadOnlySpan<byte>

The domain-separation context string used at signing time. May be empty.

Returns

bool

true when the signature is valid; false for any invalid, malformed, or wrong-length signature.

Exceptions

ObjectDisposedException

The instance has been disposed.

ArgumentException

context is longer than 255 bytes.

CryptographicException

The instance does not hold a public key.

Applies to

ProductVersions
.NET8, 10