Skip to content

Commit 1d0f857

Browse files
committed
Better performance for KALES19 and KISS17 NR-OPRFS.
1 parent 1c5b393 commit 1d0f857

File tree

10 files changed

+65
-44
lines changed

10 files changed

+65
-44
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,4 @@ bin/
4343
.idea/vcs.xml
4444
.idea/misc.xml
4545
.idea/gradle.xml
46+
.idea/uiDesigner.xml

build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
}
55

66
group 'com.github.pvriel'
7-
version '1.2.0'
7+
version '1.2.1'
88

99
repositories {
1010
mavenLocal()

src/main/java/com/github/pvriel/oprf4j/nroprf/semihonest/KALES19/KALES19NROPRFEvaluator.java

+31-15
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
import java.io.InputStream;
1212
import java.io.OutputStream;
1313
import java.math.BigInteger;
14+
import java.util.concurrent.ExecutionException;
15+
import java.util.concurrent.ForkJoinPool;
16+
import java.util.concurrent.ForkJoinTask;
17+
import java.util.stream.IntStream;
1418

1519
/**
1620
* Implementation of the {@link NROPRFEvaluator} class that uses the <a href="https://eprint.iacr.org/2019/517">KALES19 variant</a>.
@@ -40,36 +44,48 @@ public Pair<boolean[], BigInteger[]> executeOfflinePhase(BigInteger[] elements,
4044
}
4145

4246
@Override
43-
public BigInteger[] executeOnlinePhase(Pair<boolean[], BigInteger[]> resultOfflinePhase, BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
47+
public BigInteger[] executeOnlinePhase(Pair<boolean[], BigInteger[]> resultOfflinePhase, BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException, ExecutionException, InterruptedException {
4448
boolean[] choices = resultOfflinePhase.getLeft();
4549
boolean[] b = new boolean[elements.length * bitLength];
46-
for (int i = 0; i < elements.length; i ++) {
50+
IntStream.range(0, elements.length).parallel().forEach(i -> {
4751
BigInteger element = elements[i];
4852
for (int j = 0; j < bitLength; j ++) b[i * bitLength + j] = (choices[i * bitLength + j] != element.testBit(j));
49-
}
53+
});
5054
BigInteger bAsBigInteger = ArrayUtils.convertToBigInteger(b);
5155
StreamUtils.writeBigIntegerToOutputStream(bAsBigInteger, outputStream);
5256
outputStream.flush();
5357

5458
BigInteger[] r_i_j_c_i_j = resultOfflinePhase.getRight();
55-
BigInteger[] R = new BigInteger[elements.length * bitLength];
56-
for (int i = 0; i < elements.length; i ++) {
59+
BigInteger[] C_i = new BigInteger[elements.length];
60+
BigInteger[] xor_product = new BigInteger[elements.length * bitLength];
61+
for (int i = 0; i < xor_product.length; i ++) xor_product[i] = StreamUtils.readBigIntegerFromInputStream(inputStream);
62+
ForkJoinTask<BigInteger[]> g_modded_task = ForkJoinPool.commonPool().submit(() -> {
63+
BigInteger[] g_modded = new BigInteger[elements.length];
64+
for (int i = 0; i < g_modded.length; i ++) {
65+
try {
66+
g_modded[i] = StreamUtils.readBigIntegerFromInputStream(inputStream);
67+
} catch (IOException e) {
68+
throw new RuntimeException(e);
69+
}
70+
}
71+
return g_modded;
72+
});
73+
IntStream.range(0, elements.length).parallel().forEach(i -> {
5774
BigInteger element = elements[i];
58-
for (int j = 0; j < bitLength; j ++) R[i * bitLength + j] = r_i_j_c_i_j[i * bitLength + j].xor((element.testBit(j) ? BigInteger.ONE : BigInteger.ZERO).multiply(StreamUtils.readBigIntegerFromInputStream(inputStream)));
59-
}
6075

61-
BigInteger[] C_i = new BigInteger[elements.length];
62-
for (int i = 0; i < elements.length; i ++) {
76+
BigInteger[] R = new BigInteger[bitLength];
77+
for (int j = 0; j < bitLength; j ++) R[j] = r_i_j_c_i_j[i * bitLength + j].xor((element.testBit(j) ? BigInteger.ONE : BigInteger.ZERO).multiply(xor_product[i * bitLength + j]));
78+
6379
BigInteger exponent = BigInteger.ONE;
64-
for (int j = 0; j < bitLength; j ++) exponent = exponent.multiply(R[i * bitLength + j]);
80+
for (int j = 0; j < bitLength; j ++) exponent = exponent.multiply(R[j]);
6581
C_i[i] = exponent.mod(getQ());
66-
}
82+
});
6783

6884
BigInteger[] returnValue = new BigInteger[elements.length];
69-
for (int i = 0; i < returnValue.length; i ++) {
70-
BigInteger g_modded = StreamUtils.readBigIntegerFromInputStream(inputStream);
71-
returnValue[i] = g_modded.modPow(C_i[i], getP());
72-
}
85+
BigInteger[] g_modded = g_modded_task.get();
86+
IntStream.range(0, returnValue.length).parallel().forEach(i -> {
87+
returnValue[i] = g_modded[i].modPow(C_i[i], getP());
88+
});
7389
return returnValue;
7490
}
7591
}

src/main/java/com/github/pvriel/oprf4j/nroprf/semihonest/KALES19/KALES19NROPRFProvider.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,16 @@ public void executeOnlinePhase(BigInteger[][] resultOfflinePhase, int amountOfVa
6464
for (int i = 0; i < xor_product.length; i ++) StreamUtils.writeBigIntegerToOutputStream(xor_product[i], outputStream);
6565
outputStream.flush();
6666

67-
// TODO: performance optimization.
68-
for (int i = 0; i < amountOfValues; i++) {
67+
BigInteger[] g_i = new BigInteger[amountOfValues];
68+
IntStream.range(0, amountOfValues).parallel().forEach(i -> {
6969
BigInteger r_inv = BigInteger.ONE;
7070
for (int j = 0; j < bitLength; j++) r_inv = r_inv.multiply(r_i_j[i * bitLength + j]);
7171
r_inv = r_inv.modInverse(getQ());
7272

73-
BigInteger g_i = getG().modPow(getInitialKey().multiply(r_inv), getP());
74-
StreamUtils.writeBigIntegerToOutputStream(g_i, outputStream);
73+
g_i[i] = getG().modPow(getInitialKey().multiply(r_inv), getP());
74+
});
75+
for (int i = 0; i < amountOfValues; i++) {
76+
StreamUtils.writeBigIntegerToOutputStream(g_i[i], outputStream);
7577
}
7678
outputStream.flush();
7779
}

src/main/java/com/github/pvriel/oprf4j/nroprf/semihonest/KISS17/KISS17NROPRFEvaluator.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ public <T> KISS17NROPRFEvaluator(int bitLengthRandomValues, PrecomputedOblivious
4646
@Override
4747
public Triple<boolean[], BigInteger[], Object> executeOfflinePhase(BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
4848
boolean[] choices = new boolean[elements.length * bitLength];
49-
for (int i = 0; i < elements.length; i ++) for (int j = 0; j < bitLength; j ++) choices[i * bitLength + j] = elements[i].testBit(j);
49+
IntStream.range(0, elements.length).parallel().forEach(i -> {
50+
for (int j = 0; j < bitLength; j ++) choices[i * bitLength + j] = elements[i].testBit(j);
51+
});
5052

5153
BigInteger[] g_modded = new BigInteger[elements.length];
5254
for (int i = 0; i < g_modded.length; i ++) g_modded[i] = StreamUtils.readBigIntegerFromInputStream(inputStream);

src/main/java/com/github/pvriel/oprf4j/oprf/OPRFEvaluator.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ public interface OPRFEvaluator {
2525
* <br>This stream will not be closed after this process.
2626
* @return The (not-null) OPRF (element) results.
2727
* @throws IOException
28-
* If an IO-related problem occurred during the execution of this process.
28+
* If a problem occurred during the execution of this process.
2929
*/
30-
BigInteger[] evaluate(BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException;
30+
BigInteger[] evaluate(BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws Exception;
3131

3232
/**
3333
* Method to execute the OPRF functionality.
@@ -43,9 +43,9 @@ public interface OPRFEvaluator {
4343
* <br>This stream will not be closed after this process.
4444
* @return The (not-null) OPRF (element) result.
4545
* @throws IOException
46-
* If an IO-related problem occurred during the execution of this process.
46+
* If a problem occurred during the execution of this process.
4747
*/
48-
default BigInteger evaluate(BigInteger element, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
48+
default BigInteger evaluate(BigInteger element, int bitLength, InputStream inputStream, OutputStream outputStream) throws Exception {
4949
return evaluate(new BigInteger[] {element}, bitLength, inputStream, outputStream)[0];
5050
}
5151
}

src/main/java/com/github/pvriel/oprf4j/oprf/OPRFProvider.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ public interface OPRFProvider {
2323
* @param outputStream
2424
* The (not-null) output stream to send data to the {@link OPRFEvaluator} node.
2525
* <br>The stream will not be closed after this process.
26-
* @throws IOException
27-
* If an IO-related problem occurred during the execution of this process.
26+
* @throws Exception
27+
* If a problem occurred during the execution of this process.
2828
*/
29-
void execute(int amountOfValues, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException;
29+
void execute(int amountOfValues, int bitLength, InputStream inputStream, OutputStream outputStream) throws Exception;
3030

3131
/**
3232
* Method to provide the OPRF functionality.
@@ -38,10 +38,10 @@ public interface OPRFProvider {
3838
* @param outputStream
3939
* The (not-null) output stream to send data to the {@link OPRFEvaluator} node.
4040
* <br>The stream will not be closed after this process.
41-
* @throws IOException
42-
* If an IO-related problem occurred during the execution of this process.
41+
* @throws Exception
42+
* If a problem occurred during the execution of this process.
4343
*/
44-
default void execute(int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
44+
default void execute(int bitLength, InputStream inputStream, OutputStream outputStream) throws Exception {
4545
execute(1, bitLength, inputStream, outputStream);
4646
}
4747
}

src/main/java/com/github/pvriel/oprf4j/precomputed/PrecomputedOPRFEvaluator.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
public interface PrecomputedOPRFEvaluator<ReturnTypeOfflinePhase> extends OPRFEvaluator {
1616

1717
@Override
18-
default BigInteger[] evaluate(BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
18+
default BigInteger[] evaluate(BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws Exception {
1919
var resultOfflinePhase = executeOfflinePhase(elements, bitLength, inputStream, outputStream);
2020
return executeOnlinePhase(resultOfflinePhase, elements, bitLength, inputStream, outputStream);
2121
}
@@ -33,10 +33,10 @@ default BigInteger[] evaluate(BigInteger[] elements, int bitLength, InputStream
3333
* The (not-null) output stream to send data to the {@link PrecomputedOPRFProvider} node.
3434
* <br>This stream will not be closed after executing the protocol.
3535
* @return An intermediate result, that can be used to execute the online phase of this protocol with.
36-
* @throws IOException
37-
* If an IO-related problem occurred while executing the protocol.
36+
* @throws Exception
37+
* If a problem occurred while executing the protocol.
3838
*/
39-
ReturnTypeOfflinePhase executeOfflinePhase(BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException;
39+
ReturnTypeOfflinePhase executeOfflinePhase(BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws Exception;
4040

4141
/**
4242
* Method to execute the online phase of the OPRF protocol.
@@ -54,7 +54,7 @@ default BigInteger[] evaluate(BigInteger[] elements, int bitLength, InputStream
5454
* <br>This stream will not be closed after executing the protocol.
5555
* @return The not-null OPRF(element) results.
5656
* @throws IOException
57-
* If an IO-related problem occurred while executing the protocol.
57+
* If a problem occurred while executing the protocol.
5858
*/
59-
BigInteger[] executeOnlinePhase(ReturnTypeOfflinePhase resultOfflinePhase, BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException;
59+
BigInteger[] executeOnlinePhase(ReturnTypeOfflinePhase resultOfflinePhase, BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws Exception;
6060
}

src/main/java/com/github/pvriel/oprf4j/precomputed/PrecomputedOPRFProvider.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
public interface PrecomputedOPRFProvider<ReturnTypeOfflinePhase> extends OPRFProvider {
1515

1616
@Override
17-
default void execute(int amountOfValues, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
17+
default void execute(int amountOfValues, int bitLength, InputStream inputStream, OutputStream outputStream) throws Exception {
1818
var resultOfflinePhase = executeOfflinePhase(amountOfValues, bitLength, inputStream, outputStream);
1919
executeOnlinePhase(resultOfflinePhase, amountOfValues, bitLength, inputStream, outputStream);
2020
}
@@ -34,9 +34,9 @@ default void execute(int amountOfValues, int bitLength, InputStream inputStream,
3434
* <br>This stream will not be closed after executing the protocol.
3535
* @return An intermediate result, that can be used to execute the online phase of this protocol with.
3636
* @throws IOException
37-
* If an IO-related problem occurred while executing the protocol.
37+
* If a problem occurred while executing the protocol.
3838
*/
39-
ReturnTypeOfflinePhase executeOfflinePhase(int amountOfValues, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException;
39+
ReturnTypeOfflinePhase executeOfflinePhase(int amountOfValues, int bitLength, InputStream inputStream, OutputStream outputStream) throws Exception;
4040

4141
/**
4242
* Method to execute the online phase of the OPRF protocol.
@@ -53,8 +53,8 @@ default void execute(int amountOfValues, int bitLength, InputStream inputStream,
5353
* @param outputStream
5454
* The (not-null) output stream to send data to the {@link PrecomputedOPRFProvider} node.
5555
* <br>This stream will not be closed after executing the protocol.
56-
* @throws IOException
57-
* If an IO-related problem occurred while executing the protocol.
56+
* @throws Exception
57+
* If a problem occurred while executing the protocol.
5858
*/
59-
void executeOnlinePhase(ReturnTypeOfflinePhase resultOfflinePhase, int amountOfValues, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException;
59+
void executeOnlinePhase(ReturnTypeOfflinePhase resultOfflinePhase, int amountOfValues, int bitLength, InputStream inputStream, OutputStream outputStream) throws Exception;
6060
}

src/test/java/com/github/pvriel/oprf4j/AbstractOPRFTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public abstract class AbstractOPRFTest {
2020

2121
@Test
2222
@DisplayName("Check if the OPRF function works as expected.")
23-
public void test() throws IOException, InterruptedException {
23+
public void test() throws Exception {
2424
Triple<Integer, Pair<BigInteger[], BigInteger[]>, Pair<OPRFProvider, OPRFEvaluator>> setup = setup();
2525
int bitLength = setup.getLeft();
2626
Pair<BigInteger[], BigInteger[]> inputsAndExpectedOutputs = setup.getMiddle();

0 commit comments

Comments
 (0)