Skip to content

Commit ebf4a10

Browse files
committed
restructure + usage of mpcutils4j
1 parent e313ca5 commit ebf4a10

17 files changed

+203
-295
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
A Java library for the OPRF functions I programmed during my PhD.
33

44
[![Project Status: Active](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
5-
[![Coverage](https://badgen.net/badge/coverage/82%25/green)](https://badgen.net/badge/coverage/82%25/green)
5+
[![Coverage](https://badgen.net/badge/coverage/95%25/green)](https://badgen.net/badge/coverage/95%25/green)
66

77
***
88

build.gradle

+11-2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,20 @@ plugins {
44
}
55

66
group 'com.github.pvriel'
7-
version '1.0.1'
7+
version '1.1.0'
88

99
repositories {
1010
mavenLocal()
1111
mavenCentral()
1212

13+
maven {
14+
url = uri("https://maven.pkg.github.com/pvriel/mpcutils4j")
15+
credentials {
16+
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
17+
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
18+
}
19+
}
20+
1321
maven {
1422
url = uri("https://maven.pkg.github.com/pvriel/oblivioustransfer4j")
1523
credentials {
@@ -28,11 +36,12 @@ repositories {
2836
}
2937

3038
dependencies {
39+
implementation 'com.github.pvriel:mpcutils4j:1.+'
3140
implementation 'com.github.pvriel:oblivioustransfer4j:1.+'
3241
implementation 'org.apache.commons:commons-lang3:3.+'
3342

3443
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.+'
35-
testImplementation 'com.github.pvriel:prf4j:1.1.0'
44+
testImplementation 'com.github.pvriel:prf4j:1.+'
3645
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.+'
3746
}
3847

gradle/wrapper/gradle-wrapper.jar

818 Bytes
Binary file not shown.
+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
4+
networkTimeout=10000
45
zipStoreBase=GRADLE_USER_HOME
56
zipStorePath=wrapper/dists

gradlew

+8-4
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
# Darwin, MinGW, and NonStop.
5656
#
5757
# (3) This script is generated from the Groovy template
58-
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
58+
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
5959
# within the Gradle project.
6060
#
6161
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -80,10 +80,10 @@ do
8080
esac
8181
done
8282

83-
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84-
85-
APP_NAME="Gradle"
83+
# This is normally unused
84+
# shellcheck disable=SC2034
8685
APP_BASE_NAME=${0##*/}
86+
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
8787

8888
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
8989
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
@@ -143,12 +143,16 @@ fi
143143
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144144
case $MAX_FD in #(
145145
max*)
146+
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
147+
# shellcheck disable=SC3045
146148
MAX_FD=$( ulimit -H -n ) ||
147149
warn "Could not query maximum file descriptor limit"
148150
esac
149151
case $MAX_FD in #(
150152
'' | soft) :;; #(
151153
*)
154+
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
155+
# shellcheck disable=SC3045
152156
ulimit -n "$MAX_FD" ||
153157
warn "Could not set maximum file descriptor limit to $MAX_FD"
154158
esac

gradlew.bat

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal
2626

2727
set DIRNAME=%~dp0
2828
if "%DIRNAME%"=="" set DIRNAME=.
29+
@rem This is normally unused
2930
set APP_BASE_NAME=%~n0
3031
set APP_HOME=%DIRNAME%
3132

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

+20-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.github.pvriel.oprf4j.nroprf.semihonest.KISS17;
22

3+
import com.github.pvriel.mpcutils4j.stream.StreamUtils;
34
import com.github.pvriel.oblivioustransfer4j.precomputed.PrecomputedObliviousTransferReceiver;
4-
import com.github.pvriel.oblivioustransfer4j.utils.StreamUtils;
55
import com.github.pvriel.oprf4j.nroprf.NROPRFEvaluator;
66
import com.github.pvriel.oprf4j.precomputed.PrecomputedOPRFEvaluator;
77
import org.apache.commons.lang3.tuple.Triple;
@@ -10,12 +10,13 @@
1010
import java.io.InputStream;
1111
import java.io.OutputStream;
1212
import java.math.BigInteger;
13+
import java.util.stream.IntStream;
1314

1415
/**
1516
* Class representing the <a href="https://www.semanticscholar.org/paper/Private-Set-Intersection-for-Unequal-Set-Sizes-with-Kiss-Liu/ef148d510ce6fd445b73584a238f6244660efbe6">KISS17</a> variant of the
1617
* {@link NROPRFEvaluator} protocol.
1718
*/
18-
public class KISS17NROPRFEvaluator extends NROPRFEvaluator implements PrecomputedOPRFEvaluator<Triple<boolean[], BigInteger, Object>> {
19+
public class KISS17NROPRFEvaluator extends NROPRFEvaluator implements PrecomputedOPRFEvaluator<Triple<boolean[], BigInteger[], Object>> {
1920

2021
private final PrecomputedObliviousTransferReceiver<Object> precomputedObliviousTransferReceiver;
2122
private final int bitLengthRandomValues;
@@ -31,6 +32,8 @@ public class KISS17NROPRFEvaluator extends NROPRFEvaluator implements Precompute
3132
* The (not-null) prime number that is used for the group (the result of applying the PRF is always part of F_{p}).
3233
* @param q
3334
* The (not-null) prime number, for which q | p - 1 holds. This prime number is used to apply mod operations with the exponents.
35+
* @param <T>
36+
* The type of the elements that are used in the oblivious transfer.
3437
*/
3538
public <T> KISS17NROPRFEvaluator(int bitLengthRandomValues, PrecomputedObliviousTransferReceiver<T> precomputedObliviousTransferReceiver,
3639
BigInteger p, BigInteger q) {
@@ -41,25 +44,31 @@ public <T> KISS17NROPRFEvaluator(int bitLengthRandomValues, PrecomputedOblivious
4144
}
4245

4346
@Override
44-
public Triple<boolean[], BigInteger, Object> executeOfflinePhase(BigInteger element, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
45-
boolean[] choices = new boolean[bitLength];
46-
for (int i = 0; i < bitLength; i ++) choices[i] = element.testBit(i);
47+
public Triple<boolean[], BigInteger[], Object> executeOfflinePhase(BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
48+
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);
4750

48-
BigInteger g_modded = StreamUtils.readBigIntegerFromInputStream(inputStream);
51+
BigInteger[] g_modded = new BigInteger[elements.length];
52+
for (int i = 0; i < g_modded.length; i ++) g_modded[i] = StreamUtils.readBigIntegerFromInputStream(inputStream);
4953
var resultOfflinePhaseOTs = precomputedObliviousTransferReceiver.executeOfflinePhase(choices, bitLengthRandomValues, inputStream, outputStream);
5054
return Triple.of(choices, g_modded, resultOfflinePhaseOTs);
5155
}
5256

5357
@Override
54-
public BigInteger executeOnlinePhase(Triple<boolean[], BigInteger, Object> resultOfflinePhase, BigInteger element, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
58+
public BigInteger[] executeOnlinePhase(Triple<boolean[], BigInteger[], Object> resultOfflinePhase, BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
5559
boolean[] choices = resultOfflinePhase.getLeft();
56-
BigInteger g_modded = resultOfflinePhase.getMiddle();
60+
BigInteger[] g_modded = resultOfflinePhase.getMiddle();
5761
Object resultOfflinePhaseOTs = resultOfflinePhase.getRight();
5862

5963
BigInteger[] R_s = precomputedObliviousTransferReceiver.executeOnlinePhase(resultOfflinePhaseOTs, choices, bitLengthRandomValues, inputStream, outputStream);
6064

61-
BigInteger exponent = BigInteger.ONE;
62-
for (BigInteger r : R_s) exponent = exponent.multiply(r).mod(getQ());
63-
return g_modded.modPow(exponent, getP());
65+
BigInteger[] result = new BigInteger[elements.length];
66+
IntStream.range(0, elements.length).parallel().forEach(i -> {
67+
BigInteger g_modded_i = g_modded[i];
68+
BigInteger exponent = BigInteger.ONE;
69+
for (int j = 0; j < bitLength; j ++) exponent = exponent.multiply(R_s[i * bitLength + j]).mod(getQ());
70+
result[i] = g_modded_i.modPow(exponent, getP());
71+
});
72+
return result;
6473
}
6574
}

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

+23-15
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
package com.github.pvriel.oprf4j.nroprf.semihonest.KISS17;
22

3+
import com.github.pvriel.mpcutils4j.math.MultiplicativeGroup;
4+
import com.github.pvriel.mpcutils4j.stream.StreamUtils;
35
import com.github.pvriel.oblivioustransfer4j.precomputed.PrecomputedObliviousTransferSender;
4-
import com.github.pvriel.oblivioustransfer4j.utils.StreamUtils;
56
import com.github.pvriel.oprf4j.nroprf.NROPRFProvider;
67
import com.github.pvriel.oprf4j.precomputed.PrecomputedOPRFProvider;
7-
import com.github.pvriel.oprf4j.utils.MultiplicativeGroup;
88
import org.apache.commons.lang3.tuple.Pair;
99

1010
import java.io.IOException;
1111
import java.io.InputStream;
1212
import java.io.OutputStream;
1313
import java.math.BigInteger;
14+
import java.util.stream.IntStream;
1415

1516
/**
1617
* Class representing the <a href="https://www.semanticscholar.org/paper/Private-Set-Intersection-for-Unequal-Set-Sizes-with-Kiss-Liu/ef148d510ce6fd445b73584a238f6244660efbe6">KISS17</a> variant of the
@@ -38,6 +39,8 @@ public class KISS17NROPRFProvider extends NROPRFProvider implements PrecomputedO
3839
* The (not-null) element to perform the modulus operation with for the exponents.
3940
* @param g
4041
* The (not-null) generator of the multiplicative group.
42+
* @param <T>
43+
* The type of the elements in the {@link PrecomputedObliviousTransferSender}.
4144
*/
4245
public <T> KISS17NROPRFProvider(int bitLengthRandomValues, PrecomputedObliviousTransferSender<T> precomputedObliviousTransferSender,
4346
BigInteger[] a0, BigInteger[] a1, BigInteger p, BigInteger q, BigInteger g) {
@@ -48,28 +51,33 @@ public <T> KISS17NROPRFProvider(int bitLengthRandomValues, PrecomputedObliviousT
4851
}
4952

5053
@Override
51-
public Pair<Object, BigInteger[][]> executeOfflinePhase(int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
54+
public Pair<Object, BigInteger[][]> executeOfflinePhase(int amountOfElements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
5255
MultiplicativeGroup multiplicativeGroupQ = new MultiplicativeGroup(getQ());
53-
BigInteger[] r = multiplicativeGroupQ.getRandomElements(bitLength);
56+
BigInteger[] r = multiplicativeGroupQ.getRandomElements(amountOfElements * bitLength);
5457

55-
BigInteger[][] R = new BigInteger[bitLength][2];
56-
BigInteger r_inv = BigInteger.ONE;
57-
for (int i = 0; i < R.length; i ++) {
58-
r_inv = r_inv.multiply(r[i]).mod(getQ());
59-
R[i][0] = r[i].multiply(getA0()[i]).mod(getQ());
60-
R[i][1] = r[i].multiply(getA1()[i]).mod(getQ());
61-
}
62-
r_inv = r_inv.modInverse(getQ());
63-
BigInteger g_modded = getG().modPow(r_inv, getP());
64-
StreamUtils.writeBigIntegerToOutputStream(g_modded, outputStream);
58+
BigInteger[][] R = new BigInteger[amountOfElements * bitLength][2];
59+
BigInteger[] g_modded = new BigInteger[amountOfElements];
60+
IntStream.range(0, amountOfElements).parallel().forEach(i -> {
61+
BigInteger r_inv_i = BigInteger.ONE;
62+
for (int j = 0; j < bitLength; j ++) {
63+
r_inv_i = r_inv_i.multiply(r[i * bitLength + j]).mod(getQ());
64+
R[i * bitLength + j][0] = r[i * bitLength + j].multiply(getA0()[j]).mod(getQ());
65+
R[i * bitLength + j][1] = r[i * bitLength + j].multiply(getA1()[j]).mod(getQ());
66+
}
67+
r_inv_i = r_inv_i.modInverse(getQ());
68+
g_modded[i] = getG().modPow(r_inv_i, getP());
69+
});
70+
71+
for (BigInteger bigInteger : g_modded) StreamUtils.writeBigIntegerToOutputStream(bigInteger, outputStream);
72+
outputStream.flush();
6573

6674
Object resultOfflinePhaseOTs = precomputedObliviousTransferSender.executeOfflinePhase(R, bitLengthRandomValues, inputStream, outputStream);
6775

6876
return Pair.of(resultOfflinePhaseOTs, R);
6977
}
7078

7179
@Override
72-
public void executeOnlinePhase(Pair<Object, BigInteger[][]> resultOfflinePhase, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
80+
public void executeOnlinePhase(Pair<Object, BigInteger[][]> resultOfflinePhase, int amountOfElements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
7381
var resultOfflinePhaseOTs = resultOfflinePhase.getLeft();
7482
var R = resultOfflinePhase.getRight();
7583

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

+23-3
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,41 @@
1111
*/
1212
public interface OPRFEvaluator {
1313

14+
/**
15+
* Method to execute the OPRF functionality.
16+
* @param elements
17+
* The (not-null) elements to apply the PRF to.
18+
* @param bitLength
19+
* The bit length of the elements. Should be strictly positive, and should match the value used by the {@link OPRFProvider} node.
20+
* @param inputStream
21+
* The (not-null) input stream to receive data from the {@link OPRFProvider} node.
22+
* <br>This stream will not be closed after this process.
23+
* @param outputStream
24+
* The (not-null) output stream to send data to the {@link OPRFProvider} node.
25+
* <br>This stream will not be closed after this process.
26+
* @return The (not-null) OPRF (element) results.
27+
* @throws IOException
28+
* If an IO-related problem occurred during the execution of this process.
29+
*/
30+
BigInteger[] evaluate(BigInteger[] elements, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException;
31+
1432
/**
1533
* Method to execute the OPRF functionality.
1634
* @param element
1735
* The (not-null) element to apply the PRF to.
1836
* @param bitLength
19-
* The bitlength of the element. Should be strictly positive, and should match the value used by the {@link OPRFProvider} node.
37+
* The bit length of the element. Should be strictly positive, and should match the value used by the {@link OPRFProvider} node.
2038
* @param inputStream
2139
* The (not-null) input stream to receive data from the {@link OPRFProvider} node.
2240
* <br>This stream will not be closed after this process.
2341
* @param outputStream
2442
* The (not-null) output stream to send data to the {@link OPRFProvider} node.
2543
* <br>This stream will not be closed after this process.
26-
* @return The (not-null) OPRF(element) result.
44+
* @return The (not-null) OPRF (element) result.
2745
* @throws IOException
2846
* If an IO-related problem occurred during the execution of this process.
2947
*/
30-
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 IOException {
49+
return evaluate(new BigInteger[] {element}, bitLength, inputStream, outputStream)[0];
50+
}
3151
}

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

+22-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ public interface OPRFProvider {
1212

1313
/**
1414
* Method to provide the OPRF functionality.
15+
* @param amountOfValues
16+
* The amount of values to apply the PRF to (from the evaluator side).
17+
* This value should match the amount of values provided by the {@link OPRFEvaluator} node.
1518
* @param bitLength
16-
* The bit length of the message to apply the PRF to. Should be strictly positive, and should match the value used by the {@link OPRFEvaluator} node.
19+
* The bit length of the messages to apply the PRF to. Should be strictly positive, and should match the value used by the {@link OPRFEvaluator} node.
1720
* @param inputStream
1821
* The (not-null) input stream to receive data from the {@link OPRFEvaluator} node.
1922
* <br>The stream will not be closed after this process.
@@ -23,5 +26,22 @@ public interface OPRFProvider {
2326
* @throws IOException
2427
* If an IO-related problem occurred during the execution of this process.
2528
*/
26-
void execute(int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException;
29+
void execute(int amountOfValues, int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException;
30+
31+
/**
32+
* Method to provide the OPRF functionality.
33+
* @param bitLength
34+
* The bit length of the messages to apply the PRF to. Should be strictly positive, and should match the value used by the {@link OPRFEvaluator} node.
35+
* @param inputStream
36+
* The (not-null) input stream to receive data from the {@link OPRFEvaluator} node.
37+
* <br>The stream will not be closed after this process.
38+
* @param outputStream
39+
* The (not-null) output stream to send data to the {@link OPRFEvaluator} node.
40+
* <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.
43+
*/
44+
default void execute(int bitLength, InputStream inputStream, OutputStream outputStream) throws IOException {
45+
execute(1, bitLength, inputStream, outputStream);
46+
}
2747
}

0 commit comments

Comments
 (0)