summary refs log tree commit diff
path: root/crypto/src/pqc
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-10-13 00:30:14 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-10-13 00:30:14 +0700
commita0513bc308839a6d6b3deb32ee76122181175569 (patch)
tree884db1c09bd048aac480d55a5515833b30f5f60d /crypto/src/pqc
parentReorganize FrodoVectorTest (diff)
downloadBouncyCastle.NET-ed25519-a0513bc308839a6d6b3deb32ee76122181175569.tar.xz
Refactor FrodoMatrixGenerator (performance)
Diffstat (limited to 'crypto/src/pqc')
-rw-r--r--crypto/src/pqc/crypto/frodo/FrodoMatrixGenerator.cs43
1 files 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('<H', b, 0, i)
-                        //                struct.pack_into('<H', b, 2, j)
+                        Pack.UInt16_To_LE((ushort)i, b, 0);
+                        Pack.UInt16_To_LE((ushort)j, b, 2);
                         // 4. c = AES128(seedA, b)
-                        m_cipher.ProcessBlock(b, 0, c, 0);
+                        cipher.ProcessBlock(b, 0, c, 0);
                         // 5. for k = 0; k < 8; k += 1
                         for (int k = 0; k < 8; k++)
                         {
                             // 6. A[i][j+k] = c[k] where c is treated as a sequence of 8 16-bit integers each in little-endian byte order
-                            A[i * n + j + k] = (short) (Pack.LE_To_UInt16(c, 2 * k) % q); //todo add % q
+                            A[i * n + j + k] = (short)(Pack.LE_To_UInt16(c, 2 * k) & (q - 1));
                         }
                     }
                 }
-
                 return A;
             }
         }