From 744c0dc2958870899d8b604bc3cclalef04db5 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 3 Jul 2020 23:18:22 +0700 Subject: [PATCH] Methods for generating random FEs --- .../org/bouncycastle/math/ec/ECCurve.java | 90 ++++++++++++++++++- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java b/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java index 7c10c78..19cbd92 100644 --- a/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java +++ b/core/src/main/java/org/bouncycastle/math/ec/ECCurve.java @@ -1,6 +1,7 @@ package org.bouncycastle.math.ec; import java.math.BigInteger; +import java.security.SecureRandom; import java.util.Hashtable; import java.util.Random; @@ -107,6 +108,10 @@ protected ECCurve(FiniteField field) public abstract boolean isValidFieldElement(BigInteger x); + public abstract ECFieldElement randomFieldElement(SecureRandom r); + + public abstract ECFieldElement randomFieldElementMult(SecureRandom r); + public synchronized Config configure() { return new Config(this.coord, this.endomorphism, this.multiplier); @@ -589,6 +594,30 @@ public boolean isValidFieldElement(BigInteger x) return x != null && x.signum() >= 0 && x.compareTo(this.getField().getCharacteristic()) < 0; } + public ECFieldElement randomFieldElement(SecureRandom r) + { + /* + * NOTE: BigInteger comparisons in the rejection sampling are not constant-time, so we + * use the product of two independent elements to mitigate side-channels. + */ + BigInteger p = getField().getCharacteristic(); + ECFieldElement fe1 = fromBigInteger(implRandomFieldElement(r, p)); + ECFieldElement fe2 = fromBigInteger(implRandomFieldElement(r, p)); + return fe1.multiply(fe2); + } + + public ECFieldElement randomFieldElementMult(SecureRandom r) + { + /* + * NOTE: BigInteger comparisons in the rejection sampling are not constant-time, so we + * use the product of two independent elements to mitigate side-channels. + */ + BigInteger p = getField().getCharacteristic(); + ECFieldElement fe1 = fromBigInteger(implRandomFieldElementMult(r, p)); + ECFieldElement fe2 = fromBigInteger(implRandomFieldElementMult(r, p)); + return fe1.multiply(fe2); + } + protected ECPoint decompressPoint(int yTilde, BigInteger X1) { ECFieldElement x = this.fromBigInteger(X1); @@ -611,6 +640,28 @@ protected ECPoint decompressPoint(int yTilde, BigInteger X1) return this.createRawPoint(x, y, true); } + + private static BigInteger implRandomFieldElement(SecureRandom r, BigInteger p) + { + BigInteger x; + do + { + x = BigIntegers.createRandomBigInteger(p.bitLength(), r); + } + while (x.compareTo(p) >= 0); + return x; + } + + private static BigInteger implRandomFieldElementMult(SecureRandom r, BigInteger p) + { + BigInteger x; + do + { + x = BigIntegers.createRandomBigInteger(p.bitLength(), r); + } + while (x.signum() <= 0 || x.compareTo(p) >= 0); + return x; + } } /** @@ -790,10 +841,6 @@ protected AbstractF2m(int m, int k1, int k2, int k3) super(buildField(m, k1, k2, k3)); } - public boolean isValidFieldElement(BigInteger x) - { - return x != null && x.signum() >= 0 && x.bitLength() <= this.getFieldSize(); - } public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) { @@ -840,6 +887,30 @@ public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression) return this.createRawPoint(X, Y, withCompression); } + public boolean isValidFieldElement(BigInteger x) + { + return x != null && x.signum() >= 0 && x.bitLength() <= this.getFieldSize(); + } + + public ECFieldElement randomFieldElement(SecureRandom r) + { + int m = getFieldSize(); + return fromBigInteger(BigIntegers.createRandomBigInteger(m, r)); + } + + public ECFieldElement randomFieldElementMult(SecureRandom r) + { + /* + * NOTE: BigInteger comparisons in the rejection sampling are not constant-time, so we + * use the product of two independent elements to mitigate side-channels. + */ + int m = getFieldSize(); + ECFieldElement fe1 = fromBigInteger(implRandomFieldElementMult(r, m)); + ECFieldElement fe2 = fromBigInteger(implRandomFieldElementMult(r, m)); + return fe1.multiply(fe2); + } + + /** * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). * @@ -956,6 +1027,17 @@ public boolean isKoblitz() { return this.order != null && this.cofactor != null && this.b.isOne() && (this.a.isZero() || this.a.isOne()); } + + private static BigInteger implRandomFieldElementMult(SecureRandom r, int m) + { + BigInteger x; + do + { + x = BigIntegers.createRandomBigInteger(m, r); + } + while (x.signum() <= 0); + return x; + } } /** -- 2.23.0