From a0513bc308839a6d6b3deb32ee76122181175569 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 13 Oct 2022 00:30:14 +0700 Subject: Refactor FrodoMatrixGenerator (performance) --- .../src/pqc/crypto/frodo/FrodoMatrixGenerator.cs | 43 ++++++++-------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/crypto/src/pqc/crypto/frodo/FrodoMatrixGenerator.cs b/crypto/src/pqc/crypto/frodo/FrodoMatrixGenerator.cs index ce985c9ab..95a7de18d 100644 --- a/crypto/src/pqc/crypto/frodo/FrodoMatrixGenerator.cs +++ b/crypto/src/pqc/crypto/frodo/FrodoMatrixGenerator.cs @@ -4,7 +4,6 @@ using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Utilities; -using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Pqc.Crypto.Frodo { @@ -33,52 +32,47 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo { short[] A = new short[n * n]; ushort i, j; - byte[] b, tmp = new byte[(16 * n) / 8]; - byte[] temp = new byte[2]; + byte[] tmp = new byte[(16 * n) / 8]; + byte[] b = new byte[2 + seedA.Length]; + Array.Copy(seedA, 0, b, 2, seedA.Length); + + IXof digest = new ShakeDigest(128); + for (i = 0; i < n; i++) { // 1. b = i || seedA in {0,1}^{16 + len_seedA}, where i is encoded as a 16-bit integer in little-endian byte order - Pack.UInt16_To_LE(i, temp); - b = Arrays.Concatenate(temp, seedA); + Pack.UInt16_To_LE(i, b); // 2. c_{i,0} || c_{i,1} || ... || c_{i,n-1} = SHAKE128(b, 16n) (length in bits) where each c_{i,j} is parsed as a 16-bit integer in little-endian byte order format - IXof digest = new ShakeDigest(128); digest.BlockUpdate(b, 0, b.Length); digest.OutputFinal(tmp, 0, tmp.Length); for (j = 0; j < n; j++) { - A[i * n + j] = (short) (Pack.LE_To_UInt16(tmp, 2 * j) % q);//todo add % q + A[i * n + j] = (short) (Pack.LE_To_UInt16(tmp, 2 * j) & (q - 1)); } - } - return A; } - } internal class Aes128MatrixGenerator : FrodoMatrixGenerator { - private readonly IBlockCipher m_cipher; - public Aes128MatrixGenerator(int n, int q) : base(n, q) { - m_cipher = AesUtilities.CreateEngine(); } internal override short[] GenMatrix(byte[] seedA) { - KeyParameter kp = new KeyParameter(seedA); - m_cipher.Init(true, kp); - // """Generate matrix A using AES-128 (FrodoKEM specification, Algorithm 7)""" // A = [[None for j in range(self.n)] for i in range(self.n)] short[] A = new short[n * n]; byte[] b = new byte[16]; byte[] c = new byte[16]; - byte[] temp = new byte[4]; + + IBlockCipher cipher = AesUtilities.CreateEngine(); + cipher.Init(true, new KeyParameter(seedA)); // 1. for i = 0; i < n; i += 1 for (int i = 0; i < n; i++) @@ -86,26 +80,19 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo // 2. for j = 0; j < n; j += 8 for (int j = 0; j < n; j += 8) { - // 3. b = i || j || 0 || ... || 0 in {0,1}^128, where i and j are encoded as 16-bit integers in little-endian byte order - Pack.UInt16_To_LE((ushort) (i & 0xffff), temp); - Array.Copy(temp, 0, b, 0, 2); - Pack.UInt16_To_LE((ushort) (j & 0xffff), temp); - Array.Copy(temp, 0, b, 2, 2); - // b = bytearray(16) - // struct.pack_into('