Skip to content

Commit 7acda24

Browse files
author
gefeili
committed
TODO: Fix the bug in generating SNOVA_24_5_5_ESK public key
1 parent 7f0c8f6 commit 7acda24

File tree

5 files changed

+256
-73
lines changed

5 files changed

+256
-73
lines changed

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

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,62 +26,87 @@ public MapGroup1(SnovaParameters params)
2626
qAlpha2 = new byte[m][alpha][lsq];
2727
}
2828

29-
public int decode(byte[] input, int len)
30-
{
31-
int inOff = decodeP(input, 0, p11, len);
32-
inOff += decodeP(input, inOff, p12, len - inOff);
33-
inOff += decodeP(input, inOff, p21, len - inOff);
34-
inOff += decodeAlpha(input, inOff, aAlpha, len - inOff);
35-
inOff += decodeAlpha(input, inOff, bAlpha, len - inOff);
36-
inOff += decodeAlpha(input, inOff, qAlpha1, len - inOff);
37-
inOff += decodeAlpha(input, inOff, qAlpha2, len - inOff);
38-
return inOff;
39-
}
40-
41-
// public int encode(byte[] output, int len)
29+
// public int decode(byte[] input, int len)
4230
// {
43-
// int outOff = encodeP(p11, output, 0, len);
44-
// outOff += encodeP(p12, output, outOff, len - outOff);
45-
// outOff += encodeP(p21, output, outOff, len - outOff);
46-
// outOff += encodeAlpha(aAlpha, output, outOff, len - outOff);
47-
// outOff += encodeAlpha(bAlpha, output, outOff, len - outOff);
48-
// outOff += encodeAlpha(qAlpha1, output, outOff, len - outOff);
49-
// outOff += encodeAlpha(qAlpha2, output, outOff, len - outOff);
50-
// return outOff;
31+
// int inOff = decodeP(input, 0, p11, len);
32+
// inOff += decodeP(input, inOff, p12, len - inOff);
33+
// inOff += decodeP(input, inOff, p21, len - inOff);
34+
// inOff += decodeAlpha(input, inOff, aAlpha, len - inOff);
35+
// inOff += decodeAlpha(input, inOff, bAlpha, len - inOff);
36+
// inOff += decodeAlpha(input, inOff, qAlpha1, len - inOff);
37+
// inOff += decodeAlpha(input, inOff, qAlpha2, len - inOff);
38+
// return inOff;
5139
// }
5240

53-
static int decodeP(byte[] input, int inOff, byte[][][][] p, int len)
41+
public void fill(byte[] input)
42+
{
43+
int inOff = fillP(input, 0, p11, input.length);
44+
inOff += fillP(input, inOff, p12, input.length - inOff);
45+
inOff += fillP(input, inOff, p21, input.length - inOff);
46+
inOff += fillAlpha(input, inOff, aAlpha, input.length - inOff);
47+
inOff += fillAlpha(input, inOff, bAlpha, input.length - inOff);
48+
inOff += fillAlpha(input, inOff, qAlpha1, input.length - inOff);
49+
fillAlpha(input, inOff, qAlpha2, input.length - inOff);
50+
}
51+
52+
static int fillP(byte[] input, int inOff, byte[][][][] p, int len)
5453
{
5554
int rlt = 0;
5655
for (int i = 0; i < p.length; ++i)
5756
{
58-
rlt += decodeAlpha(input, inOff + rlt, p[i], len);
57+
rlt += fillAlpha(input, inOff + rlt, p[i], len - rlt);
5958
}
6059
return rlt;
6160
}
6261

63-
private static int decodeAlpha(byte[] input, int inOff, byte[][][] alpha, int len)
62+
private static int fillAlpha(byte[] input, int inOff, byte[][][] alpha, int len)
6463
{
6564
int rlt = 0;
6665
for (int i = 0; i < alpha.length; ++i)
6766
{
6867
for (int j = 0; j < alpha[i].length; ++j)
6968
{
70-
int tmp = Math.min(alpha[i][j].length, len << 1);
71-
GF16Utils.decode(input, inOff + rlt, alpha[i][j], 0, tmp);
72-
rlt += (tmp + 1) >> 1;
73-
len -= (tmp + 1) >> 1;
69+
int tmp = Math.min(alpha[i][j].length, len - rlt);
70+
System.arraycopy(input, inOff + rlt, alpha[i][j], 0, tmp);
71+
rlt += tmp;
7472
}
7573
}
7674
return rlt;
7775
}
7876

77+
78+
// static int decodeP(byte[] input, int inOff, byte[][][][] p, int len)
79+
// {
80+
// int rlt = 0;
81+
// for (int i = 0; i < p.length; ++i)
82+
// {
83+
// rlt += decodeAlpha(input, inOff + rlt, p[i], len);
84+
// }
85+
// return rlt;
86+
// }
87+
88+
// private static int decodeAlpha(byte[] input, int inOff, byte[][][] alpha, int len)
89+
// {
90+
// int rlt = 0;
91+
// for (int i = 0; i < alpha.length; ++i)
92+
// {
93+
// for (int j = 0; j < alpha[i].length; ++j)
94+
// {
95+
// int tmp = Math.min(alpha[i][j].length, len << 1);
96+
// GF16Utils.decode(input, inOff + rlt, alpha[i][j], 0, tmp);
97+
// rlt += (tmp + 1) >> 1;
98+
// len -= (tmp + 1) >> 1;
99+
// }
100+
// }
101+
// return rlt;
102+
// }
103+
79104
static int encodeP(byte[][][][] p, byte[] output, int outOff, int len)
80105
{
81106
int rlt = 0;
82107
for (int i = 0; i < p.length; ++i)
83108
{
84-
rlt += encodeAlpha(p[i], output, outOff + rlt, len);
109+
rlt += encodeAlpha(p[i], output, outOff + rlt, len - rlt);
85110
}
86111
return rlt;
87112
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class PublicKey
88
public PublicKey(SnovaParameters params)
99
{
1010
publicKeySeed = new byte[SnovaKeyPairGenerator.publicSeedLength];
11-
P22 = new byte[(params.getM() * params.getO() * params.getO() * params.getL() * params.getL()) >> 1];
11+
P22 = new byte[(params.getM() * params.getO() * params.getO() * params.getL() * params.getL() + 1) >> 1];
1212
}
1313
}
1414

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

Lines changed: 66 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,26 @@ private byte determinant3x3(byte[] m)
185185
);
186186
}
187187

188+
private byte determinant3x3(byte[] m, int i0, int i1, int i2, int j0, int j1, int j2)
189+
{
190+
return gf16Add(
191+
gf16Add(
192+
gf16Mul(getGF16m(m, j0, i0), gf16Add(
193+
gf16Mul(getGF16m(m, j1, i1), getGF16m(m, j2, i2)),
194+
gf16Mul(getGF16m(m, j1, i2), getGF16m(m, j2, i1))
195+
)),
196+
gf16Mul(getGF16m(m, j0, i1), gf16Add(
197+
gf16Mul(getGF16m(m, j1, i0), getGF16m(m, j2, i2)),
198+
gf16Mul(getGF16m(m, j1, i2), getGF16m(m, j2, i0))
199+
))
200+
),
201+
gf16Mul(getGF16m(m, j0, i2), gf16Add(
202+
gf16Mul(getGF16m(m, j1, i0), getGF16m(m, j2, i1)),
203+
gf16Mul(getGF16m(m, j1, i1), getGF16m(m, j2, i0))
204+
))
205+
);
206+
}
207+
188208
private byte determinant4x4(byte[] m)
189209
{
190210
byte d0 = gf16Mul(getGF16m(m, 0, 0), gf16Add(
@@ -224,30 +244,48 @@ private byte determinant4x4(byte[] m)
224244

225245
private byte determinant5x5(byte[] m)
226246
{
227-
return 0;
228-
//TODO:
229-
// byte result;
230-
//
231-
// result = gf16Mul(det3x3(m, 0, 1, 2, 0, 1, 2),
232-
// gf16Add(gf16Mul(m[3][3], m[4][4]), gf16Mul(m[3][4], m[4][3])));
233-
// ... similar calculations for other components ...
234-
//result ^= gf16Mul(det3x3(m, 0, 1, 2, 0, 1, 2),
235-
// gf16Add(gf16Mul(m[3][3], m[4][4]), gf16Mul(m[3][4], m[4][3])));
236-
//return result;
237-
}
238-
239-
private byte det3x3(byte[] m, int row1, int row2, int row3, int col1, int col2, int col3)
240-
{
241-
//TODO:
242-
// byte[][] sub = new byte[3][3];
243-
// for (int i = 0; i < 3; i++)
244-
// {
245-
// sub[0][i] = m[row1][col1 + i];
246-
// sub[1][i] = m[row2][col1 + i];
247-
// sub[2][i] = m[row3][col1 + i];
248-
// }
249-
// return determinant3x3(sub);
250-
return 0;
247+
byte result = gf16Mul(determinant3x3(m, 0, 1, 2, 0, 1, 2),
248+
gf16Add(gf16Mul(getGF16m(m, 3,3), getGF16m(m, 4,4)), gf16Mul(getGF16m(m, 3,4),getGF16m(m, 4,3))));
249+
result ^= gf16Mul(determinant3x3(m, 0, 1, 3, 0, 1, 2),
250+
gf16Add(gf16Mul(getGF16m(m, 3,2), getGF16m(m, 4,4)), gf16Mul(getGF16m(m, 3,4),getGF16m(m, 4,2))));
251+
result ^= gf16Mul(determinant3x3(m, 0, 1, 4, 0, 1, 2),
252+
gf16Add(gf16Mul(getGF16m(m, 3,2), getGF16m(m, 4,3)), gf16Mul(getGF16m(m, 3,3),getGF16m(m, 4,2))));
253+
result ^= gf16Mul(determinant3x3(m, 0, 2, 3, 0, 1, 2),
254+
gf16Add(gf16Mul(getGF16m(m, 3,1), getGF16m(m, 4,4)), gf16Mul(getGF16m(m, 3,4),getGF16m(m, 4,1))));
255+
result ^= gf16Mul(determinant3x3(m, 0, 2, 4, 0, 1, 2),
256+
gf16Add(gf16Mul(getGF16m(m, 3,1), getGF16m(m, 4,3)), gf16Mul(getGF16m(m, 3,3),getGF16m(m, 4,1))));
257+
result ^= gf16Mul(determinant3x3(m, 0, 3, 4, 0, 1, 2),
258+
gf16Add(gf16Mul(getGF16m(m, 3,1), getGF16m(m, 4,2)), gf16Mul(getGF16m(m, 3,2),getGF16m(m, 4,1))));
259+
result ^= gf16Mul(determinant3x3(m, 1, 2, 3, 0, 1, 2),
260+
gf16Add(gf16Mul(getGF16m(m, 3,0), getGF16m(m, 4,4)), gf16Mul(getGF16m(m, 3,4),getGF16m(m, 4,0))));
261+
result ^= gf16Mul(determinant3x3(m, 1, 2, 4, 0, 1, 2),
262+
gf16Add(gf16Mul(getGF16m(m, 3,0), getGF16m(m, 4,3)), gf16Mul(getGF16m(m, 3,3),getGF16m(m, 4,0))));
263+
result ^= gf16Mul(determinant3x3(m, 1, 3, 4, 0, 1, 2),
264+
gf16Add(gf16Mul(getGF16m(m, 3,0), getGF16m(m, 4,2)), gf16Mul(getGF16m(m, 3,2),getGF16m(m, 4,0))));
265+
result ^= gf16Mul(determinant3x3(m, 2, 3, 4, 0, 1, 2),
266+
gf16Add(gf16Mul(getGF16m(m, 3,0), getGF16m(m, 4,1)), gf16Mul(getGF16m(m, 3,1),getGF16m(m, 4,0))));
267+
// return result;
268+
byte a012 = determinant3x3(m, 0, 1, 2, 0, 1, 2);
269+
byte b012 = gf16Add(gf16Mul(getGF16m(m, 3, 3), getGF16m(m, 4, 4)), gf16Mul(getGF16m(m, 3, 4), getGF16m(m, 4, 3)));
270+
byte a013 = determinant3x3(m, 0, 1, 3, 0, 1, 2);
271+
byte b013 = gf16Add(gf16Mul(getGF16m(m, 3, 2), getGF16m(m, 4, 4)), gf16Mul(getGF16m(m, 3, 4), getGF16m(m, 4, 2)));
272+
byte a014 = determinant3x3(m, 0, 1, 4, 0, 1, 2);
273+
byte b014 = gf16Add(gf16Mul(getGF16m(m, 3, 2), getGF16m(m, 4, 3)), gf16Mul(getGF16m(m, 3, 3), getGF16m(m, 4, 2)));
274+
byte a023 = determinant3x3(m, 0, 2, 3, 0, 1, 2);
275+
byte b023 = gf16Add(gf16Mul(getGF16m(m, 3, 1), getGF16m(m, 4, 4)), gf16Mul(getGF16m(m, 3, 4), getGF16m(m, 4, 1)));
276+
byte a024 = determinant3x3(m, 0, 2, 4, 0, 1, 2);
277+
byte b024 = gf16Add(gf16Mul(getGF16m(m, 3, 1), getGF16m(m, 4, 3)), gf16Mul(getGF16m(m, 3, 3), getGF16m(m, 4, 1)));
278+
byte a034 = determinant3x3(m, 0, 3, 4, 0, 1, 2);
279+
byte b034 = gf16Add(gf16Mul(getGF16m(m, 3, 1), getGF16m(m, 4, 2)), gf16Mul(getGF16m(m, 3, 2), getGF16m(m, 4, 1)));
280+
byte a123 = determinant3x3(m, 1, 2, 3, 0, 1, 2);
281+
byte b123 = gf16Add(gf16Mul(getGF16m(m, 3, 0), getGF16m(m, 4, 4)), gf16Mul(getGF16m(m, 3, 4), getGF16m(m, 4, 0)));
282+
byte a124 = determinant3x3(m, 1, 2, 4, 0, 1, 2);
283+
byte b124 = gf16Add(gf16Mul(getGF16m(m, 3, 0), getGF16m(m, 4, 3)), gf16Mul(getGF16m(m, 3, 3), getGF16m(m, 4, 0)));
284+
byte a134 = determinant3x3(m, 1, 3, 4, 0, 1, 2);
285+
byte b134 = gf16Add(gf16Mul(getGF16m(m, 3, 0), getGF16m(m, 4, 2)), gf16Mul(getGF16m(m, 3, 2), getGF16m(m, 4, 0)));
286+
byte a234 = determinant3x3(m, 2, 3, 4, 0, 1, 2);
287+
byte b234 = gf16Add(gf16Mul(getGF16m(m, 3, 0), getGF16m(m, 4, 1)), gf16Mul(getGF16m(m, 3, 1), getGF16m(m, 4, 0)));
288+
return result;
251289
}
252290

253291
private void generateASMatrix(byte[] target, byte a)
@@ -269,9 +307,7 @@ private void generateASMatrix(byte[] target, byte a)
269307
// POD -> entry[a][b] * (entry[c][d] * entry[e][f] + entry[g][h] * entry[i][j])
270308
private byte pod(byte[] m, int a, int b, int c, int d, int e, int f, int g, int h, int i, int j)
271309
{
272-
return gf16Add(
273-
gf16Mul(getGF16m(m, a, b), gf16Mul(getGF16m(m, c, d), getGF16m(m, e, f))),
274-
gf16Mul(getGF16m(m, g, h), getGF16m(m, i, j)));
310+
return gf16Mul(getGF16m(m, a, b), (byte)(gf16Mul(getGF16m(m, c, d), getGF16m(m, e, f)) ^ gf16Mul(getGF16m(m, g, h), getGF16m(m, i, j))));
275311
}
276312

277313
private void addMatrices(byte[] a, byte[] b, byte[] c)
@@ -312,8 +348,7 @@ public void genAFqS(byte[] c, int cOff, byte[] ptMatrix)
312348
}
313349

314350
// Handle last term with special case
315-
byte lastScalar = (c[cOff + l - 1] != 0) ? c[cOff + l - 1] :
316-
gf16Add((byte)16, gf16Add(c[cOff], (byte)(c[cOff] == 0 ? 1 : 0)));
351+
byte lastScalar = (byte)((c[cOff + l - 1] != 0) ? c[cOff + l - 1] : 16 - (c[cOff] + (c[cOff] == 0 ? 1 : 0)));
317352
gf16mScale(S[l - 1], lastScalar, temp);
318353
addMatrices(ptMatrix, temp, ptMatrix);
319354

@@ -437,14 +472,14 @@ public void genP22(byte[] outP22, byte[][][] T12, byte[][][][] P21, byte[][][][]
437472
GF16Utils.gf16mAdd(temp1, temp2, temp1, l);
438473

439474
// P22[i][j][k] += temp1
440-
GF16Utils.gf16mAdd(P22[i][j][k], temp1, P22[i][j][k], l);
475+
GF16Utils.gf16mAdd(P22[i][j][k], temp1, P22[i][j][k], l);
441476
}
442477
}
443478
}
444479
}
445480

446481
// Convert GF16 elements to packed bytes
447-
MapGroup1.encodeP(P22, outP22, 0, m * o * o *lsq);
482+
MapGroup1.encodeP(P22, outP22, 0, outP22.length);
448483
}
449484
finally
450485
{

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

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ public AsymmetricCipherKeyPair generateKeyPair()
5353
byte[] ptPublicKeySeed = Arrays.copyOfRange(seedPair, 0, publicSeedLength);
5454
byte[] ptPrivateKeySeed = Arrays.copyOfRange(seedPair, publicSeedLength, seedPair.length);
5555

56-
// System.arraycopy(ptPublicKeySeed, 0, sk, 0, ptPublicKeySeed.length);
57-
// System.arraycopy(ptPrivateKeySeed, 0, sk, ptPublicKeySeed.length, ptPrivateKeySeed.length);
5856
SnovaKeyElements keyElements = new SnovaKeyElements(params);
5957
generateKeysCore(keyElements, ptPublicKeySeed, ptPrivateKeySeed);
6058

@@ -133,15 +131,16 @@ private void genABQP(MapGroup1 map1, byte[] pkSeed)
133131
int n = v + o;
134132

135133
int gf16sPrngPublic = lsq * (2 * m * alpha + m * (n * n - m * m)) + l * 2 * m * alpha;
136-
byte[] qTemp = new byte[(m * alpha * 16 + m * alpha * 16) / l];
134+
byte[] qTemp = new byte[(m * alpha * lsq + m * alpha * lsq) / l];
137135
byte[] prngOutput = new byte[(gf16sPrngPublic + 1) >> 1];
138136

139137
if (params.isPkExpandShake())
140138
{
139+
snovaShake(pkSeed, prngOutput.length, prngOutput);
141140
// SHAKE-based expansion
142-
SHAKEDigest shake = new SHAKEDigest(256);
143-
shake.update(pkSeed, 0, pkSeed.length);
144-
shake.doFinal(prngOutput, 0, prngOutput.length);
141+
// SHAKEDigest shake = new SHAKEDigest(128);
142+
// shake.update(pkSeed, 0, pkSeed.length);
143+
// shake.doFinal(prngOutput, 0, prngOutput.length);
145144
}
146145
else
147146
{
@@ -174,11 +173,11 @@ private void genABQP(MapGroup1 map1, byte[] pkSeed)
174173
System.arraycopy(blockOut, 0, prngOutput, offset, remaining);
175174
}
176175
}
176+
byte[] temp = new byte[gf16sPrngPublic - qTemp.length];
177+
GF16Utils.decode(prngOutput, temp, temp.length);
178+
map1.fill(temp);
179+
GF16Utils.decode(prngOutput, temp.length >> 1, qTemp, 0, qTemp.length);
177180

178-
// Convert bytes to GF16 structures
179-
int inOff = map1.decode(prngOutput, (gf16sPrngPublic - qTemp.length) >> 1);
180-
GF16Utils.decode(prngOutput, inOff, qTemp, 0, qTemp.length);
181-
//
182181
// Post-processing for invertible matrices
183182
for (int pi = 0; pi < m; ++pi)
184183
{
@@ -213,4 +212,42 @@ private void genABQP(MapGroup1 map1, byte[] pkSeed)
213212
}
214213
}
215214
}
215+
216+
public static void snovaShake(byte[] ptSeed, int outputBytes, byte[] out)
217+
{
218+
final int SHAKE128_RATE = 168; // 1344-bit rate = 168 bytes
219+
long blockCounter = 0;
220+
int offset = 0;
221+
int remaining = outputBytes;
222+
223+
while (remaining > 0)
224+
{
225+
SHAKEDigest shake = new SHAKEDigest(128);
226+
227+
// Process seed + counter
228+
shake.update(ptSeed, 0, ptSeed.length);
229+
updateWithCounter(shake, blockCounter);
230+
231+
// Calculate bytes to generate in this iteration
232+
int bytesToGenerate = Math.min(remaining, SHAKE128_RATE);
233+
234+
// Generate output (XOF mode)
235+
shake.doFinal(out, offset, bytesToGenerate);
236+
237+
offset += bytesToGenerate;
238+
remaining -= bytesToGenerate;
239+
blockCounter++;
240+
}
241+
}
242+
243+
private static void updateWithCounter(SHAKEDigest shake, long counter)
244+
{
245+
byte[] counterBytes = new byte[8];
246+
// Little-endian conversion
247+
for (int i = 0; i < 8; i++)
248+
{
249+
counterBytes[i] = (byte)(counter >> (i * 8));
250+
}
251+
shake.update(counterBytes, 0, 8);
252+
}
216253
}

0 commit comments

Comments
 (0)