diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-09-28 15:54:37 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-09-28 15:54:37 +0700 |
commit | 2c0198457d4e32f2cb967b44f3caeb17c838069b (patch) | |
tree | 31b46480de94b562d440f0771304215aca834668 | |
parent | Add LE_To_UInt24, refactor (diff) | |
download | BouncyCastle.NET-ed25519-2c0198457d4e32f2cb967b44f3caeb17c838069b.tar.xz |
Kyber refactoring
17 files changed, 452 insertions, 578 deletions
diff --git a/crypto/src/pqc/crypto/crystals/kyber/CBD.cs b/crypto/src/pqc/crypto/crystals/kyber/CBD.cs index 843b0d8f6..be0ed7296 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/CBD.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/CBD.cs @@ -1,76 +1,52 @@ - -using System; +using System; + +using Org.BouncyCastle.Crypto.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { - internal static class CBD + internal static class Cbd { - public static void Eta(Poly r, byte[] bytes, int eta) + internal static void Eta(Poly r, byte[] bytes, int eta) { - int i, j; - uint t, d; - short a, b; - switch (eta) { - case 2: - for (i = 0; i < KyberEngine.N / 8; i++) + case 2: + { + for (int i = 0; i < KyberEngine.N / 8; i++) + { + uint t = Pack.LE_To_UInt32(bytes, 4 * i); + uint d = t & 0x55555555; + d += (t >> 1) & 0x55555555; + for (int j = 0; j < 8; j++) { - t = LittleEndianToUInt32(bytes, 4 * i); - d = t & 0x55555555; - d += (t >> 1) & 0x55555555; - for (j = 0; j < 8; j++) - { - a = (short)((d >> (4 * j + 0)) & 0x3); - b = (short)((d >> (4 * j + eta)) & 0x3); - r.Coeffs[8 * i + j] = (short) (a - b); - } + short a = (short)((d >> (4 * j + 0)) & 0x3); + short b = (short)((d >> (4 * j + eta)) & 0x3); + r.Coeffs[8 * i + j] = (short) (a - b); } - break; - case 3: - for (i = 0; i < KyberEngine.N / 4; i++) + } + break; + } + case 3: + { + for (int i = 0; i < KyberEngine.N / 4; i++) + { + uint t = Pack.LE_To_UInt24(bytes, 3 * i); + uint d = t & 0x00249249; + d += (t >> 1) & 0x00249249; + d += (t >> 2) & 0x00249249; + + for (int j = 0; j < 4; j++) { - t = LittleEndianToUInt24(bytes, 3 * i); - d = t & 0x00249249; - d += (t >> 1) & 0x00249249; - d += (t >> 2) & 0x00249249; - - for (j = 0; j < 4; j++) - { - a = (short)((d >> (6 * j + 0)) & 0x7); - b = (short)((d >> (6 * j + 3)) & 0x7); - r.Coeffs[4 * i + j] = (short)(a - b); - } + short a = (short)((d >> (6 * j + 0)) & 0x7); + short b = (short)((d >> (6 * j + 3)) & 0x7); + r.Coeffs[4 * i + j] = (short)(a - b); } - break; - default: - throw new ArgumentException("Wrong Eta"); + } + break; + } + default: + throw new ArgumentException("Wrong Eta"); } } - - private static uint LittleEndianToUInt24(byte[] x, int offset) - { - // Refer to convertByteTo32-BitUnsignedInt for explanation - uint r = (uint) (x[offset] & 0xFF); - r = r | ((uint)(x[offset + 1] & 0xFF) << 8); - r = r | ((uint)(x[offset + 2] & 0xFF) << 16); - return r; - } - - private static uint LittleEndianToUInt32(byte[] x, int offset) - { - // Convert first byte to an unsigned integer - // byte x & 0xFF allows us to grab the last 8 bits - uint r = (uint)(x[offset] & 0xFF); - - // Perform the same operation then left bit shift to store the next 8 bits without - // altering the previous bits - r = r | ((uint)(x[offset + 1] & 0xFF) << 8); - r = r | ((uint)(x[offset + 2] & 0xFF) << 16); - r = r | ((uint)(x[offset + 3] & 0xFF) << 24); - return r; - } - - } } diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberEngine.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberEngine.cs index 0cbd56e7f..556803e57 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberEngine.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberEngine.cs @@ -1,4 +1,5 @@ using System; + using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; @@ -7,9 +8,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { internal class KyberEngine { - private SecureRandom _random; - private KyberIndCpa IndCpa; - private byte[] Seed; + private SecureRandom m_random; + private KyberIndCpa m_indCpa; // Constant Parameters public const int N = 256; @@ -45,28 +45,28 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber public int CryptoPublicKeyBytes { get; private set; } public int CryptoCipherTextBytes { get; private set; } - public KyberEngine(int k) + internal KyberEngine(int k) { K = k; switch (k) { - case 2: - Eta1 = 3; - PolyCompressedBytes = 128; - PolyVecCompressedBytes = K * 320; - break; - case 3: - Eta1 = 2; - PolyCompressedBytes = 128; - PolyVecCompressedBytes = K * 320; - break; - case 4: - Eta1 = 2; - PolyCompressedBytes = 160; - PolyVecCompressedBytes = K * 352; - break; - default: - break; + case 2: + Eta1 = 3; + PolyCompressedBytes = 128; + PolyVecCompressedBytes = K * 320; + break; + case 3: + Eta1 = 2; + PolyCompressedBytes = 128; + PolyVecCompressedBytes = K * 320; + break; + case 4: + Eta1 = 2; + PolyCompressedBytes = 160; + PolyVecCompressedBytes = K * 352; + break; + default: + break; } PolyVecBytes = k * PolyBytes; @@ -83,38 +83,37 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber CryptoPublicKeyBytes = PublicKeyBytes; CryptoCipherTextBytes = CipherTextBytes; - IndCpa = new KyberIndCpa(this); + m_indCpa = new KyberIndCpa(this); } - public void Init(SecureRandom random) + internal void Init(SecureRandom random) { - this._random = random; + m_random = random; } - public void UpdateSeed(byte[] seed) + internal void UpdateSeed(byte[] seed) { - this.Seed = seed; - _random.SetSeed(seed); + m_random.SetSeed(seed); } - - public void GenerateKemKeyPair(byte[] pk, byte[] sk) + + internal void GenerateKemKeyPair(byte[] pk, byte[] sk) { Sha3Digest Sha3Digest256 = new Sha3Digest(256); - IndCpa.GenerateKeyPair(pk, sk); + m_indCpa.GenerateKeyPair(pk, sk); Array.Copy(pk, 0, sk, IndCpaSecretKeyBytes, IndCpaPublicKeyBytes); Sha3Digest256.BlockUpdate(pk, 0, PublicKeyBytes); Sha3Digest256.DoFinal(sk, SecretKeyBytes - 2 * SymBytes); - _random.NextBytes(sk, SecretKeyBytes - SymBytes, SymBytes); + m_random.NextBytes(sk, SecretKeyBytes - SymBytes, SymBytes); } - public void KemEncrypt(byte[] cipherText, byte[] sharedSecret, byte[] pk) + internal void KemEncrypt(byte[] cipherText, byte[] sharedSecret, byte[] pk) { byte[] buf = new byte[2 * SymBytes]; byte[] kr = new byte[2 * SymBytes]; Sha3Digest Sha3Digest256 = new Sha3Digest(256); - _random.NextBytes(buf, 0, SymBytes); + m_random.NextBytes(buf, 0, SymBytes); Sha3Digest256.BlockUpdate(buf, 0, SymBytes); Sha3Digest256.DoFinal(buf, 0); @@ -126,7 +125,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber Sha3Digest512.BlockUpdate(buf, 0, 2 * SymBytes); Sha3Digest512.DoFinal(kr, 0); - IndCpa.Encrypt(cipherText, Arrays.CopyOfRange(buf, 0, SymBytes), pk, Arrays.CopyOfRange(kr, SymBytes, 2 * SymBytes)); + m_indCpa.Encrypt(cipherText, Arrays.CopyOfRange(buf, 0, SymBytes), pk, Arrays.CopyOfRange(kr, SymBytes, 2 * SymBytes)); Sha3Digest256.BlockUpdate(cipherText, 0, CipherTextBytes); Sha3Digest256.DoFinal(kr, SymBytes); @@ -136,39 +135,39 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber ShakeDigest128.DoFinal(sharedSecret, 0, SymBytes); } - public void KemDecrypt(byte[] SharedSecret, byte[] CipherText, byte[] SecretKey) + internal void KemDecrypt(byte[] sharedSecret, byte[] cipherText, byte[] secretKey) { - int i; - bool fail; - byte[] buf = new byte[2 * SymBytes], - kr = new byte[2 * SymBytes], - cmp = new byte[CipherTextBytes]; - byte[] pk = Arrays.CopyOfRange(SecretKey, IndCpaSecretKeyBytes, SecretKey.Length); - IndCpa.Decrypt(buf, CipherText, SecretKey); - Array.Copy(SecretKey, SecretKeyBytes - 2 * SymBytes, buf, SymBytes, SymBytes); + byte[] buf = new byte[2 * SymBytes], kr = new byte[2 * SymBytes], cmp = new byte[CipherTextBytes]; + byte[] pk = Arrays.CopyOfRange(secretKey, IndCpaSecretKeyBytes, secretKey.Length); + m_indCpa.Decrypt(buf, cipherText, secretKey); + Array.Copy(secretKey, SecretKeyBytes - 2 * SymBytes, buf, SymBytes, SymBytes); Sha3Digest Sha3Digest512 = new Sha3Digest(512); Sha3Digest512.BlockUpdate(buf, 0, 2 * SymBytes); Sha3Digest512.DoFinal(kr, 0); - IndCpa.Encrypt(cmp, Arrays.CopyOf(buf, SymBytes), pk, Arrays.CopyOfRange(kr, SymBytes, kr.Length)); + m_indCpa.Encrypt(cmp, Arrays.CopyOf(buf, SymBytes), pk, Arrays.CopyOfRange(kr, SymBytes, kr.Length)); - fail = !(Arrays.AreEqual(CipherText, cmp)); + bool fail = !Arrays.ConstantTimeAreEqual(cipherText, cmp); Sha3Digest Sha3Digest256 = new Sha3Digest(256); - Sha3Digest256.BlockUpdate(CipherText, 0, CipherTextBytes); + Sha3Digest256.BlockUpdate(cipherText, 0, CipherTextBytes); Sha3Digest256.DoFinal(kr, SymBytes); - Cmov(kr, Arrays.CopyOfRange(SecretKey, SecretKeyBytes - SymBytes, SecretKeyBytes), SymBytes, fail); + CMov(kr, Arrays.CopyOfRange(secretKey, SecretKeyBytes - SymBytes, SecretKeyBytes), SymBytes, fail); ShakeDigest ShakeDigest256 = new ShakeDigest(256); ShakeDigest256.BlockUpdate(kr, 0, 2 * SymBytes); - ShakeDigest256.DoFinal(SharedSecret, 0, SymBytes); + ShakeDigest256.DoFinal(sharedSecret, 0, SymBytes); + } + + internal void RandomBytes(byte[] buf, int len) + { + m_random.NextBytes(buf, 0, len); } - private void Cmov(byte[] r, byte[] x, int len, bool b) + private void CMov(byte[] r, byte[] x, int len, bool b) { - int i; if (b) { Array.Copy(x, 0, r, 0, len); @@ -178,11 +177,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber Array.Copy(r, 0, r, 0, len); } } - - public void RandomBytes(byte[] buf, int len) - { - _random.NextBytes(buf,0,len); - } } } diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberIndCpa.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberIndCpa.cs index da4f94b88..1628ed90d 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberIndCpa.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberIndCpa.cs @@ -1,96 +1,93 @@ -using Org.BouncyCastle.Crypto.Digests; +using System; + +using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Utilities; -using System; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { internal class KyberIndCpa { - KyberEngine Engine; - int K; - public KyberIndCpa(KyberEngine engine) + private readonly KyberEngine m_engine; + + internal KyberIndCpa(KyberEngine engine) { - Engine = engine; - this.K = engine.K; - return; + m_engine = engine; } - private int XOFBlockBytes => Symmetric.Shake128Rate; + private int XofBlockBytes => Symmetric.Shake128Rate; - private int GenerateMatrixNBlocks => ((12 * KyberEngine.N / 8 * (1 << 12) / KyberEngine.Q + XOFBlockBytes) / XOFBlockBytes); + private int GenerateMatrixNBlocks => ((12 * KyberEngine.N / 8 * (1 << 12) / KyberEngine.Q + XofBlockBytes) / XofBlockBytes); private void GenerateMatrix(PolyVec[] a, byte[] seed, bool transposed) { - int ctr, i, j, k; - int buflen, off; - ShakeDigest XOF = new ShakeDigest(128); - byte[] buf = new byte[GenerateMatrixNBlocks * XOFBlockBytes + 2]; - for (i = 0; i < K; i++) + int K = m_engine.K; + ShakeDigest shake128 = new ShakeDigest(128); + byte[] buf = new byte[GenerateMatrixNBlocks * XofBlockBytes + 2]; + + for (int i = 0; i < K; i++) { - for (j = 0; j < K; j++) + for (int j = 0; j < K; j++) { if (transposed) { - XOF = Symmetric.XOF(seed, (byte) i, (byte) j); + shake128 = Symmetric.Xof(seed, (byte) i, (byte) j); } else { - XOF = Symmetric.XOF(seed, (byte) j, (byte) i); + shake128 = Symmetric.Xof(seed, (byte) j, (byte) i); } - XOF.DoOutput(buf, 0, GenerateMatrixNBlocks * XOFBlockBytes); - buflen = GenerateMatrixNBlocks * XOFBlockBytes; - ctr = RejectionSampling(a[i].Vec[j].Coeffs, 0, KyberEngine.N, buf, buflen); + shake128.DoOutput(buf, 0, GenerateMatrixNBlocks * XofBlockBytes); + int buflen = GenerateMatrixNBlocks * XofBlockBytes; + int ctr = RejectionSampling(a[i].m_vec[j].Coeffs, 0, KyberEngine.N, buf, buflen); while (ctr < KyberEngine.N) { - off = buflen % 3; - for (k = 0; k < off; k++) + int off = buflen % 3; + for (int k = 0; k < off; k++) { buf[k] = buf[buflen - off + k]; } - XOF.DoOutput(buf, off, XOFBlockBytes * 2); - buflen = off + XOFBlockBytes; - ctr += RejectionSampling(a[i].Vec[j].Coeffs, ctr, KyberEngine.N - ctr, buf, buflen); + shake128.DoOutput(buf, off, XofBlockBytes * 2); + buflen = off + XofBlockBytes; + ctr += RejectionSampling(a[i].m_vec[j].Coeffs, ctr, KyberEngine.N - ctr, buf, buflen); } } } - return; } private int RejectionSampling(short[] r, int off, int len, byte[] buf, int buflen) { - int ctr, pos; - ushort val0, val1; - ctr = pos = 0; + int ctr = 0, pos = 0; while (ctr < len && pos + 3 <= buflen) { - val0 = (ushort) ((((ushort) (buf[pos + 0] & 0xFF) >> 0) | ((ushort)(buf[pos + 1] & 0xFF) << 8)) & 0xFFF); - val1 = (ushort) ((((ushort) (buf[pos + 1] & 0xFF) >> 4) | ((ushort)(buf[pos + 2] & 0xFF) << 4)) & 0xFFF); + ushort val0 = (ushort) ((((ushort) (buf[pos + 0] & 0xFF) >> 0) | ((ushort)(buf[pos + 1] & 0xFF) << 8)) & 0xFFF); + ushort val1 = (ushort) ((((ushort) (buf[pos + 1] & 0xFF) >> 4) | ((ushort)(buf[pos + 2] & 0xFF) << 4)) & 0xFFF); pos += 3; if (val0 < KyberEngine.Q) { - r[off + ctr++] = (short) val0; + r[off + ctr++] = (short)val0; } if (ctr < len && val1 < KyberEngine.Q) { - r[off + ctr++] = (short) val1; + r[off + ctr++] = (short)val1; } } return ctr; } - public void GenerateKeyPair(byte[] pk, byte[] sk) + internal void GenerateKeyPair(byte[] pk, byte[] sk) { - uint i; + int K = m_engine.K; + byte[] buf = new byte[2 * KyberEngine.SymBytes]; byte nonce = 0; PolyVec[] Matrix = new PolyVec[K]; - PolyVec e = new PolyVec(Engine), pkpv = new PolyVec(Engine), skpv = new PolyVec(Engine); + PolyVec e = new PolyVec(m_engine), pkpv = new PolyVec(m_engine), skpv = new PolyVec(m_engine); Sha3Digest Sha3Digest512 = new Sha3Digest(512); - Engine.RandomBytes(buf, KyberEngine.SymBytes); + m_engine.RandomBytes(buf, KyberEngine.SymBytes); Sha3Digest512.BlockUpdate(buf, 0, KyberEngine.SymBytes); Sha3Digest512.DoFinal(buf, 0); @@ -99,30 +96,28 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber byte[] PublicSeed = Arrays.CopyOfRange(buf, 0, KyberEngine.SymBytes); byte[] NoiseSeed = Arrays.CopyOfRange(buf, KyberEngine.SymBytes, 2 * KyberEngine.SymBytes); - for (i = 0; i < K; i++) + for (int i = 0; i < K; i++) { - Matrix[i] = new PolyVec(Engine); + Matrix[i] = new PolyVec(m_engine); } GenerateMatrix(Matrix, PublicSeed, false); - for (i = 0; i < K; i++) + for (int i = 0; i < K; i++) { - skpv.Vec[i].GetNoiseEta1(NoiseSeed, nonce++); + skpv.m_vec[i].GetNoiseEta1(NoiseSeed, nonce++); } - for (i = 0; i < K; i++) + for (int i = 0; i < K; i++) { - e.Vec[i].GetNoiseEta1(NoiseSeed, nonce++); + e.m_vec[i].GetNoiseEta1(NoiseSeed, nonce++); } - - skpv.Ntt(); e.Ntt(); //Console.WriteLine("skpv = "); - //for (i = 0; i < K; i++) + //for (int i = 0; i < K; i++) //{ // Console.Write(String.Format("{0} [", i)); // foreach (short coeff in skpv.Vec[i].Coeffs) @@ -132,7 +127,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber // Console.Write("]\n"); //} - //for (i = 0; i < K; i++) + //for (int i = 0; i < K; i++) //{ // Console.Write("["); // for (int j = 0; j < K; j++) @@ -147,14 +142,14 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber // Console.Write("] \n"); //} - for (i = 0; i < K; i++) + for (int i = 0; i < K; i++) { - PolyVec.PointwiseAccountMontgomery(pkpv.Vec[i], Matrix[i], skpv, Engine); - pkpv.Vec[i].ToMont(); + PolyVec.PointwiseAccountMontgomery(pkpv.m_vec[i], Matrix[i], skpv, m_engine); + pkpv.m_vec[i].ToMont(); } //Console.WriteLine("pkpv = "); - //for (i = 0; i < K; i++) + //for (int i = 0; i < K; i++) //{ // Console.Write(String.Format("{0} [", i)); // foreach (short coeff in pkpv.Vec[i].Coeffs) @@ -166,14 +161,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber pkpv.Add(e); pkpv.Reduce(); - - - PackSecretKey(sk, skpv); PackPublicKey(pk, pkpv, PublicSeed); - - - return; } private void PackSecretKey(byte[] sk, PolyVec skpv) @@ -188,57 +177,57 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber private void PackPublicKey(byte[] pk, PolyVec pkpv, byte[] seed) { - int i; pkpv.ToBytes(pk); - Array.Copy(seed, 0, pk, Engine.PolyVecBytes, KyberEngine.SymBytes); + Array.Copy(seed, 0, pk, m_engine.PolyVecBytes, KyberEngine.SymBytes); } private void UnpackPublicKey(PolyVec pkpv, byte[] seed, byte[] pk) { - int i; pkpv.FromBytes(pk); - Array.Copy(pk, Engine.PolyVecBytes, seed, 0, KyberEngine.SymBytes); + Array.Copy(pk, m_engine.PolyVecBytes, seed, 0, KyberEngine.SymBytes); } - public void Encrypt(byte[] c, byte[] m, byte[] pk, byte[] coins) + internal void Encrypt(byte[] c, byte[] m, byte[] pk, byte[] coins) { - int i; + int K = m_engine.K; + byte[] seed = new byte[KyberEngine.SymBytes]; - byte nonce = (byte)0; - PolyVec sp = new PolyVec(Engine), pkpv = new PolyVec(Engine), ep = new PolyVec(Engine), bp = new PolyVec(Engine); + byte nonce = 0; + PolyVec sp = new PolyVec(m_engine), pkpv = new PolyVec(m_engine), ep = new PolyVec(m_engine), + bp = new PolyVec(m_engine); PolyVec[] MatrixTransposed = new PolyVec[K]; - Poly v = new Poly(Engine), k = new Poly(Engine), epp = new Poly(Engine); + Poly v = new Poly(m_engine), k = new Poly(m_engine), epp = new Poly(m_engine); UnpackPublicKey(pkpv, seed, pk); k.FromMsg(m); - for (i = 0; i < K; i++) + for (int i = 0; i < K; i++) { - MatrixTransposed[i] = new PolyVec(Engine); + MatrixTransposed[i] = new PolyVec(m_engine); } GenerateMatrix(MatrixTransposed, seed, true); - for (i = 0; i < K; i++) + for (int i = 0; i < K; i++) { - sp.Vec[i].GetNoiseEta1(coins, nonce++); + sp.m_vec[i].GetNoiseEta1(coins, nonce++); } - for (i = 0; i < K; i++) + for (int i = 0; i < K; i++) { - ep.Vec[i].GetNoiseEta2(coins, nonce++); + ep.m_vec[i].GetNoiseEta2(coins, nonce++); } epp.GetNoiseEta2(coins, nonce++); sp.Ntt(); - for (i = 0; i < K; i++) + for (int i = 0; i < K; i++) { - PolyVec.PointwiseAccountMontgomery(bp.Vec[i], MatrixTransposed[i], sp, Engine); + PolyVec.PointwiseAccountMontgomery(bp.m_vec[i], MatrixTransposed[i], sp, m_engine); } - PolyVec.PointwiseAccountMontgomery(v, pkpv, sp, Engine); + PolyVec.PointwiseAccountMontgomery(v, pkpv, sp, m_engine); bp.InverseNttToMont(); @@ -258,36 +247,31 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber private void PackCipherText(byte[] r, PolyVec b, Poly v) { b.CompressPolyVec(r); - v.CompressPoly(r, Engine.PolyVecCompressedBytes); + v.CompressPoly(r, m_engine.PolyVecCompressedBytes); } private void UnpackCipherText(PolyVec b, Poly v, byte[] c) { b.DecompressPolyVec(c); - v.DecompressPoly(c, Engine.PolyVecCompressedBytes); + v.DecompressPoly(c, m_engine.PolyVecCompressedBytes); } - public void Decrypt(byte[] m, byte[] c, byte[] sk) + internal void Decrypt(byte[] m, byte[] c, byte[] sk) { - PolyVec bp = new PolyVec(Engine), - skpv = new PolyVec(Engine); - Poly v = new Poly(Engine), - mp = new Poly(Engine); - int i; + PolyVec bp = new PolyVec(m_engine), skpv = new PolyVec(m_engine); + Poly v = new Poly(m_engine), mp = new Poly(m_engine); UnpackCipherText(bp, v, c); - UnpackSecretKey(skpv, sk); bp.Ntt(); - PolyVec.PointwiseAccountMontgomery(mp, skpv, bp, Engine); + PolyVec.PointwiseAccountMontgomery(mp, skpv, bp, m_engine); mp.PolyInverseNttToMont(); mp.Subtract(v); mp.PolyReduce(); mp.ToMsg(m); - } } } diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberKEMExtractor.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberKEMExtractor.cs index 38b826f43..a9f27c4ed 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberKEMExtractor.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberKEMExtractor.cs @@ -1,36 +1,29 @@ - using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { - public class KyberKEMExtractor + public sealed class KyberKemExtractor : IEncapsulatedSecretExtractor { - private KyberEngine engine; - - private KyberKeyParameters key; - - public KyberKEMExtractor(KyberKeyParameters privParams) - { - this.key = privParams; - InitCipher(key.Parameters); - } + private readonly KyberKeyParameters m_key; + private readonly KyberEngine m_engine; - private void InitCipher(KyberParameters param) + public KyberKemExtractor(KyberKeyParameters privParams) { - engine = param.GetEngine(); + m_key = privParams; + m_engine = m_key.Parameters.Engine; } public byte[] ExtractSecret(byte[] encapsulation) { - byte[] sessionKey = new byte[engine.CryptoBytes]; - engine.KemDecrypt(sessionKey, encapsulation, ((KyberPrivateKeyParameters) key).privateKey); - byte[] rv = Arrays.CopyOfRange(sessionKey, 0, key.Parameters.DefaultKeySize / 8); + byte[] sessionKey = new byte[m_engine.CryptoBytes]; + m_engine.KemDecrypt(sessionKey, encapsulation, ((KyberPrivateKeyParameters)m_key).m_privateKey); + byte[] rv = Arrays.CopyOfRange(sessionKey, 0, m_key.Parameters.DefaultKeySize / 8); Arrays.Clear(sessionKey); return rv; } - public int EncapsulationLength => engine.CryptoCipherTextBytes; + public int EncapsulationLength => m_engine.CryptoCipherTextBytes; } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberKEMGenerator.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberKEMGenerator.cs index c43f10ff1..a0c070069 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberKEMGenerator.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberKEMGenerator.cs @@ -1,85 +1,80 @@ - using System; + using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { - public class KyberKEMGenerator + public sealed class KyberKemGenerator : IEncapsulatedSecretGenerator { // the source of randomness - private SecureRandom sr; + private readonly SecureRandom m_random; - public KyberKEMGenerator(SecureRandom random) + public KyberKemGenerator(SecureRandom random) { - this.sr = random; + m_random = random; } public ISecretWithEncapsulation GenerateEncapsulated(AsymmetricKeyParameter recipientKey) { - KyberPublicKeyParameters key = (KyberPublicKeyParameters) recipientKey; - KyberEngine engine = key.Parameters.GetEngine(); - engine.Init(sr); - byte[] CipherText = new byte[engine.CryptoCipherTextBytes]; - byte[] SessionKey = new byte[engine.CryptoBytes]; - engine.KemEncrypt(CipherText, SessionKey, key.publicKey); - byte[] rv = Arrays.CopyOfRange(SessionKey, 0, key.Parameters.DefaultKeySize / 8); - Arrays.Clear(SessionKey); - return new SecretWithEncapsulationImpl(rv, CipherText); + KyberPublicKeyParameters key = (KyberPublicKeyParameters)recipientKey; + KyberEngine engine = key.Parameters.Engine; + engine.Init(m_random); + byte[] cipherText = new byte[engine.CryptoCipherTextBytes]; + byte[] sessionKey = new byte[engine.CryptoBytes]; + engine.KemEncrypt(cipherText, sessionKey, key.m_publicKey); + byte[] rv = Arrays.CopyOfRange(sessionKey, 0, key.Parameters.DefaultKeySize / 8); + Arrays.Clear(sessionKey); + return new SecretWithEncapsulationImpl(rv, cipherText); } - private class SecretWithEncapsulationImpl + private sealed class SecretWithEncapsulationImpl : ISecretWithEncapsulation { - private volatile bool hasBeenDestroyed = false; + private volatile bool m_hasBeenDestroyed = false; - private byte[] SessionKey; - private byte[] CipherText; + private readonly byte[] m_sessionKey; + private readonly byte[] m_cipherText; - public SecretWithEncapsulationImpl(byte[] sessionKey, byte[] cipher_text) + internal SecretWithEncapsulationImpl(byte[] sessionKey, byte[] cipher_text) { - this.SessionKey = sessionKey; - this.CipherText = cipher_text; + m_sessionKey = sessionKey; + m_cipherText = cipher_text; } public byte[] GetSecret() { CheckDestroyed(); - return Arrays.Clone(SessionKey); + return Arrays.Clone(m_sessionKey); } public byte[] GetEncapsulation() { CheckDestroyed(); - return Arrays.Clone(CipherText); + return Arrays.Clone(m_cipherText); } public void Dispose() { - if (!hasBeenDestroyed) + if (!m_hasBeenDestroyed) { - hasBeenDestroyed = true; - Arrays.Clear(SessionKey); - Arrays.Clear(CipherText); + m_hasBeenDestroyed = true; + Arrays.Clear(m_sessionKey); + Arrays.Clear(m_cipherText); } } - public bool IsDestroyed() - { - return hasBeenDestroyed; - } + internal bool IsDestroyed => m_hasBeenDestroyed; - void CheckDestroyed() + private void CheckDestroyed() { - if (IsDestroyed()) - { + if (IsDestroyed) throw new ArgumentException("data has been destroyed"); - } } } } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberKeyGenerationParameters.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberKeyGenerationParameters.cs index f6adb0071..e42d6fdeb 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberKeyGenerationParameters.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberKeyGenerationParameters.cs @@ -1,22 +1,19 @@ - using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Security; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { - public class KyberKeyGenerationParameters + public sealed class KyberKeyGenerationParameters : KeyGenerationParameters { - private KyberParameters parameters; + private readonly KyberParameters m_parameters; - public KyberKeyGenerationParameters( - SecureRandom random, - KyberParameters KyberParameters) + public KyberKeyGenerationParameters(SecureRandom random, KyberParameters KyberParameters) : base(random, 256) { - this.parameters = KyberParameters; + m_parameters = KyberParameters; } - public KyberParameters Parameters => parameters; + public KyberParameters Parameters => m_parameters; } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberKeyPairGenerator.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberKeyPairGenerator.cs index 39ee496f2..fde26f727 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberKeyPairGenerator.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberKeyPairGenerator.cs @@ -1,6 +1,4 @@ - using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber; using Org.BouncyCastle.Security; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber @@ -8,42 +6,26 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber public class KyberKeyPairGenerator : IAsymmetricCipherKeyPairGenerator { - private KyberKeyGenerationParameters KyberParams; - - private int k; + private KyberKeyGenerationParameters m_kyberParams; + private SecureRandom m_random; - private SecureRandom random; - - private void Initialize( - KeyGenerationParameters param) + public void Init(KeyGenerationParameters param) { - this.KyberParams = (KyberKeyGenerationParameters) param; - this.random = param.Random; - - this.k = this.KyberParams.Parameters.K; + m_kyberParams = (KyberKeyGenerationParameters)param; + m_random = param.Random; } - private AsymmetricCipherKeyPair GenKeyPair() + public AsymmetricCipherKeyPair GenerateKeyPair() { - KyberEngine engine = KyberParams.Parameters.GetEngine(); - engine.Init(random); + KyberEngine engine = m_kyberParams.Parameters.Engine; + engine.Init(m_random); byte[] sk = new byte[engine.CryptoSecretKeyBytes]; byte[] pk = new byte[engine.CryptoPublicKeyBytes]; engine.GenerateKemKeyPair(pk, sk); - KyberPublicKeyParameters pubKey = new KyberPublicKeyParameters(KyberParams.Parameters, pk); - KyberPrivateKeyParameters privKey = new KyberPrivateKeyParameters(KyberParams.Parameters, sk); + KyberPublicKeyParameters pubKey = new KyberPublicKeyParameters(m_kyberParams.Parameters, pk); + KyberPrivateKeyParameters privKey = new KyberPrivateKeyParameters(m_kyberParams.Parameters, sk); return new AsymmetricCipherKeyPair(pubKey, privKey); } - - public void Init(KeyGenerationParameters param) - { - this.Initialize(param); - } - - public AsymmetricCipherKeyPair GenerateKeyPair() - { - return GenKeyPair(); - } } } \ No newline at end of file diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberKeyParameters.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberKeyParameters.cs index 37650cb4d..9fb26c2ad 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberKeyParameters.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberKeyParameters.cs @@ -1,21 +1,18 @@ - using Org.BouncyCastle.Crypto; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { - public class KyberKeyParameters + public abstract class KyberKeyParameters : AsymmetricKeyParameter { - private KyberParameters parameters; + private readonly KyberParameters m_parameters; - public KyberKeyParameters( - bool isPrivate, - KyberParameters parameters) + public KyberKeyParameters(bool isPrivate, KyberParameters parameters) : base(isPrivate) { - this.parameters = parameters; + m_parameters = parameters; } - public KyberParameters Parameters => parameters; + public KyberParameters Parameters => m_parameters; } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs index d0fd8a631..ea9f90c98 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs @@ -1,38 +1,31 @@ - using System; + using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { - public class KyberParameters + public sealed class KyberParameters : ICipherParameters { - public static KyberParameters kyber512 = new KyberParameters("kyber512", 2); public static KyberParameters kyber768 = new KyberParameters("kyber768", 3); public static KyberParameters kyber1024 = new KyberParameters("kyber1024", 4); - private String name; - private int k; - private KyberEngine engine; + private string m_name; + private KyberEngine m_engine; - public KyberParameters(String name, int k) + public KyberParameters(string name, int k) { - this.name = name; - this.k = k; - this.engine = new KyberEngine(k); + m_name = name; + m_engine = new KyberEngine(k); } - public String Name => name; + public string Name => m_name; - public int K => k; + public int K => m_engine.K; - public int DefaultKeySize => 64 * k; + public int DefaultKeySize => 64 * m_engine.K; - internal KyberEngine GetEngine() - { - return engine; - } + internal KyberEngine Engine => m_engine; } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs index 955b44673..d58a59c40 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberPrivateKeyParameters.cs @@ -2,20 +2,20 @@ using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { - public class KyberPrivateKeyParameters + public sealed class KyberPrivateKeyParameters : KyberKeyParameters { - internal byte[] privateKey; + internal readonly byte[] m_privateKey; public KyberPrivateKeyParameters(KyberParameters parameters, byte[] privateKey) : base(true, parameters) { - this.privateKey = Arrays.Clone(privateKey); + m_privateKey = Arrays.Clone(privateKey); } public byte[] GetEncoded() { - return Arrays.Clone(privateKey); + return Arrays.Clone(m_privateKey); } } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs index 1092c7e96..02e467530 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberPublicKeyParameters.cs @@ -2,20 +2,20 @@ using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { - public class KyberPublicKeyParameters + public sealed class KyberPublicKeyParameters : KyberKeyParameters { - internal byte[] publicKey; + internal readonly byte[] m_publicKey; - public byte[] GetEncoded() + public KyberPublicKeyParameters(KyberParameters parameters, byte[] publicKey) + : base(false, parameters) { - return Arrays.Clone(publicKey); + m_publicKey = Arrays.Clone(publicKey); } - public KyberPublicKeyParameters(KyberParameters parameters, byte[] publicKey) - : base(false, parameters) + public byte[] GetEncoded() { - this.publicKey = Arrays.Clone(publicKey); + return Arrays.Clone(m_publicKey); } } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/crystals/kyber/Ntt.cs b/crypto/src/pqc/crypto/crystals/kyber/Ntt.cs index f07e8da26..1b0c05c8e 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/Ntt.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/Ntt.cs @@ -3,7 +3,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { internal static class Ntt { - public static readonly short[] Zetas = { + internal static readonly short[] Zetas = { 2285, 2571, 2970, 1812, 1493, 1422, 287, 202, 3158, 622, 1577, 182, 962, 2127, 1855, 1468, 573, 2004, 264, 383, 2500, 1458, 1727, 3199, 2648, 1017, 732, 608, 1787, 411, 3124, 1758, 1223, 652, 2777, 1015, 2036, 1491, 3047, @@ -16,7 +16,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber 478, 3221, 3021, 996, 991, 958, 1869, 1522, 1628 }; - public static readonly short[] ZetasInv = { + internal static readonly short[] ZetasInv = { 1701, 1807, 1460, 2371, 2338, 2333, 308, 108, 2851, 870, 854, 1510, 2535, 1278, 1530, 1185, 1659, 1187, 3109, 874, 1335, 2111, 136, 1215, 2945, 1465, 1285, 2007, 2719, 2726, 2232, 2512, 75, 156, 3000, 2911, 2980, 872, 2685, @@ -34,20 +34,17 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber return Reduce.MontgomeryReduce(a * b); } - public static void NTT(short[] r) + internal static void NTT(short[] r) { - int len, start, j, k; - short t, zeta; - - k = 1; - for (len = 128; len >= 2; len >>= 1) + int j = 0, k = 1; + for (int len = 128; len >= 2; len >>= 1) { - for (start = 0; start < 256; start = j + len) + for (int start = 0; start < 256; start = j + len) { - zeta = Zetas[k++]; + short zeta = Zetas[k++]; for (j = start; j < start + len; ++j) { - t = FactorQMulMont(zeta, r[j + len]); + short t = FactorQMulMont(zeta, r[j + len]); r[j + len] = (short)(r[j] - t); r[j] = (short)(r[j] + t); } @@ -55,20 +52,17 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber } } - public static void InvNTT(short[] r) + internal static void InvNTT(short[] r) { - int len, start, j, k; - short t, zeta; - - k = 0; - for (len = 2; len <= 128; len <<= 1) + int j = 0, k = 0; + for (int len = 2; len <= 128; len <<= 1) { - for (start = 0; start < 256; start = j + len) + for (int start = 0; start < 256; start = j + len) { - zeta = ZetasInv[k++]; + short zeta = ZetasInv[k++]; for (j = start; j < start + len; ++j) { - t = r[j]; + short t = r[j]; r[j] = Reduce.BarrettReduce((short)(t + r[j + len])); r[j + len] = (short)(t - r[j + len]); r[j + len] = FactorQMulMont(zeta, r[j + len]); @@ -76,22 +70,22 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber } } } - for (j = 0; j < 256; ++j) + for (int i = 0; i < 256; ++i) { - r[j] = FactorQMulMont(r[j], Ntt.ZetasInv[127]); + r[i] = FactorQMulMont(r[i], ZetasInv[127]); } } - public static void BaseMult(short[] r, int off, short a0, short a1, short b0, short b1, short zeta) + internal static void BaseMult(short[] r, int off, short a0, short a1, short b0, short b1, short zeta) { - short OutVal0 = FactorQMulMont(a1, b1); - OutVal0 = FactorQMulMont(OutVal0, zeta); - OutVal0 += FactorQMulMont(a0, b0); - r[off] = OutVal0; + short outVal0 = FactorQMulMont(a1, b1); + outVal0 = FactorQMulMont(outVal0, zeta); + outVal0 += FactorQMulMont(a0, b0); + r[off] = outVal0; - short OutVal1 = FactorQMulMont(a0, b1); - OutVal1 += FactorQMulMont(a1, b0); - r[off + 1] = OutVal1; + short outVal1 = FactorQMulMont(a0, b1); + outVal1 += FactorQMulMont(a1, b0); + r[off + 1] = outVal1; } } } diff --git a/crypto/src/pqc/crypto/crystals/kyber/Poly.cs b/crypto/src/pqc/crypto/crystals/kyber/Poly.cs index 0b226bca1..fc2f7ec70 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/Poly.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/Poly.cs @@ -1,54 +1,48 @@ - -using System; +using System; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { - class Poly + internal class Poly { - private KyberEngine Engine; - public short[] Coeffs { get; set; } - private int PolyCompressedBytes; - private int Eta1; - private int Eta2; - private int N; - public Poly(KyberEngine engine) + private short[] m_coeffs = new short[KyberEngine.N]; + + private KyberEngine m_engine; + + internal Poly(KyberEngine engine) { - Engine = engine; - Coeffs = new short[KyberEngine.N]; - PolyCompressedBytes = engine.PolyCompressedBytes; - Eta1 = engine.Eta1; - N = KyberEngine.N; + m_engine = engine; } - public void GetNoiseEta1(byte[] seed, byte nonce) + internal short[] Coeffs => m_coeffs; + + internal void GetNoiseEta1(byte[] seed, byte nonce) { - byte[] buf = new byte[Engine.Eta1 * KyberEngine.N / 4]; - Symmetric.PRF(buf, buf.Length, seed, nonce); - CBD.Eta(this, buf, Engine.Eta1); + byte[] buf = new byte[m_engine.Eta1 * KyberEngine.N / 4]; + Symmetric.Prf(buf, buf.Length, seed, nonce); + Cbd.Eta(this, buf, m_engine.Eta1); } - public void GetNoiseEta2(byte[] seed, byte nonce) + internal void GetNoiseEta2(byte[] seed, byte nonce) { byte[] buf = new byte[KyberEngine.Eta2 * KyberEngine.N / 4]; - Symmetric.PRF(buf, buf.Length, seed, nonce); - CBD.Eta(this, buf, KyberEngine.Eta2); + Symmetric.Prf(buf, buf.Length, seed, nonce); + Cbd.Eta(this, buf, KyberEngine.Eta2); } - public void PolyNtt() + internal void PolyNtt() { Ntt.NTT(Coeffs); PolyReduce(); } - public void PolyInverseNttToMont() + internal void PolyInverseNttToMont() { Ntt.InvNTT(Coeffs); } - public static void BaseMultMontgomery(Poly r, Poly a, Poly b) + internal static void BaseMultMontgomery(Poly r, Poly a, Poly b) { - int i; - for (i = 0; i < KyberEngine.N/4; i++) + for (int i = 0; i < KyberEngine.N/4; i++) { Ntt.BaseMult(r.Coeffs, 4 * i, a.Coeffs[4 * i], a.Coeffs[4 * i + 1], @@ -61,55 +55,55 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber } } - public void ToMont() + internal void ToMont() { - int i; const short f = (short) ((1UL << 32) % KyberEngine.Q); - for (i = 0; i < KyberEngine.N; i++) + for (int i = 0; i < KyberEngine.N; i++) { Coeffs[i] = Reduce.MontgomeryReduce(Coeffs[i] * f); } } - public void Add(Poly a) + internal void Add(Poly a) { - int i; - for (i = 0; i < N; i++) + for (int i = 0; i < KyberEngine.N; i++) { Coeffs[i] += a.Coeffs[i]; } } - public void Subtract(Poly a) + internal void Subtract(Poly a) { - int i; - for (i = 0; i < N; i++) + for (int i = 0; i < KyberEngine.N; i++) { - Coeffs[i] = (short) (a.Coeffs[i] - Coeffs[i]); + Coeffs[i] = (short)(a.Coeffs[i] - Coeffs[i]); } } - public void PolyReduce() + internal void PolyReduce() { - int i; - for (i = 0; i < KyberEngine.N; i++) + for (int i = 0; i < KyberEngine.N; i++) { Coeffs[i] = Reduce.BarrettReduce(Coeffs[i]); } } - public void CompressPoly(byte[] r, int off) + internal void CompressPoly(byte[] r, int off) { - int i, j; +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span<byte> t = stackalloc byte[8]; +#else byte[] t = new byte[8]; +#endif + int count = 0; CondSubQ(); - if (Engine.PolyCompressedBytes == 128) + if (m_engine.PolyCompressedBytes == 128) { - for (i = 0; i < KyberEngine.N / 8; i++) + for (int i = 0; i < KyberEngine.N / 8; i++) { - for (j = 0; j < 8; j++) + for (int j = 0; j < 8; j++) { t[j] = (byte)(((((Coeffs[8 * i + j]) << 4) @@ -126,11 +120,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber count += 4; } } - else if (Engine.PolyCompressedBytes == 160) + else if (m_engine.PolyCompressedBytes == 160) { - for (i = 0; i < KyberEngine.N / 8; i++) + for (int i = 0; i < KyberEngine.N / 8; i++) { - for (j = 0; j < 8; j++) + for (int j = 0; j < 8; j++) { t[j] = (byte)((((Coeffs[8 * i + j] << 5) @@ -154,24 +148,23 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber } } - public void DecompressPoly(byte[] CompressedCipherText, int off) + internal void DecompressPoly(byte[] CompressedCipherText, int off) { - int i, count = off; + int count = off; - if (Engine.PolyCompressedBytes == 128) + if (m_engine.PolyCompressedBytes == 128) { - for (i = 0; i < KyberEngine.N / 2; i++) + for (int i = 0; i < KyberEngine.N / 2; i++) { Coeffs[2 * i + 0] = (short)((((short)((CompressedCipherText[count] & 0xFF) & 15) * KyberEngine.Q) + 8) >> 4); Coeffs[2 * i + 1] = (short)((((short)((CompressedCipherText[count] & 0xFF) >> 4) * KyberEngine.Q) + 8) >> 4); count += 1; } } - else if (Engine.PolyCompressedBytes == 160) + else if (m_engine.PolyCompressedBytes == 160) { - int j; byte[] t = new byte[8]; - for (i = 0; i < KyberEngine.N / 8; i++) + for (int i = 0; i < KyberEngine.N / 8; i++) { t[0] = (byte)((CompressedCipherText[count + 0] & 0xFF) >> 0); t[1] = (byte)(((CompressedCipherText[count + 0] & 0xFF) >> 5) | ((CompressedCipherText[count + 1] & 0xFF) << 3)); @@ -182,7 +175,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber t[6] = (byte)(((CompressedCipherText[count + 3] & 0xFF) >> 6) | ((CompressedCipherText[count + 4] & 0xFF) << 2)); t[7] = (byte)((CompressedCipherText[count + 4] & 0xFF) >> 3); count += 5; - for (j = 0; j < 8; j++) + for (int j = 0; j < 8; j++) { Coeffs[8 * i + j] = (short)(((t[j] & 31) * KyberEngine.Q + 16) >> 5); } @@ -193,74 +186,63 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber throw new ArgumentException("PolyCompressedBytes is neither 128 or 160!"); } } - - public void ToBytes(byte[] r, int off) - { - int i; - ushort t0, t1; + internal void ToBytes(byte[] r, int off) + { CondSubQ(); - for (i = 0; i < KyberEngine.N/2; i++) + for (int i = 0; i < KyberEngine.N/2; i++) { - t0 = (ushort) Coeffs[2 * i]; - t1 = (ushort) Coeffs[2 * i + 1]; + ushort t0 = (ushort) Coeffs[2 * i]; + ushort t1 = (ushort) Coeffs[2 * i + 1]; r[off + 3 * i + 0] = (byte) (ushort) (t0 >> 0); r[off + 3 * i + 1] = (byte)((t0 >> 8) | (ushort) (t1 << 4)); r[off + 3 * i + 2] = (byte) (ushort) (t1 >> 4); } } - public void FromBytes(byte[] a, int off) + internal void FromBytes(byte[] a, int off) { - int i; - for (i = 0; i < KyberEngine.N / 2; i++) + for (int i = 0; i < KyberEngine.N / 2; i++) { Coeffs[2 * i] = (short) ((((a[off + 3 * i + 0] & 0xFF) >> 0) | (ushort)((a[off + 3 * i + 1] & 0xFF) << 8)) & 0xFFF); Coeffs[2 * i + 1] = (short) ((((a[off + 3 * i + 1] & 0xFF) >> 4) | (ushort)((a[off + 3 * i + 2] & 0xFF) << 4)) & 0xFFF); } } - public void ToMsg(byte[] msg) + internal void ToMsg(byte[] msg) { - int i, j; - short t; - CondSubQ(); - for (i = 0; i < KyberEngine.N / 8; i++) + for (int i = 0; i < KyberEngine.N / 8; i++) { msg[i] = 0; - for (j = 0; j < 8; j++) + for (int j = 0; j < 8; j++) { - t = (short)(((((short)(Coeffs[8 * i + j] << 1) + KyberEngine.Q / 2) / KyberEngine.Q) & 1)); + short t = (short)(((((short)(Coeffs[8 * i + j] << 1) + KyberEngine.Q / 2) / KyberEngine.Q) & 1)); msg[i] |= (byte)(t << j); } } } - public void FromMsg(byte[] m) + internal void FromMsg(byte[] m) { - int i, j; - short mask; if (m.Length != KyberEngine.N / 8) - { throw new ArgumentException("KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!"); - } - for (i = 0; i < KyberEngine.N / 8; i++) + + for (int i = 0; i < KyberEngine.N / 8; i++) { - for (j = 0; j < 8; j++) + for (int j = 0; j < 8; j++) { - mask = (short)((-1) * (short)(((m[i] & 0xFF) >> j) & 1)); + short mask = (short)((-1) * (short)(((m[i] & 0xFF) >> j) & 1)); Coeffs[8 * i + j] = (short)(mask & ((KyberEngine.Q + 1) / 2)); } } } - public void CondSubQ() + internal void CondSubQ() { - int i; - for (i = 0; i < KyberEngine.N; i++) + for (int i = 0; i < KyberEngine.N; i++) { Coeffs[i] = Reduce.CondSubQ(Coeffs[i]); } diff --git a/crypto/src/pqc/crypto/crystals/kyber/PolyVec.cs b/crypto/src/pqc/crypto/crystals/kyber/PolyVec.cs index 7c915dcce..5c92441b9 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/PolyVec.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/PolyVec.cs @@ -1,98 +1,88 @@ -using Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber; -using System; +using System; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { - class PolyVec + internal class PolyVec { - private KyberEngine Engine; - private int K; - private int PolyVecBytes; - public Poly[] Vec; + private KyberEngine m_engine; + internal Poly[] m_vec; - - - - public PolyVec(KyberEngine engine) + internal PolyVec(KyberEngine engine) { - Engine = engine; - K = engine.K; - PolyVecBytes = engine.PolyVecBytes; - Vec = new Poly[engine.K]; - for (int i = 0; i < K; i++) + m_engine = engine; + m_vec = new Poly[engine.K]; + for (int i = 0; i < engine.K; i++) { - Vec[i] = new Poly(engine); + m_vec[i] = new Poly(engine); } } - public void Ntt() + internal void Ntt() { - int i; - for (i = 0; i < K; i++) + for (int i = 0; i < m_engine.K; i++) { - Vec[i].PolyNtt(); + m_vec[i].PolyNtt(); } } - public void InverseNttToMont() + internal void InverseNttToMont() { - int i; - for (i = 0; i < K; i++) + for (int i = 0; i < m_engine.K; i++) { - Vec[i].PolyInverseNttToMont(); + m_vec[i].PolyInverseNttToMont(); } } - - public static void PointwiseAccountMontgomery(Poly r, PolyVec a, PolyVec b, KyberEngine engine) + + internal static void PointwiseAccountMontgomery(Poly r, PolyVec a, PolyVec b, KyberEngine engine) { - int i; Poly t = new Poly(engine); - Poly.BaseMultMontgomery(r, a.Vec[0], b.Vec[0]); - for (i = 1; i < engine.K; i++) + Poly.BaseMultMontgomery(r, a.m_vec[0], b.m_vec[0]); + for (int i = 1; i < engine.K; i++) { - Poly.BaseMultMontgomery(t, a.Vec[i], b.Vec[i]); + Poly.BaseMultMontgomery(t, a.m_vec[i], b.m_vec[i]); r.Add(t); } r.PolyReduce(); } - public void Add(PolyVec a) + internal void Add(PolyVec a) { - uint i; - for (i = 0; i < K; i++) + for (int i = 0; i < m_engine.K; i++) { - Vec[i].Add(a.Vec[i]); + m_vec[i].Add(a.m_vec[i]); } } - public void Reduce() + internal void Reduce() { - int i; - for (i = 0; i < K; i++) + for (int i = 0; i < m_engine.K; i++) { - Vec[i].PolyReduce(); + m_vec[i].PolyReduce(); } } - public void CompressPolyVec(byte[] r) + internal void CompressPolyVec(byte[] r) { - int i, j, k; ConditionalSubQ(); - short[] t; int count = 0; - if (Engine.PolyVecCompressedBytes == K * 320) + if (m_engine.PolyVecCompressedBytes == m_engine.K * 320) { - t = new short[4]; - for (i = 0; i < K; i++) +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span<short> t = stackalloc short[4]; +#else + short[] t = new short[4]; +#endif + + for (int i = 0; i < m_engine.K; i++) { - for (j = 0; j < KyberEngine.N / 4; j++) + for (int j = 0; j < KyberEngine.N / 4; j++) { - for (k = 0; k < 4; k++) + for (int k = 0; k < 4; k++) { t[k] = (short) ( ( - (((uint) Vec[i].Coeffs[4 * j + k] << 10) + (((uint) m_vec[i].Coeffs[4 * j + k] << 10) + (KyberEngine.Q / 2)) / KyberEngine.Q) & 0x3ff); @@ -106,19 +96,24 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber } } } - else if (Engine.PolyVecCompressedBytes == K * 352) + else if (m_engine.PolyVecCompressedBytes == m_engine.K * 352) { - t = new short[8]; - for (i = 0; i < K; i++) +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span<short> t = stackalloc short[8]; +#else + short[] t = new short[8]; +#endif + + for (int i = 0; i < m_engine.K; i++) { - for (j = 0; j < KyberEngine.N / 8; j++) + for (int j = 0; j < KyberEngine.N / 8; j++) { - for (k = 0; k < 8; k++) + for (int k = 0; k < 8; k++) { t[k] = (short) ( ( - (((uint) Vec[i].Coeffs[8 * j + k] << 11) + (((uint) m_vec[i].Coeffs[8 * j + k] << 11) + (KyberEngine.Q / 2)) / KyberEngine.Q) & 0x7ff); @@ -144,50 +139,58 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber } } - public void DecompressPolyVec(byte[] CompressedCipherText) + internal void DecompressPolyVec(byte[] compressedCipherText) { - int i, j, k, count = 0; + int count = 0; - if (Engine.PolyVecCompressedBytes == (K * 320)) + if (m_engine.PolyVecCompressedBytes == (m_engine.K * 320)) { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span<short> t = stackalloc short[4]; +#else short[] t = new short[4]; - for (i = 0; i < K; i++) +#endif + + for (int i = 0; i < m_engine.K; i++) { - for (j = 0; j < KyberEngine.N / 4; j++) + for (int j = 0; j < KyberEngine.N / 4; j++) { - t[0] = (short)(((CompressedCipherText[count] & 0xFF) >> 0) | ((ushort)(CompressedCipherText[count + 1] & 0xFF) << 8)); - t[1] = (short)(((CompressedCipherText[count + 1] & 0xFF) >> 2) | ((ushort)(CompressedCipherText[count + 2] & 0xFF) << 6)); - t[2] = (short)(((CompressedCipherText[count + 2] & 0xFF) >> 4) | ((ushort)(CompressedCipherText[count + 3] & 0xFF) << 4)); - t[3] = (short)(((CompressedCipherText[count + 3] & 0xFF) >> 6) | ((ushort)(CompressedCipherText[count + 4] & 0xFF) << 2)); + t[0] = (short)(((compressedCipherText[count] & 0xFF) >> 0) | ((ushort)(compressedCipherText[count + 1] & 0xFF) << 8)); + t[1] = (short)(((compressedCipherText[count + 1] & 0xFF) >> 2) | ((ushort)(compressedCipherText[count + 2] & 0xFF) << 6)); + t[2] = (short)(((compressedCipherText[count + 2] & 0xFF) >> 4) | ((ushort)(compressedCipherText[count + 3] & 0xFF) << 4)); + t[3] = (short)(((compressedCipherText[count + 3] & 0xFF) >> 6) | ((ushort)(compressedCipherText[count + 4] & 0xFF) << 2)); count += 5; - for (k = 0; k < 4; k++) + for (int k = 0; k < 4; k++) { - Vec[i].Coeffs[4 * j + k] = (short)(((t[k] & 0x3FF) * KyberEngine.Q + 512) >> 10); + m_vec[i].Coeffs[4 * j + k] = (short)(((t[k] & 0x3FF) * KyberEngine.Q + 512) >> 10); } } - } - } - else if (Engine.PolyVecCompressedBytes == (K * 352)) + else if (m_engine.PolyVecCompressedBytes == (m_engine.K * 352)) { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span<short> t = stackalloc short[8]; +#else short[] t = new short[8]; - for (i = 0; i < K; i++) +#endif + + for (int i = 0; i < m_engine.K; i++) { - for (j = 0; j < KyberEngine.N / 8; j++) + for (int j = 0; j < KyberEngine.N / 8; j++) { - t[0] = (short)(((CompressedCipherText[count] & 0xFF) >> 0) | ((ushort)(CompressedCipherText[count + 1] & 0xFF) << 8)); - t[1] = (short)(((CompressedCipherText[count + 1] & 0xFF) >> 3) | ((ushort)(CompressedCipherText[count + 2] & 0xFF) << 5)); - t[2] = (short)(((CompressedCipherText[count + 2] & 0xFF) >> 6) | ((ushort)(CompressedCipherText[count + 3] & 0xFF) << 2) | ((ushort)((CompressedCipherText[count + 4] & 0xFF) << 10))); - t[3] = (short)(((CompressedCipherText[count + 4] & 0xFF) >> 1) | ((ushort)(CompressedCipherText[count + 5] & 0xFF) << 7)); - t[4] = (short)(((CompressedCipherText[count + 5] & 0xFF) >> 4) | ((ushort)(CompressedCipherText[count + 6] & 0xFF) << 4)); - t[5] = (short)(((CompressedCipherText[count + 6] & 0xFF) >> 7) | ((ushort)(CompressedCipherText[count + 7] & 0xFF) << 1) | ((ushort)((CompressedCipherText[count + 8] & 0xFF) << 9))); - t[6] = (short)(((CompressedCipherText[count + 8] & 0xFF) >> 2) | ((ushort)(CompressedCipherText[count + 9] & 0xFF) << 6)); - t[7] = (short)(((CompressedCipherText[count + 9] & 0xFF) >> 5) | ((ushort)(CompressedCipherText[count + 10] & 0xFF) << 3)); + t[0] = (short)(((compressedCipherText[count] & 0xFF) >> 0) | ((ushort)(compressedCipherText[count + 1] & 0xFF) << 8)); + t[1] = (short)(((compressedCipherText[count + 1] & 0xFF) >> 3) | ((ushort)(compressedCipherText[count + 2] & 0xFF) << 5)); + t[2] = (short)(((compressedCipherText[count + 2] & 0xFF) >> 6) | ((ushort)(compressedCipherText[count + 3] & 0xFF) << 2) | ((ushort)((compressedCipherText[count + 4] & 0xFF) << 10))); + t[3] = (short)(((compressedCipherText[count + 4] & 0xFF) >> 1) | ((ushort)(compressedCipherText[count + 5] & 0xFF) << 7)); + t[4] = (short)(((compressedCipherText[count + 5] & 0xFF) >> 4) | ((ushort)(compressedCipherText[count + 6] & 0xFF) << 4)); + t[5] = (short)(((compressedCipherText[count + 6] & 0xFF) >> 7) | ((ushort)(compressedCipherText[count + 7] & 0xFF) << 1) | ((ushort)((compressedCipherText[count + 8] & 0xFF) << 9))); + t[6] = (short)(((compressedCipherText[count + 8] & 0xFF) >> 2) | ((ushort)(compressedCipherText[count + 9] & 0xFF) << 6)); + t[7] = (short)(((compressedCipherText[count + 9] & 0xFF) >> 5) | ((ushort)(compressedCipherText[count + 10] & 0xFF) << 3)); count += 11; - for (k = 0; k < 8; k++) + for (int k = 0; k < 8; k++) { - Vec[i].Coeffs[8 * j + k] = (short)(((t[k] & 0x7FF) * KyberEngine.Q + 1024) >> 11); + m_vec[i].Coeffs[8 * j + k] = (short)(((t[k] & 0x7FF) * KyberEngine.Q + 1024) >> 11); } } } @@ -198,32 +201,28 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber } } - public void ToBytes(byte[] r) + internal void ToBytes(byte[] r) { - int i; - for (i = 0; i < K; i++) + for (int i = 0; i < m_engine.K; i++) { - Vec[i].ToBytes(r, i * KyberEngine.PolyBytes); + m_vec[i].ToBytes(r, i * KyberEngine.PolyBytes); } } - public void FromBytes(byte[] pk) + internal void FromBytes(byte[] pk) { - int i; - for (i = 0; i < K; i++) + for (int i = 0; i < m_engine.K; i++) { - Vec[i].FromBytes(pk, i * KyberEngine.PolyBytes); + m_vec[i].FromBytes(pk, i * KyberEngine.PolyBytes); } } private void ConditionalSubQ() { - int i; - for (i = 0; i < K; i++) + for (int i = 0; i < m_engine.K; i++) { - Vec[i].CondSubQ(); + m_vec[i].CondSubQ(); } } - } } diff --git a/crypto/src/pqc/crypto/crystals/kyber/Reduce.cs b/crypto/src/pqc/crypto/crystals/kyber/Reduce.cs index b222cdc17..db80d6967 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/Reduce.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/Reduce.cs @@ -1,35 +1,29 @@ - -namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber +namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { internal static class Reduce { - public static short MontgomeryReduce(int a) + internal static short MontgomeryReduce(int a) { - int t; - short u; - - u = (short)(a * KyberEngine.QInv); - t = (int)(u * KyberEngine.Q); + short u = (short)(a * KyberEngine.QInv); + int t = u * KyberEngine.Q; t = a - t; t >>= 16; return (short)t; } - public static short BarrettReduce(short a) + internal static short BarrettReduce(short a) { - short t; short v = (short)(((1U << 26) + (KyberEngine.Q / 2)) / KyberEngine.Q); - t = (short)((v * a) >> 26); + short t = (short)((v * a) >> 26); t = (short)(t * KyberEngine.Q); return (short)(a - t); } - - public static short CondSubQ(short a) + + internal static short CondSubQ(short a) { a -= KyberEngine.Q; - a += (short) ((a >> 15) & KyberEngine.Q); + a += (short)((a >> 15) & KyberEngine.Q); return a; } - } } diff --git a/crypto/src/pqc/crypto/crystals/kyber/Symmetric.cs b/crypto/src/pqc/crypto/crystals/kyber/Symmetric.cs index 711209e2b..d02990635 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/Symmetric.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/Symmetric.cs @@ -1,32 +1,26 @@ using Org.BouncyCastle.Crypto.Digests; -using System; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { internal static class Symmetric { - public static readonly int Shake128Rate = 168; - public static void PRF(byte[] outbuf, int outlen, byte[] key, byte nonce) + internal const int Shake128Rate = 168; + + internal static void Prf(byte[] outbuf, int outlen, byte[] key, byte nonce) { - uint i; - byte[] ExtraKey = new byte[KyberEngine.SymBytes + 1]; - Array.Copy(key, ExtraKey, KyberEngine.SymBytes); - ExtraKey[KyberEngine.SymBytes] = nonce; - ShakeDigest Shake256 = new ShakeDigest(256); - Shake256.BlockUpdate(ExtraKey, 0, KyberEngine.SymBytes + 1); - Shake256.DoFinal(outbuf, 0, outlen); + ShakeDigest shake256 = new ShakeDigest(256); + shake256.BlockUpdate(key, 0, KyberEngine.SymBytes); + shake256.Update(nonce); + shake256.DoFinal(outbuf, 0, outlen); } - public static ShakeDigest XOF(byte[] seed, byte a, byte b) + internal static ShakeDigest Xof(byte[] seed, byte a, byte b) { - ShakeDigest OutDigest = new ShakeDigest(128); - byte[] buf = new byte[seed.Length + 2]; - Array.Copy(seed, buf, seed.Length); - buf[seed.Length] = a; - buf[seed.Length + 1] = b; - OutDigest.BlockUpdate(buf, 0, buf.Length); - return OutDigest; + ShakeDigest shake128 = new ShakeDigest(128); + shake128.BlockUpdate(seed, 0, seed.Length); + shake128.Update(a); + shake128.Update(b); + return shake128; } - } } diff --git a/crypto/test/src/pqc/crypto/test/CrystalsKyberTest.cs b/crypto/test/src/pqc/crypto/test/CrystalsKyberTest.cs index 6130db774..856fe1b7a 100644 --- a/crypto/test/src/pqc/crypto/test/CrystalsKyberTest.cs +++ b/crypto/test/src/pqc/crypto/test/CrystalsKyberTest.cs @@ -91,7 +91,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Tests Assert.True(Arrays.AreEqual(sk, privParams.GetEncoded()), name + " " + count + ": secret key"); // KEM Enc - KyberKEMGenerator KyberEncCipher = new KyberKEMGenerator(random); + KyberKemGenerator KyberEncCipher = new KyberKemGenerator(random); ISecretWithEncapsulation secWenc = KyberEncCipher.GenerateEncapsulated(pubParams); byte[] generated_cipher_text = secWenc.GetEncapsulation(); @@ -111,7 +111,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Tests Assert.True(Arrays.AreEqual(ss, 0, secret.Length, secret, 0, secret.Length), name + " " + count + ": kem_enc key"); // KEM Dec - KyberKEMExtractor KyberDecCipher = new KyberKEMExtractor(privParams); + KyberKemExtractor KyberDecCipher = new KyberKemExtractor(privParams); byte[] dec_key = KyberDecCipher.ExtractSecret(generated_cipher_text); |