Closed
Description
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