Skip to content

Commit ef27efe

Browse files
author
gefeili
committed
Add SecretSplitter.splitAround
1 parent 14fbee9 commit ef27efe

File tree

7 files changed

+118
-13
lines changed

7 files changed

+118
-13
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package org.bouncycastle.crypto.threshold;
22

3+
import org.bouncycastle.util.Encodable;
4+
35
public interface SecretShare
6+
extends Encodable
47
{
58
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.bouncycastle.crypto.threshold;
22

3+
import java.io.IOException;
4+
35
/**
46
* Secret sharing (also called secret splitting) refers to methods for distributing a secret among a group.
57
* In this process, no individual holds any intelligible information about the secret.
@@ -13,4 +15,7 @@ public interface SecretSplitter
1315
* @return An array of {@code byte[][]} representing the generated secret shares for m users with l bytes each.
1416
*/
1517
SplitSecret split();
18+
19+
SplitSecret splitAround(SecretShare s)
20+
throws IOException;
1621
}

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

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.bouncycastle.crypto.threshold;
22

3+
import java.io.IOException;
34
import java.security.SecureRandom;
45

56
public class ShamirSecretSplitter
@@ -68,7 +69,7 @@ public ShamirSplitSecret split()
6869
byte[][] sr = new byte[m][l];
6970
ShamirSplitSecretShare[] secretShares = new ShamirSplitSecretShare[l];
7071
int i;
71-
for (i = 0; i < m; ++i)
72+
for (i = 0; i < m; i++)
7273
{
7374
random.nextBytes(sr[i]);
7475
}
@@ -78,4 +79,35 @@ public ShamirSplitSecret split()
7879
}
7980
return new ShamirSplitSecret(poly, secretShares);
8081
}
82+
83+
@Override
84+
public ShamirSplitSecret splitAround(SecretShare s)
85+
throws IOException
86+
{
87+
byte[][] sr = new byte[m][l];
88+
ShamirSplitSecretShare[] secretShares = new ShamirSplitSecretShare[l];
89+
byte[] ss0 = s.getEncoded();
90+
secretShares[0] = new ShamirSplitSecretShare(ss0, 1);
91+
int i, j;
92+
byte tmp;
93+
for (i = 0; i < m; i++)
94+
{
95+
random.nextBytes(sr[i]);
96+
}
97+
for (i = 0; i < l; i++)
98+
{
99+
tmp = sr[1][i];
100+
for (j = 2; j < m; j++)
101+
{
102+
tmp ^= sr[j][i];
103+
}
104+
sr[0][i] = (byte)(tmp ^ ss0[i]);
105+
}
106+
for (i = 1; i < p.length; i++)
107+
{
108+
secretShares[i] = new ShamirSplitSecretShare(poly.gfVecMul(p[i], sr), i + 1);
109+
}
110+
111+
return new ShamirSplitSecret(poly, secretShares);
112+
}
81113
}

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

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

3+
import java.io.IOException;
4+
35
public class ShamirSplitSecret
46
implements SplitSecret
57
{
@@ -18,22 +20,25 @@ public ShamirSplitSecret(ShamirSecretSplitter.Algorithm algorithm, ShamirSecretS
1820
this.poly = poly;
1921
}
2022

21-
public ShamirSplitSecretShare[] getSecretShare()
23+
public ShamirSplitSecretShare[] getSecretShares()
2224
{
2325
return secretShares;
2426
}
2527

28+
//internal TODO: multiple/divide
29+
2630
@Override
2731
public byte[] recombine()
32+
throws IOException
2833
{
2934
int n = secretShares.length;
3035
byte[] r = new byte[n];
3136
byte tmp;
3237
byte[] products = new byte[n - 1];
33-
byte[][] splits = new byte[n][secretShares[0].getSecretShare().length];
38+
byte[][] splits = new byte[n][secretShares[0].getEncoded().length];
3439
for (int i = 0; i < n; i++)
3540
{
36-
splits[i] = secretShares[i].getSecretShare();
41+
splits[i] = secretShares[i].getEncoded();
3742
tmp = 0;
3843
for (int j = 0; j < n; j++)
3944
{

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.bouncycastle.crypto.threshold;
22

3+
import java.io.IOException;
4+
35
import org.bouncycastle.util.Arrays;
46

57
public class ShamirSplitSecretShare
@@ -14,8 +16,16 @@ public ShamirSplitSecretShare(byte[] secretShare, int r)
1416
this.r = r;
1517
}
1618

17-
public byte[] getSecretShare()
19+
public ShamirSplitSecretShare(byte[] secretShare)
20+
{
21+
this.secretShare = Arrays.clone(secretShare);
22+
this.r = 1;
23+
}
24+
25+
@Override
26+
public byte[] getEncoded()
27+
throws IOException
1828
{
19-
return secretShare;
29+
return Arrays.clone(secretShare);
2030
}
2131
}
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package org.bouncycastle.crypto.threshold;
22

3+
import java.io.IOException;
4+
35
public interface SplitSecret
46
{
5-
SecretShare[] getSecretShare();
7+
SecretShare[] getSecretShares();
68

79
/**
810
* Recombines secret shares to reconstruct the original secret.
911
*
1012
* @return A byte array containing the reconstructed secret.
1113
*/
12-
byte[] recombine();
14+
byte[] recombine()
15+
throws IOException;
1316
}

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

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.bouncycastle.crypto.threshold.test;
22

3+
import java.io.IOException;
34
import java.security.SecureRandom;
45
import java.util.Arrays;
56

@@ -9,31 +10,72 @@
910
import org.bouncycastle.crypto.threshold.ShamirSplitSecret;
1011
import org.bouncycastle.crypto.threshold.ShamirSplitSecretShare;
1112
import org.bouncycastle.util.test.FixedSecureRandom;
13+
1214
import org.junit.Assert;
1315

1416
public class ShamirSecretSplitterTest
1517
extends TestCase
1618
{
1719
public static void main(String[] args)
20+
throws IOException
1821
{
1922
ShamirSecretSplitterTest test = new ShamirSecretSplitterTest();
2023
test.performTest();
2124
}
2225

2326
public void performTest()
27+
throws IOException
2428
{
29+
testShamirSecretSplitterSplitAround();
2530
testPolynomial();
2631
testShamirSecretSplitter();
2732
}
2833

34+
public void testShamirSecretSplitterSplitAround()
35+
throws IOException
36+
{
37+
int l = 9, m = 3, n = 9;
38+
ShamirSecretSplitter.Algorithm algorithm = ShamirSecretSplitter.Algorithm.AES;
39+
ShamirSecretSplitter.Mode mode = ShamirSecretSplitter.Mode.Table;
40+
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);
44+
ShamirSplitSecretShare ss = new ShamirSplitSecretShare(seed);
45+
ShamirSplitSecret splitSecret = splitter.splitAround(ss);
46+
ShamirSplitSecretShare[] secretShares = splitSecret.getSecretShares();
47+
Assert.assertTrue(Arrays.equals(secretShares[0].getEncoded(), seed));
48+
49+
ShamirSplitSecretShare[] secretShares1 = new ShamirSplitSecretShare[]{secretShares[0], secretShares[1], secretShares[2]};
50+
ShamirSplitSecret splitSecret1 = new ShamirSplitSecret(algorithm, mode, secretShares1);
51+
byte[] secret1 = splitSecret1.recombine();
52+
53+
ShamirSplitSecretShare[] secretShares4 = new ShamirSplitSecretShare[]{secretShares[1], secretShares[2], secretShares[5]};
54+
ShamirSplitSecret splitSecret4 = new ShamirSplitSecret(algorithm, mode, secretShares4);
55+
byte[] secret4 = splitSecret4.recombine();
56+
57+
ShamirSplitSecretShare[] secretShares2 = new ShamirSplitSecretShare[]{secretShares[4], secretShares[7], secretShares[8]};
58+
ShamirSplitSecret splitSecret2 = new ShamirSplitSecret(algorithm, mode, secretShares2);
59+
byte[] secret2 = splitSecret2.recombine();
60+
61+
Assert.assertTrue(Arrays.equals(secret1, secret2));
62+
63+
// not enough secret shares cannot correctly recover the secret
64+
ShamirSplitSecretShare[] secretShares3 = new ShamirSplitSecretShare[]{secretShares[3], secretShares[6]};
65+
ShamirSplitSecret splitSecret3 = new ShamirSplitSecret(algorithm, mode, secretShares3);
66+
byte[] secret3 = splitSecret3.recombine();
67+
Assert.assertFalse(Arrays.equals(secret1, secret3));
68+
}
69+
2970
public void testShamirSecretSplitter()
71+
throws IOException
3072
{
3173
int l = 9, m = 3, n = 9;
3274
ShamirSecretSplitter.Algorithm algorithm = ShamirSecretSplitter.Algorithm.AES;
3375
ShamirSecretSplitter.Mode mode = ShamirSecretSplitter.Mode.Table;
34-
ShamirSecretSplitter splitter = new ShamirSecretSplitter(algorithm, mode, l, m, n, new SecureRandom());
35-
ShamirSplitSecret splitSecret = splitter.split();
36-
ShamirSplitSecretShare[] secretShares = splitSecret.getSecretShare();
76+
ShamirSecretSplitter splitter = new ShamirSecretSplitter(algorithm, mode, l, m, n, new SecureRandom());//, secretshare);
77+
ShamirSplitSecret splitSecret = splitter.split(); //integers multiply/ divide
78+
ShamirSplitSecretShare[] secretShares = splitSecret.getSecretShares();
3779

3880
ShamirSplitSecretShare[] secretShares1 = new ShamirSplitSecretShare[]{secretShares[0], secretShares[1], secretShares[2]};
3981
ShamirSplitSecret splitSecret1 = new ShamirSplitSecret(algorithm, mode, secretShares1);
@@ -825,6 +867,7 @@ public String getName()
825867
}
826868

827869
public void testPolynomial()
870+
throws IOException
828871
{
829872
testPolynoimial1(new PolynomialFactory()
830873
{
@@ -888,6 +931,7 @@ public ShamirSplitSecret newInstance(ShamirSplitSecretShare[] secretShares)
888931
}
889932

890933
private void testPolynoimial1(PolynomialFactory polynomialFactory)
934+
throws IOException
891935
{
892936
ShamirSecretSplitter splitter = polynomialFactory.newInstance(5, 2, 2, getSecureRandom(TV011B_TV1_SR));
893937
testMatrixMultiplication(splitter, TV011B_TV1_SPLITS);
@@ -916,6 +960,7 @@ private void testPolynoimial1(PolynomialFactory polynomialFactory)
916960
}
917961

918962
private void testPolynoimial2(PolynomialFactory polynomialFactory)
963+
throws IOException
919964
{
920965
ShamirSecretSplitter poly = polynomialFactory.newInstance(5, 2, 2, getSecureRandom(TV011D_TV1_SR));
921966
testMatrixMultiplication(poly, TV011D_TV1_SPLITS);
@@ -967,17 +1012,19 @@ static ShamirSplitSecretShare[] getShamirSplitSecretShareArray(int[] rr, byte[][
9671012
}
9681013

9691014
static void testMatrixMultiplication(ShamirSecretSplitter poly, byte[][] splits)
1015+
throws IOException
9701016
{
971-
ShamirSplitSecretShare[] secretShares = poly.split().getSecretShare();
1017+
ShamirSplitSecretShare[] secretShares = poly.split().getSecretShares();
9721018
byte[][] result = new byte[splits.length][splits[0].length];
9731019
for (int i = 0; i < result.length; ++i)
9741020
{
975-
result[i] = secretShares[i].getSecretShare();
1021+
result[i] = secretShares[i].getEncoded();
9761022
}
9771023
assertEquals(Arrays.deepToString(splits), Arrays.deepToString(result));
9781024
}
9791025

9801026
public void testRecombine(ShamirSplitSecret splitSecret, byte[] secret)
1027+
throws IOException
9811028
{
9821029
byte[] result = splitSecret.recombine();
9831030
assertTrue(Arrays.equals(secret, result));

0 commit comments

Comments
 (0)