Skip to content

[API Proposal]: MLKem #114453

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions