File: src\libraries\Common\src\System\Security\Cryptography\MLKemAlgorithm.cs
Web Access
Project: src\src\libraries\System.Security.Cryptography\src\System.Security.Cryptography.csproj (System.Security.Cryptography)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
 
namespace System.Security.Cryptography
{
    /// <summary>
    ///   Represents a specific algorithm within the ML-KEM family.
    /// </summary>
    /// <seealso cref="MLKem" />
    [DebuggerDisplay("{Name,nq}")]
    [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
    public sealed class MLKemAlgorithm : IEquatable<MLKemAlgorithm>
    {
        private MLKemAlgorithm(
            string name,
            int encapsulationKeySizeInBytes,
            int decapsulationKeySizeInBytes,
            int ciphertextSizeInBytes,
            string oid)
        {
            Name = name;
            EncapsulationKeySizeInBytes = encapsulationKeySizeInBytes;
            DecapsulationKeySizeInBytes = decapsulationKeySizeInBytes;
            CiphertextSizeInBytes = ciphertextSizeInBytes;
            Oid = oid;
        }
 
        // Values are from NIST FIPS-203 table 3.
 
        /// <summary>
        ///   Gets an ML-KEM algorithm identifier for the ML-KEM-512 algorithm.
        /// </summary>
        /// <value>
        ///   An ML-KEM algorithm identifier for the ML-KEM-512 algorithm.
        /// </value>
        public static MLKemAlgorithm MLKem512 { get; } = new("ML-KEM-512", 800, 1632, 768, Oids.MlKem512);
 
        /// <summary>
        ///   Gets an ML-KEM algorithm identifier for the ML-KEM-768 algorithm.
        /// </summary>
        /// <value>
        ///   An ML-KEM algorithm identifier for the ML-KEM-768 algorithm.
        /// </value>
        public static MLKemAlgorithm MLKem768 { get; } = new("ML-KEM-768", 1184, 2400, 1088, Oids.MlKem768);
 
        /// <summary>
        ///   Gets an ML-KEM algorithm identifier for the ML-KEM-1024 algorithm.
        /// </summary>
        /// <value>
        ///   An ML-KEM algorithm identifier for the ML-KEM-1024 algorithm.
        /// </value>
        public static MLKemAlgorithm MLKem1024 { get; } = new("ML-KEM-1024", 1568, 3168, 1568, Oids.MlKem1024);
 
        /// <summary>
        ///   Gets the name of the algorithm.
        /// </summary>
        /// <value>
        ///   An a string representing the algorithm name.
        /// </value>
        public string Name { get; }
 
        /// <summary>
        ///   Gets the size of the encapsulation key for the algorithm, in bytes.
        /// </summary>
        /// <value>
        ///   The size of the encapsulation key for the algorithm, in bytes.
        /// </value>
        public int EncapsulationKeySizeInBytes { get; }
 
        /// <summary>
        ///   Gets the size of the decapsulation key for the algorithm, in bytes.
        /// </summary>
        /// <value>
        ///   The size of the decapsulation key for the algorithm, in bytes.
        /// </value>
        public int DecapsulationKeySizeInBytes { get; }
 
        /// <summary>
        ///   Gets the size of the ciphertext for the algorithm, in bytes.
        /// </summary>
        /// <value>
        ///   The size of the ciphertext for the algorithm, in bytes.
        /// </value>
        public int CiphertextSizeInBytes { get; }
 
        /// <summary>
        ///   Gets the size of the shared secret for the algorithm, in bytes.
        /// </summary>
        /// <value>
        ///   The size of the shared secret for the algorithm, in bytes.
        /// </value>
        // Right now every shared secret for ML-KEM is 32 bytes. If or when a different shared secret
        // size is needed, then it can be provided as input to the private constructor.
        public int SharedSecretSizeInBytes { get; } = 32;
 
        /// <summary>
        ///   Gets the size of the private seed for the algorithm, in bytes.
        /// </summary>
        /// <value>
        ///   The size of the private seed for the algorithm, in bytes.
        /// </value>
        // Right now every seed for ML-KEM is 64 bytes. If or when a different seed
        // size is needed, then it can be provided as input to the private constructor.
        public int PrivateSeedSizeInBytes { get; } = 64;
 
        internal string Oid { get; }
 
        /// <summary>
        ///   Compares two <see cref="MLKemAlgorithm" /> objects.
        /// </summary>
        /// <param name="other">
        ///   An object to be compared to the current <see cref="MLKemAlgorithm"/> object.
        /// </param>
        /// <returns>
        ///   <see langword="true" /> if the objects are considered equal; otherwise, <see langword="false" />.
        /// </returns>
        // This is a closed type, so all we need to compare are the names.
        public bool Equals([NotNullWhen(true)] MLKemAlgorithm? other) => other is not null && other.Name == Name;
 
        /// <inheritdoc />
        public override bool Equals([NotNullWhen(true)] object? obj) => obj is MLKemAlgorithm alg && alg.Name == Name;
 
        /// <inheritdoc />
        public override int GetHashCode() => Name.GetHashCode();
 
        /// <inheritdoc />
        public override string ToString() => Name;
 
        /// <summary>
        ///   Determines whether two <see cref="MLKemAlgorithm" /> objects specify the same algorithm name.
        /// </summary>
        /// <param name="left">
        ///   An object that specifies an algorithm name.
        /// </param>
        /// <param name="right">
        ///   A second object, to be compared to the object that is identified by the <paramref name="left" /> parameter.
        /// </param>
        /// <returns>
        ///   <see langword="true" /> if the objects are considered equal; otherwise, <see langword="false" />.
        /// </returns>
        public static bool operator ==(MLKemAlgorithm? left, MLKemAlgorithm? right)
        {
            return left is null ? right is null : left.Equals(right);
        }
 
        /// <summary>
        ///   Determines whether two <see cref="MLKemAlgorithm" /> objects do not specify the same algorithm name.
        /// </summary>
        /// <param name="left">
        ///   An object that specifies an algorithm name.
        /// </param>
        /// <param name="right">
        ///   A second object, to be compared to the object that is identified by the <paramref name="left" /> parameter.
        /// </param>
        /// <returns>
        ///   <see langword="true" /> if the objects are not considered equal; otherwise, <see langword="false" />.
        /// </returns>
        public static bool operator !=(MLKemAlgorithm? left, MLKemAlgorithm? right)
        {
            return !(left == right);
        }
 
        internal static MLKemAlgorithm? FromOid(string? oid)
        {
            return oid switch
            {
                Oids.MlKem512 => MLKem512,
                Oids.MlKem768 => MLKem768,
                Oids.MlKem1024 => MLKem1024,
                _ => null,
            };
        }
    }
}