Skip to content

Commit 26ce10e

Browse files
author
gefeili
committed
Reduce the size of SnovaKeyElements
1 parent a1544a8 commit 26ce10e

File tree

5 files changed

+48
-72
lines changed

5 files changed

+48
-72
lines changed

core/src/main/java/org/bouncycastle/pqc/crypto/snova/SnovaEngine.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ private static void copy4DMatrix(byte[][][][] src, byte[][][][] dest, int dim1,
349349
}
350350
}
351351

352-
public void genP22(byte[] outP22, byte[][][] T12, byte[][][][] P21, byte[][][][] F12)
352+
public void genP22(byte[] outP22, int outOff, byte[][][] T12, byte[][][][] P21, byte[][][][] F12)
353353
{
354354
// Initialize P22 with zeros
355355
byte[] P22 = new byte[m * o * o * lsq];
@@ -374,7 +374,7 @@ public void genP22(byte[] outP22, byte[][][] T12, byte[][][][] P21, byte[][][][]
374374
}
375375

376376
// Convert GF16 elements to packed bytes
377-
GF16.encode(P22, outP22, P22.length);
377+
GF16.encode(P22, outP22, outOff, P22.length);
378378
}
379379

380380
void genSeedsAndT12(byte[][][] T12, byte[] skSeed)
@@ -405,7 +405,7 @@ void genSeedsAndT12(byte[][][] T12, byte[] skSeed)
405405
}
406406
}
407407

408-
void genABQP(MapGroup1 map1, byte[] pkSeed, byte[] fixedAbq)
408+
void genABQP(MapGroup1 map1, byte[] pkSeed)
409409
{
410410
int gf16sPrngPublic = lsq * (2 * m * alpha + m * (n * n - m * m)) + l * 2 * m * alpha;
411411
byte[] qTemp = new byte[(m * alpha * lsq + m * alpha * lsq) / l];
@@ -497,10 +497,23 @@ void genABQP(MapGroup1 map1, byte[] pkSeed, byte[] fixedAbq)
497497
}
498498
else
499499
{
500+
byte[] fixedAbq = SnovaParameters.fixedAbqSet.get(o);
500501
MapGroup1.fillAlpha(fixedAbq, 0, map1.aAlpha, m * o * alpha * lsq);
501502
MapGroup1.fillAlpha(fixedAbq, o * alpha * lsq, map1.bAlpha, (m - 1) * o * alpha * lsq);
502503
MapGroup1.fillAlpha(fixedAbq, o * alpha * lsq * 2, map1.qAlpha1, (m - 2) * o * alpha * lsq);
503504
MapGroup1.fillAlpha(fixedAbq, o * alpha * lsq * 3, map1.qAlpha2, (m - 3) * o * alpha * lsq);
504505
}
505506
}
507+
508+
void genMap1T12Map2(SnovaKeyElements keyElements, byte[] pkSeed, byte[] skSeed)
509+
{
510+
// Generate T12 matrix
511+
genSeedsAndT12(keyElements.T12, skSeed);
512+
513+
// Generate map components
514+
genABQP(keyElements.map1, pkSeed);
515+
516+
// Generate F matrices
517+
genF(keyElements.map2, keyElements.map1, keyElements.T12);
518+
}
506519
}

core/src/main/java/org/bouncycastle/pqc/crypto/snova/SnovaKeyElements.java

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ class SnovaKeyElements
77
public final MapGroup2 map2;
88
public byte[] ptPrivateKeySeed;
99

10-
byte[] fixedAbq;
11-
1210
public SnovaKeyElements(SnovaParameters params)
1311
{
1412
int o = params.getO();
@@ -18,46 +16,8 @@ public SnovaKeyElements(SnovaParameters params)
1816
map1 = new MapGroup1(params);
1917
T12 = new byte[v][o][lsq];
2018
map2 = new MapGroup2(params);
21-
22-
if (l < 4)
23-
{
24-
fixedAbq = SnovaParameters.fixedAbqSet.get(o);
25-
}
2619
}
2720

28-
// public void encodeMergerInHalf(byte[] output)
29-
// {
30-
// byte[] input = new byte[length];
31-
// int inOff = 0;
32-
// inOff = copy3d(map1.aAlpha, input, inOff);
33-
// inOff = copy3d(map1.bAlpha, input, inOff);
34-
// inOff = copy3d(map1.qAlpha1, input, inOff);
35-
// inOff = copy3d(map1.qAlpha2, input, inOff);
36-
// inOff = copy3d(T12, input, inOff);
37-
// inOff = copy4d(map2.f11, input, inOff);
38-
// inOff = copy4d(map2.f12, input, inOff);
39-
// copy4d(map2.f21, input, inOff);
40-
// GF16Utils.encodeMergeInHalf(input, length, output);
41-
// }
42-
43-
// public void skUnpack(byte[] input)
44-
// {
45-
// byte[] tmp = new byte[(input.length - SnovaKeyPairGenerator.publicSeedLength - SnovaKeyPairGenerator.privateSeedLength) << 1];
46-
// GF16Utils.decodeMergeInHalf(input, tmp, tmp.length);
47-
// int inOff = 0;
48-
// inOff = copy3d(tmp, inOff, map1.aAlpha);
49-
// inOff = copy3d(tmp, inOff, map1.bAlpha);
50-
// inOff = copy3d(tmp, inOff, map1.qAlpha1);
51-
// inOff = copy3d(tmp, inOff, map1.qAlpha2);
52-
// inOff = copy3d(tmp, inOff, T12);
53-
// inOff = copy4d(tmp, inOff, map2.f11);
54-
// inOff = copy4d(tmp, inOff, map2.f12);
55-
// copy4d(tmp, inOff, map2.f21);
56-
// System.arraycopy(input, input.length - SnovaKeyPairGenerator.publicSeedLength - SnovaKeyPairGenerator.privateSeedLength, publicKey.publicKeySeed, 0, publicKey.publicKeySeed.length);
57-
// ptPrivateKeySeed = new byte[SnovaKeyPairGenerator.privateSeedLength];
58-
// System.arraycopy(input, input.length - SnovaKeyPairGenerator.privateSeedLength, ptPrivateKeySeed, 0, ptPrivateKeySeed.length);
59-
// }
60-
6121
static int copy3d(byte[][][] alpha, byte[] output, int outOff)
6222
{
6323
for (int i = 0; i < alpha.length; ++i)

core/src/main/java/org/bouncycastle/pqc/crypto/snova/SnovaKeyPairGenerator.java

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,11 @@ public AsymmetricCipherKeyPair generateKeyPair()
4747
byte[] ptPrivateKeySeed = Arrays.copyOfRange(seedPair, publicSeedLength, seedPair.length);
4848

4949
SnovaKeyElements keyElements = new SnovaKeyElements(params);
50-
byte[] p22 = new byte[(params.getM() * params.getO() * params.getO() * params.getL() * params.getL() + 1) >> 1];
51-
generateKeysCore(keyElements, ptPublicKeySeed, ptPrivateKeySeed, p22);
50+
System.arraycopy(ptPublicKeySeed, 0, pk, 0, ptPublicKeySeed.length);
51+
generateKeysCore(keyElements, ptPublicKeySeed, ptPrivateKeySeed, pk, ptPublicKeySeed.length);
5252

5353
// Pack public key components
5454
System.arraycopy(ptPublicKeySeed, 0, pk, 0, ptPublicKeySeed.length);
55-
System.arraycopy(p22, 0, pk, ptPublicKeySeed.length, p22.length);
5655

5756
if (params.isSkIsSeed())
5857
{
@@ -85,18 +84,11 @@ public AsymmetricCipherKeyPair generateKeyPair()
8584
);
8685
}
8786

88-
private void generateKeysCore(SnovaKeyElements keyElements, byte[] pkSeed, byte[] skSeed, byte[] p22)
87+
private void generateKeysCore(SnovaKeyElements keyElements, byte[] pkSeed, byte[] skSeed, byte[] p22, int p22Off)
8988
{
90-
// Generate T12 matrix
91-
engine.genSeedsAndT12(keyElements.T12, skSeed);
92-
93-
// Generate map components
94-
engine.genABQP(keyElements.map1, pkSeed, keyElements.fixedAbq);
95-
96-
// Generate F matrices
97-
engine.genF(keyElements.map2, keyElements.map1, keyElements.T12);
89+
engine.genMap1T12Map2(keyElements, pkSeed, skSeed);
9890

9991
// Generate P22 matrix
100-
engine.genP22(p22, keyElements.T12, keyElements.map1.p21, keyElements.map2.f12);
92+
engine.genP22(p22, p22Off, keyElements.T12, keyElements.map1.p21, keyElements.map2.f12);
10193
}
10294
}

core/src/main/java/org/bouncycastle/pqc/crypto/snova/SnovaSigner.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,7 @@ public byte[] generateSignature(byte[] message)
6666
byte[] seedPair = privKey.getPrivateKey();
6767
publicKeySeed = Arrays.copyOfRange(seedPair, 0, SnovaKeyPairGenerator.publicSeedLength);
6868
keyElements.ptPrivateKeySeed = Arrays.copyOfRange(seedPair, SnovaKeyPairGenerator.publicSeedLength, seedPair.length);
69-
engine.genSeedsAndT12(keyElements.T12, keyElements.ptPrivateKeySeed);
70-
71-
// Generate map components
72-
engine.genABQP(keyElements.map1, publicKeySeed, keyElements.fixedAbq);
73-
74-
// Generate F matrices
75-
engine.genF(keyElements.map2, keyElements.map1, keyElements.T12);
69+
engine.genMap1T12Map2(keyElements, publicKeySeed, keyElements.ptPrivateKeySeed);
7670
}
7771
else
7872
{
@@ -103,11 +97,11 @@ public boolean verifySignature(byte[] message, byte[] signature)
10397
byte[] hash = new byte[shake.getDigestSize()];
10498
shake.update(message, 0, message.length);
10599
shake.doFinal(hash, 0);
106-
SnovaKeyElements keyElements = new SnovaKeyElements(params);
100+
MapGroup1 map1 = new MapGroup1(params);
107101
byte[] pk = pubKey.getEncoded();
108102
byte[] publicKeySeed = Arrays.copyOf(pk, SnovaKeyPairGenerator.publicSeedLength);
109103
byte[] p22_source = Arrays.copyOfRange(pk, SnovaKeyPairGenerator.publicSeedLength, pk.length);
110-
engine.genABQP(keyElements.map1, publicKeySeed, keyElements.fixedAbq);
104+
engine.genABQP(map1, publicKeySeed);
111105
byte[][][][] p22 = new byte[params.getM()][params.getO()][params.getO()][params.getLsq()];
112106
if ((params.getLsq() & 1) == 0)
113107
{
@@ -120,7 +114,7 @@ public boolean verifySignature(byte[] message, byte[] signature)
120114
MapGroup1.fillP(p22_gf16s, 0, p22, p22_gf16s.length);
121115
}
122116

123-
return verifySignatureCore(hash, signature, publicKeySeed, keyElements.map1, p22);
117+
return verifySignatureCore(hash, signature, publicKeySeed, map1, p22);
124118
}
125119

126120
public void createSignedHash(

core/src/main/java/org/bouncycastle/util/GF16.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,27 +120,44 @@ public static void decode(byte[] input, int inOff, byte[] output, int outOff, in
120120
* Two 4-bit values are packed into one byte, with the first nibble stored in the lower 4 bits
121121
* and the second nibble stored in the upper 4 bits.
122122
*
123-
* @param input the input array of 4-bit values (stored as bytes, only lower 4 bits used)
124-
* @param output the output byte array that will hold the encoded bytes
125-
* @param outputLen the number of nibbles in the input array
123+
* @param input the input array of 4-bit values (stored as bytes, only lower 4 bits used)
124+
* @param output the output byte array that will hold the encoded bytes
125+
* @param inputLen the number of nibbles in the input array
126126
*/
127-
public static void encode(byte[] input, byte[] output, int outputLen)
127+
public static void encode(byte[] input, byte[] output, int inputLen)
128128
{
129129
int i, inOff = 0;
130130
// Process pairs of 4-bit values
131-
for (i = 0; i < outputLen / 2; i++)
131+
for (i = 0; i < inputLen / 2; i++)
132132
{
133133
int lowerNibble = input[inOff++] & 0x0F;
134134
int upperNibble = (input[inOff++] & 0x0F) << 4;
135135
output[i] = (byte)(lowerNibble | upperNibble);
136136
}
137137
// If there is an extra nibble (odd number of nibbles), store it directly in lower 4 bits.
138-
if ((outputLen & 1) == 1)
138+
if ((inputLen & 1) == 1)
139139
{
140140
output[i] = (byte)(input[inOff] & 0x0F);
141141
}
142142
}
143143

144+
public static void encode(byte[] input, byte[] output, int outOff, int inputLen)
145+
{
146+
int i, inOff = 0;
147+
// Process pairs of 4-bit values
148+
for (i = 0; i < inputLen / 2; i++)
149+
{
150+
int lowerNibble = input[inOff++] & 0x0F;
151+
int upperNibble = (input[inOff++] & 0x0F) << 4;
152+
output[outOff++] = (byte)(lowerNibble | upperNibble);
153+
}
154+
// If there is an extra nibble (odd number of nibbles), store it directly in lower 4 bits.
155+
if ((inputLen & 1) == 1)
156+
{
157+
output[outOff] = (byte)(input[inOff] & 0x0F);
158+
}
159+
}
160+
144161
public static byte innerProduct(byte[] a, int aOff, byte[] b, int bOff, int rank)
145162
{
146163
byte result = 0;

0 commit comments

Comments
 (0)