Skip to content

[API Proposal]: MLKem #114453

Closed
Closed
@vcsjones

Description

@vcsjones

Background and motivation

This is the proposed API that resulted from the MLKem work in #113508.

API Proposal

namespace System.Security.Cryptogrpahy
{
    // Present in both System.Security.Cryptography and Microsoft.Bcl.Cryptography
    [ExperimentalAttribute("SYSLIB5006")]
    public abstract partial class MLKem : IDisposable
    {
        protected MLKem(MLKemAlgorithm algorithm);

        public static bool IsSupported { get; }

        public MLKemAlgorithm Algorithm { get; }

        public byte[] Decapsulate(byte[] ciphertext);
        public void Decapsulate(ReadOnlySpan<byte> ciphertext, Span<byte> sharedSecret);
        public void Decapsulate(ReadOnlySpan<byte> ciphertext, Span<byte> sharedSecret, out int sharedSecretBytesWritten);
        protected abstract void DecapsulateCore(ReadOnlySpan<byte> ciphertext, Span<byte> sharedSecret);

        public byte[] Encapsulate(out byte[] sharedSecret);
        public byte[] Encapsulate(Span<byte> sharedSecret);
        public void Encapsulate(Span<byte> ciphertext, Span<byte> sharedSecret);
        public void Encapsulate(
            Span<byte> ciphertext,
            Span<byte> sharedSecret,
            out int ciphertextBytesWritten,
            out int sharedSecretBytesWritten);
        protected abstract void EncapsulateCore(Span<byte> ciphertext, Span<byte> sharedSecret);

        public byte[] ExportDecapsulationKey();
        public void ExportDecapsulationKey(Span<byte> destination);
        protected abstract void ExportDecapsulationKeyCore(Span<byte> destination);

        public byte[] ExportEncapsulationKey();
        public void ExportEncapsulationKey(Span<byte> destination);
        protected abstract void ExportEncapsulationKeyCore(Span<byte> destination);

        public byte[] ExportPrivateSeed();
        public void ExportPrivateSeed(Span<byte> destination);
        protected abstract void ExportPrivateSeedCore(Span<byte> destination);

        public static MLKem GenerateKey(MLKemAlgorithm algorithm);

        public static MLKem ImportDecapsulationKey(MLKemAlgorithm algorithm, byte[] source);
        public static MLKem ImportDecapsulationKey(MLKemAlgorithm algorithm, ReadOnlySpan<byte> source);
        public static MLKem ImportEncapsulationKey(MLKemAlgorithm algorithm, byte[] source);
        public static MLKem ImportEncapsulationKey(MLKemAlgorithm algorithm, ReadOnlySpan<byte> source);

        public static MLKem ImportPrivateSeed(MLKemAlgorithm algorithm, byte[] source);
        public static MLKem ImportPrivateSeed(MLKemAlgorithm algorithm, ReadOnlySpan<byte> source);

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

#region SPKI / PKCS8

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

        public byte[] ExportEncryptedPkcs8PrivateKey(ReadOnlySpan<byte> passwordBytes, PbeParameters pbeParameters);
        public byte[] ExportEncryptedPkcs8PrivateKey(ReadOnlySpan<char> password, PbeParameters pbeParameters);
        public byte[] ExportEncryptedPkcs8PrivateKey(string password, PbeParameters pbeParameters);
        public string ExportEncryptedPkcs8PrivateKeyPem(ReadOnlySpan<byte> passwordBytes, PbeParameters pbeParameters);
        public string ExportEncryptedPkcs8PrivateKeyPem(ReadOnlySpan<char> password, PbeParameters pbeParameters);
        public string ExportEncryptedPkcs8PrivateKeyPem(string password, PbeParameters pbeParameters);

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

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

        public static MLKem ImportEncryptedPkcs8PrivateKey(ReadOnlySpan<byte> passwordBytes, ReadOnlySpan<byte> source);
        public static MLKem ImportEncryptedPkcs8PrivateKey(ReadOnlySpan<char> password, ReadOnlySpan<byte> source);
        public static MLKem ImportEncryptedPkcs8PrivateKey(string password, ReadOnlySpan<byte> source);

        public static MLKem ImportFromEncryptedPem(ReadOnlySpan<char> source, ReadOnlySpan<byte> passwordBytes);
        public static MLKem ImportFromEncryptedPem(ReadOnlySpan<char> source, ReadOnlySpan<char> password);
        public static MLKem ImportFromEncryptedPem(string source, byte[] passwordBytes);
        public static MLKem ImportFromEncryptedPem(string source, string password);

        public static MLKem ImportFromPem(ReadOnlySpan<char> source);
        public static MLKem ImportFromPem(string source);

        public static MLKem ImportPkcs8PrivateKey(byte[] source);
        public static MLKem ImportPkcs8PrivateKey(ReadOnlySpan<byte> source);

        public static MLKem ImportSubjectPublicKeyInfo(byte[] source);
        public static MLKem ImportSubjectPublicKeyInfo(ReadOnlySpan<byte> source);
#endregion
    }

    // Present in both System.Security.Cryptography and Microsoft.Bcl.Cryptography
    [ExperimentalAttribute("SYSLIB5006")]
    public sealed partial class MLKemAlgorithm : IEquatable<MLKemAlgorithm>
    {
        internal MLKemAlgorithm();

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

        public string Name { get; }

        public int CiphertextSizeInBytes { get; }
        public int DecapsulationKeySizeInBytes { get; }
        public int EncapsulationKeySizeInBytes { get; }
        public int PrivateSeedSizeInBytes { get; }
        public int SharedSecretSizeInBytes { get; }

        public bool Equals(MLKemAlgorithm? other);

        public static bool operator ==(MLKemAlgorithm? left, MLKemAlgorithm? right);
        public static bool operator !=(MLKemAlgorithm? left, MLKemAlgorithm? right);
    }

    // Present in System.Security.Cryptography only
    [ExperimentalAttribute("SYSLIB5006")]
    public sealed partial class MLKemOpenSsl : MLKem
    {
        [UnsupportedOSPlatform("android")]
        [UnsupportedOSPlatform("browser")]
        [UnsupportedOSPlatform("ios")]
        [UnsupportedOSPlatform("osx")]
        [UnsupportedOSPlatform("tvos")]
        [UnsupportedOSPlatform("windows")]
        public MLKemOpenSsl(SafeEvpPKeyHandle pkeyHandle);

        public SafeEvpPKeyHandle DuplicateKeyHandle();
    }
}

namespace System.Security.Cryptography.X509Certificates
{
    // Existing class
    // Present in System.Security.Cryptography only
    public sealed partial class PublicKey
    {
        [Experimental("SYSLIB5006")]
        public PublicKey(MLKem key);

        [Experimental("SYSLIB5006")]
        [UnsupportedOSPlatform("browser")]
        public MLKem? GetMLKemPublicKey();
    }

    // Existing class
    // Present in System.Security.Cryptography only
    public partial class X509Certificate2
    {
        [ExperimentalAttribute("SYSLIB5006")]
        public MLKem GetMLKemPublicKey();

        [ExperimentalAttribute("SYSLIB5006")]
        public MLKem GetMLKemPrivateKey();

        [ExperimentalAttribute("SYSLIB5006")]
        public X509Certificate2 CopyWithPrivateKey(MLKem privateKey);
    }

    // New class (will also be used for future algorithms)
    // Present in Microsoft.Bcl.Cryptography only
    public static class X509CertificateKeyAccessors
    {
        [ExperimentalAttribute("SYSLIB5006")]
        public static MLKem GetMLKemPublicKey(this X509Certificate2 certificate);

        [ExperimentalAttribute("SYSLIB5006")]
        public static MLKem GetMLKemPrivateKey(this X509Certificate2 certificate);

        [ExperimentalAttribute("SYSLIB5006")]
        public static X509Certificate2 CopyWithPrivateKey(this X509Certificate2 certificate, MLKem key);
    }
}

API Usage

See https://github.com/vcsjones/ml-kem-demo/blob/main/Program.cs for an example of the end-to-end scenarios for MLKem.

Alternative Designs

No response

Risks

No response

Metadata

Metadata

Labels

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions