summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2020-07-04 13:24:19 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2020-07-04 13:24:19 +0700
commitaca28312569e39751d8c926653823d4016718898 (patch)
tree8e0cf987ee5e2c03e7334dee41dfe877f0f6a8b1
parentUpdate Asn1OctetString.GetInstance from bc-java (diff)
downloadBouncyCastle.NET-ed25519-aca28312569e39751d8c926653823d4016718898.tar.xz
Methods for generating random FEs
-rw-r--r--crypto/src/math/ec/ECCurve.cs91
1 files changed, 85 insertions, 6 deletions
diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs
index 60fbc887a..7d60e5f99 100644
--- a/crypto/src/math/ec/ECCurve.cs
+++ b/crypto/src/math/ec/ECCurve.cs
@@ -5,7 +5,7 @@ using Org.BouncyCastle.Math.EC.Abc;
 using Org.BouncyCastle.Math.EC.Endo;
 using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Math.Field;
-using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Math.EC
@@ -99,6 +99,10 @@ namespace Org.BouncyCastle.Math.EC
         public abstract ECFieldElement FromBigInteger(BigInteger x);
         public abstract bool IsValidFieldElement(BigInteger x);
 
+        public abstract ECFieldElement RandomFieldElement(SecureRandom r);
+
+        public abstract ECFieldElement RandomFieldElementMult(SecureRandom r);
+
         public virtual Config Configure()
         {
             return new Config(this, this.m_coord, this.m_endomorphism, this.m_multiplier);
@@ -598,6 +602,30 @@ namespace Org.BouncyCastle.Math.EC
             return x != null && x.SignValue >= 0 && x.CompareTo(Field.Characteristic) < 0;
         }
 
+        public override 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 = Field.Characteristic;
+            ECFieldElement fe1 = FromBigInteger(ImplRandomFieldElement(r, p));
+            ECFieldElement fe2 = FromBigInteger(ImplRandomFieldElement(r, p));
+            return fe1.Multiply(fe2);
+        }
+
+        public override 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 = Field.Characteristic;
+            ECFieldElement fe1 = FromBigInteger(ImplRandomFieldElementMult(r, p));
+            ECFieldElement fe2 = FromBigInteger(ImplRandomFieldElementMult(r, p));
+            return fe1.Multiply(fe2);
+        }
+
         protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
         {
             ECFieldElement x = FromBigInteger(X1);
@@ -618,6 +646,28 @@ namespace Org.BouncyCastle.Math.EC
 
             return 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.SignValue <= 0 || x.CompareTo(p) >= 0);
+            return x;
+        }
     }
 
     /**
@@ -793,11 +843,6 @@ namespace Org.BouncyCastle.Math.EC
         {
         }
 
-        public override bool IsValidFieldElement(BigInteger x)
-        {
-            return x != null && x.SignValue >= 0 && x.BitLength <= FieldSize;
-        }
-
         [Obsolete("Per-point compression property will be removed")]
         public override ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression)
         {
@@ -829,6 +874,29 @@ namespace Org.BouncyCastle.Math.EC
             return CreateRawPoint(X, Y, withCompression);
         }
 
+        public override bool IsValidFieldElement(BigInteger x)
+        {
+            return x != null && x.SignValue >= 0 && x.BitLength <= FieldSize;
+        }
+
+        public override ECFieldElement RandomFieldElement(SecureRandom r)
+        {
+            int m = FieldSize;
+            return FromBigInteger(BigIntegers.CreateRandomBigInteger(m, r));
+        }
+
+        public override 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 = FieldSize;
+            ECFieldElement fe1 = FromBigInteger(ImplRandomFieldElementMult(r, m));
+            ECFieldElement fe2 = FromBigInteger(ImplRandomFieldElementMult(r, m));
+            return fe1.Multiply(fe2);
+        }
+
         protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
         {
             ECFieldElement xp = FromBigInteger(X1), yp = null;
@@ -958,6 +1026,17 @@ namespace Org.BouncyCastle.Math.EC
                 return m_order != null && m_cofactor != null && m_b.IsOne && (m_a.IsZero || m_a.IsOne);
             }
         }
+
+        private static BigInteger ImplRandomFieldElementMult(SecureRandom r, int m)
+        {
+            BigInteger x;
+            do
+            {
+                x = BigIntegers.CreateRandomBigInteger(m, r);
+            }
+            while (x.SignValue <= 0);
+            return x;
+        }
     }
 
     /**