summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-10-20 22:50:19 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-10-20 22:50:19 +0700
commite6bfddbc04a51c803ac43e96a8d2361a4cf46b60 (patch)
treec2f3ec67e97ec64e020bc05014c909f0a84e7135
parentInitial import of HQC (diff)
downloadBouncyCastle.NET-ed25519-e6bfddbc04a51c803ac43e96a8d2361a4cf46b60.tar.xz
Refactoring in Pqc.Crypto.Hqc (performance)
-rw-r--r--crypto/src/pqc/crypto/hqc/FastFourierTransform.cs5
-rw-r--r--crypto/src/pqc/crypto/hqc/GF2PolynomialCalculator.cs138
-rw-r--r--crypto/src/pqc/crypto/hqc/GFCalculator.cs9
-rw-r--r--crypto/src/pqc/crypto/hqc/HqcEngine.cs104
-rw-r--r--crypto/src/pqc/crypto/hqc/HqcKeccakRandomGenerator.cs8
-rw-r--r--crypto/src/pqc/crypto/hqc/HqcKemExtractor.cs1
-rw-r--r--crypto/src/pqc/crypto/hqc/HqcKemGenerator.cs5
-rw-r--r--crypto/src/pqc/crypto/hqc/HqcKeyParameters.cs6
-rw-r--r--crypto/src/pqc/crypto/hqc/HqcParameters.cs4
-rw-r--r--crypto/src/pqc/crypto/hqc/HqcPrivateKeyParameters.cs3
-rw-r--r--crypto/src/pqc/crypto/hqc/HqcPublicKeyParameters.cs5
-rw-r--r--crypto/src/pqc/crypto/hqc/ReedMuller.cs24
-rw-r--r--crypto/src/pqc/crypto/hqc/ReedSolomon.cs10
-rw-r--r--crypto/src/pqc/crypto/hqc/Utils.cs137
-rw-r--r--crypto/test/src/pqc/crypto/test/HqcVectorTest.cs2
15 files changed, 153 insertions, 308 deletions
diff --git a/crypto/src/pqc/crypto/hqc/FastFourierTransform.cs b/crypto/src/pqc/crypto/hqc/FastFourierTransform.cs
index f6e033897..be7e822d0 100644
--- a/crypto/src/pqc/crypto/hqc/FastFourierTransform.cs
+++ b/crypto/src/pqc/crypto/hqc/FastFourierTransform.cs
@@ -1,9 +1,4 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
diff --git a/crypto/src/pqc/crypto/hqc/GF2PolynomialCalculator.cs b/crypto/src/pqc/crypto/hqc/GF2PolynomialCalculator.cs
index 0114791e6..8a460932e 100644
--- a/crypto/src/pqc/crypto/hqc/GF2PolynomialCalculator.cs
+++ b/crypto/src/pqc/crypto/hqc/GF2PolynomialCalculator.cs
@@ -1,46 +1,39 @@
-using Org.BouncyCastle.Utilities;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading;
+using System;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+using System.Buffers.Binary;
+using System.Runtime.InteropServices;
+#endif
+
+using Org.BouncyCastle.Math.Raw;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
     internal class GF2PolynomialCalculator
     {
-        static volatile int TABLE = 16;
-        static volatile int WORD = 64;
+        private const int TABLE = 16;
+
         static void Mod(ulong[] res, ulong[] a, int n, int nByte64)
         {
-            ulong r;
-            ulong carry;
             for (int i = 0; i < nByte64; i++)
             {
-                r = a[i + nByte64 - 1] >> (n & 0x3F);
-                carry = a[i + nByte64] << (64 - (n & 0x3F));
+                ulong r = a[i + nByte64 - 1] >> (n & 0x3F);
+                ulong carry = a[i + nByte64] << (64 - (n & 0x3F));
                 res[i] = a[i] ^ r ^ carry;
             }
-            res[nByte64 - 1] &= (ulong) Utils.BitMask(n, 64);
+            res[nByte64 - 1] &= Utils.BitMask((ulong)n, 64);
         }
 
-        static void Swap(int[] table, int fisrtIndex, int secIndex)
+        static void Swap(int[] table, int firstIndex, int secondIndex)
         {
-            int tmp = table[fisrtIndex];
-            table[fisrtIndex] = table[secIndex];
-            table[secIndex] = tmp;
+            int tmp = table[firstIndex];
+            table[firstIndex] = table[secondIndex];
+            table[secondIndex] = tmp;
         }
 
-        static void FastConvolutionMult(ulong[] res, int[] a, long[] b, int weight, int nByte64, int we, HqcKeccakRandomGenerator random)
+        static void FastConvolutionMult(ulong[] res, int[] a, ulong[] b, int weight, int nByte64, int we,
+            HqcKeccakRandomGenerator random)
         {
-            ulong carry;
-            int dec, s;
-            ulong[] table = new ulong[TABLE * (nByte64 + 1)];
             int[] permutedTable = new int[TABLE];
-            int[] permutationTable = new int[TABLE];
-            int[] permutedSparseVect = new int[we];
-            int[] permutationSparseVect = new int[we];
-
             for (int i = 0; i < 16; i++)
             {
                 permutedTable[i] = i;
@@ -49,6 +42,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             byte[] permutationTableByte = new byte[TABLE*2];
             random.ExpandSeed(permutationTableByte, TABLE << 1);
 
+            int[] permutationTable = new int[TABLE];
             Utils.FromByteArrayToByte16Array(permutationTable, permutationTableByte);
 
             for (int i = 0; i < TABLE - 1; i++)
@@ -56,35 +50,18 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
                 Swap(permutedTable, i, i + permutationTable[i] % (TABLE - i));
             }
 
-            //int count = (permutedTable[0] * (nByte64 + 1));
+            ulong[] table = new ulong[TABLE * (nByte64 + 1)];
             int idx = permutedTable[0] * (nByte64 + 1);
-            ulong[] pt = new ulong[nByte64+1];
-
-            for (int i = 0; i < nByte64; i++)
-            {
-                pt[i] = (ulong) b[i];
-            }
-
-            pt[nByte64] = 0x0UL;
-
-            Array.Copy(pt, 0, table, idx, pt.Length);
+            Array.Copy(b, 0, table, idx, nByte64);
+            table[idx + nByte64] = 0UL;
 
             for (int i = 1; i < TABLE; i++)
             {
-                carry = 0x0UL;
                 idx = permutedTable[i] * (nByte64 + 1);
-                ulong[] pt2 = new ulong[nByte64+1];
-
-                for (int j = 0; j < nByte64; j++)
-                {
-                    pt2[j] = ((ulong) b[j] << i) ^ carry;
-                    carry = ((ulong) b[j] >> ((WORD - i)));
-                }
-
-                pt2[nByte64] = carry;
-                Array.Copy(pt2, 0, table, idx, pt2.Length);
+                table[idx + nByte64] = Nat.ShiftUpBits64(nByte64, b, 0, i, 0UL, table, idx);
             }
 
+            int[] permutedSparseVect = new int[we];
             for (int i = 0; i < weight; i++)
             {
                 permutedSparseVect[i] = i;
@@ -93,6 +70,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             byte[] permutationSparseVectBytes = new byte[we * 2];
             random.ExpandSeed(permutationSparseVectBytes, weight << 1);
 
+            int[] permutationSparseVect = new int[we];
             Utils.FromByteArrayToByte16Array(permutationSparseVect, permutationSparseVectBytes);
 
             for (int i = 0; i < (weight - 1); i++)
@@ -100,63 +78,51 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
                 Swap(permutedSparseVect, i, i + permutationSparseVect[i] % (weight - i));
             }
 
-            int[] resByte16 = new int[res.Length * 4];
-
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            Span<byte> resBytes = MemoryMarshal.Cast<ulong, byte>(res);
             for (int i = 0; i < weight; i++)
             {
-                carry = 0x0UL;
-                dec = a[permutedSparseVect[i]] & 0xf;
-                s = a[permutedSparseVect[i]] >> 4;
+                int dec = a[permutedSparseVect[i]] & 0xf;
+                int s = a[permutedSparseVect[i]] >> 4;
 
-                idx = (permutedTable[dec] * (nByte64 + 1));
-                ulong[] pt3 = new ulong[nByte64+1];
-                for (int j = 0; j< pt3.Length; j++)
+                idx = permutedTable[dec] * (nByte64 + 1);
+
+                int count = s * 2 + nByte64 * 8;
+                for (int j = nByte64; j >= 0; --j)
                 {
-                    pt3[j] = table[j + idx];
+                    ulong tmp = BinaryPrimitives.ReadUInt64LittleEndian(resBytes[count..]);
+                    BinaryPrimitives.WriteUInt64LittleEndian(resBytes[count..], tmp ^ table[idx + j]);
+                    count -= 8;
                 }
+            }
+#else
+            ushort[] resByte16 = new ushort[res.Length * 4];
+            for (int i = 0; i < weight; i++)
+            {
+                int dec = a[permutedSparseVect[i]] & 0xf;
+                int s = a[permutedSparseVect[i]] >> 4;
+
+                idx = permutedTable[dec] * (nByte64 + 1);
+
                 int count = s;
-                for (int j = 0; j < nByte64 + 1; j++)
+                for (int j = 0; j <= nByte64; j++)
                 {
-                    ulong tmp = (ulong) (((ulong) resByte16[count]) | (((ulong) resByte16[count + 1]) << 16) | ((ulong) (resByte16[count + 2]) << 32) | (((ulong)(resByte16[count + 3])) << 48));
-                    tmp ^= pt3[j];
-                    AddULongToByte16Array(resByte16, tmp, count);
+                    Utils.XorULongToByte16Array(resByte16, count, table[idx + j]);
                     count += 4;
                 }
             }
-            Utils.FromByte16ArrayToLongArray(res, resByte16);
+            Utils.FromByte16ArrayToULongArray(res, resByte16);
+#endif
         }
 
-        internal static void ModMult(ulong[] res, int[] a, long[] b, int weight,int n,  int nByte64, int we,  HqcKeccakRandomGenerator random)
+        internal static void ModMult(ulong[] res, int[] a, ulong[] b, int weight,int n,  int nByte64, int we,
+            HqcKeccakRandomGenerator random)
         {
             ulong[] tmp = new ulong[(nByte64 << 1) + 1];
             FastConvolutionMult(tmp, a, b, weight, nByte64, we, random);
             Mod(res, tmp, n, nByte64);
         }
 
-        private static void AddULongToByte16Array(int[] array, ulong t, int startIndex)
-        {
-            ulong[] tmp = new ulong[] { t };
-            int[] tmpArray = new int[4];
-            Utils.FromULongArrayToByte16Array(tmpArray, tmp);
-            Array.Copy(tmpArray, 0, array, startIndex, tmpArray.Length);
-        }
-
-        internal static void AddBytes(byte[] res, byte[] a, byte[] b)
-        {
-            for (int i = 0; i < a.Length; i++)
-            {
-                res[i] =(byte) (a[i] ^ b[i]);
-            }
-        }
-
-        internal static void AddLongs(ulong[] res, ulong[] a, long[] b)
-        {
-            for (int i = 0; i < a.Length; i++)
-            {
-                res[i] = a[i] ^ (ulong) b[i];
-            }
-        }
-
         internal static void AddULongs(ulong[] res, ulong[] a, ulong[] b)
         {
             for (int i = 0; i < a.Length; i++)
diff --git a/crypto/src/pqc/crypto/hqc/GFCalculator.cs b/crypto/src/pqc/crypto/hqc/GFCalculator.cs
index 22a7b5b2a..d63e70513 100644
--- a/crypto/src/pqc/crypto/hqc/GFCalculator.cs
+++ b/crypto/src/pqc/crypto/hqc/GFCalculator.cs
@@ -1,11 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Org.BouncyCastle.Pqc.Crypto.Hqc
+namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
     internal class GFCalculator
     {
diff --git a/crypto/src/pqc/crypto/hqc/HqcEngine.cs b/crypto/src/pqc/crypto/hqc/HqcEngine.cs
index 7bc157796..ac1a96f00 100644
--- a/crypto/src/pqc/crypto/hqc/HqcEngine.cs
+++ b/crypto/src/pqc/crypto/hqc/HqcEngine.cs
@@ -1,6 +1,6 @@
-
+using System;
+
 using Org.BouncyCastle.Utilities;
-using System;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
@@ -84,7 +84,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             HqcKeccakRandomGenerator secretKeySeedExpander = new HqcKeccakRandomGenerator(256);
             secretKeySeedExpander.SeedExpanderInit(secretKeySeed, secretKeySeed.Length);
 
-            long[] xLongBytes = new long[N_BYTE_64];
+            ulong[] xLongBytes = new ulong[N_BYTE_64];
             int[] yPos = new int[this.w];
 
             GenerateSecretKey(xLongBytes, secretKeySeedExpander, w);
@@ -97,13 +97,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             HqcKeccakRandomGenerator randomPublic = new HqcKeccakRandomGenerator(256);
             randomPublic.SeedExpanderInit(publicKeySeed, publicKeySeed.Length);
 
-            long[] hLongBytes = new long[N_BYTE_64];
+            ulong[] hLongBytes = new ulong[N_BYTE_64];
             GeneratePublicKeyH(hLongBytes, randomPublic);
 
             // 3. Compute s
             ulong[] s = new ulong[N_BYTE_64];
             GF2PolynomialCalculator.ModMult(s, yPos, hLongBytes, w, n, N_BYTE_64, we, secretKeySeedExpander);
-            GF2PolynomialCalculator.AddLongs(s, s, xLongBytes);
+            GF2PolynomialCalculator.AddULongs(s, s, xLongBytes);
             byte[] sBytes = new byte[N_BYTE];
             Utils.FromULongArrayToByteArray(sBytes, s);
 
@@ -150,13 +150,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 
             // 3. Generate ciphertext c = (u,v)
             // Extract public keys
-            long[] h = new long[N_BYTE_64];
+            ulong[] h = new ulong[N_BYTE_64];
             byte[] s = new byte[N_BYTE];
             ExtractPublicKeys(h, s, pk);
 
-            long[] vTmp = new long[N1N2_BYTE_64];
+            ulong[] vTmp = new ulong[N1N2_BYTE_64];
             Encrypt(u, vTmp, h, s, m, theta);
-            Utils.FromLongArrayToByteArray(v, vTmp);
+            Utils.FromULongArrayToByteArray(v, vTmp);
 
             // 4. Compute d
             shakeDigest.SHAKE256_512_ds(d, m, m.Length, new byte[] { H_FCT_DOMAIN });
@@ -201,15 +201,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 
             // 3. Compute c' = Enc(pk, m', theta')
             // Extract public keys
-            long[] h = new long[N_BYTE_64];
+            ulong[] h = new ulong[N_BYTE_64];
             byte[] s = new byte[N_BYTE];
             ExtractPublicKeys(h, s, pk);
 
             byte[] u2Bytes = new byte[N_BYTE];
             byte[] v2Bytes = new byte[N1N2_BYTE];
-            long[] vTmp = new long[N1N2_BYTE_64];
+            ulong[] vTmp = new ulong[N1N2_BYTE_64];
             Encrypt(u2Bytes, vTmp, h, s, mPrimeBytes, theta);
-            Utils.FromLongArrayToByteArray(v2Bytes, vTmp);
+            Utils.FromULongArrayToByteArray(v2Bytes, vTmp);
 
             // 4. Compute d' = H(m')
             byte[] dPrime = new byte[SHA512_BYTES];
@@ -263,13 +263,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
          * @param u ciphertext
          * @param v ciphertext
          **/
-        private void Encrypt(byte[] u, long[] v, long[] h, byte[] s, byte[] m, byte[] theta)
+        private void Encrypt(byte[] u, ulong[] v, ulong[] h, byte[] s, byte[] m, byte[] theta)
         {
             // Randomly generate e, r1, r2
             HqcKeccakRandomGenerator randomGenerator = new HqcKeccakRandomGenerator(256);
             randomGenerator.SeedExpanderInit(theta, SEED_SIZE);
-            long[] e = new long[N_BYTE_64];
-            long[] r1 = new long[N_BYTE_64];
+            ulong[] e = new ulong[N_BYTE_64];
+            ulong[] r1 = new ulong[N_BYTE_64];
             int[] r2 = new int[wr];
             GenerateSecretKey(r1, randomGenerator, wr);
             GenerateSecretKeyByCoordinates(r2, randomGenerator, wr);
@@ -278,29 +278,28 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             // Calculate u
             ulong[] uLong = new ulong[N_BYTE_64];
             GF2PolynomialCalculator.ModMult(uLong, r2, h, wr, n, N_BYTE_64, we, randomGenerator);
-            GF2PolynomialCalculator.AddLongs(uLong, uLong, r1);
-            Utils.FromULongArrayToByteArray(u,uLong);
+            GF2PolynomialCalculator.AddULongs(uLong, uLong, r1);
+            Utils.FromULongArrayToByteArray(u, uLong);
 
             // Calculate v
             // encode m
             byte[] res = new byte[n1];
-            long[] vLong = new long[N1N2_BYTE_64];
-            long[] tmpVLong = new long[N_BYTE_64];
+            ulong[] vLong = new ulong[N1N2_BYTE_64];
+            ulong[] tmpVLong = new ulong[N_BYTE_64];
             ReedSolomon.Encode(res, m, K_BYTE * 8, n1, k, g, generatorPoly);
             ReedMuller.Encode(vLong, res, n1, mulParam);
             Array.Copy(vLong, 0, tmpVLong, 0, vLong.Length);
 
-
             //Compute v
-            long[] sLong = new long[N_BYTE_64];
-            Utils.FromByteArrayToLongArray(sLong, s);
+            ulong[] sLong = new ulong[N_BYTE_64];
+            Utils.FromByteArrayToULongArray(sLong, s);
 
             ulong[] tmpLong = new ulong[N_BYTE_64];
             GF2PolynomialCalculator.ModMult(tmpLong, r2, sLong, wr, n, N_BYTE_64, we, randomGenerator);
-            GF2PolynomialCalculator.AddLongs(tmpLong, tmpLong, tmpVLong);
-            GF2PolynomialCalculator.AddLongs(tmpLong, tmpLong, e);
+            GF2PolynomialCalculator.AddULongs(tmpLong, tmpLong, tmpVLong);
+            GF2PolynomialCalculator.AddULongs(tmpLong, tmpLong, e);
 
-            Utils.ResizeArray(v, n1n2, Utils.FromULongArrayToLongArray(tmpLong), n, N1N2_BYTE_64, N1N2_BYTE_64);
+            Utils.ResizeArray(v, n1n2, tmpLong, n, N1N2_BYTE_64, N1N2_BYTE_64);
         }
 
         private void Decrypt(byte[] output, byte[] m, byte[] u, byte[] v, int[] y)
@@ -309,38 +308,37 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             HqcKeccakRandomGenerator randomGenerator = new HqcKeccakRandomGenerator(256);
             randomGenerator.SeedExpanderInit(tmpSeed, SEED_SIZE);
 
-            long[] uLongs = new long[N_BYTE_64];
-            Utils.FromByteArrayToLongArray(uLongs, u);
+            ulong[] uLongs = new ulong[N_BYTE_64];
+            Utils.FromByteArrayToULongArray(uLongs, u);
 
-            long[] vLongs = new long[N1N2_BYTE_64];
-            Utils.FromByteArrayToLongArray(vLongs, v);
+            ulong[] vLongs = new ulong[N1N2_BYTE_64];
+            Utils.FromByteArrayToULongArray(vLongs, v);
 
-            long[] tmpV = new long[N_BYTE_64];
+            ulong[] tmpV = new ulong[N_BYTE_64];
             Array.Copy(vLongs, 0, tmpV, 0, vLongs.Length);
 
             ulong[] tmpLong = new ulong[N_BYTE_64];
             GF2PolynomialCalculator.ModMult(tmpLong, y, uLongs, w, n, N_BYTE_64, we, randomGenerator);
-            GF2PolynomialCalculator.AddLongs(tmpLong, tmpLong, tmpV);
+            GF2PolynomialCalculator.AddULongs(tmpLong, tmpLong, tmpV);
 
             // Decode res
             byte[] tmp = new byte[n1];
-            ReedMuller.decode(tmp, Utils.FromULongArrayToLongArray(tmpLong), n1, mulParam);
-            ReedSolomon.decode(m, tmp, n1, fft, delta, k, g);
+            ReedMuller.Decode(tmp, tmpLong, n1, mulParam);
+            ReedSolomon.Decode(m, tmp, n1, fft, delta, k, g);
 
-           Array.Copy(m, 0, output, 0, output.Length);
+            Array.Copy(m, 0, output, 0, output.Length);
         }
 
-        private void GenerateSecretKey(long[] output, HqcKeccakRandomGenerator random, int w)
+        private void GenerateSecretKey(ulong[] output, HqcKeccakRandomGenerator random, int w)
         {
             int[] tmp = new int[w];
-
             GenerateSecretKeyByCoordinates(tmp, random, w);
 
             for (int i = 0; i < w; ++i)
             {
                 int index = tmp[i] / 64;
                 int pos = tmp[i] % 64;
-                long t = ((1L) << pos);
+                ulong t = 1UL << pos;
                 output[index] |= t;
             }
         }
@@ -384,57 +382,55 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             }
         }
 
-        void GeneratePublicKeyH(long[] output, HqcKeccakRandomGenerator random)
+        void GeneratePublicKeyH(ulong[] output, HqcKeccakRandomGenerator random)
         {
             byte[] randBytes = new byte[N_BYTE];
             random.ExpandSeed(randBytes, N_BYTE);
-            long[] tmp = new long[N_BYTE_64];
-            Utils.FromByteArrayToLongArray(tmp, randBytes);
-            tmp[N_BYTE_64 - 1] &= Utils.BitMask(n, 64);
+            ulong[] tmp = new ulong[N_BYTE_64];
+            Utils.FromByteArrayToULongArray(tmp, randBytes);
+            tmp[N_BYTE_64 - 1] &= Utils.BitMask((ulong)n, 64);
             Array.Copy(tmp, 0, output, 0, output.Length);
         }
 
-
-
-        private void ExtractPublicKeys(long[] h, byte[] s, byte[] pk)
+        private void ExtractPublicKeys(ulong[] h, byte[] s, byte[] pk)
         {
             byte[] publicKeySeed = new byte[SEED_SIZE];
-           Array.Copy(pk, 0, publicKeySeed, 0, publicKeySeed.Length);
+            Array.Copy(pk, 0, publicKeySeed, 0, publicKeySeed.Length);
 
             HqcKeccakRandomGenerator randomPublic = new HqcKeccakRandomGenerator(256);
             randomPublic.SeedExpanderInit(publicKeySeed, publicKeySeed.Length);
 
-           long[] hLongBytes = new long[N_BYTE_64];
+            ulong[] hLongBytes = new ulong[N_BYTE_64];
             GeneratePublicKeyH(hLongBytes, randomPublic);
 
-           Array.Copy(hLongBytes, 0, h, 0, h.Length);
-           Array.Copy(pk, 40, s, 0, s.Length);
+            Array.Copy(hLongBytes, 0, h, 0, h.Length);
+            Array.Copy(pk, 40, s, 0, s.Length);
         }
 
         private void ExtractKeysFromSecretKeys(int[] y, byte[] pk, byte[] sk)
         {
             byte[] secretKeySeed = new byte[SEED_SIZE];
-           Array.Copy(sk, 0, secretKeySeed, 0, secretKeySeed.Length);
+            Array.Copy(sk, 0, secretKeySeed, 0, secretKeySeed.Length);
 
             // Randomly generate secret keys x, y
             HqcKeccakRandomGenerator secretKeySeedExpander = new HqcKeccakRandomGenerator(256);
             secretKeySeedExpander.SeedExpanderInit(secretKeySeed, secretKeySeed.Length);
 
-            long[] xLongBytes = new long[N_BYTE_64];
+            ulong[] xLongBytes = new ulong[N_BYTE_64];
             int[] yPos = new int[this.w];
 
             GenerateSecretKey(xLongBytes, secretKeySeedExpander, w);
             GenerateSecretKeyByCoordinates(yPos, secretKeySeedExpander, w);
 
-           Array.Copy(yPos, 0, y, 0, yPos.Length);
-           Array.Copy(sk, SEED_SIZE, pk, 0, pk.Length);
+            Array.Copy(yPos, 0, y, 0, yPos.Length);
+            Array.Copy(sk, SEED_SIZE, pk, 0, pk.Length);
         }
 
         private static void ExtractCiphertexts(byte[] u, byte[] v, byte[] d, byte[] ct)
         {
-           Array.Copy(ct, 0, u, 0, u.Length);
-           Array.Copy(ct, u.Length, v, 0, v.Length);
-           Array.Copy(ct, u.Length + v.Length, d, 0, d.Length);
+            Array.Copy(ct, 0, u, 0, u.Length);
+            Array.Copy(ct, u.Length, v, 0, v.Length);
+            Array.Copy(ct, u.Length + v.Length, d, 0, d.Length);
         }
     }
 }
diff --git a/crypto/src/pqc/crypto/hqc/HqcKeccakRandomGenerator.cs b/crypto/src/pqc/crypto/hqc/HqcKeccakRandomGenerator.cs
index 83e7bf1af..655abb82f 100644
--- a/crypto/src/pqc/crypto/hqc/HqcKeccakRandomGenerator.cs
+++ b/crypto/src/pqc/crypto/hqc/HqcKeccakRandomGenerator.cs
@@ -1,10 +1,6 @@
-using Org.BouncyCastle.Crypto.Utilities;
+using System;
+
 using Org.BouncyCastle.Utilities;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
diff --git a/crypto/src/pqc/crypto/hqc/HqcKemExtractor.cs b/crypto/src/pqc/crypto/hqc/HqcKemExtractor.cs
index 9dfbd2018..32890f80b 100644
--- a/crypto/src/pqc/crypto/hqc/HqcKemExtractor.cs
+++ b/crypto/src/pqc/crypto/hqc/HqcKemExtractor.cs
@@ -1,4 +1,5 @@
 using Org.BouncyCastle.Crypto;
+
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
     public class HqcKemExtractor : IEncapsulatedSecretExtractor
diff --git a/crypto/src/pqc/crypto/hqc/HqcKemGenerator.cs b/crypto/src/pqc/crypto/hqc/HqcKemGenerator.cs
index 30c81ad27..918dadd38 100644
--- a/crypto/src/pqc/crypto/hqc/HqcKemGenerator.cs
+++ b/crypto/src/pqc/crypto/hqc/HqcKemGenerator.cs
@@ -1,7 +1,8 @@
-using Org.BouncyCastle.Crypto;
+using System;
+
+using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Utilities;
-using System;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
diff --git a/crypto/src/pqc/crypto/hqc/HqcKeyParameters.cs b/crypto/src/pqc/crypto/hqc/HqcKeyParameters.cs
index 54e42455e..8fc900a64 100644
--- a/crypto/src/pqc/crypto/hqc/HqcKeyParameters.cs
+++ b/crypto/src/pqc/crypto/hqc/HqcKeyParameters.cs
@@ -1,10 +1,4 @@
 using Org.BouncyCastle.Crypto;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
diff --git a/crypto/src/pqc/crypto/hqc/HqcParameters.cs b/crypto/src/pqc/crypto/hqc/HqcParameters.cs
index 641e557f0..da5948296 100644
--- a/crypto/src/pqc/crypto/hqc/HqcParameters.cs
+++ b/crypto/src/pqc/crypto/hqc/HqcParameters.cs
@@ -30,8 +30,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
         private int[] generatorPoly;
         private int defaultKeySize;
 
-        volatile internal static int PARAM_M = 8;
-        volatile internal static int GF_MUL_ORDER = 255;
+        internal const int PARAM_M = 8;
+        internal const int GF_MUL_ORDER = 255;
 
         private HqcEngine hqcEngine;
 
diff --git a/crypto/src/pqc/crypto/hqc/HqcPrivateKeyParameters.cs b/crypto/src/pqc/crypto/hqc/HqcPrivateKeyParameters.cs
index 703f778bd..96963e53c 100644
--- a/crypto/src/pqc/crypto/hqc/HqcPrivateKeyParameters.cs
+++ b/crypto/src/pqc/crypto/hqc/HqcPrivateKeyParameters.cs
@@ -1,5 +1,4 @@
-
-using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
diff --git a/crypto/src/pqc/crypto/hqc/HqcPublicKeyParameters.cs b/crypto/src/pqc/crypto/hqc/HqcPublicKeyParameters.cs
index 678e65975..a87d24704 100644
--- a/crypto/src/pqc/crypto/hqc/HqcPublicKeyParameters.cs
+++ b/crypto/src/pqc/crypto/hqc/HqcPublicKeyParameters.cs
@@ -1,9 +1,4 @@
 using Org.BouncyCastle.Utilities;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
diff --git a/crypto/src/pqc/crypto/hqc/ReedMuller.cs b/crypto/src/pqc/crypto/hqc/ReedMuller.cs
index ac23cf75f..5f1f8e2bf 100644
--- a/crypto/src/pqc/crypto/hqc/ReedMuller.cs
+++ b/crypto/src/pqc/crypto/hqc/ReedMuller.cs
@@ -1,9 +1,6 @@
-using Org.BouncyCastle.Utilities;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System;
+
+using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
@@ -59,9 +56,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
                 }
 
                 //swap srcCode and desCode
-                int[] tmp = Arrays.Clone(srcCodeCopy);
-                srcCodeCopy = Arrays.Clone(desCodeCopy);
-                desCodeCopy = Arrays.Clone(tmp);
+                int[] tmp = srcCodeCopy; srcCodeCopy = desCodeCopy; desCodeCopy = tmp;
             }
 
             // swap
@@ -122,7 +117,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             return (int) ((-(b & 1)) & 0xffffffff);
         }
 
-        public static void Encode(long[] codeword, byte[] m, int n1, int mulParam)
+        public static void Encode(ulong[] codeword, byte[] m, int n1, int mulParam)
         {
             byte[] mBytes = Arrays.Clone(m);
 
@@ -152,17 +147,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
                 off += 4;
             }
 
-            Utils.FromByte32ArrayToLongArray(codeword, cwd64);
+            Utils.FromByte32ArrayToULongArray(codeword, cwd64);
         }
 
-
-        public static void decode(byte[] m, long[] codeword, int n1, int mulParam)
+        public static void Decode(byte[] m, ulong[] codeword, int n1, int mulParam)
         {
             byte[] mBytes = Arrays.Clone(m);
 
             Codeword[] codewordCopy = new Codeword[codeword.Length / 2]; // because each codewordCopy has a 32 bit array size 4
             int[] byteCodeWords = new int[codeword.Length * 2];
-            Utils.FromLongArrayToByte32Array(byteCodeWords, codeword);
+            Utils.FromULongArrayToByte32Array(byteCodeWords, codeword);
 
             for (int i = 0; i < codewordCopy.Length; i++)
             {
@@ -195,7 +189,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
                 Array.Copy(codewordCopy[i].type32, 0, cwd64, off, codewordCopy[i].type32.Length);
                 off += 4;
             }
-            Utils.FromByte32ArrayToLongArray(codeword, cwd64);
+            Utils.FromByte32ArrayToULongArray(codeword, cwd64);
             Array.Copy(mBytes, 0, m, 0, m.Length);
         }
     }
diff --git a/crypto/src/pqc/crypto/hqc/ReedSolomon.cs b/crypto/src/pqc/crypto/hqc/ReedSolomon.cs
index 043b5221b..8e7fc664d 100644
--- a/crypto/src/pqc/crypto/hqc/ReedSolomon.cs
+++ b/crypto/src/pqc/crypto/hqc/ReedSolomon.cs
@@ -1,10 +1,6 @@
-using Org.BouncyCastle.Pqc.Crypto.Hqc;
+using System;
+
 using Org.BouncyCastle.Utilities;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
@@ -47,7 +43,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
         }
 
         // Decode
-        internal static void decode(byte[] message, byte[] codeWord, int n1, int fft, int delta, int paramK, int paramG)
+        internal static void Decode(byte[] message, byte[] codeWord, int n1, int fft, int delta, int paramK, int paramG)
         {
             int fftSize = 1 << fft;
             int mSize = 1 << (HqcParameters.PARAM_M - 1);
diff --git a/crypto/src/pqc/crypto/hqc/Utils.cs b/crypto/src/pqc/crypto/hqc/Utils.cs
index a03633e64..bbd72b05b 100644
--- a/crypto/src/pqc/crypto/hqc/Utils.cs
+++ b/crypto/src/pqc/crypto/hqc/Utils.cs
@@ -1,19 +1,15 @@
-using Org.BouncyCastle.Crypto.Utilities;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Text;
-using System.Threading.Tasks;
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
 
 namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 {
     internal class Utils
     {
-        internal static void ResizeArray(long[] output, int sizeOutBits, long[] input, int sizeInBits, int n1n2ByteSize, int n1n2Byte64Size)
+        internal static void ResizeArray(ulong[] output, int sizeOutBits, ulong[] input, int sizeInBits,
+            int n1n2ByteSize, int n1n2Byte64Size)
         {
-
-            long mask = 0x7FFFFFFFFFFFFFFFl;
+            ulong mask = 0x7FFFFFFFFFFFFFFFUL;
             int val = 0;
             if (sizeOutBits < sizeInBits)
             {
@@ -26,7 +22,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
 
                 for (int i = 0; i < val; ++i)
                 {
-                    output[n1n2Byte64Size - 1] &= (mask >> i);
+                    output[n1n2Byte64Size - 1] &= mask >> i;
                 }
             }
             else
@@ -35,79 +31,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             }
         }
 
-        internal static long[] FromULongArrayToLongArray(ulong[] input)
-        {
-            long[] output = new long[input.Length];
-            for (int i =0; i< output.Length; i++)
-            {
-                output[i] = (long) input[i];
-            }
-            return output;
-        }
-
-        internal static void FromByteArrayToBitArray(byte[] output, byte[] input)
-        {
-            int max = (output.Length / 8);
-            for (int i = 0; i < max; i++)
-            {
-                for (int j = 0; j != 8; j++)
-                {
-                    output[i * 8 + j] = (byte) UnsignedRightBitShiftLong((input[i] & (1 << j)), j);
-                }
-            }
-            if (output.Length % 8 != 0)
-            {
-                int off = max * 8;
-                int count = 0;
-                while (off < output.Length)
-                {
-                    output[off++] = (byte) UnsignedRightBitShiftLong((input[max] & (1 << count)), count);
-                    count++;
-                }
-            }
-        }
-
-        internal static void FromLongArrayToBitArray(byte[] output, long[] input)
-        {
-            int max = (output.Length / 64);
-            for (int i = 0; i < max; i++)
-            {
-                for (int j = 0; j != 64; j++)
-                {
-                    output[i * 64 + j] = (byte)UnsignedRightBitShiftLong((input[i] & (1L << j)), j);
-                }
-            }
-            if (output.Length % 64 != 0)
-            {
-                int off = max * 64;
-                int count = 0;
-                while (off < output.Length)
-                {
-                    output[off++] = (byte) UnsignedRightBitShiftLong((input[max] & (1L << count)), count);
-                    count++;
-                }
-            }
-        }
-
-        internal static void FromLongArrayToByteArray(byte[] output, long[] input)
-        {
-            int max = output.Length / 8;
-            for (int i = 0; i != max; i++)
-            {
-                Pack.UInt64_To_LE((ulong) input[i], output, i * 8); 
-            }
-
-            if (output.Length % 8 != 0)
-            {
-                int off = max * 8;
-                int count = 0;
-                while (off < output.Length)
-                {
-                    output[off++] = (byte) UnsignedRightBitShiftLong(input[max], (count++ * 8));
-                }
-            }
-        }
-
         internal static void FromULongArrayToByteArray(byte[] output, ulong[] input)
         {
             int max = output.Length / 8;
@@ -127,13 +50,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             }
         }
 
-        internal static long BitMask(long a, long b)
+        internal static ulong BitMask(ulong a, ulong b)
         {
-            int tmp = (int) (a % b);
-            return ((1L << tmp) - 1);
+            uint tmp = (uint)(a % b);
+            return ((1UL << (int)tmp) - 1);
         }
 
-        internal static void FromByteArrayToLongArray(long[] output, byte[] input)
+        internal static void FromByteArrayToULongArray(ulong[] output, byte[] input)
         {
             byte[] tmp = input;
             if (input.Length % 8 != 0)
@@ -145,7 +68,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             int off = 0;
             for (int i = 0; i < output.Length; i++)
             {
-                output[i] = (long) Pack.LE_To_UInt64(tmp, off);
+                output[i] = Pack.LE_To_UInt64(tmp, off);
                 off += 8;
             }
         }
@@ -167,38 +90,27 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             }
         }
 
-        internal static void FromByte32ArrayToLongArray(long[] output, int[] input)
+        internal static void FromByte32ArrayToULongArray(ulong[] output, int[] input)
         {
             for (int i = 0; i != input.Length; i += 2)
             {
-                output[i / 2] = input[i] & 0xffffffffL;
-                output[i / 2] |= (long)input[i + 1] << 32;
+                output[i / 2] = (uint)input[i];
+                output[i / 2] |= (ulong)input[i + 1] << 32;
             }
         }
 
-        internal static void FromByte16ArrayToLongArray(ulong[] output, int[] input)
+        internal static void FromByte16ArrayToULongArray(ulong[] output, ushort[] input)
         {
             for (int i = 0; i != input.Length; i += 4)
             {
-                output[i / 4] = (ulong) input[i] & 0xffffL;
-                output[i / 4] |= (ulong) input[i + 1] << 16;
-                output[i / 4] |= (ulong) input[i + 2] << 32;
-                output[i / 4] |= (ulong) input[i + 3] << 48;
-            }
-        }
-
-        internal static void FromULongArrayToByte16Array(int[] output, ulong[] input)
-        {
-            for (int i = 0; i != input.Length; i++)
-            {
-                output[4 * i] = (UInt16)input[i];
-                output[4 * i + 1] = (UInt16)(input[i] >> 16);
-                output[4 * i + 2] = (UInt16)(input[i] >> 32);
-                output[4 * i + 3] = (UInt16)(input[i] >> 48);
+                output[i / 4] = input[i];
+                output[i / 4] |= (ulong)input[i + 1] << 16;
+                output[i / 4] |= (ulong)input[i + 2] << 32;
+                output[i / 4] |= (ulong)input[i + 3] << 48;
             }
         }
 
-        internal static void FromLongArrayToByte32Array(int[] output, long[] input)
+        internal static void FromULongArrayToByte32Array(int[] output, ulong[] input)
         {
             for (int i = 0; i != input.Length; i++)
             {
@@ -239,5 +151,12 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc
             return (long)tmp;
         }
 
+        internal static void XorULongToByte16Array(ushort[] output, int outOff, ulong input)
+        {
+            output[outOff + 0] ^= (ushort)input;
+            output[outOff + 1] ^= (ushort)(input >> 16);
+            output[outOff + 2] ^= (ushort)(input >> 32);
+            output[outOff + 3] ^= (ushort)(input >> 48);
+        }
     }
 }
diff --git a/crypto/test/src/pqc/crypto/test/HqcVectorTest.cs b/crypto/test/src/pqc/crypto/test/HqcVectorTest.cs
index a881b73c2..108508f9d 100644
--- a/crypto/test/src/pqc/crypto/test/HqcVectorTest.cs
+++ b/crypto/test/src/pqc/crypto/test/HqcVectorTest.cs
@@ -47,7 +47,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Tests
         private static void RunTestVector(string name, IDictionary<string, string> buf)
         {
             string count = buf["count"];
-            byte[] seed = Hex.Decode(buf["seed"]); // seed for Cmce secure random
+            byte[] seed = Hex.Decode(buf["seed"]); // seed for SecureRandom
             byte[] pk = Hex.Decode(buf["pk"]);     // public key
             byte[] sk = Hex.Decode(buf["sk"]);     // private key
             byte[] ct = Hex.Decode(buf["ct"]);     // ciphertext