Skip to content

Add ML-KEM #113508

Open
0 of 2 issues completed
Open
Add ML-KEM#113508
Feature
0 of 2 issues completed
@bartonjs

Description

@bartonjs

As part of the Post-Quantum Cryptography effort, we should add support for Module-Lattice-Based Key Encapsulation Mechanism (ML-KEM).

There is no precedent for Key Encapsulation Mechanism (KEM) algorithms in .NET. Seemingly it makes sense to incorporate in areas where an RSA Encryption Scheme (RSAES) is utilized. This is currently only the case for EnvelopedCms, but KEM support for CMS EnvelopedData is new and not widely supported, so it is not being proposed as active work at this time.

Based on Elliptic-Curve Digital Signature Algorithm's name of "EC-DSA" becoming ECDsa, the class name for ML-KEM is proposed as MLKem.

namespace System.Security.Cryptography
{
    [Experimental("SYSLIB5006")]
    public abstract class MLKem : IDisposable
    {
        public static bool IsSupported { get; }

        protected MLKem(MLKemAlgorithm algorithm);

        public MLKemAlgorithm Algorithm { get; }
        public void Dispose();

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

        public byte[] ExportSubjectPublicKeyInfo();
        public bool TryExportSubjectPublicKeyInfo(Span<byte> destination, out int bytesWritten);
        public string ExportSubjectPublicKeyInfoPem();

        public byte[] ExportPkcs8PrivateKey();
        public bool TryExportPkcs8PrivateKey(Span<byte> destination, out int bytesWritten);
        public string ExportPkcs8PrivateKeyPem();

        public byte[] ExportEncryptedPkcs8PrivateKey(
            ReadOnlySpan<char> password,
            PbeParameters pbeParameters);
        public byte[] ExportEncryptedPkcs8PrivateKey(
            ReadOnlySpan<byte> passwordBytes,
            PbeParameters pbeParameters);
        public bool TryExportEncryptedPkcs8PrivateKey(
            ReadOnlySpan<char> password,
            PbeParameters pbeParameters,
            Span<byte> destination,
            out int bytesWritten);
        public bool TryExportEncryptedPkcs8PrivateKey(
            ReadOnlySpan<byte> passwordBytes,
            PbeParameters pbeParameters,
            Span<byte> destination,
            out int bytesWritten);
        public string ExportEncryptedPkcs8PrivateKeyPem(
            ReadOnlySpan<char> password,
            PbeParameters pbeParameters);
        public string ExportEncryptedPkcs8PrivateKeyPem(
            ReadOnlySpan<byte> passwordBytes,
            PbeParameters pbeParameters);

        public int ExportMLKemEncapsulationKey(Span<byte> destination);
        public int ExportMLKemDecapsulationKey(Span<byte> destination);
        public int ExportMLKemPrivateSeed(Span<byte> destination);

        public static MLKem GenerateMLKem512Key();
        public static MLKem GenerateMLKem768Key();
        public static MLKem GenerateMLKem1024Key();

        public static MLKem ImportSubjectPublicKeyInfo(ReadOnlySpan<byte> source);
        public static MLKem ImportPkcs8PrivateKey(ReadOnlySpan<byte> source);
        public static MLKem ImportEncryptedPkcs8PrivateKey(ReadOnlySpan<byte> passwordBytes, ReadOnlySpan<byte> source);
        public static MLKem ImportEncryptedPkcs8PrivateKey(ReadOnlySpan<char> password, ReadOnlySpan<byte> source);
        public static MLKem ImportFromPem(ReadOnlySpan<char> source);
        public static MLKem ImportFromEncryptedPem(ReadOnlySpan<char> source, ReadOnlySpan<char> password);
        public static MLKem ImportFromEncryptedPem(ReadOnlySpan<char> source, ReadOnlySpan<byte> passwordBytes);
        public static MLDsa ImportMLKemEncapsulationKey(MLKemAlgorithm algorithm, ReadOnlySpan<byte> source);
        public static MLDsa ImportMLKemDecapsulationKey(MLKemAlgorithm algorithm, ReadOnlySpan<byte> source);
        public static MLDsa ImportMLKemPrivateSeed(MLKemAlgorithm algorithm, ReadOnlySpan<byte> source);

        protected void ThrowIfDisposed();
        protected virtual void Dispose(bool disposing);

        protected abstract void EncapsulateCore(Span<byte> ciphertext, Span<byte> sharedSecret);
        protected abstract void DecapsulateCore(ReadOnlySpan<byte> ciphertext, Span<byte> sharedSecret);

        protected abstract void ExportMLKemEncapsulationKey(Span<byte> destination);
        protected abstract void ExportMLKemDecapsulationKey(Span<byte> destination);
        protected abstract void ExportMLKemPrivateSeed(Span<byte> destination);
    }

    [DebuggerDisplay("{Name,nq}")]
    [Experimental("SYSLIB5006")]
    public sealed class MLKemAlgorithm
    {
        private MLKemAlgorithm();

        public static MLKemAlgorithm MLKem512 { get; }
        public static MLKemAlgorithm MLKem768 { get; }
        public static MLKemAlgorithm MLKem1024 { get; }

        public string Name { get; }
        public int EncapsulationKeySizeInBytes { get; }
        public int DecapsulationKeySizeInBytes { get; }
    }

    [Experimental("SYSLIB5006")]
    public class MLKemCng : MLKem
    {
         public MLKemCng(CngKey key);
         // On ECDsaCng this is an allocating property. Changed to a method here.
         public CngKey GetCngKey();
    }

    [Experimental("SYSLIB5006")]
    public class MLKemOpenSsl : MLKem
    {
         public MLKemOpenSsl(SafeEvpPKeyHandle keyHandle);
         public SafeEvpPKeyHandle DuplicateKeyHandle();
    }
}

namespace System.Security.Cryptography.X509Certificates
{
    // Extension class to enable porting to Microsoft.Bcl.Cryptography
    [Experimental("SYSLIB5006")]
    public sealed class MLKemCertificateExtensions
    {
        public static MLKem GetMLKemPublicKey(this X509Certificate2 certificate);
        public static MLKem GetMLKemPrivateKey(this X509Certificate2 certificate);
    }
}

Sub-issues

Metadata

Metadata

Assignees

Labels

area-System.Securitycryptographic-docs-impactIssues impacting cryptographic docs. Cleared and reused after documentation is updated each release.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions