-
Notifications
You must be signed in to change notification settings - Fork 55
/
ArithmeticDummyDataSupplier.java
139 lines (121 loc) · 4.79 KB
/
ArithmeticDummyDataSupplier.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package dk.alexandra.fresco.framework.util;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* Supplies generic pre-processed material common across arithmetic SPDZ-like suites, including
* random elements, bits, and multiplication triples.
*
* <p>Uses {@link Random} to deterministically generate all material. This is not secure, and should not be used in production code!
*/
public class ArithmeticDummyDataSupplier {
private final int myId;
private final int noOfParties;
private final BigInteger modulus;
private final int modBitLength;
private final Random random;
private final SecretSharer<BigInteger> sharer;
private final ModularReductionAlgorithm reducer;
public ArithmeticDummyDataSupplier(int myId, int noOfParties, BigInteger modulus) {
ValidationUtils.assertValidId(myId, noOfParties);
this.myId = myId;
this.noOfParties = noOfParties;
this.modulus = modulus;
this.modBitLength = modulus.bitLength();
random = new Random(42);
sharer = new DummyBigIntegerSharer(modulus, random);
reducer = ModularReductionAlgorithm.getReductionAlgorithm(modulus);
}
/**
* Computes the next random element and this party's share.
*/
public Pair<BigInteger, BigInteger> getRandomElementShare() {
BigInteger element = sampleRandomBigInteger();
return new Pair<>(element, sharer.share(element, noOfParties).get(myId - 1));
}
/**
* Computes the next random bit (expressed as {@link BigInteger}) and this party's share.
*/
public Pair<BigInteger, BigInteger> getRandomBitShare() {
BigInteger bit = getNextBit();
return new Pair<>(bit, sharer.share(bit, noOfParties).get(myId - 1));
}
/**
* Computes the next random multiplication triple and this party's shares.
*/
public MultiplicationTripleShares getMultiplicationTripleShares() {
BigInteger left = sampleRandomBigInteger();
BigInteger right = sampleRandomBigInteger();
BigInteger product = reducer.apply(left.multiply(right));
return new MultiplicationTripleShares(
new Pair<>(left, sharer.share(left, noOfParties).get(myId - 1)),
new Pair<>(right, sharer.share(right, noOfParties).get(myId - 1)),
new Pair<>(product, sharer.share(product, noOfParties).get(myId - 1))
);
}
/**
* Constructs an exponentiation pipe. <p>An exponentiation pipe is a list of numbers in the
* following format: r^{-1}, r, r^{2}, r^{3}, ..., r^{expPipeLength}, where r is a random element
* and all exponentiations are mod {@link #modulus}.</p>
*/
public List<Pair<BigInteger, BigInteger>> getExpPipe(int expPipeLength) {
List<BigInteger> openExpPipe = getOpenExpPipe(expPipeLength);
return openExpPipe.stream()
.map(r -> new Pair<>(r, sharer.share(r, noOfParties).get(myId - 1)))
.collect(Collectors.toList());
}
private BigInteger sampleRandomBigInteger() {
return reducer.apply(new BigInteger(modBitLength, random));
}
private List<BigInteger> getOpenExpPipe(int expPipeLength) {
List<BigInteger> openExpPipe = new ArrayList<>(expPipeLength);
BigInteger first = sampleRandomBigInteger();
BigInteger inverse = first.modInverse(modulus);
openExpPipe.add(inverse);
openExpPipe.add(first);
for (int i = 1; i < expPipeLength; i++) {
BigInteger previous = openExpPipe.get(openExpPipe.size() - 1);
openExpPipe.add(reducer.apply(previous.multiply(first)));
}
return openExpPipe;
}
private BigInteger getNextBit() {
return random.nextBoolean() ? BigInteger.ONE : BigInteger.ZERO;
}
class DummyBigIntegerSharer implements SecretSharer<BigInteger> {
private final BigInteger modulus;
private final int modBitLength;
private final Random random;
DummyBigIntegerSharer(BigInteger modulus, Random random) {
this.modulus = modulus;
this.modBitLength = modulus.bitLength();
this.random = random;
}
/**
* Computes an additive secret-sharing of the input element.
*/
@Override
public List<BigInteger> share(BigInteger input, int numShares) {
List<BigInteger> shares = getNextRandomElements(numShares - 1);
BigInteger sumShares = MathUtils.sum(shares, modulus);
BigInteger diff = reducer.apply(input.subtract(sumShares));
shares.add(diff);
return shares;
}
/**
* Recombines additive secret-shares into secret.
*/
@Override
public BigInteger recombine(List<BigInteger> shares) {
return MathUtils.sum(shares, modulus);
}
private List<BigInteger> getNextRandomElements(int numElements) {
return IntStream.range(0, numElements)
.mapToObj(i -> reducer.apply(new BigInteger(modBitLength, random)))
.collect(Collectors.toList());
}
}
}