Skip to content

Commit c8c0b46

Browse files
author
gefeili
committed
Add interface SecretSharing
1 parent f6a07db commit c8c0b46

File tree

3 files changed

+95
-36
lines changed

3 files changed

+95
-36
lines changed

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

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package org.bouncycastle.crypto.split;
22

3+
import java.security.SecureRandom;
4+
35
public abstract class Polynomial
6+
implements SecretSharing
47
{
58
public static final byte AES = 0;
69
public static final byte RSA = 1;
@@ -27,7 +30,18 @@ public abstract class Polynomial
2730

2831
protected Polynomial(int l, int m, int n)
2932
{
30-
//TODO: check m <= n <= 255
33+
if (l < 0 || l > 65534)
34+
{
35+
throw new IllegalArgumentException("Invalid input: l ranges from 0 to 65534 (2^16-2) bytes.");
36+
}
37+
if (m < 1 || m > 255)
38+
{
39+
throw new IllegalArgumentException("Invalid input: m must be less than 256 and positive.");
40+
}
41+
if (n < m || n > 255)
42+
{
43+
throw new IllegalArgumentException("Invalid input: n must be less than 256 and greater than or equal to n.");
44+
}
3145
this.l = l;
3246
this.m = m;
3347
this.n = n;
@@ -45,17 +59,23 @@ protected void init()
4559
}
4660
}
4761

48-
public byte[][] createShares(byte[][] sr)
62+
public byte[][] createShares(SecureRandom random)
4963
{
50-
byte[][] result = new byte[p.length][sr[0].length];
51-
for (int i = 0; i < p.length; i++)
64+
byte[][] sr = new byte[m][l];
65+
byte[][] result = new byte[p.length][l];
66+
int i;
67+
for (i = 0; i < m; ++i)
68+
{
69+
random.nextBytes(sr[i]);
70+
}
71+
for (i = 0; i < p.length; i++)
5272
{
5373
result[i] = gfVecMul(p[i], sr);
5474
}
5575
return result;
5676
}
5777

58-
public byte[] recombine(byte[] rr, byte[][] splits)
78+
public byte[] recombineShares(int[] rr, byte[]... splits)
5979
{
6080
int n = rr.length;
6181
byte[] r = new byte[n];
@@ -68,7 +88,7 @@ public byte[] recombine(byte[] rr, byte[][] splits)
6888
{
6989
if (j != i)
7090
{
71-
products[tmp++] = gfDiv(rr[j] & 0xff, (rr[i] ^ rr[j]) & 0xff);
91+
products[tmp++] = gfDiv(rr[j], rr[i] ^ rr[j]);
7292
}
7393
}
7494

@@ -94,11 +114,11 @@ protected byte gfPow(int n, byte k)
94114
{
95115
if ((k & (1 << i)) != 0)
96116
{
97-
result = (byte) gfMul(result & 0xff, n & 0xff);
117+
result = (byte)gfMul(result & 0xff, n & 0xff);
98118
}
99119
n = gfMul(n & 0xff, n & 0xff);
100120
}
101-
return (byte) result;
121+
return (byte)result;
102122
}
103123

104124
private byte[] gfVecMul(byte[] xs, byte[][] yss)
@@ -112,7 +132,7 @@ private byte[] gfVecMul(byte[] xs, byte[][] yss)
112132
{
113133
sum ^= gfMul(xs[k] & 0xff, yss[k][j] & 0xff);
114134
}
115-
result[j] = (byte) sum;
135+
result[j] = (byte)sum;
116136
}
117137
return result;
118138
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.bouncycastle.crypto.split;
2+
3+
import java.security.SecureRandom;
4+
5+
/**
6+
* Secret sharing (also called secret splitting) refers to methods for distributing a secret among a group.
7+
* In this process, no individual holds any intelligible information about the secret.
8+
* However, when a sufficient number of individuals combine their 'shares', the secret can be reconstructed.
9+
*/
10+
public interface SecretSharing
11+
{
12+
/**
13+
* Creates secret shares from a given secret. The secret will be divided into shares, where the secret has a length of L bytes.
14+
*
15+
* @param random the source of secure random
16+
* @return An array of {@code byte[][]} representing the generated secret shares for m users with l bytes each.
17+
*/
18+
byte[][] createShares(SecureRandom random);
19+
20+
/**
21+
* Recombines secret shares to reconstruct the original secret.
22+
*
23+
* @param rr The threshold number of shares required for recombination.
24+
* @param splits A vector of byte arrays representing the shares, where each share is l bytes long.
25+
* @return A byte array containing the reconstructed secret.
26+
*/
27+
byte[] recombineShares(int[] rr, byte[]... splits);
28+
}

core/src/test/java/org/bouncycastle/crypto/split/test/PolynomialTest.java

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package org.bouncycastle.crypto.split.test;
22

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

56
import junit.framework.TestCase;
67

78
import org.bouncycastle.crypto.split.Polynomial;
89
import org.bouncycastle.crypto.split.PolynomialNative;
910
import org.bouncycastle.crypto.split.PolynomialTable;
11+
import org.bouncycastle.util.test.FixedSecureRandom;
1012

1113
public class PolynomialTest
1214
extends TestCase
@@ -825,67 +827,76 @@ private void testPolynoimial1(PolynomialFactory polynomialFactory)
825827
{
826828
Polynomial poly = polynomialFactory.newInstance(5, 2, 2);
827829
testMatrixMultiplication(poly, TV011B_TV1_SR, TV011B_TV1_SPLITS);
828-
testRecombine(poly, new byte[]{1, 2}, TV011B_TV1_1_2_SPLITS, TV011B_TV1_SECRET);
830+
testRecombine(poly, new int[]{1, 2}, TV011B_TV1_1_2_SPLITS, TV011B_TV1_SECRET);
829831
poly = polynomialFactory.newInstance(5, 2, 4);
830832
testMatrixMultiplication(poly, TV011B_TV2_SR, TV011B_TV2_SPLITS);
831-
testRecombine(poly, new byte[]{1, 2}, TV011B_TV2_1_2_SPLITS, TV011B_TV2_SECRET);
832-
testRecombine(poly, new byte[]{1, 4}, TV011B_TV2_1_4_SPLITS, TV011B_TV2_SECRET);
833-
testRecombine(poly, new byte[]{3, 4}, TV011B_TV2_3_4_SPLITS, TV011B_TV2_SECRET);
833+
testRecombine(poly, new int[]{1, 2}, TV011B_TV2_1_2_SPLITS, TV011B_TV2_SECRET);
834+
testRecombine(poly, new int[]{1, 4}, TV011B_TV2_1_4_SPLITS, TV011B_TV2_SECRET);
835+
testRecombine(poly, new int[]{3, 4}, TV011B_TV2_3_4_SPLITS, TV011B_TV2_SECRET);
834836
poly = polynomialFactory.newInstance(5, 3, 4);
835837
testMatrixMultiplication(poly, TV011B_TV3_SR, TV011B_TV3_SPLITS);
836-
testRecombine(poly, new byte[]{1, 2, 3}, TV011B_TV3_1_2_3_SPLITS, TV011B_TV3_SECRET);
837-
testRecombine(poly, new byte[]{1, 2, 4}, TV011B_TV3_1_2_4_SPLITS, TV011B_TV3_SECRET);
838-
testRecombine(poly, new byte[]{1, 3, 4}, TV011B_TV3_1_3_4_SPLITS, TV011B_TV3_SECRET);
838+
testRecombine(poly, new int[]{1, 2, 3}, TV011B_TV3_1_2_3_SPLITS, TV011B_TV3_SECRET);
839+
testRecombine(poly, new int[]{1, 2, 4}, TV011B_TV3_1_2_4_SPLITS, TV011B_TV3_SECRET);
840+
testRecombine(poly, new int[]{1, 3, 4}, TV011B_TV3_1_3_4_SPLITS, TV011B_TV3_SECRET);
839841
poly = polynomialFactory.newInstance(5, 4, 4);
840842
testMatrixMultiplication(poly, TV011B_TV4_SR, TV011B_TV4_SPLITS);
841-
testRecombine(poly, new byte[]{1, 2, 3, 4}, TV011B_TV4_1_2_3_4_SPLITS, TV011B_TV4_SECRET);
843+
testRecombine(poly, new int[]{1, 2, 3, 4}, TV011B_TV4_1_2_3_4_SPLITS, TV011B_TV4_SECRET);
842844
poly = polynomialFactory.newInstance(9, 2, 9);
843845
testMatrixMultiplication(poly, TV011B_TV5_SR, TV011B_TV5_SPLITS);
844-
testRecombine(poly, new byte[]{1, 2}, TV011B_TV5_1_2_SPLITS, TV011B_TV5_SECRET);
845-
testRecombine(poly, new byte[]{8, 9}, TV011B_TV5_8_9_SPLITS, TV011B_TV5_SECRET);
846+
testRecombine(poly, new int[]{1, 2}, TV011B_TV5_1_2_SPLITS, TV011B_TV5_SECRET);
847+
testRecombine(poly, new int[]{8, 9}, TV011B_TV5_8_9_SPLITS, TV011B_TV5_SECRET);
846848
poly = polynomialFactory.newInstance(15, 3, 5);
847849
testMatrixMultiplication(poly, TV011B_TV6_SR, TV011B_TV6_SPLITS);
848-
testRecombine(poly, new byte[]{1, 2, 3}, TV011B_TV6_1_2_3_SPLITS, TV011B_TV6_SECRET);
849-
testRecombine(poly, new byte[]{2, 3, 4}, TV011B_TV6_2_3_4_SPLITS, TV011B_TV6_SECRET);
850+
testRecombine(poly, new int[]{1, 2, 3}, TV011B_TV6_1_2_3_SPLITS, TV011B_TV6_SECRET);
851+
testRecombine(poly, new int[]{2, 3, 4}, TV011B_TV6_2_3_4_SPLITS, TV011B_TV6_SECRET);
850852
}
851853

852854
private void testPolynoimial2(PolynomialFactory polynomialFactory)
853855
{
854856
Polynomial poly = polynomialFactory.newInstance(5, 2, 2);
855857
testMatrixMultiplication(poly, TV011D_TV1_SR, TV011D_TV1_SPLITS);
856-
testRecombine(poly, new byte[]{1, 2}, TV011D_TV1_1_2_SPLITS, TV011D_TV1_SECRET);
858+
testRecombine(poly, new int[]{1, 2}, TV011D_TV1_1_2_SPLITS, TV011D_TV1_SECRET);
857859
poly = polynomialFactory.newInstance(5, 2, 4);
858860
testMatrixMultiplication(poly, TV011D_TV2_SR, TV011D_TV2_SPLITS);
859-
testRecombine(poly, new byte[]{1, 2}, TV011D_TV2_1_2_SPLITS, TV011D_TV2_SECRET);
860-
testRecombine(poly, new byte[]{1, 4}, TV011D_TV2_1_4_SPLITS, TV011D_TV2_SECRET);
861-
testRecombine(poly, new byte[]{3, 4}, TV011D_TV2_3_4_SPLITS, TV011D_TV2_SECRET);
861+
testRecombine(poly, new int[]{1, 2}, TV011D_TV2_1_2_SPLITS, TV011D_TV2_SECRET);
862+
testRecombine(poly, new int[]{1, 4}, TV011D_TV2_1_4_SPLITS, TV011D_TV2_SECRET);
863+
testRecombine(poly, new int[]{3, 4}, TV011D_TV2_3_4_SPLITS, TV011D_TV2_SECRET);
862864
poly = polynomialFactory.newInstance(5, 3, 4);
863865
testMatrixMultiplication(poly, TV011D_TV3_SR, TV011D_TV3_SPLITS);
864-
testRecombine(poly, new byte[]{1, 2, 3}, TV011D_TV3_1_2_3_SPLITS, TV011D_TV3_SECRET);
865-
testRecombine(poly, new byte[]{1, 2, 4}, TV011D_TV3_1_2_4_SPLITS, TV011D_TV3_SECRET);
866-
testRecombine(poly, new byte[]{1, 3, 4}, TV011D_TV3_1_3_4_SPLITS, TV011D_TV3_SECRET);
866+
testRecombine(poly, new int[]{1, 2, 3}, TV011D_TV3_1_2_3_SPLITS, TV011D_TV3_SECRET);
867+
testRecombine(poly, new int[]{1, 2, 4}, TV011D_TV3_1_2_4_SPLITS, TV011D_TV3_SECRET);
868+
testRecombine(poly, new int[]{1, 3, 4}, TV011D_TV3_1_3_4_SPLITS, TV011D_TV3_SECRET);
867869
poly = polynomialFactory.newInstance(5, 4, 4);
868870
testMatrixMultiplication(poly, TV011D_TV4_SR, TV011D_TV4_SPLITS);
869-
testRecombine(poly, new byte[]{1, 2, 3, 4}, TV011D_TV4_1_2_3_4_SPLITS, TV011D_TV4_SECRET);
871+
testRecombine(poly, new int[]{1, 2, 3, 4}, TV011D_TV4_1_2_3_4_SPLITS, TV011D_TV4_SECRET);
870872
poly = polynomialFactory.newInstance(9, 2, 9);
871873
testMatrixMultiplication(poly, TV011D_TV5_SR, TV011D_TV5_SPLITS);
872-
testRecombine(poly, new byte[]{1, 2}, TV011D_TV5_1_2_SPLITS, TV011D_TV5_SECRET);
873-
testRecombine(poly, new byte[]{8, 9}, TV011D_TV5_8_9_SPLITS, TV011D_TV5_SECRET);
874+
testRecombine(poly, new int[]{1, 2}, TV011D_TV5_1_2_SPLITS, TV011D_TV5_SECRET);
875+
testRecombine(poly, new int[]{8, 9}, TV011D_TV5_8_9_SPLITS, TV011D_TV5_SECRET);
874876
poly = polynomialFactory.newInstance(15, 3, 5);
875877
testMatrixMultiplication(poly, TV011D_TV6_SR, TV011D_TV6_SPLITS);
876-
testRecombine(poly, new byte[]{1, 2, 3}, TV011D_TV6_1_2_3_SPLITS, TV011D_TV6_SECRET);
877-
testRecombine(poly, new byte[]{2, 3, 4}, TV011D_TV6_2_3_4_SPLITS, TV011D_TV6_SECRET);
878+
testRecombine(poly, new int[]{1, 2, 3}, TV011D_TV6_1_2_3_SPLITS, TV011D_TV6_SECRET);
879+
testRecombine(poly, new int[]{2, 3, 4}, TV011D_TV6_2_3_4_SPLITS, TV011D_TV6_SECRET);
878880
}
879881

880882
static void testMatrixMultiplication(Polynomial poly, byte[][] sr, byte[][] splits)
881883
{
882-
byte[][] result = poly.createShares(sr);
884+
byte[] source = new byte[sr.length * sr[0].length];
885+
int currentIndex = 0;
886+
887+
for (byte[] subArray : sr)
888+
{
889+
System.arraycopy(subArray, 0, source, currentIndex, subArray.length);
890+
currentIndex += subArray.length;
891+
}
892+
SecureRandom random = new FixedSecureRandom(new FixedSecureRandom.Source[]{new FixedSecureRandom.Data(source)});
893+
byte[][] result = poly.createShares(random);
883894
assertEquals(Arrays.deepToString(splits), Arrays.deepToString(result));
884895
}
885896

886-
public void testRecombine(Polynomial poly, byte[] rr, byte[][] splits, byte[] secret)
897+
public void testRecombine(Polynomial poly, int[] rr, byte[][] splits, byte[] secret)
887898
{
888-
byte[] result = poly.recombine(rr, splits);
899+
byte[] result = poly.recombineShares(rr, splits);
889900
assertTrue(Arrays.equals(secret, result));
890901
}
891902
}

0 commit comments

Comments
 (0)