38 switch (Name.ToUpper())
50 throw new ArgumentException(
"Unknown model name: " + Name, nameof(Name));
58 private static readonly ushort[] nttTransformZeta =
60 1, 1729, 2580, 3289, 2642, 630, 1897, 848,
61 1062, 1919, 193, 797, 2786, 3260, 569, 1746,
62 296, 2447, 1339, 1476, 3046, 56, 2240, 1333,
63 1426, 2094, 535, 2882, 2393, 2879, 1974, 821,
64 289, 331, 3253, 1756, 1197, 2304, 2277, 2055,
65 650, 1977, 2513, 632, 2865, 33, 1320, 1915,
66 2319, 1435, 807, 452, 1438, 2868, 1534, 2402,
67 2647, 2617, 1481, 648, 2474, 3110, 1227, 910,
68 17, 2761, 583, 2649, 1637, 723, 2288, 1100,
69 1409, 2662, 3281, 233, 756, 2156, 3015, 3050,
70 1703, 1651, 2789, 1789, 1847, 952, 1461, 2687,
71 939, 2308, 2437, 2388, 733, 2337, 268, 641,
72 1584, 2298, 2037, 3220, 375, 2549, 2090, 1645,
73 1063, 319, 2773, 757, 2099, 561, 2466, 2594,
74 2804, 1092, 403, 1026, 1143, 2150, 2775, 886,
75 1722, 1212, 1874, 1029, 2110, 2935, 885, 2154
82 private static readonly ushort[] nttTransformZeta2 =
84 17, q - 17, 2761, q - 2761, 583, q - 583, 2649, q - 2649,
85 1637, q - 1637, 723, q - 723, 2288, q - 2288, 1100, q - 1100,
86 1409, q - 1409, 2662, q - 2662, 3281, q - 3281, 233, q - 233,
87 756, q - 756, 2156, q - 2156, 3015, q - 3015, 3050, q - 3050,
88 1703, q - 1703, 1651, q - 1651, 2789, q - 2789, 1789, q - 1789,
89 1847, q - 1847, 952, q - 952, 1461, q - 1461, 2687, q - 2687,
90 939, q - 939, 2308, q - 2308, 2437, q - 2437, 2388, q - 2388,
91 733, q - 733, 2337, q - 2337, 268, q - 268, 641, q - 641,
92 1584, q - 1584, 2298, q - 2298, 2037, q - 2037, 3220, q - 3220,
93 375, q - 375, 2549, q - 2549, 2090, q - 2090, 1645, q - 1645,
94 1063, q - 1063, 319, q - 319, 2773, q - 2773, 757, q - 757,
95 2099, q - 2099, 561, q - 561, 2466, q - 2466, 2594, q - 2594,
96 2804, q - 2804, 1092, q - 1092, 403, q - 403, 1026, q - 1026,
97 1143, q - 1143, 2150, q - 2150, 2775, q - 2775, 886, q - 886,
98 1722, q - 1722, 1212, q - 1212, 1874, q - 1874, 1029, q - 1029,
99 2110, q - 2110, 2935, q - 2935, 885, q - 885, 2154, q - 2154
102 private const int n = 256;
103 private const ushort q = 3329;
104 private const ushort half_q_rounded = (q + 1) >> 1;
106 private readonly
int k384;
107 private readonly
int cipherTextLength;
108 private readonly
byte k;
109 private readonly
int η1;
110 private readonly
int η2;
111 private readonly
int dᵤ;
112 private readonly
int dᵥ;
123 public ML_KEM(
byte k,
int η1,
int η2,
int dᵤ,
int dᵥ)
131 this.k384 = this.k * 384;
132 this.cipherTextLength = 32 * (this.dᵤ * this.k + this.dᵥ);
152 public static byte[]
PRF(
byte[] Seed,
byte Data,
int η)
156 byte[] Bin =
new byte[c + 1];
157 Buffer.BlockCopy(Seed, 0, Bin, 0, c);
169 public static byte[]
H(
byte[] Data)
179 public static byte[]
J(
byte[] Data)
189 public static byte[]
G(
byte[] Data)
200 public static byte[]
XOF(
byte[] Input,
int OutputLength)
215 throw new ArgumentOutOfRangeException(nameof(d),
"d must be between 1 and 12.");
234 throw new ArgumentOutOfRangeException(nameof(d),
"d must be between 1 and 12.");
236 int j, c = Value.Length;
241 for (j = 0; j < c; j++)
248 Value[j] = (ushort)i;
258 public static void Compress(ushort[][] Value,
int d)
260 int i, c = Value.Length;
262 for (i = 0; i < c; i++)
276 throw new ArgumentOutOfRangeException(nameof(d),
"d must be between 1 and 12.");
295 throw new ArgumentOutOfRangeException(nameof(d),
"d must be between 1 and 12.");
297 int j, c = Value.Length;
300 for (j = 0; j < c; j++)
307 Value[j] = (ushort)i;
321 int c = Values.Length;
323 int NrBytes = (NrBits + 7) >> 3;
324 byte[] Result =
new byte[NrBytes];
341 public static int ByteEncode(ushort[] Values,
int d,
byte[] Output,
int Index)
344 throw new ArgumentOutOfRangeException(nameof(d),
"d must be between 1 and 12.");
346 int i, c = Values.Length;
350 for (i = 0; i < c; i++)
352 ushort Value = Values[i];
355 Output[Index] |= (byte)(Value << BitOffset);
357 while (BitOffset >= 8)
363 Output[Index] = (byte)(Value >> (d - BitOffset));
367 return Index - Index0;
380 public static int ByteEncode(ushort[][] Values,
int d,
byte[] Output,
int Index)
383 int i, c = Values.Length;
385 for (i = 0; i < c; i++)
387 int NrBytes =
ByteEncode(Values[i], d, Output, Pos);
417 public static ushort[]
ByteDecode(
byte[] Data,
int Offset,
int Length,
int d)
420 throw new ArgumentOutOfRangeException(nameof(d),
"d must be between 1 and 12.");
422 int NrBits = Length << 3;
423 int NrIntegers = (NrBits + d - 1) / d;
424 ushort[] Result =
new ushort[NrIntegers];
432 byte b = Data[Offset++];
437 BitsToUse = d - BitOffset;
438 if (BitsToUse > BitsLeft)
439 BitsToUse = BitsLeft;
441 Result[Pos] |= (ushort)((b &
ushortBitMask[BitsToUse]) << BitOffset);
442 BitOffset += BitsToUse;
443 BitsLeft -= BitsToUse;
465 private static ushort[] SampleNTT(
byte[] Seed)
469 ushort[] Result =
new ushort[n];
475 ushort d1 = (ushort)(C[0] + ((C[1] & 15) << 8));
476 ushort d2 = (ushort)((C[1] >> 4) + (C[2] << 4));
481 if (d2 < q && Pos < n)
498 throw new ArgumentOutOfRangeException(nameof(η),
"η must be either 2 or 3.");
514 if (c != 128 && c != 192)
515 throw new ArgumentOutOfRangeException(nameof(Seed),
"Seed must be either 128 or 192 bytes.");
521 ushort[] Result =
new ushort[n];
523 for (i = 0; i < n; i++)
525 for (j = x = y = 0; j < η; j++)
528 dx = (Seed[k >> 3] & (1 << (k & 7))) != 0 ? (ushort)1 : (ushort)0;
532 dy = (Seed[k >> 3] & (1 << (k & 7))) != 0 ? (ushort)1 : (ushort)0;
537 Result[i] = (ushort)(q + x - y);
539 Result[i] = (ushort)(x - y);
550 public static void NTT(ushort[] f)
553 throw new ArgumentException(
"Polynomial must have " + n +
" coefficients.", nameof(f));
562 for (Len = n >> 1; Len >= 2; Len >>= 1)
564 for (Start = 0; Start < n; Start += Len << 1)
566 ζ = nttTransformZeta[i++];
568 for (j = Start; j < Start + Len; j++)
570 t = (ushort)(ζ * f[j + Len] % q);
571 f[j + Len] = (ushort)((f[j] + q - t) % q);
572 f[j] = (ushort)((f[j] + t) % q);
582 public static void NTT(ushort[][] f)
586 for (i = 0; i < c; i++)
598 throw new ArgumentException(
"Polynomial must have " + n +
" coefficients.", nameof(f));
609 for (Len = 2; Len <= 128; Len <<= 1)
613 for (Start = 0; Start < n; Start += Len2)
615 ζ = nttTransformZeta[i--];
617 StartLen = Start + Len;
618 for (j = Start; j < StartLen; j++)
621 f[j] = (ushort)((t + f[j + Len]) % q);
622 f[j + Len] = (ushort)(ζ * (f[j + Len] + q - t) % q);
627 for (i = 0; i < n; i++)
628 f[i] = (ushort)(3303 * f[i] % q);
639 for (i = 0; i < c; i++)
653 ushort[] Result =
new ushort[n];
669 if (f.Length != n || g.Length != n)
670 throw new ArgumentException(
"Polynomials must have " + n +
" coefficients.", nameof(f));
673 ushort a0, a1, b0, b1, γ;
675 for (i = 0; i < n; i += 2)
681 γ = nttTransformZeta2[i >> 1];
683 Result[i] = (ushort)((Result[i] + a0 * b0 + γ * a1 % q * b1) % q);
684 Result[i + 1] = (ushort)((Result[i + 1] + a0 * b1 + a1 * b0) % q);
693 public static void AddTo(ushort[] f, ushort[] g)
697 for (i = 0; i < n; i++)
698 f[i] = (ushort)((f[i] + g[i]) % q);
706 public static void AddTo(ushort[][] f, ushort[][] g)
710 throw new ArgumentException(
"Vectors must have the same number of polynomials.", nameof(g));
712 for (i = 0; i < c; i++)
724 for (i = 0; i < c; i++)
725 f[i] = (ushort)((q - f[i]) % q);
737 int i, c = v1.Length;
740 throw new ArgumentException(
"Vectors must have the same number of polynomials.", nameof(v2));
742 ushort[] Result =
new ushort[n];
744 for (i = 0; i < c; i++)
776 throw new ArgumentException(
"Seed must be 32 bytes long.", nameof(d));
778 byte[] Temp =
new byte[33];
779 Buffer.BlockCopy(d, 0, Temp, 0, 32);
781 byte[] Bin =
G(Temp);
784 byte[] ρ =
new byte[32];
785 Buffer.BlockCopy(Bin, 0, ρ, 0, 32);
787 byte[] σ =
new byte[32];
788 Buffer.BlockCopy(Bin, 32, σ, 0, 32);
793 ushort[,][] Â =
new ushort[this.k, this.k][];
794 ushort[][] s =
new ushort[this.k][];
795 ushort[][] e =
new ushort[this.k][];
797 byte[] B =
new byte[34];
798 Buffer.BlockCopy(ρ, 0, B, 0, 32);
800 for (i = 0; i < this.k; i++)
804 for (j = 0; j < this.k; j++)
807 Â[i, j] = SampleNTT(B);
813 for (i = 0; i < this.k; i++)
816 for (i = 0; i < this.k; i++)
822 ushort[][] t =
new ushort[this.k][];
825 for (i = 0; i < this.k; i++)
827 t[i] = f = (ushort[])e[i].Clone();
829 for (j = 0; j < this.k; j++)
833 byte[] EncryptionKey =
new byte[32 + this.k384];
834 byte[] DecryptionKey =
new byte[this.k384];
837 for (i = 0; i < this.k; i++)
844 Buffer.BlockCopy(ρ, 0, EncryptionKey, Pos, 32);
852 return new K_PKE_Keys(Â, EncryptionKey, DecryptionKey);
892 public byte[]
K_PKE_Encrypt(
byte[] EncryptionKey,
byte[] Message,
byte[] Seed)
908 throw new ArgumentNullException(nameof(Keys),
"Encryption key cannot be null.");
911 throw new ArgumentException(
"Encryption key must be 384k+32 bytes long.", nameof(Keys));
913 if (Message.Length != 32)
914 throw new ArgumentException(
"Message must be 32 bytes long.", nameof(Message));
916 ushort[][] t =
new ushort[this.k][];
917 byte[] ρ =
new byte[32];
923 for (i = Pos = 0; i < this.k; i++)
931 ushort[][] y =
new ushort[this.k][];
932 ushort[][] e1 =
new ushort[this.k][];
934 ushort[,][] Â = Keys.
Â;
938 Keys. =  =
new ushort[this.k, this.k][];
940 byte[] B =
new byte[34];
941 Buffer.BlockCopy(ρ, 0, B, 0, 32);
943 for (i = 0; i < this.k; i++)
947 for (j = 0; j < this.k; j++)
950 Â[i, j] = SampleNTT(B);
956 else if (Â.GetLength(0) !=
this.k || Â.GetLength(1) !=
this.k)
957 throw new ArgumentException(
"Matrix  must be " + this.k +
"x" + this.k +
".", nameof(Â));
959 for (i = 0; i < this.k; i++)
962 for (i = 0; i < this.k; i++)
969 ushort[][] u =
new ushort[this.k][];
972 for (i = 0; i < this.k; i++)
974 u[i] = f =
new ushort[n];
976 for (j = 0; j < this.k; j++)
987 ushort[] μ =
new ushort[n];
989 for (i = j = 0, k = 1; i < n; i++)
991 μ[i] = (Message[j] & k) != 0 ? half_q_rounded : (ushort)0;
1004 int dᵤk32 = this.dᵤ * this.k << 5;
1005 int dᵥ32 = this.dᵥ << 5;
1006 byte[] CipherText =
new byte[dᵤk32 + dᵥ32];
1026 if (DecryptionKey is
null)
1027 throw new ArgumentNullException(nameof(DecryptionKey),
"Decryption key cannot be null.");
1029 if (DecryptionKey.Length !=
this.k384)
1030 throw new ArgumentException(
"Decryption key must be 384k bytes long.", nameof(DecryptionKey));
1032 int dᵤ32 = this.dᵤ << 5;
1033 int dᵤk32 = dᵤ32 * this.k;
1034 int dᵥ32 = this.dᵥ << 5;
1036 if (CipherText.Length != dᵤk32 + dᵥ32)
1037 throw new ArgumentException(
"Message must be " + (dᵤk32 + dᵥ32) +
" bytes long.", nameof(CipherText));
1039 ushort[][] u =
new ushort[this.k][];
1044 for (i = Pos = 0; i < this.k; i++)
1046 u[i] =
ByteDecode(CipherText, Pos, dᵤ32, this.dᵤ);
1051 v =
ByteDecode(CipherText, Pos, dᵥ32, this.dᵥ);
1054 ushort[][] s =
new ushort[this.k][];
1056 for (i = Pos = 0; i < this.k; i++)
1058 s[i] =
ByteDecode(DecryptionKey, Pos, 384, 12);
1082 return this.
KeyGen(
false);
1132 throw new ArgumentException(
"Seed must be 32 bytes long.", nameof(z));
1135 byte[] DecryptionKey =
new byte[768 * this.k + 96];
1138 Buffer.BlockCopy(Keys.
DecryptionKey, 0, DecryptionKey, 0, Pos =
this.k384);
1139 Buffer.BlockCopy(Keys.
EncryptionKey, 0, DecryptionKey, Pos, Pos + 32);
1143 Buffer.BlockCopy(Bin, 0, DecryptionKey, Pos, 32);
1146 Buffer.BlockCopy(z, 0, DecryptionKey, Pos, 32);
1149 return new ML_KEM_Keys(Keys, DecryptionKey,
null);
1151 byte[] Seed =
new byte[64];
1153 Buffer.BlockCopy(d, 0, Seed, 0, 32);
1154 Buffer.BlockCopy(z, 0, Seed, 32, 32);
1156 return new ML_KEM_Keys(Keys, DecryptionKey, Seed);
1168 throw new ArgumentNullException(nameof(Seed));
1170 if (Seed.Length != 64)
1171 throw new ArgumentException(
"Seed must be 64 bytes long.", nameof(Seed));
1173 byte[] d =
new byte[32];
1174 byte[] z =
new byte[32];
1176 Buffer.BlockCopy(Seed, 0, d, 0, 32);
1177 Buffer.BlockCopy(Seed, 32, z, 0, 32);
1202 throw new ArgumentException(
"Encapsulation key length mismatch.", nameof(Keys));
1205 int i, c = x.Length;
1207 for (i = 0; i < c; i++)
1210 throw new ArgumentException(
"Invalid encapsulation key.", nameof(Keys));
1243 throw new ArgumentException(
"Encapsulation key length mismatch.", nameof(Keys));
1246 throw new ArgumentException(
"Message length mismatch.", nameof(m));
1248 byte[] Bin =
new byte[64];
1250 Buffer.BlockCopy(m, 0, Bin, 0, 32);
1253 byte[] Bin2 =
G(Bin);
1256 byte[] K =
new byte[32];
1257 Buffer.BlockCopy(Bin2, 0, K, 0, 32);
1259 byte[] r =
new byte[32];
1260 Buffer.BlockCopy(Bin2, 32, r, 0, 32);
1278 if (DecapsulationKey.Length != 768 *
this.k + 96)
1279 throw new ArgumentException(
"Decapsulation key length mismatch.", nameof(DecapsulationKey));
1281 byte[] Bin =
new byte[this.k384 + 32];
1282 Buffer.BlockCopy(DecapsulationKey, this.k384, Bin, 0, this.k384 + 32);
1284 byte[] Test =
H(Bin);
1287 for (
int i = 0, j = (this.k384 << 1) + 32; i < 32; i++, j++)
1289 if (Test[i] != DecapsulationKey[j])
1290 throw new ArgumentException(
"Invalid decapsulation key.", nameof(DecapsulationKey));
1310 if (DecapsulationKey.Length != 768 *
this.k + 96)
1311 throw new ArgumentException(
"Decapsulation key length mismatch.", nameof(DecapsulationKey));
1313 if (c.Length !=
this.cipherTextLength)
1314 throw new ArgumentException(
"Cipher text length mismatch.", nameof(c));
1317 byte[] DecryptionKey =
new byte[Pos = this.k384];
1318 Buffer.BlockCopy(DecapsulationKey, 0, DecryptionKey, 0, Pos);
1321 byte[] EncryptionKey =
new byte[Len = (768 - 384) * this.k + 32];
1322 Buffer.BlockCopy(DecapsulationKey, Pos, EncryptionKey, 0, Len);
1325 byte[] h =
new byte[32];
1326 Buffer.BlockCopy(DecapsulationKey, Pos, h, 0, 32);
1330 byte[] Bin =
new byte[64];
1331 Buffer.BlockCopy(m, 0, Bin, 0, 32);
1332 Buffer.BlockCopy(h, 0, Bin, 32, 32);
1334 byte[] Bin2 =
G(Bin);
1336 byte[] K =
new byte[32];
1337 Buffer.BlockCopy(Bin2, 0, K, 0, 32);
1339 byte[] r =
new byte[32];
1340 Buffer.BlockCopy(Bin2, 32, r, 0, 32);
1348 byte[] zc =
new byte[32 + c.Length];
1349 Buffer.BlockCopy(DecapsulationKey, Pos + 32, zc, 0, 32);
1350 Buffer.BlockCopy(c, 0, zc, 32, c.Length);
1360 for (
int i = 0; i < c.Length; i++)
1361 diff |= c[i] ^ c2[i];
1367 byte mask = (byte)((diff | -diff) >> 31);
1369 byte[] Result =
new byte[32];
1370 for (
int i = 0; i < 32; i++)
1371 Result[i] = (
byte)((K[i] & ~mask) | (K2[i] & mask));
K-PKE encryption and decryption keys, as defined in §5.1.
byte[] DecryptionKey
Encoded decryption key, as defined in §5.1.
byte[] EncryptionKey
Encoded encryption key, as defined in §5.1.
Methods common to ML algorithms.
static void Clear(byte[] Bin)
Clears a byte array.
static readonly ushort[] ushortBitMask
Bit masks corresponding to mod 2^d arithmetic, where d is the index of the mask in the array.
static byte[] CreateSeed()
Creates a random seed value.
ML_KEM encapsulation keys, as defined in §7.2.
ML_KEM encryption and decryption keys, as defined in §6.1.
byte[] EncapsulationKey
Encoded encapsulation key, as defined in §6.1.
static ML_KEM_Keys FromEncapsulationKey(byte[] EncapsulationKey)
Creates a key object instance from an encapsulation key.
ushort[,][] Â
Matrix of encryption keys, as defined in §5.1.
Implements the ML-KEM algorithm for post-quantum cryptography, as defined in NIST FIPS 203: https://n...
ML_KEM_Encapsulation Encapsulate(byte[] EncapsulationKey)
The method (Algorithm 17) accepts an encapsulation key and a random byte array as input and outputs a...
override int PublicKeyLength
Length of the public key.
byte[] K_PKE_Encrypt(byte[] EncryptionKey, byte[] Message)
Uses the encryption key to encrypt a plaintext message using the given randomness and algorithm 14 (K...
static ushort[] MultiplyNTTs(ushort[] f, ushort[] g)
Computes the product (in the ring 𝑇𝑞) of two NTT representations. (Algorithm 11 in §4....
static byte[] ByteEncode(ushort[] Values, int d)
Encodes an array of integers (mod 2^d) into a byte array, as defined by Algorithm 5 in §4....
static readonly ML_KEM ML_KEM_512
Model parameters for a required RBG strength 128 (cryptographic security strength),...
ML_KEM(byte k, int η1, int η2, int dᵤ, int dᵥ)
Implements the ML-KEM algorithm for post-quantum cryptography, as defined in NIST FIPS 203: https://n...
ML_KEM_Encapsulation Encapsulate_Internal(byte[] EncapsulationKey, byte[] m)
The method (Algorithm 17) accepts an encapsulation key and a random byte array as input and outputs a...
static void Compress(ushort[][] Value, int d)
Canonical extension of Compress function, as defined in §4.2.1.
static int ByteEncode(ushort[][] Values, int d, byte[] Output, int Index)
Encodes an array of vectors of integers (mod 2^d) into a byte array. Canonical extension of ByteEncod...
static ushort Decompress(ushort Value, int d)
Decompress function, as defined in §4.2.1.
int CipherTextLength
Expected cipher text length for the decapsulation method.
K_PKE_Keys K_PKE_KeyGen()
Uses randomness to generate an encryption key and a corresponding decryption key. (Algorithm 13 K-PKE...
static void InverseNTT(ushort[] f)
Computes the NTT^-1 representation f of the given polynomial f̂ ∈ 𝑇𝑞. (Algorithm 10 in §4....
static void MultiplyNTTsAndAdd(ushort[] f, ushort[] g, ushort[] Result)
Computes the product (in the ring 𝑇𝑞) of two NTT representations (Algorithm 11 in §4....
ML_KEM_Encapsulation Encapsulate(ML_KEM_Keys Keys)
The method (Algorithm 17) accepts an encapsulation key and a random byte array as input and outputs a...
static ushort Compress(ushort Value, int d)
Compress function, as defined in §4.2.1.
ML_KEM_Keys KeyGen_Internal(byte[] d, byte[] z, bool ReturnSeed)
Uses randomness to generate an encryption key and a corresponding decryption key. (Algorithm 16 ML-KE...
static ushort[] DotProductNTT(ushort[][] v1, ushort[][] v2)
Computes the dot product of two vectors of polynomials in 𝑇𝑞.
override int PrivateKeyLength
Length of the private key.
static int ByteEncode(ushort[] Values, int d, byte[] Output, int Index)
Encodes an array of integers (mod 2^d) into a byte array, as defined by Algorithm 5 in §4....
static ushort[] SamplePolyCBD(int η)
The algorithm SamplePolyCBD (Algorithm 8, §4.2.1) samples the coefficient array of a polynomial 𝑓 ∈ 𝑅...
byte[] K_PKE_Encrypt(byte[] EncryptionKey, byte[] Message, byte[] Seed)
Uses the encryption key to encrypt a plaintext message using the given randomness and algorithm 14 (K...
byte[] Decapsulate(byte[] DecapsulationKey, byte[] c)
Uses the decapsulation key to produce a shared secret key from a ciphertext. Algorithm 21 ML-KEM....
byte[] K_PKE_Encrypt(ML_KEM_Keys Keys, byte[] Message)
Uses the encryption key to encrypt a plaintext message using the given randomness and algorithm 14 (K...
static void InverseNTT(ushort[][] f)
Canonical extension of InverseNTT(ushort[]).
static readonly ML_KEM ML_KEM_768
Model parameters for a required RBG strength 192 (cryptographic security strength),...
ML_KEM_Keys KeyGen(bool ReturnSeed)
Generates an encapsulation key and a corresponding decapsulation key. (Algorithm 19 ML-KEM....
byte[] K_PKE_Decrypt(byte[] DecryptionKey, byte[] CipherText)
Uses the decryption key to decrypt a ciphertext message using algorithm 15 (K-PKE....
static void Decompress(ushort[] Value, int d)
Canonical extension of Decompress function, as defined in §4.2.1.
byte[] Decapsulate_Internal(byte[] DecapsulationKey, byte[] c)
The method (Algorithm 18) accepts a decapsulation key and a cipher text as input, does not use any ra...
static ushort[] ByteDecode(byte[] Data, int Offset, int Length, int d)
Decodes an array of integers (mod 2^d) from a byte array, as defined by Algorithm 6 in §4....
static byte[] XOF(byte[] Input, int OutputLength)
eXtendable-Output Function (XOF), as defined in §4.1.
ML_KEM_Encapsulation Encapsulate_Internal(ML_KEM_Keys Keys, byte[] m)
The method (Algorithm 17) accepts an encapsulation key and a random byte array as input and outputs a...
static byte[] G(byte[] Data)
Hash function G, as defined in §4.1.
static void NTT(ushort[] f)
Computes the NTT representation f̂ of the given polynomial f ∈ 𝑅𝑞. (Algorithm 9 in §4....
static byte[] J(byte[] Data)
Hash function J, as defined in §4.1.
static ML_KEM GetModel(string Name)
Gets a model by name, as defined in §8.
static byte[] PRF(byte[] Seed, byte Data, int η)
Pseudorandom function (PRF), as defined in §4.1.
byte[] K_PKE_Encrypt(ML_KEM_Keys Keys, byte[] Message, byte[] Seed)
Uses the encryption key to encrypt a plaintext message using the given randomness and algorithm 14 (K...
static byte[] H(byte[] Data)
Hash function H, as defined in §4.1.
static void AddTo(ushort[] f, ushort[] g)
Adds g to f .
K_PKE_Keys K_PKE_KeyGen(byte[] d)
Uses randomness to generate an encryption key and a corresponding decryption key. (Algorithm 13 K-PKE...
static void Compress(ushort[] Value, int d)
Canonical extension of Compress function, as defined in §4.2.1.
static void NTT(ushort[][] f)
Canonical extension of NTT(ushort[]).
static void Negate(ushort[] f)
Negates a polynomial in 𝑅𝑞.
ML_KEM_Keys KeyGen_Internal(byte[] d, byte[] z)
Uses randomness to generate an encryption key and a corresponding decryption key. (Algorithm 16 ML-KE...
ML_KEM_Keys KeyGen_FromSeed(byte[] Seed, bool ReturnSeed)
Creates a key object instance from a seed.
static ushort[] ByteDecode(byte[] Data, int d)
Decodes an array of integers (mod 2^d) from a byte array, as defined by Algorithm 6 in §4....
static readonly ML_KEM ML_KEM_1024
Model parameters for a required RBG strength 256 (cryptographic security strength),...
static ushort[] SamplePolyCBD(byte[] Seed)
The algorithm SamplePolyCBD (Algorithm 8, §4.2.1) samples the coefficient array of a polynomial 𝑓 ∈ 𝑅...
ML_KEM_Keys KeyGen()
Generates an encapsulation key and a corresponding decapsulation key. (Algorithm 19 ML-KEM....
static void AddTo(ushort[][] f, ushort[][] g)
Adds vector g to vector f .
Hash digest computation context.
byte[] Squeeze(int NrBytes)
Calculates another NrBytes number of bytes of the digest.
byte[] ComputeVariable(byte[] N)
Computes the SPONGE function, as defined in section 4 of NIST FIPS 202.
Implements the SHA3-256 hash function, as defined in section 6.1 in the NIST FIPS 202: https://nvlpub...
Implements the SHA3-512 hash function, as defined in section 6.1 in the NIST FIPS 202: https://nvlpub...
Implements the SHA3 SHAKE128 extendable-output functions, as defined in section 6....
Implements the SHA3 SHAKE256 extendable-output functions, as defined in section 6....
HashFunction
Hash method enumeration.