diff --git a/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/Comparison.java b/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/Comparison.java index 91d4ac2b9..9ec941f9d 100644 --- a/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/Comparison.java +++ b/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/Comparison.java @@ -72,20 +72,29 @@ default DRes equals(DRes x, DRes y, int bitlength) { /** * Computes if x < y. * - * @param x the first input - * @param y the second input + * @param x the first input. Must be less than 2^{@code bitlength} + * @param y the second input. Must be less than 2^{@code bitlength} + * @param bitlength the amount of bits to do the comparison on. Must be less than or equal to + * the max bitlength allowed * @param algorithm the algorithm to use - * @return A deferred result computing x < y. Result will be either [1] (true) or [0] (false). + * @return A deferred result computing x' < y'. Where x' and y' represent the {@code bitlength} + * least significant bits of x, respectively y. Result will be either [1] (true) or [0] (false). */ - DRes compareLT(DRes x, DRes y, Algorithm algorithm); + DRes compareLT(DRes x, DRes y, int bitlength, Algorithm algorithm); /** - * Call to {@link #compareLT(DRes, DRes, Algorithm)} with default comparison algorithm. + * Call to {@link #compareLT(DRes, DRes, int, Algorithm)} with default comparison algorithm. */ - default DRes compareLT(DRes x, DRes y) { - return compareLT(x, y, Algorithm.LOG_ROUNDS); + default DRes compareLT(DRes x, DRes y, int bitlength) { + return compareLT(x, y, bitlength, Algorithm.LOG_ROUNDS); } + /** + * Call to {@link #compareLT(DRes, DRes, int, Algorithm)} with default comparison algorithm, + * comparing all bits. + */ + DRes compareLT(DRes x, DRes y); + /** * Computes if the bit decomposition of an open value is less than the bit decomposition of a * secret value. diff --git a/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/DefaultComparison.java b/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/DefaultComparison.java index ca410b04c..a28e000f4 100644 --- a/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/DefaultComparison.java +++ b/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/DefaultComparison.java @@ -59,21 +59,29 @@ public DRes compareLEQ(DRes x, DRes y) { } @Override - public DRes compareLT(DRes x, DRes y, Algorithm algorithm) { + public DRes compareLT(DRes x, DRes y, int bitlength, Algorithm algorithm) { + if (bitlength > builder.getBasicNumericContext().getMaxBitLength()) { + throw new IllegalArgumentException("The bitlength is more than allowed for elements."); + } if (algorithm == Algorithm.LOG_ROUNDS) { - if (builder.getBasicNumericContext().getStatisticalSecurityParam() + builder - .getBasicNumericContext().getMaxBitLength() > builder.getBasicNumericContext() - .getModulus().bitLength()) { + if (builder.getBasicNumericContext().getStatisticalSecurityParam() + bitlength + > builder.getBasicNumericContext().getModulus().bitLength()) { throw new IllegalArgumentException( "The max bitlength plus the statistical security parameter overflows the size of the modulus."); } DRes difference = builder.numeric().sub(x, y); - return builder.seq(new LessThanZero(difference)); + return builder.seq(new LessThanZero(difference, bitlength)); } else { throw new UnsupportedOperationException("Not implemented yet"); } } + @Override + public DRes compareLT(DRes x, DRes y) { + int maxBitLength = builder.getBasicNumericContext().getMaxBitLength(); + return compareLT(x, y, maxBitLength); + } + @Override public DRes compareLTBits(BigInteger openValue, DRes>> secretBits) { return builder.seq(new BitLessThanOpen(openValue, secretBits)); diff --git a/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/lt/LessThanZero.java b/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/lt/LessThanZero.java index 10bc970e5..a8bae58ed 100644 --- a/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/lt/LessThanZero.java +++ b/lib/common/src/main/java/dk/alexandra/fresco/lib/common/compare/lt/LessThanZero.java @@ -10,24 +10,26 @@ /** * Given secret value a, computes a <? 0. + * https://www.researchgate.net/publication/225092133_Improved_Primitives_for_Secure_Multiparty_Integer_Computation */ public class LessThanZero implements Computation { - // TODO add reference to protocol description private final DRes input; + private final int maxBitlength; /** * Constructs new {@link LessThanZero}. * * @param input input to compare to 0 + * @param maxBitlength number of bits to compare */ - public LessThanZero(DRes input) { + public LessThanZero(DRes input, int maxBitlength) { this.input = input; + this.maxBitlength = maxBitlength; } @Override public DRes buildComputation(ProtocolBuilderNumeric builder) { - final int maxBitlength = builder.getBasicNumericContext().getMaxBitLength(); final int statisticalSecurity = builder.getBasicNumericContext() .getStatisticalSecurityParam(); return builder.seq(seq -> { diff --git a/lib/common/src/main/java/dk/alexandra/fresco/lib/common/math/integer/binary/NormalizeSInt.java b/lib/common/src/main/java/dk/alexandra/fresco/lib/common/math/integer/binary/NormalizeSInt.java index 10a214323..633e0f8bb 100644 --- a/lib/common/src/main/java/dk/alexandra/fresco/lib/common/math/integer/binary/NormalizeSInt.java +++ b/lib/common/src/main/java/dk/alexandra/fresco/lib/common/math/integer/binary/NormalizeSInt.java @@ -36,7 +36,9 @@ public DRes, DRes>> buildComputation(ProtocolBuilderNumeri DRes>> bits = advancedNumeric.toBits(input, l); // Sign bit (0 or 1) - DRes signBit = new LessThanZero(input).buildComputation(par); + DRes signBit = + new LessThanZero(input, par.getBasicNumericContext().getMaxBitLength()) + .buildComputation(par); return Pair.lazy(bits, signBit); }).seq((seq, params) -> { diff --git a/lib/common/src/test/java/dk/alexandra/fresco/lib/common/compare/CompareTests.java b/lib/common/src/test/java/dk/alexandra/fresco/lib/common/compare/CompareTests.java index 7f3efb8c0..7c4f0b914 100644 --- a/lib/common/src/test/java/dk/alexandra/fresco/lib/common/compare/CompareTests.java +++ b/lib/common/src/test/java/dk/alexandra/fresco/lib/common/compare/CompareTests.java @@ -331,7 +331,7 @@ public void test() { List> actualInner = new ArrayList<>(left.size()); for (int i = 0; i < left.size(); i++) { actualInner.add(Comparison.using(builder).compareLT(left.get(i), right.get(i), - Comparison.Algorithm.LOG_ROUNDS)); + builder.getBasicNumericContext().getMaxBitLength(), Comparison.Algorithm.LOG_ROUNDS)); } DRes>> opened = Collections.using(builder).openList(() -> actualInner); return () -> opened.out().stream().map(DRes::out).collect(Collectors.toList()); @@ -437,7 +437,7 @@ public void test() throws Exception { DRes x = input.known(BigInteger.valueOf(3)); DRes y = input.known(BigInteger.valueOf(5)); Comparison comparison = Comparison.using(builder); - DRes result = comparison.compareLT(x, y, Algorithm.CONST_ROUNDS); + DRes result = comparison.compareLT(x, y, 3, Algorithm.CONST_ROUNDS); return input.open(result); }; runApplication(app); diff --git a/lib/common/src/test/java/dk/alexandra/fresco/lib/common/compare/lt/LessThanZeroTests.java b/lib/common/src/test/java/dk/alexandra/fresco/lib/common/compare/lt/LessThanZeroTests.java index c8abc1cac..33aea8270 100644 --- a/lib/common/src/test/java/dk/alexandra/fresco/lib/common/compare/lt/LessThanZeroTests.java +++ b/lib/common/src/test/java/dk/alexandra/fresco/lib/common/compare/lt/LessThanZeroTests.java @@ -53,10 +53,11 @@ public TestThread next() { public void test() { Application, ProtocolBuilderNumeric> app = builder -> { Numeric numeric = builder.numeric(); - List> inputs = openInputs.stream().map(numeric::known).collect(Collectors.toList());; + List> inputs = openInputs.stream().map(numeric::known).collect(Collectors.toList()); List> actualInner = new ArrayList<>(inputs.size()); for (DRes input : inputs) { - actualInner.add(builder.seq(new LessThanZero(input))); + actualInner.add(builder.seq( + new LessThanZero(input, builder.getBasicNumericContext().getMaxBitLength()))); } DRes>> opened = Collections.using(builder).openList(DRes.of(actualInner)); return () -> opened.out().stream().map(DRes::out).collect(Collectors.toList());