Skip to content

Commit 666e548

Browse files
author
gefeili
committed
Add SecretSplitter.resplit
1 parent ef27efe commit 666e548

File tree

6 files changed

+165
-31
lines changed

6 files changed

+165
-31
lines changed

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public static Polynomial newInstance(ShamirSecretSplitter.Algorithm algorithm, S
1414
}
1515
}
1616

17-
protected abstract int gfMul(int x, int y);
17+
protected abstract byte gfMul(int x, int y);
1818

1919
protected abstract byte gfDiv(int x, int y);
2020

@@ -25,7 +25,7 @@ protected byte gfPow(int n, byte k)
2525
{
2626
if ((k & (1 << i)) != 0)
2727
{
28-
result = (byte)gfMul(result & 0xff, n & 0xff);
28+
result = gfMul(result & 0xff, n & 0xff);
2929
}
3030
n = gfMul(n & 0xff, n & 0xff);
3131
}
@@ -212,13 +212,13 @@ public PolynomialTable(ShamirSecretSplitter.Algorithm algorithm)
212212
}
213213
}
214214

215-
protected int gfMul(int x, int y)
215+
protected byte gfMul(int x, int y)
216216
{
217217
if (x == 0 || y == 0)
218218
{
219219
return 0;
220220
}
221-
return EXP[((LOG[x] & 0xff) + (LOG[y] & 0xff)) % 255] & 0xff;
221+
return (byte)(EXP[((LOG[x] & 0xff) + (LOG[y] & 0xff)) % 255] & 0xff);
222222
}
223223

224224
protected byte gfDiv(int x, int y)
@@ -251,7 +251,7 @@ public PolynomialNative(ShamirSecretSplitter.Algorithm algorithm)
251251
}
252252
}
253253

254-
protected int gfMul(int x, int y)
254+
protected byte gfMul(int x, int y)
255255
{
256256
//pmult
257257
int result = 0;
@@ -277,11 +277,11 @@ protected int gfMul(int x, int y)
277277
}
278278
result <<= 1;
279279
}
280-
return result & 0xFF;
280+
return (byte) (result & 0xFF);
281281
}
282282

283283
protected byte gfDiv(int x, int y)
284284
{
285-
return (byte)gfMul(x, gfPow((byte)y, (byte)254) & 0xff);
285+
return gfMul(x, gfPow((byte)y, (byte)254) & 0xff);
286286
}
287287
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@ public interface SecretSplitter
1818

1919
SplitSecret splitAround(SecretShare s)
2020
throws IOException;
21+
22+
SplitSecret resplit(byte[] secret);
2123
}

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import java.io.IOException;
44
import java.security.SecureRandom;
55

6+
import org.bouncycastle.util.Arrays;
7+
68
public class ShamirSecretSplitter
79
implements SecretSplitter
810
{
@@ -110,4 +112,24 @@ public ShamirSplitSecret splitAround(SecretShare s)
110112

111113
return new ShamirSplitSecret(poly, secretShares);
112114
}
115+
116+
@Override
117+
public ShamirSplitSecret resplit(byte[] secret)
118+
{
119+
byte[][] sr = new byte[m][l];
120+
ShamirSplitSecretShare[] secretShares = new ShamirSplitSecretShare[l];
121+
sr[0] = secret;
122+
int i;
123+
for (i = 1; i < m; i++)
124+
{
125+
random.nextBytes(sr[i]);
126+
}
127+
for (i = 0; i < p.length; i++)
128+
{
129+
secretShares[i] = new ShamirSplitSecretShare(poly.gfVecMul(p[i], sr), i + 1);
130+
}
131+
return new ShamirSplitSecret(poly, secretShares);
132+
}
133+
134+
113135
}

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

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,40 @@ public ShamirSplitSecretShare[] getSecretShares()
2525
return secretShares;
2626
}
2727

28-
//internal TODO: multiple/divide
28+
public ShamirSplitSecret multiple(int mul)
29+
throws IOException
30+
{
31+
byte[] ss;
32+
for (int i = 0; i < secretShares.length; ++i)
33+
{
34+
ss = secretShares[i].getEncoded();
35+
for (int j = 0; j < ss.length; ++j)
36+
{
37+
ss[j] = poly.gfMul(ss[j] & 0xFF, mul);
38+
}
39+
secretShares[i] = new ShamirSplitSecretShare(ss, i + 1);
40+
}
41+
return this;
42+
}
43+
44+
public ShamirSplitSecret divide(int div)
45+
throws IOException
46+
{
47+
byte[] ss;
48+
for (int i = 0; i < secretShares.length; ++i)
49+
{
50+
ss = secretShares[i].getEncoded();
51+
for (int j = 0; j < ss.length; ++j)
52+
{
53+
ss[j] = poly.gfDiv(ss[j] & 0xFF, div);
54+
}
55+
secretShares[i] = new ShamirSplitSecretShare(ss, i + 1);
56+
}
57+
return this;
58+
}
2959

3060
@Override
31-
public byte[] recombine()
61+
public byte[] getSecret()
3262
throws IOException
3363
{
3464
int n = secretShares.length;
@@ -46,13 +76,12 @@ public byte[] recombine()
4676
{
4777
products[tmp++] = poly.gfDiv(secretShares[j].r, secretShares[i].r ^ secretShares[j].r);
4878
}
49-
5079
}
5180

5281
tmp = 1;
5382
for (byte p : products)
5483
{
55-
tmp = (byte)poly.gfMul(tmp & 0xff, p & 0xff);
84+
tmp = poly.gfMul(tmp & 0xff, p & 0xff);
5685
}
5786
r[i] = tmp;
5887
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ public interface SplitSecret
1111
*
1212
* @return A byte array containing the reconstructed secret.
1313
*/
14-
byte[] recombine()
14+
byte[] getSecret()
1515
throws IOException;
1616
}

core/src/test/java/org/bouncycastle/crypto/threshold/test/ShamirSecretSplitterTest.java

Lines changed: 100 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22

33
import java.io.IOException;
44
import java.security.SecureRandom;
5-
import java.util.Arrays;
5+
66

77
import junit.framework.TestCase;
88

99
import org.bouncycastle.crypto.threshold.ShamirSecretSplitter;
1010
import org.bouncycastle.crypto.threshold.ShamirSplitSecret;
1111
import org.bouncycastle.crypto.threshold.ShamirSplitSecretShare;
12+
import org.bouncycastle.util.encoders.Hex;
1213
import org.bouncycastle.util.test.FixedSecureRandom;
14+
import org.bouncycastle.util.Arrays;
1315

1416
import org.junit.Assert;
1517

@@ -26,45 +28,124 @@ public static void main(String[] args)
2628
public void performTest()
2729
throws IOException
2830
{
31+
testShamirSecretResplit();
32+
testShamirSecretMultipleDivide();
2933
testShamirSecretSplitterSplitAround();
3034
testPolynomial();
3135
testShamirSecretSplitter();
3236
}
3337

38+
public void testShamirSecretResplit()
39+
throws IOException
40+
{
41+
int l = 9, m = 3, n = 9;
42+
SecureRandom random = new SecureRandom();
43+
ShamirSecretSplitter.Algorithm algorithm = ShamirSecretSplitter.Algorithm.AES;
44+
ShamirSecretSplitter.Mode mode = ShamirSecretSplitter.Mode.Table;
45+
ShamirSecretSplitter splitter = new ShamirSecretSplitter(algorithm, mode, l, m, n, random);//, secretshare);
46+
47+
ShamirSplitSecret splitSecret = splitter.split();
48+
ShamirSplitSecretShare[] secretShares = splitSecret.getSecretShares();
49+
50+
ShamirSplitSecretShare[] secretShares1 = new ShamirSplitSecretShare[]{secretShares[0], secretShares[1], secretShares[2]};
51+
ShamirSplitSecret splitSecret1 = new ShamirSplitSecret(algorithm, mode, secretShares1);
52+
byte[] secret1 = splitSecret1.getSecret();
53+
54+
55+
ShamirSplitSecret splitSecret2 = splitter.resplit(secret1);
56+
ShamirSplitSecretShare[] secretShares2 = splitSecret2.getSecretShares();
57+
ShamirSplitSecretShare[] secretShares3 = new ShamirSplitSecretShare[]{secretShares2[0], secretShares2[1], secretShares2[2]};
58+
ShamirSplitSecret splitSecret3 = new ShamirSplitSecret(algorithm, mode, secretShares3);
59+
byte[] secret3 = splitSecret3.getSecret();
60+
61+
62+
Assert.assertArrayEquals(secret1, secret3);
63+
Assert.assertFalse(Arrays.areEqual(Arrays.concatenate(secretShares[0].getEncoded(), secretShares[1].getEncoded(), secretShares[2].getEncoded()),
64+
Arrays.concatenate(secretShares2[0].getEncoded(), secretShares2[1].getEncoded(), secretShares2[2].getEncoded())));
65+
66+
}
67+
68+
public void testShamirSecretMultipleDivide()
69+
throws IOException
70+
{
71+
int l = 9, m = 3, n = 9;
72+
SecureRandom random = new SecureRandom();
73+
ShamirSecretSplitter.Algorithm algorithm = ShamirSecretSplitter.Algorithm.AES;
74+
ShamirSecretSplitter.Mode mode = ShamirSecretSplitter.Mode.Table;
75+
ShamirSecretSplitter splitter = new ShamirSecretSplitter(algorithm, mode, l, m, n, random);//, secretshare);
76+
77+
ShamirSplitSecret splitSecret = splitter.split();
78+
ShamirSplitSecretShare[] secretShares = splitSecret.getSecretShares();
79+
80+
ShamirSplitSecretShare[] secretShares1 = new ShamirSplitSecretShare[]{secretShares[0], secretShares[1], secretShares[2]};
81+
ShamirSplitSecret splitSecret1 = new ShamirSplitSecret(algorithm, mode, secretShares1);
82+
byte[] secret1 = splitSecret1.getSecret();
83+
84+
int mul = random.nextInt(255);
85+
splitSecret.multiple(mul);
86+
secretShares = splitSecret.getSecretShares();
87+
ShamirSplitSecretShare[] secretShares4 = new ShamirSplitSecretShare[]{secretShares[1], secretShares[2], secretShares[5]};
88+
ShamirSplitSecret splitSecret4 = new ShamirSplitSecret(algorithm, mode, secretShares4);
89+
byte[] secret4 = splitSecret4.getSecret();
90+
91+
splitSecret.divide(mul);
92+
secretShares = splitSecret.getSecretShares();
93+
ShamirSplitSecretShare[] secretShares2 = new ShamirSplitSecretShare[]{secretShares[4], secretShares[7], secretShares[8]};
94+
ShamirSplitSecret splitSecret2 = new ShamirSplitSecret(algorithm, mode, secretShares2);
95+
byte[] secret2 = splitSecret2.getSecret();
96+
97+
Assert.assertArrayEquals(secret1, secret2);
98+
99+
100+
// not enough secret shares cannot correctly recover the secret
101+
ShamirSplitSecretShare[] secretShares3 = new ShamirSplitSecretShare[]{secretShares[3], secretShares[6]};
102+
ShamirSplitSecret splitSecret3 = new ShamirSplitSecret(algorithm, mode, secretShares3);
103+
byte[] secret3 = splitSecret3.getSecret();
104+
Assert.assertFalse(Arrays.areEqual(secret1, secret3));
105+
}
106+
34107
public void testShamirSecretSplitterSplitAround()
35108
throws IOException
36109
{
37110
int l = 9, m = 3, n = 9;
38111
ShamirSecretSplitter.Algorithm algorithm = ShamirSecretSplitter.Algorithm.AES;
39112
ShamirSecretSplitter.Mode mode = ShamirSecretSplitter.Mode.Table;
40113
ShamirSecretSplitter splitter = new ShamirSecretSplitter(algorithm, mode, l, m, n, new SecureRandom());//, secretshare);
41-
byte[] seed = new byte[l];
42-
SecureRandom random = new SecureRandom();
43-
random.nextBytes(seed);
114+
byte[] seed = Hex.decode("010203040506070809");
115+
//SecureRandom random = new SecureRandom();
116+
117+
//random.nextBytes(seed);
118+
//System.out.println(Hex.decode(seed));
44119
ShamirSplitSecretShare ss = new ShamirSplitSecretShare(seed);
45120
ShamirSplitSecret splitSecret = splitter.splitAround(ss);
46121
ShamirSplitSecretShare[] secretShares = splitSecret.getSecretShares();
47-
Assert.assertTrue(Arrays.equals(secretShares[0].getEncoded(), seed));
122+
Assert.assertArrayEquals(secretShares[0].getEncoded(), seed);
48123

49124
ShamirSplitSecretShare[] secretShares1 = new ShamirSplitSecretShare[]{secretShares[0], secretShares[1], secretShares[2]};
50125
ShamirSplitSecret splitSecret1 = new ShamirSplitSecret(algorithm, mode, secretShares1);
51-
byte[] secret1 = splitSecret1.recombine();
126+
byte[] secret1 = splitSecret1.getSecret();
52127

53128
ShamirSplitSecretShare[] secretShares4 = new ShamirSplitSecretShare[]{secretShares[1], secretShares[2], secretShares[5]};
54129
ShamirSplitSecret splitSecret4 = new ShamirSplitSecret(algorithm, mode, secretShares4);
55-
byte[] secret4 = splitSecret4.recombine();
130+
byte[] secret4 = splitSecret4.getSecret();
56131

57132
ShamirSplitSecretShare[] secretShares2 = new ShamirSplitSecretShare[]{secretShares[4], secretShares[7], secretShares[8]};
58133
ShamirSplitSecret splitSecret2 = new ShamirSplitSecret(algorithm, mode, secretShares2);
59-
byte[] secret2 = splitSecret2.recombine();
134+
byte[] secret2 = splitSecret2.getSecret();
60135

61-
Assert.assertTrue(Arrays.equals(secret1, secret2));
136+
Assert.assertArrayEquals(secret1, secret2);
137+
Assert.assertArrayEquals(secret1, secret4);
62138

63139
// not enough secret shares cannot correctly recover the secret
64140
ShamirSplitSecretShare[] secretShares3 = new ShamirSplitSecretShare[]{secretShares[3], secretShares[6]};
65141
ShamirSplitSecret splitSecret3 = new ShamirSplitSecret(algorithm, mode, secretShares3);
66-
byte[] secret3 = splitSecret3.recombine();
67-
Assert.assertFalse(Arrays.equals(secret1, secret3));
142+
byte[] secret3 = splitSecret3.getSecret();
143+
Assert.assertFalse(Arrays.areEqual(secret1, secret3));
144+
145+
secretShares3 = new ShamirSplitSecretShare[]{secretShares[0], secretShares[1]};
146+
splitSecret3 = new ShamirSplitSecret(algorithm, mode, secretShares3);
147+
secret3 = splitSecret3.getSecret();
148+
Assert.assertFalse(Arrays.areEqual(secret1, secret3));
68149
}
69150

70151
public void testShamirSecretSplitter()
@@ -79,19 +160,19 @@ public void testShamirSecretSplitter()
79160

80161
ShamirSplitSecretShare[] secretShares1 = new ShamirSplitSecretShare[]{secretShares[0], secretShares[1], secretShares[2]};
81162
ShamirSplitSecret splitSecret1 = new ShamirSplitSecret(algorithm, mode, secretShares1);
82-
byte[] secret1 = splitSecret1.recombine();
163+
byte[] secret1 = splitSecret1.getSecret();
83164

84165
ShamirSplitSecretShare[] secretShares2 = new ShamirSplitSecretShare[]{secretShares[4], secretShares[7], secretShares[8]};
85166
ShamirSplitSecret splitSecret2 = new ShamirSplitSecret(algorithm, mode, secretShares2);
86-
byte[] secret2 = splitSecret2.recombine();
167+
byte[] secret2 = splitSecret2.getSecret();
87168

88-
Assert.assertTrue(Arrays.equals(secret1, secret2));
169+
Assert.assertArrayEquals(secret1, secret2);
89170

90171
// not enough secret shares cannot correctly recover the secret
91172
ShamirSplitSecretShare[] secretShares3 = new ShamirSplitSecretShare[]{secretShares[3], secretShares[6]};
92173
ShamirSplitSecret splitSecret3 = new ShamirSplitSecret(algorithm, mode, secretShares3);
93-
byte[] secret3 = splitSecret3.recombine();
94-
Assert.assertFalse(Arrays.equals(secret1, secret3));
174+
byte[] secret3 = splitSecret3.getSecret();
175+
Assert.assertFalse(Arrays.areEqual(secret1, secret3));
95176
}
96177
// private static Polynomial polynomial1 = new PolynomialTable(Polynomial.AES);
97178
// private static Polynomial polynomial2 = new PolynomialTable(Polynomial.RSA);
@@ -1020,13 +1101,13 @@ static void testMatrixMultiplication(ShamirSecretSplitter poly, byte[][] splits)
10201101
{
10211102
result[i] = secretShares[i].getEncoded();
10221103
}
1023-
assertEquals(Arrays.deepToString(splits), Arrays.deepToString(result));
1104+
assertEquals(java.util.Arrays.deepToString(splits), java.util.Arrays.deepToString(result));
10241105
}
10251106

10261107
public void testRecombine(ShamirSplitSecret splitSecret, byte[] secret)
10271108
throws IOException
10281109
{
1029-
byte[] result = splitSecret.recombine();
1030-
assertTrue(Arrays.equals(secret, result));
1110+
byte[] result = splitSecret.getSecret();
1111+
assertTrue(Arrays.areEqual(secret, result));
10311112
}
10321113
}

0 commit comments

Comments
 (0)