Skip to content

Commit 4e3d763

Browse files
author
gefeili
committed
Add SplitSecret.recombine
1 parent eadf2be commit 4e3d763

File tree

7 files changed

+254
-164
lines changed

7 files changed

+254
-164
lines changed

core/src/main/java/org/bouncycastle/crypto/threshold/ShamirTableSecretSplitter.java renamed to core/src/main/java/org/bouncycastle/crypto/threshold/Polynomial.java

Lines changed: 108 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,56 @@
11
package org.bouncycastle.crypto.threshold;
22

3-
import java.security.SecureRandom;
3+
abstract class Polynomial
4+
{
5+
public static Polynomial newInstance(ShamirSecretSplitter.Algorithm algorithm, ShamirSecretSplitter.Mode mode)
6+
{
7+
if (mode == ShamirSecretSplitter.Mode.Native)
8+
{
9+
return new PolynomialNative(algorithm);
10+
}
11+
else
12+
{
13+
return new PolynomialTable(algorithm);
14+
}
15+
}
16+
17+
protected abstract int gfMul(int x, int y);
18+
19+
protected abstract byte gfDiv(int x, int y);
420

5-
public class ShamirTableSecretSplitter
6-
extends ShamirSecretSplitter
21+
protected byte gfPow(int n, byte k)
22+
{
23+
int result = 1;
24+
for (int i = 0; i < 8; i++)
25+
{
26+
if ((k & (1 << i)) != 0)
27+
{
28+
result = (byte)gfMul(result & 0xff, n & 0xff);
29+
}
30+
n = gfMul(n & 0xff, n & 0xff);
31+
}
32+
return (byte)result;
33+
}
34+
35+
public byte[] gfVecMul(byte[] xs, byte[][] yss)
36+
{
37+
byte[] result = new byte[yss[0].length];
38+
int sum;
39+
for (int j = 0; j < yss[0].length; j++)
40+
{
41+
sum = 0;
42+
for (int k = 0; k < xs.length; k++)
43+
{
44+
sum ^= gfMul(xs[k] & 0xff, yss[k][j] & 0xff);
45+
}
46+
result[j] = (byte)sum;
47+
}
48+
return result;
49+
}
50+
}
51+
52+
class PolynomialTable
53+
extends Polynomial
754
{
855
private final byte[] LOG;
956
private final byte[] EXP;
@@ -148,9 +195,8 @@ public class ShamirTableSecretSplitter
148195
(byte)0x1b, (byte)0x36, (byte)0x6c, (byte)0xd8, (byte)0xad, (byte)0x47, (byte)0x8e, (byte)0x01
149196
};
150197

151-
public ShamirTableSecretSplitter(int algorithm, int l, int m, int n, SecureRandom random)
198+
public PolynomialTable(ShamirSecretSplitter.Algorithm algorithm)
152199
{
153-
super(l, m, n, random);
154200
switch (algorithm)
155201
{
156202
case AES:
@@ -164,7 +210,6 @@ public ShamirTableSecretSplitter(int algorithm, int l, int m, int n, SecureRando
164210
default:
165211
throw new IllegalArgumentException("The algorithm is not correct");
166212
}
167-
init();
168213
}
169214

170215
protected int gfMul(int x, int y)
@@ -173,7 +218,7 @@ protected int gfMul(int x, int y)
173218
{
174219
return 0;
175220
}
176-
return EXP[((LOG[x] &0xff) + (LOG[y] & 0xff)) % 255] & 0xff;
221+
return EXP[((LOG[x] & 0xff) + (LOG[y] & 0xff)) % 255] & 0xff;
177222
}
178223

179224
protected byte gfDiv(int x, int y)
@@ -182,6 +227,61 @@ protected byte gfDiv(int x, int y)
182227
{
183228
return 0;
184229
}
185-
return EXP[((LOG[x] &0xff) - (LOG[y] & 0xff) + 255) % 255];
230+
return EXP[((LOG[x] & 0xff) - (LOG[y] & 0xff) + 255) % 255];
186231
}
187232
}
233+
234+
class PolynomialNative
235+
extends Polynomial
236+
{
237+
private final int IRREDUCIBLE;
238+
239+
public PolynomialNative(ShamirSecretSplitter.Algorithm algorithm)
240+
{
241+
switch (algorithm)
242+
{
243+
case AES:
244+
IRREDUCIBLE = 0x11B;
245+
break;
246+
case RSA:
247+
IRREDUCIBLE = 0x11D;
248+
break;
249+
default:
250+
throw new IllegalArgumentException("The algorithm is not correct");
251+
}
252+
}
253+
254+
protected int gfMul(int x, int y)
255+
{
256+
//pmult
257+
int result = 0;
258+
while (y > 0)
259+
{
260+
if ((y & 1) != 0)
261+
{ // If the lowest bit of y is 1
262+
result ^= x; // XOR x into the result
263+
}
264+
x <<= 1; // Shift x left (multiply by 2 in GF)
265+
if ((x & 0x100) != 0)
266+
{ // If x is larger than 8 bits, reduce
267+
x ^= IRREDUCIBLE; // XOR with the irreducible polynomial
268+
}
269+
y >>= 1; // Shift y right
270+
}
271+
//mod
272+
while (result >= (1 << 8))
273+
{
274+
if ((result & (1 << 8)) != 0)
275+
{
276+
result ^= IRREDUCIBLE;
277+
}
278+
result <<= 1;
279+
}
280+
return result & 0xFF;
281+
}
282+
283+
protected byte gfDiv(int x, int y)
284+
{
285+
return (byte)gfMul(x, gfPow((byte)y, (byte)254) & 0xff);
286+
}
287+
}

core/src/main/java/org/bouncycastle/crypto/threshold/ShamirNativeSecretSplitter.java

Lines changed: 0 additions & 60 deletions
This file was deleted.

core/src/main/java/org/bouncycastle/crypto/threshold/ShamirSecretSplitter.java

Lines changed: 22 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,22 @@
22

33
import java.security.SecureRandom;
44

5-
public abstract class ShamirSecretSplitter
5+
public class ShamirSecretSplitter
66
implements SecretSplitter
77
{
8-
public static final int AES = 0;
9-
public static final int RSA = 1;
8+
public enum Algorithm
9+
{
10+
AES,
11+
RSA
12+
}
13+
14+
public enum Mode
15+
{
16+
Native,
17+
Table
18+
}
19+
20+
private Polynomial poly;
1021
/**
1122
* Length of the secret
1223
*/
@@ -23,7 +34,7 @@ public abstract class ShamirSecretSplitter
2334
protected byte[][] p;
2435
protected SecureRandom random;
2536

26-
protected ShamirSecretSplitter(int l, int m, int n, SecureRandom random)
37+
public ShamirSecretSplitter(Algorithm algorithm, Mode mode, int l, int m, int n, SecureRandom random)
2738
{
2839
if (l < 0 || l > 65534)
2940
{
@@ -37,20 +48,17 @@ protected ShamirSecretSplitter(int l, int m, int n, SecureRandom random)
3748
{
3849
throw new IllegalArgumentException("Invalid input: n must be less than 256 and greater than or equal to n.");
3950
}
51+
poly = Polynomial.newInstance(algorithm, mode);
4052
this.l = l;
4153
this.m = m;
4254
this.n = n;
4355
this.random = random;
44-
}
45-
46-
protected void init()
47-
{
4856
p = new byte[n][m];
4957
for (int i = 0; i < n; i++)
5058
{
5159
for (int j = 0; j < m; j++)
5260
{
53-
p[i][j] = gfPow((byte)(i + 1), (byte)j);
61+
p[i][j] = poly.gfPow((byte)(i + 1), (byte)j);
5462
}
5563
}
5664
}
@@ -66,9 +74,9 @@ public ShamirSplitSecret split()
6674
}
6775
for (i = 0; i < p.length; i++)
6876
{
69-
secretShares[i] = new ShamirSplitSecretShare(gfVecMul(p[i], sr), i + 1);
77+
secretShares[i] = new ShamirSplitSecretShare(poly.gfVecMul(p[i], sr), i + 1);
7078
}
71-
return new ShamirSplitSecret(secretShares);
79+
return new ShamirSplitSecret(poly, secretShares);
7280
}
7381

7482
public byte[] recombineShares(int[] rr, byte[]... splits)
@@ -84,52 +92,18 @@ public byte[] recombineShares(int[] rr, byte[]... splits)
8492
{
8593
if (j != i)
8694
{
87-
products[tmp++] = gfDiv(rr[j], rr[i] ^ rr[j]);
95+
products[tmp++] = poly.gfDiv(rr[j], rr[i] ^ rr[j]);
8896
}
8997
}
9098

9199
tmp = 1;
92100
for (byte p : products)
93101
{
94-
tmp = (byte)gfMul(tmp & 0xff, p & 0xff);
102+
tmp = (byte)poly.gfMul(tmp & 0xff, p & 0xff);
95103
}
96104
r[i] = tmp;
97105
}
98106

99-
return gfVecMul(r, splits);
100-
}
101-
102-
protected abstract int gfMul(int x, int y);
103-
104-
protected abstract byte gfDiv(int x, int y);
105-
106-
protected byte gfPow(int n, byte k)
107-
{
108-
int result = 1;
109-
for (int i = 0; i < 8; i++)
110-
{
111-
if ((k & (1 << i)) != 0)
112-
{
113-
result = (byte)gfMul(result & 0xff, n & 0xff);
114-
}
115-
n = gfMul(n & 0xff, n & 0xff);
116-
}
117-
return (byte)result;
118-
}
119-
120-
private byte[] gfVecMul(byte[] xs, byte[][] yss)
121-
{
122-
byte[] result = new byte[yss[0].length];
123-
int sum;
124-
for (int j = 0; j < yss[0].length; j++)
125-
{
126-
sum = 0;
127-
for (int k = 0; k < xs.length; k++)
128-
{
129-
sum ^= gfMul(xs[k] & 0xff, yss[k][j] & 0xff);
130-
}
131-
result[j] = (byte)sum;
132-
}
133-
return result;
107+
return poly.gfVecMul(r, splits);
134108
}
135109
}

core/src/main/java/org/bouncycastle/crypto/threshold/ShamirSplitSecret.java

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,55 @@
33
public class ShamirSplitSecret
44
implements SplitSecret
55
{
6-
private ShamirSplitSecretShare[] secretShares;
6+
private final ShamirSplitSecretShare[] secretShares;
7+
private final Polynomial poly;
78

8-
public ShamirSplitSecret(ShamirSplitSecretShare[] secretShares)
9+
public ShamirSplitSecret(ShamirSecretSplitter.Algorithm algorithm, ShamirSecretSplitter.Mode mode, ShamirSplitSecretShare[] secretShares)
910
{
1011
this.secretShares = secretShares;
12+
this.poly = Polynomial.newInstance(algorithm, mode);
13+
}
14+
15+
ShamirSplitSecret(Polynomial poly, ShamirSplitSecretShare[] secretShares)
16+
{
17+
this.secretShares = secretShares;
18+
this.poly = poly;
1119
}
1220

1321
public ShamirSplitSecretShare[] getSecretShare()
1422
{
1523
return secretShares;
1624
}
25+
26+
@Override
27+
public byte[] recombine()
28+
{
29+
int n = secretShares.length;
30+
byte[] r = new byte[n];
31+
byte tmp;
32+
byte[] products = new byte[n - 1];
33+
byte[][] splits = new byte[n][secretShares[0].getSecretShare().length];
34+
for (int i = 0; i < n; i++)
35+
{
36+
splits[i] = secretShares[i].getSecretShare();
37+
tmp = 0;
38+
for (int j = 0; j < n; j++)
39+
{
40+
if (j != i)
41+
{
42+
products[tmp++] = poly.gfDiv(secretShares[j].r, secretShares[i].r ^ secretShares[j].r);
43+
}
44+
45+
}
46+
47+
tmp = 1;
48+
for (byte p : products)
49+
{
50+
tmp = (byte)poly.gfMul(tmp & 0xff, p & 0xff);
51+
}
52+
r[i] = tmp;
53+
}
54+
55+
return poly.gfVecMul(r, splits);
56+
}
1757
}

0 commit comments

Comments
 (0)