diff options
Diffstat (limited to 'crypto/src')
-rw-r--r-- | crypto/src/pqc/crypto/hqc/GF2PolynomialCalculator.cs | 266 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/hqc/GFCalculator.cs | 4 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/hqc/HqcEngine.cs | 258 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/hqc/HqcKeccakRandomGenerator.cs | 13 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/hqc/HqcKemExtractor.cs | 2 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/hqc/HqcKemGenerator.cs | 13 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/hqc/HqcKeyPairGenerator.cs | 18 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/hqc/HqcParameters.cs | 7 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/hqc/ReedMuller.cs | 15 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/hqc/ReedSolomon.cs | 1 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/hqc/Utils.cs | 25 |
11 files changed, 364 insertions, 258 deletions
diff --git a/crypto/src/pqc/crypto/hqc/GF2PolynomialCalculator.cs b/crypto/src/pqc/crypto/hqc/GF2PolynomialCalculator.cs index 0c01ade96..48774cde3 100644 --- a/crypto/src/pqc/crypto/hqc/GF2PolynomialCalculator.cs +++ b/crypto/src/pqc/crypto/hqc/GF2PolynomialCalculator.cs @@ -1,129 +1,223 @@ -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 +namespace Org.BouncyCastle.Pqc.Crypto.Hqc { internal class GF2PolynomialCalculator { - private const int TABLE = 16; + private readonly int _vecNSize64; + private readonly int _paramN; + private readonly long _redMask; - static void Mod(ulong[] res, ulong[] a, int n, int nByte64) + public GF2PolynomialCalculator(int vecNSize64, int paramN, ulong redMask) { - for (int i = 0; i < nByte64; i++) - { - 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] &= Utils.BitMask((ulong)n, 64); + _vecNSize64 = vecNSize64; + _paramN = paramN; + _redMask = (long)redMask; } - static void Swap(int[] table, int firstIndex, int secondIndex) + internal void MultLongs(long[] res, long[] a, long[] b) { - int tmp = table[firstIndex]; - table[firstIndex] = table[secondIndex]; - table[secondIndex] = tmp; + long[] stack = new long[_vecNSize64 << 3]; + long[] oKarat = new long[(_vecNSize64 << 1) + 1]; + + karatsuba(oKarat, 0, a, 0, b, 0, _vecNSize64, stack, 0); + reduce(res, oKarat); } - static void FastConvolutionMult(ulong[] res, int[] a, ulong[] b, int weight, int nByte64, int we, - HqcKeccakRandomGenerator random) + + private void base_mul(long[] c, int cOffset, long a, long b) { - int[] permutedTable = new int[TABLE]; - for (int i = 0; i < 16; i++) + long h = 0; + long l = 0; + long g; + long[] u = new long[16]; + long[] maskTab = new long[4]; + + // Step 1 + u[0] = 0; + u[1] = b & ((1L << (64 - 4)) - 1L); + u[2] = u[1] << 1; + u[3] = u[2] ^ u[1]; + u[4] = u[2] << 1; + u[5] = u[4] ^ u[1]; + u[6] = u[3] << 1; + u[7] = u[6] ^ u[1]; + u[8] = u[4] << 1; + u[9] = u[8] ^ u[1]; + u[10] = u[5] << 1; + u[11] = u[10] ^ u[1]; + u[12] = u[6] << 1; + u[13] = u[12] ^ u[1]; + u[14] = u[7] << 1; + u[15] = u[14] ^ u[1]; + + g=0; + long tmp1 = a & 15; + + for(int i = 0; i < 16; i++) { - permutedTable[i] = i; + long tmp2 = tmp1 - i; + g ^= (u[i] & -(1 - (long)((ulong)(tmp2 | -tmp2) >> 63))); } + l = g; + h = 0; - 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++) + // Step 2 + for (byte i = 4; i < 64; i += 4) { - Swap(permutedTable, i, i + permutationTable[i] % (TABLE - i)); + g = 0; + long temp1 = (a >> i) & 15; + for (int j = 0; j < 16; ++j) + { + long tmp2 = temp1 - j; + g ^= (u[j] & -(1 - (long)((ulong)(tmp2 | -tmp2) >> 63))); + } + + l ^= g << i; + h ^= (long)((ulong)g) >> (64 - i); } - ulong[] table = new ulong[TABLE * (nByte64 + 1)]; - int idx = permutedTable[0] * (nByte64 + 1); - Array.Copy(b, 0, table, idx, nByte64); - table[idx + nByte64] = 0UL; + // Step 3 + maskTab [0] = -((b >> 60) & 1); + maskTab [1] = -((b >> 61) & 1); + maskTab [2] = -((b >> 62) & 1); + maskTab [3] = -((b >> 63) & 1); + + l ^= ((a << 60) & maskTab[0]); + h ^= ((long)((ulong)a >> 4) & maskTab[0]); + + l ^= ((a << 61) & maskTab[1]); + h ^= ((long)((ulong)a >> 3) & maskTab[1]); - for (int i = 1; i < TABLE; i++) + l ^= ((a << 62) & maskTab[2]); + h ^= ((long)((ulong)a >> 2) & maskTab[2]); + + l ^= ((a << 63) & maskTab[3]); + h ^= ((long)((ulong)a >> 1) & maskTab[3]); + + c[0 + cOffset] = l; + c[1 + cOffset] = h; + } + + + + + private void karatsuba_add1(long[] alh, int alhOffset, + long[] blh, int blhOffset, + long[] a, int aOffset, + long[] b, int bOffset, + int size_l, int size_h) + { + for (int i = 0; i < size_h; i++) { - idx = permutedTable[i] * (nByte64 + 1); - table[idx + nByte64] = Nat.ShiftUpBits64(nByte64, b, 0, i, 0UL, table, idx); + alh[i + alhOffset] = a[i+ aOffset] ^ a[i + size_l + aOffset]; + blh[i + blhOffset] = b[i+ bOffset] ^ b[i + size_l + bOffset]; } - int[] permutedSparseVect = new int[we]; - for (int i = 0; i < weight; i++) + if (size_h < size_l) { - permutedSparseVect[i] = i; + alh[size_h + alhOffset] = a[size_h + aOffset]; + blh[size_h + blhOffset] = b[size_h + bOffset]; } + } - 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++) + private void karatsuba_add2(long[] o, int oOffset, + long[] tmp1, int tmp1Offset, + long[] tmp2, int tmp2Offset, + int size_l, int size_h) + { + for (int i = 0; i < (2 * size_l) ; i++) { - Swap(permutedSparseVect, i, i + permutationSparseVect[i] % (weight - i)); + tmp1[i + tmp1Offset] = tmp1[i + tmp1Offset] ^ o[i + oOffset]; } -#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - Span<byte> resBytes = MemoryMarshal.AsBytes(res.AsSpan()); - for (int i = 0; i < weight; i++) + for (int i = 0; i < ( 2 * size_h); i++) { - int dec = a[permutedSparseVect[i]] & 0xf; - int s = a[permutedSparseVect[i]] >> 4; - - idx = permutedTable[dec] * (nByte64 + 1); - - int count = s * 2 + nByte64 * 8; - for (int j = nByte64; j >= 0; --j) - { - ulong tmp = BinaryPrimitives.ReadUInt64LittleEndian(resBytes[count..]); - BinaryPrimitives.WriteUInt64LittleEndian(resBytes[count..], tmp ^ table[idx + j]); - count -= 8; - } + tmp1[i + tmp1Offset] = tmp1[i + tmp1Offset] ^ tmp2[i + tmp2Offset]; } -#else - ushort[] resByte16 = new ushort[res.Length * 4]; - for (int i = 0; i < weight; i++) + + for (int i = 0; i < (2 * size_l); i++) { - int dec = a[permutedSparseVect[i]] & 0xf; - int s = a[permutedSparseVect[i]] >> 4; + o[i + size_l + oOffset] = o[i + size_l + oOffset] ^ tmp1[i + tmp1Offset]; + } + } - idx = permutedTable[dec] * (nByte64 + 1); - int count = s; - for (int j = 0; j <= nByte64; j++) - { - Utils.XorULongToByte16Array(resByte16, count, table[idx + j]); - count += 4; - } + + /** + * Karatsuba multiplication of a and b, Implementation inspired from the NTL library. + * + * \param[out] o Polynomial + * \param[in] a Polynomial + * \param[in] b Polynomial + * \param[in] size Length of polynomial + * \param[in] stack Length of polynomial + */ + private void karatsuba(long[] o, int oOffset, long[] a, int aOffset, long[] b, int bOffset, int size, long[] stack, int stackOffset) + { + int size_l, size_h; + int ahOffset, bhOffset; + + if (size == 1) + { + base_mul(o, oOffset, a[0 + aOffset], b[0 + bOffset]); + return; } - Utils.FromByte16ArrayToULongArray(res, resByte16); -#endif + + size_h = size / 2; + size_l = (size + 1) / 2; + + // alh = stack + int alhOffset = stackOffset; + // blh = stack with size_l offset + int blhOffset = alhOffset + size_l; + // tmp1 = stack with size_l * 2 offset; + int tmp1Offset = blhOffset + size_l; + // tmp2 = o with size_l * 2 offset; + int tmp2Offset = oOffset + size_l*2; + + stackOffset += 4 * size_l; + + ahOffset = aOffset + size_l; + bhOffset = bOffset + size_l; + + karatsuba(o, oOffset, a, aOffset, b, bOffset, size_l, stack, stackOffset); + + karatsuba(o, tmp2Offset, a, ahOffset, b, bhOffset, size_h, stack, stackOffset); + + karatsuba_add1(stack, alhOffset, stack, blhOffset, a, aOffset, b, bOffset, size_l, size_h); + + karatsuba(stack, tmp1Offset, stack, alhOffset, stack, blhOffset, size_l, stack, stackOffset); + + karatsuba_add2(o, oOffset, stack, tmp1Offset, o, tmp2Offset, size_l, size_h); } - internal static void ModMult(ulong[] res, int[] a, ulong[] b, int weight,int n, int nByte64, int we, - HqcKeccakRandomGenerator random) + + + /** + * @brief Compute o(x) = a(x) mod \f$ X^n - 1\f$ + * + * This function computes the modular reduction of the polynomial a(x) + * + * @param[in] a Pointer to the polynomial a(x) + * @param[out] o Pointer to the result + */ + private void reduce(long[] o, long[] a) { - ulong[] tmp = new ulong[(nByte64 << 1) + 1]; - FastConvolutionMult(tmp, a, b, weight, nByte64, we, random); - Mod(res, tmp, n, nByte64); + int i; + long r; + long carry; + + for (i = 0; i < _vecNSize64; i++) + { + r = (long)((ulong)a[i + _vecNSize64 - 1] >> (_paramN & 0x3F)); + carry = a[i + _vecNSize64 ] << (int)(64 - (_paramN & 0x3FL)); + o[i] = a[i] ^ r ^ carry; + } + o[_vecNSize64 - 1] &= _redMask; } - internal static void AddULongs(ulong[] res, ulong[] a, ulong[] b) + internal static void AddLongs(long[] res, long[] a, long[] 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 d63e70513..ab0359b3b 100644 --- a/crypto/src/pqc/crypto/hqc/GFCalculator.cs +++ b/crypto/src/pqc/crypto/hqc/GFCalculator.cs @@ -2,8 +2,8 @@ { internal class GFCalculator { - static int[] exp = new int[] { 1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76, 152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96, 192, 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119, 238, 193, 159, 35, 70, 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210, 185, 111, 222, 161, 95, 190, 97, 194, 153, 47, 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231, 211, 187, 107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217, 175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103, 206, 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197, 151, 51, 102, 204, 133, 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, 132, 21, 42, 84, 168, 77, 154, 41, 82, 164, 85, 170, 73, 146, 57, 114, 228, 213, 183, 115, 230, 209, 191, 99, 198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227, 219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87, 174, 65, 130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, 221, 167, 83, 166, 81, 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, 18, 36, 72, 144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, 11, 22, 44, 88, 176, 125, 250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142, 1, 2, 4 }; - static int[] log = new int[] { 0, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, 4, 100, 224, 14, 52, 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113, 5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240, 18, 130, 69, 29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9, 120, 77, 228, 114, 166, 6, 191, 139, 98, 102, 221, 48, 253, 226, 152, 37, 179, 16, 145, 34, 136, 54, 208, 148, 206, 143, 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 66, 182, 163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61, 202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115, 243, 167, 87, 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, 237, 49, 197, 254, 24, 227, 165, 153, 119, 38, 184, 180, 124, 17, 68, 146, 217, 35, 32, 137, 46, 55, 63, 209, 91, 149, 188, 207, 205, 144, 135, 151, 178, 220, 252, 190, 97, 242, 86, 211, 171, 20, 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, 31, 45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12, 111, 246, 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, 177, 187, 204, 62, 90, 203, 89, 95, 176, 156, 169, 160, 81, 11, 245, 22, 235, 122, 117, 44, 215, 79, 174, 213, 233, 230, 231, 173, 232, 116, 214, 244, 234, 168, 80, 88, 175 }; + static int[] exp = { 1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76, 152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96, 192, 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119, 238, 193, 159, 35, 70, 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210, 185, 111, 222, 161, 95, 190, 97, 194, 153, 47, 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231, 211, 187, 107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217, 175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103, 206, 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197, 151, 51, 102, 204, 133, 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, 132, 21, 42, 84, 168, 77, 154, 41, 82, 164, 85, 170, 73, 146, 57, 114, 228, 213, 183, 115, 230, 209, 191, 99, 198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227, 219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87, 174, 65, 130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, 221, 167, 83, 166, 81, 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, 18, 36, 72, 144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, 11, 22, 44, 88, 176, 125, 250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142, 1, 2, 4 }; + static int[] log = { 0, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, 4, 100, 224, 14, 52, 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113, 5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240, 18, 130, 69, 29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9, 120, 77, 228, 114, 166, 6, 191, 139, 98, 102, 221, 48, 253, 226, 152, 37, 179, 16, 145, 34, 136, 54, 208, 148, 206, 143, 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 66, 182, 163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61, 202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115, 243, 167, 87, 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, 237, 49, 197, 254, 24, 227, 165, 153, 119, 38, 184, 180, 124, 17, 68, 146, 217, 35, 32, 137, 46, 55, 63, 209, 91, 149, 188, 207, 205, 144, 135, 151, 178, 220, 252, 190, 97, 242, 86, 211, 171, 20, 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, 31, 45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12, 111, 246, 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, 177, 187, 204, 62, 90, 203, 89, 95, 176, 156, 169, 160, 81, 11, 245, 22, 235, 122, 117, 44, 215, 79, 174, 213, 233, 230, 231, 173, 232, 116, 214, 244, 234, 168, 80, 88, 175 }; internal static int mult(int a, int b) { diff --git a/crypto/src/pqc/crypto/hqc/HqcEngine.cs b/crypto/src/pqc/crypto/hqc/HqcEngine.cs index ac1a96f00..ee628e843 100644 --- a/crypto/src/pqc/crypto/hqc/HqcEngine.cs +++ b/crypto/src/pqc/crypto/hqc/HqcEngine.cs @@ -1,5 +1,5 @@ using System; - +using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Hqc @@ -33,10 +33,18 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc private int N1N2_BYTE_64; private int N1N2_BYTE; private int N1_BYTE; + + private int GF_POLY_WT = 5; + private int GF_POLY_M2 = 4; + private int SALT_SIZE_BYTES = 16; + private int SALT_SIZE_64 = 2; private int[] generatorPoly; private int SHA512_BYTES = 512 / 8; + private ulong RED_MASK; + private GF2PolynomialCalculator gfCalculator; + public HqcEngine(int n, int n1, int n2, int k, int g, int delta, int w, int wr, int we, int rejectionThreshold, int fft, int[] generatorPoly) { this.n = n; @@ -47,21 +55,25 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc this.we = we; this.n1 = n1; this.n2 = n2; - this.n1n2 = n1 * n2; + n1n2 = n1 * n2; this.generatorPoly = generatorPoly; this.g = g; this.rejectionThreshold = rejectionThreshold; this.fft = fft; - this.mulParam = (n2 + 127) / 128; - this.N_BYTE = Utils.GetByteSizeFromBitSize(n); - this.K_BYTE = k; - this.N_BYTE_64 = Utils.GetByte64SizeFromBitSize(n); - this.K_BYTE_64 = Utils.GetByteSizeFromBitSize(k); - this.N1_BYTE_64 = Utils.GetByteSizeFromBitSize(n1); - this.N1N2_BYTE_64 = Utils.GetByte64SizeFromBitSize(n1 * n2); - this.N1N2_BYTE = Utils.GetByteSizeFromBitSize(n1 * n2); - this.N1_BYTE = Utils.GetByteSizeFromBitSize(n1); + mulParam = (n2 + 127) / 128; + N_BYTE = Utils.GetByteSizeFromBitSize(n); + K_BYTE = k; + N_BYTE_64 = Utils.GetByte64SizeFromBitSize(n); + K_BYTE_64 = Utils.GetByteSizeFromBitSize(k); + N1_BYTE_64 = Utils.GetByteSizeFromBitSize(n1); + N1N2_BYTE_64 = Utils.GetByte64SizeFromBitSize(n1 * n2); + N1N2_BYTE = Utils.GetByteSizeFromBitSize(n1 * n2); + N1_BYTE = Utils.GetByteSizeFromBitSize(n1); + + RED_MASK = ((1UL << (n % 64)) - 1); + + gfCalculator = new GF2PolynomialCalculator(N_BYTE_64, n, RED_MASK); } /** @@ -84,11 +96,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc HqcKeccakRandomGenerator secretKeySeedExpander = new HqcKeccakRandomGenerator(256); secretKeySeedExpander.SeedExpanderInit(secretKeySeed, secretKeySeed.Length); - ulong[] xLongBytes = new ulong[N_BYTE_64]; - int[] yPos = new int[this.w]; + long[] xLongBytes = new long[N_BYTE_64]; + long[] yLongBytes = new long[N_BYTE_64]; - GenerateSecretKey(xLongBytes, secretKeySeedExpander, w); - GenerateSecretKeyByCoordinates(yPos, secretKeySeedExpander, w); + GenerateRandomFixedWeight(xLongBytes, secretKeySeedExpander, w); + GenerateRandomFixedWeight(yLongBytes, secretKeySeedExpander, w); // 2. Randomly generate h byte[] publicKeySeed = new byte[SEED_SIZE]; @@ -97,15 +109,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc HqcKeccakRandomGenerator randomPublic = new HqcKeccakRandomGenerator(256); randomPublic.SeedExpanderInit(publicKeySeed, publicKeySeed.Length); - ulong[] hLongBytes = new ulong[N_BYTE_64]; + long[] hLongBytes = new long[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.AddULongs(s, s, xLongBytes); + long[] s = new long[N_BYTE_64]; + gfCalculator.MultLongs(s, yLongBytes, hLongBytes); + GF2PolynomialCalculator.AddLongs(s, s, xLongBytes); byte[] sBytes = new byte[N_BYTE]; - Utils.FromULongArrayToByteArray(sBytes, s); + Utils.FromLongArrayToByteArray(sBytes, s); byte[] tmpPk = Arrays.Concatenate(publicKeySeed, sBytes); byte[] tmpSk = Arrays.Concatenate(secretKeySeed, tmpPk); @@ -126,7 +138,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc * @param pk public key * @param seed seed **/ - public void Encaps(byte[] u, byte[] v, byte[] K, byte[] d, byte[] pk, byte[] seed) + public void Encaps(byte[] u, byte[] v, byte[] K, byte[] d, byte[] pk, byte[] seed, byte[] salt) { // 1. Randomly generate m byte[] m = new byte[K_BYTE]; @@ -145,27 +157,33 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc // 2. Generate theta byte[] theta = new byte[SHA512_BYTES]; + byte[] tmp = new byte[K_BYTE + SEED_SIZE + SALT_SIZE_BYTES]; + randomGenerator.Squeeze(salt, SALT_SIZE_BYTES); + + Array.Copy(m, 0, tmp, 0, m.Length); + Array.Copy(pk, 0, tmp, K_BYTE, SEED_SIZE); + Array.Copy(salt, 0, tmp, K_BYTE + SEED_SIZE, SALT_SIZE_BYTES); HqcKeccakRandomGenerator shakeDigest = new HqcKeccakRandomGenerator(256); - shakeDigest.SHAKE256_512_ds(theta, m, m.Length, new byte[] { G_FCT_DOMAIN }); + shakeDigest.SHAKE256_512_ds(theta, tmp, tmp.Length, new[] { G_FCT_DOMAIN }); // 3. Generate ciphertext c = (u,v) // Extract public keys - ulong[] h = new ulong[N_BYTE_64]; + long[] h = new long[N_BYTE_64]; byte[] s = new byte[N_BYTE]; ExtractPublicKeys(h, s, pk); - ulong[] vTmp = new ulong[N1N2_BYTE_64]; + long[] vTmp = new long[N1N2_BYTE_64]; Encrypt(u, vTmp, h, s, m, theta); - Utils.FromULongArrayToByteArray(v, vTmp); + Utils.FromLongArrayToByteArray(v, vTmp); // 4. Compute d - shakeDigest.SHAKE256_512_ds(d, m, m.Length, new byte[] { H_FCT_DOMAIN }); + shakeDigest.SHAKE256_512_ds(d, m, m.Length, new[] { H_FCT_DOMAIN }); // 5. Compute session key K byte[] hashInputK = new byte[K_BYTE + N_BYTE + N1N2_BYTE]; hashInputK = Arrays.Concatenate(m, u); hashInputK = Arrays.Concatenate(hashInputK, v); - shakeDigest.SHAKE256_512_ds(K, hashInputK, hashInputK.Length, new byte[] { K_FCT_DOMAIN }); + shakeDigest.SHAKE256_512_ds(K, hashInputK, hashInputK.Length, new[] { K_FCT_DOMAIN }); } /** @@ -180,46 +198,52 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc public void Decaps(byte[] ss, byte[] ct, byte[] sk) { //Extract Y and Public Keys from sk - int[] yPos = new int[this.w]; + long[] x = new long[N_BYTE_64]; + long[] y = new long[N_BYTE_64]; byte[] pk = new byte[40 + N_BYTE]; - ExtractKeysFromSecretKeys(yPos, pk, sk); + ExtractKeysFromSecretKeys(x, y, pk, sk); // Extract u, v, d from ciphertext byte[] u = new byte[N_BYTE]; byte[] v = new byte[N1N2_BYTE]; byte[] d = new byte[SHA512_BYTES]; - HqcEngine.ExtractCiphertexts(u, v, d, ct); + byte[] salt = new byte[SALT_SIZE_BYTES]; + ExtractCiphertexts(u, v, d, salt, ct); // 1. Decrypt -> m' byte[] mPrimeBytes = new byte[k]; - Decrypt(mPrimeBytes, mPrimeBytes, u, v, yPos); + Decrypt(mPrimeBytes, mPrimeBytes, u, v, y); // 2. Compute theta' byte[] theta = new byte[SHA512_BYTES]; + byte[] tmp = new byte[K_BYTE + SALT_SIZE_BYTES + SEED_SIZE]; + Array.Copy(mPrimeBytes, 0, tmp, 0, mPrimeBytes.Length); + Array.Copy(pk, 0, tmp, K_BYTE, SEED_SIZE); + Array.Copy(salt, 0, tmp, K_BYTE + SEED_SIZE, SALT_SIZE_BYTES); HqcKeccakRandomGenerator shakeDigest = new HqcKeccakRandomGenerator(256); - shakeDigest.SHAKE256_512_ds(theta, mPrimeBytes, mPrimeBytes.Length, new byte[] { G_FCT_DOMAIN }); + shakeDigest.SHAKE256_512_ds(theta, tmp, tmp.Length, new[] { G_FCT_DOMAIN }); // 3. Compute c' = Enc(pk, m', theta') // Extract public keys - ulong[] h = new ulong[N_BYTE_64]; + long[] h = new long[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]; - ulong[] vTmp = new ulong[N1N2_BYTE_64]; + long[] vTmp = new long[N1N2_BYTE_64]; Encrypt(u2Bytes, vTmp, h, s, mPrimeBytes, theta); - Utils.FromULongArrayToByteArray(v2Bytes, vTmp); + Utils.FromLongArrayToByteArray(v2Bytes, vTmp); // 4. Compute d' = H(m') byte[] dPrime = new byte[SHA512_BYTES]; - shakeDigest.SHAKE256_512_ds(dPrime, mPrimeBytes, mPrimeBytes.Length, new byte[] { H_FCT_DOMAIN }); + shakeDigest.SHAKE256_512_ds(dPrime, mPrimeBytes, mPrimeBytes.Length, new[] { H_FCT_DOMAIN }); // 5. Compute session key KPrime byte[] hashInputK = new byte[K_BYTE + N_BYTE + N1N2_BYTE]; hashInputK = Arrays.Concatenate(mPrimeBytes, u); hashInputK = Arrays.Concatenate(hashInputK, v); - shakeDigest.SHAKE256_512_ds(ss, hashInputK, hashInputK.Length, new byte[] { K_FCT_DOMAIN }); + shakeDigest.SHAKE256_512_ds(ss, hashInputK, hashInputK.Length, new[] { K_FCT_DOMAIN }); int result = 1; // Compare u, v, d @@ -263,63 +287,59 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc * @param u ciphertext * @param v ciphertext **/ - private void Encrypt(byte[] u, ulong[] v, ulong[] h, byte[] s, byte[] m, byte[] theta) + private void Encrypt(byte[] u, long[] v, long[] h, byte[] s, byte[] m, byte[] theta) { // Randomly generate e, r1, r2 HqcKeccakRandomGenerator randomGenerator = new HqcKeccakRandomGenerator(256); randomGenerator.SeedExpanderInit(theta, SEED_SIZE); - 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); - GenerateSecretKey(e, randomGenerator, we); + long[] e = new long[N_BYTE_64]; + long[] r1 = new long[N_BYTE_64]; + long[] r2 = new long[N_BYTE_64]; + GenerateRandomFixedWeight(r1, randomGenerator, wr); + GenerateRandomFixedWeight(r2, randomGenerator, wr); + GenerateRandomFixedWeight(e, randomGenerator, we); // Calculate u - ulong[] uLong = new ulong[N_BYTE_64]; - GF2PolynomialCalculator.ModMult(uLong, r2, h, wr, n, N_BYTE_64, we, randomGenerator); - GF2PolynomialCalculator.AddULongs(uLong, uLong, r1); - Utils.FromULongArrayToByteArray(u, uLong); + long[] uLong = new long[N_BYTE_64]; + gfCalculator.MultLongs(uLong, r2, h); + GF2PolynomialCalculator.AddLongs(uLong, uLong, r1); + Utils.FromLongArrayToByteArray(u, uLong); // Calculate v // encode m byte[] res = new byte[n1]; - ulong[] vLong = new ulong[N1N2_BYTE_64]; - ulong[] tmpVLong = new ulong[N_BYTE_64]; + long[] vLong = new long[N1N2_BYTE_64]; + long[] tmpVLong = new long[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 - ulong[] sLong = new ulong[N_BYTE_64]; - Utils.FromByteArrayToULongArray(sLong, s); + long[] sLong = new long[N_BYTE_64]; + Utils.FromByteArrayToLongArray(sLong, s); - ulong[] tmpLong = new ulong[N_BYTE_64]; - GF2PolynomialCalculator.ModMult(tmpLong, r2, sLong, wr, n, N_BYTE_64, we, randomGenerator); - GF2PolynomialCalculator.AddULongs(tmpLong, tmpLong, tmpVLong); - GF2PolynomialCalculator.AddULongs(tmpLong, tmpLong, e); + long[] tmpLong = new long[N_BYTE_64]; + gfCalculator.MultLongs(tmpLong, r2, sLong); + GF2PolynomialCalculator.AddLongs(tmpLong, tmpLong, tmpVLong); + GF2PolynomialCalculator.AddLongs(tmpLong, tmpLong, e); 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) + private void Decrypt(byte[] output, byte[] m, byte[] u, byte[] v, long[] y) { - byte[] tmpSeed = new byte[SEED_SIZE]; - HqcKeccakRandomGenerator randomGenerator = new HqcKeccakRandomGenerator(256); - randomGenerator.SeedExpanderInit(tmpSeed, SEED_SIZE); - - ulong[] uLongs = new ulong[N_BYTE_64]; - Utils.FromByteArrayToULongArray(uLongs, u); + long[] uLongs = new long[N_BYTE_64]; + Utils.FromByteArrayToLongArray(uLongs, u); - ulong[] vLongs = new ulong[N1N2_BYTE_64]; - Utils.FromByteArrayToULongArray(vLongs, v); + long[] vLongs = new long[N1N2_BYTE_64]; + Utils.FromByteArrayToLongArray(vLongs, v); - ulong[] tmpV = new ulong[N_BYTE_64]; + long[] tmpV = new long[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.AddULongs(tmpLong, tmpLong, tmpV); + long[] tmpLong = new long[N_BYTE_64]; + gfCalculator.MultLongs(tmpLong, y, uLongs); + GF2PolynomialCalculator.AddLongs(tmpLong, tmpLong, tmpV); // Decode res byte[] tmp = new byte[n1]; @@ -329,70 +349,69 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc Array.Copy(m, 0, output, 0, output.Length); } - private void GenerateSecretKey(ulong[] output, HqcKeccakRandomGenerator random, int w) + private void GenerateRandomFixedWeight(long[] output, HqcKeccakRandomGenerator random, int weight) { - int[] tmp = new int[w]; - GenerateSecretKeyByCoordinates(tmp, random, w); + uint[] rand_u32 = new uint[wr]; + byte[] rand_bytes = new byte[wr * 4]; + int[] support = new int[wr]; + int[] index_tab = new int[wr]; + long[] bit_tab = new long[wr]; + + random.ExpandSeed(rand_bytes, 4 * weight); + Pack.LE_To_UInt32(rand_bytes, 0, rand_u32, 0, rand_u32.Length); - for (int i = 0; i < w; ++i) + for (int i = 0; i < weight; i++) { - int index = tmp[i] / 64; - int pos = tmp[i] % 64; - ulong t = 1UL << pos; - output[index] |= t; + support[i] = (int) (i + ((rand_u32[i]&0xFFFFFFFFL) % (n - i))); } - } - - private void GenerateSecretKeyByCoordinates(int[] output, HqcKeccakRandomGenerator random, int w) - { - int randomByteSize = 3 * w; - byte[] randomBytes = new byte[3 * this.wr]; - int inc; - int i = 0; - int j = randomByteSize; - while (i < w) + for (int i = (weight - 1); i >= 0; i--) { - do + int found = 0; + for (int j = i + 1; j < weight; j++) { - if (j == randomByteSize) + if (support[j] == support[i]) { - random.ExpandSeed(randomBytes, randomByteSize); - - j = 0; + found |= 1; } - - output[i] = (randomBytes[j++] & 0xff) << 16; - output[i] |= (randomBytes[j++] & 0xff) << 8; - output[i] |= (randomBytes[j++] & 0xff); - } - while (output[i] >= this.rejectionThreshold); - output[i] = output[i] % this.n; - inc = 1; - for (int k = 0; k < i; k++) + int mask = -found; + support[i] = (mask & i) ^ (~mask & support[i]); + } + + for (int i = 0; i < weight; i++) + { + index_tab[i] = (int)((uint)support[i] >> 6); + int pos = support[i] & 0x3f; + bit_tab[i] = (1L) << pos; + } + long val = 0; + for (int i = 0; i < N_BYTE_64; i++) + { + val = 0; + for (int j = 0; j < weight; j++) { - if (output[k] == output[i]) - { - inc = 0; - } + int tmp = i - index_tab[j]; + int val1 = 1 ^ ((int)((uint)(tmp | -tmp) >> 31)); + long mask = -val1; + val |= (bit_tab[j] & mask); } - i += inc; + output[i] |= val; } } - - void GeneratePublicKeyH(ulong[] output, HqcKeccakRandomGenerator random) + + void GeneratePublicKeyH(long[] output, HqcKeccakRandomGenerator random) { byte[] randBytes = new byte[N_BYTE]; random.ExpandSeed(randBytes, N_BYTE); - ulong[] tmp = new ulong[N_BYTE_64]; - Utils.FromByteArrayToULongArray(tmp, randBytes); + long[] tmp = new long[N_BYTE_64]; + Utils.FromByteArrayToLongArray(tmp, randBytes); tmp[N_BYTE_64 - 1] &= Utils.BitMask((ulong)n, 64); Array.Copy(tmp, 0, output, 0, output.Length); } - private void ExtractPublicKeys(ulong[] h, byte[] s, byte[] pk) + private void ExtractPublicKeys(long[] h, byte[] s, byte[] pk) { byte[] publicKeySeed = new byte[SEED_SIZE]; Array.Copy(pk, 0, publicKeySeed, 0, publicKeySeed.Length); @@ -400,14 +419,14 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc HqcKeccakRandomGenerator randomPublic = new HqcKeccakRandomGenerator(256); randomPublic.SeedExpanderInit(publicKeySeed, publicKeySeed.Length); - ulong[] hLongBytes = new ulong[N_BYTE_64]; + long[] hLongBytes = new long[N_BYTE_64]; GeneratePublicKeyH(hLongBytes, randomPublic); 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) + private void ExtractKeysFromSecretKeys(long[] x, long[] y, byte[] pk, byte[] sk) { byte[] secretKeySeed = new byte[SEED_SIZE]; Array.Copy(sk, 0, secretKeySeed, 0, secretKeySeed.Length); @@ -415,22 +434,19 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc // Randomly generate secret keys x, y HqcKeccakRandomGenerator secretKeySeedExpander = new HqcKeccakRandomGenerator(256); secretKeySeedExpander.SeedExpanderInit(secretKeySeed, secretKeySeed.Length); + + GenerateRandomFixedWeight(x, secretKeySeedExpander, w); + GenerateRandomFixedWeight(y, secretKeySeedExpander, w); - 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); } - private static void ExtractCiphertexts(byte[] u, byte[] v, byte[] d, byte[] ct) + private static void ExtractCiphertexts(byte[] u, byte[] v, byte[] d, byte[] salt, 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, u.Length + v.Length + d.Length, salt, 0, salt.Length); } } } diff --git a/crypto/src/pqc/crypto/hqc/HqcKeccakRandomGenerator.cs b/crypto/src/pqc/crypto/hqc/HqcKeccakRandomGenerator.cs index 090f5a9c0..3ecbef633 100644 --- a/crypto/src/pqc/crypto/hqc/HqcKeccakRandomGenerator.cs +++ b/crypto/src/pqc/crypto/hqc/HqcKeccakRandomGenerator.cs @@ -1,5 +1,4 @@ using System; - using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Hqc @@ -60,10 +59,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc { state[i] = 0L; } - Arrays.Fill(this.dataQueue, 0); - this.bitsInQueue = 0; - this.squeezing = false; - this.fixedOutputLength = (1600 - rate) / 2; + Arrays.Fill(dataQueue, 0); + bitsInQueue = 0; + squeezing = false; + fixedOutputLength = (1600 - rate) / 2; } private void KeccakPermutation() @@ -273,7 +272,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc public void RandomGeneratorInit(byte[] entropyInput, byte[] personalizationString, int entropyLen, int perLen) { - byte[] domain = new byte[] { 1 }; + byte[] domain = { 1 }; KeccakIncAbsorb(entropyInput, entropyLen); KeccakIncAbsorb(personalizationString, perLen); KeccakIncAbsorb(domain, domain.Length); @@ -282,7 +281,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc public void SeedExpanderInit(byte[] seed, int seedLen) { - byte[] domain = new byte[] { 2 }; + byte[] domain = { 2 }; KeccakIncAbsorb(seed, seedLen); KeccakIncAbsorb(domain, 1); KeccakIncFinalize(0x1F); diff --git a/crypto/src/pqc/crypto/hqc/HqcKemExtractor.cs b/crypto/src/pqc/crypto/hqc/HqcKemExtractor.cs index 32890f80b..b18c532fa 100644 --- a/crypto/src/pqc/crypto/hqc/HqcKemExtractor.cs +++ b/crypto/src/pqc/crypto/hqc/HqcKemExtractor.cs @@ -10,7 +10,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc public HqcKemExtractor(HqcPrivateKeyParameters privParams) { - this.key = privParams; + key = privParams; InitCipher(key.Parameters); } diff --git a/crypto/src/pqc/crypto/hqc/HqcKemGenerator.cs b/crypto/src/pqc/crypto/hqc/HqcKemGenerator.cs index 918dadd38..53f59be16 100644 --- a/crypto/src/pqc/crypto/hqc/HqcKemGenerator.cs +++ b/crypto/src/pqc/crypto/hqc/HqcKemGenerator.cs @@ -1,5 +1,4 @@ using System; - using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; @@ -11,7 +10,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc private SecureRandom sr; public HqcKemGenerator(SecureRandom random) { - this.sr = random; + sr = random; } public ISecretWithEncapsulation GenerateEncapsulated(AsymmetricKeyParameter recipientKey) @@ -23,22 +22,22 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc byte[] u = new byte[key.Parameters.NBytes]; byte[] v = new byte[key.Parameters.N1n2Bytes]; byte[] d = new byte[key.Parameters.Sha512Bytes]; + byte[] salt = new byte[key.Parameters.SaltSizeBytes]; byte[] pk = key.PublicKey; byte[] seed = new byte[48]; sr.NextBytes(seed); - engine.Encaps(u, v, K, d, pk, seed); + engine.Encaps(u, v, K, d, pk, seed, salt); - byte[] cipherText = Arrays.Concatenate(u, v); - cipherText = Arrays.Concatenate(cipherText, d); + byte[] cipherText = Arrays.ConcatenateAll(u, v, d, salt); - return new HqcKemGenerator.SecretWithEncapsulationImpl(K, cipherText); + return new SecretWithEncapsulationImpl(K, cipherText); } private class SecretWithEncapsulationImpl : ISecretWithEncapsulation { - private volatile bool hasBeenDestroyed = false; + private volatile bool hasBeenDestroyed; private byte[] sessionKey; private byte[] cipher_text; diff --git a/crypto/src/pqc/crypto/hqc/HqcKeyPairGenerator.cs b/crypto/src/pqc/crypto/hqc/HqcKeyPairGenerator.cs index 243b0d850..50882f432 100644 --- a/crypto/src/pqc/crypto/hqc/HqcKeyPairGenerator.cs +++ b/crypto/src/pqc/crypto/hqc/HqcKeyPairGenerator.cs @@ -36,17 +36,17 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc public void Init(KeyGenerationParameters parameters) { - this.hqcKeyGenerationParameters = (HqcKeyGenerationParameters)parameters; - this.random = parameters.Random; + hqcKeyGenerationParameters = (HqcKeyGenerationParameters)parameters; + random = parameters.Random; // get parameters - this.n = this.hqcKeyGenerationParameters.Parameters.N; - this.k = this.hqcKeyGenerationParameters.Parameters.K; - this.delta = this.hqcKeyGenerationParameters.Parameters.Delta; - this.w = this.hqcKeyGenerationParameters.Parameters.W; - this.wr = this.hqcKeyGenerationParameters.Parameters.Wr; - this.we = this.hqcKeyGenerationParameters.Parameters.We; - this.N_BYTE = (n + 7) / 8; + n = hqcKeyGenerationParameters.Parameters.N; + k = hqcKeyGenerationParameters.Parameters.K; + delta = hqcKeyGenerationParameters.Parameters.Delta; + w = hqcKeyGenerationParameters.Parameters.W; + wr = hqcKeyGenerationParameters.Parameters.Wr; + we = hqcKeyGenerationParameters.Parameters.We; + N_BYTE = (n + 7) / 8; } private AsymmetricCipherKeyPair GenKeyPair(byte[] seed) { diff --git a/crypto/src/pqc/crypto/hqc/HqcParameters.cs b/crypto/src/pqc/crypto/hqc/HqcParameters.cs index c397f65b1..d01c6fe9f 100644 --- a/crypto/src/pqc/crypto/hqc/HqcParameters.cs +++ b/crypto/src/pqc/crypto/hqc/HqcParameters.cs @@ -6,13 +6,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc : ICipherParameters { // 128 bits security - public static HqcParameters hqc128 = new HqcParameters("hqc128", 17669, 46, 384, 16, 31, 15, 66, 75, 75, 16767881, 4, new int[] { 89, 69, 153, 116, 176, 117, 111, 75, 73, 233, 242, 233, 65, 210, 21, 139, 103, 173, 67, 118, 105, 210, 174, 110, 74, 69, 228, 82, 255, 181, 1 }, 128); + public static HqcParameters hqc128 = new HqcParameters("hqc128", 17669, 46, 384, 16, 31, 15, 66, 75, 75, 16767881, 4, new[] { 89, 69, 153, 116, 176, 117, 111, 75, 73, 233, 242, 233, 65, 210, 21, 139, 103, 173, 67, 118, 105, 210, 174, 110, 74, 69, 228, 82, 255, 181, 1 }, 128); // 192 bits security - public static HqcParameters hqc192 = new HqcParameters("hqc192", 35851, 56, 640, 24, 33, 16, 100, 114, 114, 16742417, 5, new int[] { 45, 216, 239, 24, 253, 104, 27, 40, 107, 50, 163, 210, 227, 134, 224, 158, 119, 13, 158, 1, 238, 164, 82, 43, 15, 232, 246, 142, 50, 189, 29, 232, 1 }, 192); + public static HqcParameters hqc192 = new HqcParameters("hqc192", 35851, 56, 640, 24, 33, 16, 100, 114, 114, 16742417, 5, new[] { 45, 216, 239, 24, 253, 104, 27, 40, 107, 50, 163, 210, 227, 134, 224, 158, 119, 13, 158, 1, 238, 164, 82, 43, 15, 232, 246, 142, 50, 189, 29, 232, 1 }, 192); // 256 bits security - public static HqcParameters hqc256 = new HqcParameters("hqc256", 57637, 90, 640, 32, 59, 29, 131, 149, 149, 16772367, 5, new int[] { 49, 167, 49, 39, 200, 121, 124, 91, 240, 63, 148, 71, 150, 123, 87, 101, 32, 215, 159, 71, 201, 115, 97, 210, 186, 183, 141, 217, 123, 12, 31, 243, 180, 219, 152, 239, 99, 141, 4, 246, 191, 144, 8, 232, 47, 27, 141, 178, 130, 64, 124, 47, 39, 188, 216, 48, 199, 187, 1 }, 256); + public static HqcParameters hqc256 = new HqcParameters("hqc256", 57637, 90, 640, 32, 59, 29, 131, 149, 149, 16772367, 5, new[] { 49, 167, 49, 39, 200, 121, 124, 91, 240, 63, 148, 71, 150, 123, 87, 101, 32, 215, 159, 71, 201, 115, 97, 210, 186, 183, 141, 217, 123, 12, 31, 243, 180, 219, 152, 239, 99, 141, 4, 246, 191, 144, 8, 232, 47, 27, 141, 178, 130, 64, 124, 47, 39, 188, 216, 48, 199, 187, 1 }, 256); private string name; private int n; @@ -66,6 +66,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc public int NBytes => (n + 7) / 8; public int N1n2Bytes => (n1 * n2 + 7) / 8; public int DefaultKeySize => defaultKeySize; + public int SaltSizeBytes => 16; internal HqcEngine Engine => hqcEngine; } } diff --git a/crypto/src/pqc/crypto/hqc/ReedMuller.cs b/crypto/src/pqc/crypto/hqc/ReedMuller.cs index 5f1f8e2bf..a39f403e6 100644 --- a/crypto/src/pqc/crypto/hqc/ReedMuller.cs +++ b/crypto/src/pqc/crypto/hqc/ReedMuller.cs @@ -1,5 +1,4 @@ using System; - using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Hqc @@ -13,8 +12,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc public Codeword() { - this.type32 = new int[4]; - this.type8 = new int[16]; + type32 = new int[4]; + type8 = new int[16]; } } @@ -117,7 +116,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc return (int) ((-(b & 1)) & 0xffffffff); } - public static void Encode(ulong[] codeword, byte[] m, int n1, int mulParam) + public static void Encode(long[] codeword, byte[] m, int n1, int mulParam) { byte[] mBytes = Arrays.Clone(m); @@ -147,16 +146,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc off += 4; } - Utils.FromByte32ArrayToULongArray(codeword, cwd64); + Utils.FromByte32ArrayToLongArray(codeword, cwd64); } - public static void Decode(byte[] m, ulong[] codeword, int n1, int mulParam) + public static void Decode(byte[] m, long[] 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.FromULongArrayToByte32Array(byteCodeWords, codeword); + Utils.FromLongArrayToByte32Array(byteCodeWords, codeword); for (int i = 0; i < codewordCopy.Length; i++) { @@ -189,7 +188,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc Array.Copy(codewordCopy[i].type32, 0, cwd64, off, codewordCopy[i].type32.Length); off += 4; } - Utils.FromByte32ArrayToULongArray(codeword, cwd64); + Utils.FromByte32ArrayToLongArray(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 25a8c7997..4024b0a38 100644 --- a/crypto/src/pqc/crypto/hqc/ReedSolomon.cs +++ b/crypto/src/pqc/crypto/hqc/ReedSolomon.cs @@ -1,5 +1,4 @@ using System; - using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Hqc diff --git a/crypto/src/pqc/crypto/hqc/Utils.cs b/crypto/src/pqc/crypto/hqc/Utils.cs index 4d44db07c..993def057 100644 --- a/crypto/src/pqc/crypto/hqc/Utils.cs +++ b/crypto/src/pqc/crypto/hqc/Utils.cs @@ -1,15 +1,14 @@ using System; - using Org.BouncyCastle.Crypto.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Hqc { internal class Utils { - internal static void ResizeArray(ulong[] output, int sizeOutBits, ulong[] input, int sizeInBits, + internal static void ResizeArray(long[] output, int sizeOutBits, long[] input, int sizeInBits, int n1n2ByteSize, int n1n2Byte64Size) { - ulong mask = 0x7FFFFFFFFFFFFFFFUL; + long mask = 0x7FFFFFFFFFFFFFFFL; int val = 0; if (sizeOutBits < sizeInBits) { @@ -31,12 +30,12 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc } } - internal static void FromULongArrayToByteArray(byte[] output, ulong[] input) + internal static void FromLongArrayToByteArray(byte[] output, long[] input) { int max = output.Length / 8; for (int i = 0; i != max; i++) { - Pack.UInt64_To_LE(input[i], output, i * 8); + Pack.UInt64_To_LE((ulong)input[i], output, i * 8); } if (output.Length % 8 != 0) @@ -50,13 +49,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc } } - internal static ulong BitMask(ulong a, ulong b) + internal static long BitMask(ulong a, ulong b) { uint tmp = (uint)(a % b); - return ((1UL << (int)tmp) - 1); + return ((1L << (int)tmp) - 1); } - internal static void FromByteArrayToULongArray(ulong[] output, byte[] input) + internal static void FromByteArrayToLongArray(long[] output, byte[] input) { byte[] tmp = input; if (input.Length % 8 != 0) @@ -68,7 +67,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc int off = 0; for (int i = 0; i < output.Length; i++) { - output[i] = Pack.LE_To_UInt64(tmp, off); + output[i] = (long)Pack.LE_To_UInt64(tmp, off); off += 8; } } @@ -85,17 +84,17 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc int off = 0; for (int i = 0; i < output.Length; i++) { - output[i] = (int)Pack.LE_To_UInt16(tmp, off); + output[i] = Pack.LE_To_UInt16(tmp, off); off += 2; } } - internal static void FromByte32ArrayToULongArray(ulong[] output, int[] input) + internal static void FromByte32ArrayToLongArray(long[] output, int[] input) { for (int i = 0; i != input.Length; i += 2) { output[i / 2] = (uint)input[i]; - output[i / 2] |= (ulong)input[i + 1] << 32; + output[i / 2] |= (long)input[i + 1] << 32; } } @@ -110,7 +109,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Hqc } } - internal static void FromULongArrayToByte32Array(int[] output, ulong[] input) + internal static void FromLongArrayToByte32Array(int[] output, long[] input) { for (int i = 0; i != input.Length; i++) { |