summary refs log tree commit diff
path: root/crypto/src/math
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-12-05 13:24:04 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-12-05 13:24:04 +0700
commit00721e6cd0c40535c58b734d33790245bafaba0d (patch)
treecb414158b44c89ce1e2186ec17469ce67a121208 /crypto/src/math
parentAdd TODO[api] (diff)
downloadBouncyCastle.NET-ed25519-00721e6cd0c40535c58b734d33790245bafaba0d.tar.xz
Refactor ECCurve primality checks
Diffstat (limited to 'crypto/src/math')
-rw-r--r--crypto/src/math/ec/ECCurve.cs60
-rw-r--r--crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP128R1Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP160K1Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP160R1Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP160R2Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP192K1Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP192R1Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP224K1Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP224R1Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP256K1Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP256R1Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP384R1Curve.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecP521R1Curve.cs2
14 files changed, 46 insertions, 40 deletions
diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs
index 624495051..a540c719e 100644
--- a/crypto/src/math/ec/ECCurve.cs
+++ b/crypto/src/math/ec/ECCurve.cs
@@ -1,7 +1,7 @@
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 
-using Org.BouncyCastle.Math.EC.Abc;
 using Org.BouncyCastle.Math.EC.Endo;
 using Org.BouncyCastle.Math.EC.Multiplier;
 using Org.BouncyCastle.Math.Field;
@@ -675,40 +675,26 @@ namespace Org.BouncyCastle.Math.EC
     public abstract class AbstractFpCurve
         : ECCurve
     {
-        private static readonly HashSet<BigInteger> KnownQs = new HashSet<BigInteger>();
+        private static readonly ConcurrentDictionary<BigInteger, bool> KnownPrimes =
+            new ConcurrentDictionary<BigInteger, bool>();
 
         protected AbstractFpCurve(BigInteger q)
-            : this(q, false)
+            : this(q, isInternal: false)
         {
         }
 
         internal AbstractFpCurve(BigInteger q, bool isInternal)
             : base(FiniteFields.GetPrimeField(q))
         {
-            if (!isInternal)
+            if (isInternal)
             {
-                bool unknownQ;
-                lock (KnownQs) unknownQ = !KnownQs.Contains(q);
-
-                if (unknownQ)
-                {
-                    int maxBitLength = ImplGetInteger("Org.BouncyCastle.EC.Fp_MaxSize", 1042); // 2 * 521
-                    int certainty = ImplGetInteger("Org.BouncyCastle.EC.Fp_Certainty", 100);
-
-                    int qBitLength = q.BitLength;
-                    if (maxBitLength < qBitLength)
-                        throw new ArgumentException("Fp q value out of range");
-
-                    if (Primes.HasAnySmallFactors(q) ||
-                        !Primes.IsMRProbablePrime(q, SecureRandom.ArbitraryRandom,
-                            ImplGetNumberOfIterations(qBitLength, certainty)))
-                    {
-                        throw new ArgumentException("Fp q value not prime");
-                    }
-                }
+                KnownPrimes.AddOrUpdate(q, true, (key, value) => true);
+            }
+            else if (!KnownPrimes.ContainsKey(q))
+            {
+                ImplCheckPrime(q);
+                KnownPrimes.TryAdd(q, false);
             }
-
-            lock (KnownQs) KnownQs.Add(q);
         }
 
         public override bool IsValidFieldElement(BigInteger x)
@@ -761,6 +747,26 @@ namespace Org.BouncyCastle.Math.EC
             return CreateRawPoint(x, y);
         }
 
+        private static void ImplCheckPrime(BigInteger q)
+        {
+            int maxBitLength = ImplGetInteger("Org.BouncyCastle.EC.Fp_MaxSize", 1042); // 2 * 521
+
+            int qBitLength = q.BitLength;
+            if (maxBitLength < qBitLength)
+                throw new ArgumentException("Fp q value out of range");
+
+            if (!Primes.HasAnySmallFactors(q))
+            {
+                int certainty = ImplGetInteger("Org.BouncyCastle.EC.Fp_Certainty", 100);
+                int iterations = ImplGetIterations(qBitLength, certainty);
+
+                if (Primes.IsMRProbablePrime(q, SecureRandom.ArbitraryRandom, iterations))
+                    return;
+            }
+
+            throw new ArgumentException("Fp q value not prime");
+        }
+
         private static int ImplGetInteger(string envVariable, int defaultValue)
         {
             string v = Platform.GetEnvironmentVariable(envVariable);
@@ -770,7 +776,7 @@ namespace Org.BouncyCastle.Math.EC
             return int.Parse(v);
         }
 
-        private static int ImplGetNumberOfIterations(int bits, int certainty)
+        private static int ImplGetIterations(int bits, int certainty)
         {
             /*
              * NOTE: We enforce a minimum 'certainty' of 100 for bits >= 1024 (else 80). Where the
@@ -864,7 +870,7 @@ namespace Org.BouncyCastle.Math.EC
 
         internal FpCurve(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b, BigInteger order,
             BigInteger cofactor)
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_q = q;
             this.m_r = r;
diff --git a/crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs b/crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs
index 3147ccf98..6456120a6 100644
--- a/crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs
+++ b/crypto/src/math/ec/custom/gm/SM2P256V1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.GM
         protected readonly SM2P256V1Point m_infinity;
 
         public SM2P256V1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SM2P256V1Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP128R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP128R1Curve.cs
index 5fa18d470..b96fa75d0 100644
--- a/crypto/src/math/ec/custom/sec/SecP128R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP128R1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP128R1Point m_infinity;
 
         public SecP128R1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP128R1Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP160K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP160K1Curve.cs
index b757659d2..471f7f992 100644
--- a/crypto/src/math/ec/custom/sec/SecP160K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP160K1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP160K1Point m_infinity;
 
         public SecP160K1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP160K1Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP160R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP160R1Curve.cs
index 3b7e1aa06..491b10fd3 100644
--- a/crypto/src/math/ec/custom/sec/SecP160R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP160R1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP160R1Point m_infinity;
 
         public SecP160R1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP160R1Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP160R2Curve.cs b/crypto/src/math/ec/custom/sec/SecP160R2Curve.cs
index 0f226ad19..97d8b6d00 100644
--- a/crypto/src/math/ec/custom/sec/SecP160R2Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP160R2Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP160R2Point m_infinity;
 
         public SecP160R2Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP160R2Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs
index b9ff71ac8..b4a884e83 100644
--- a/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP192K1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP192K1Point m_infinity;
 
         public SecP192K1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP192K1Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs
index 77524b362..accb5a786 100644
--- a/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP192R1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP192R1Point m_infinity;
 
         public SecP192R1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP192R1Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs
index 04be47202..7f828bc87 100644
--- a/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP224K1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP224K1Point m_infinity;
 
         public SecP224K1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP224K1Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs
index 8cd2b7272..ca2b876af 100644
--- a/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP224R1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP224R1Point m_infinity;
 
         public SecP224R1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP224R1Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs
index 804b65d60..391ac7b17 100644
--- a/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP256K1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP256K1Point m_infinity;
 
         public SecP256K1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP256K1Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs
index dd2b964c6..a9d1a4a2b 100644
--- a/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP256R1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP256R1Point m_infinity;
 
         public SecP256R1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP256R1Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs
index f54dd44c2..4704bb16f 100644
--- a/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP384R1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP384R1Point m_infinity;
 
         public SecP384R1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP384R1Point(this, null, null);
 
diff --git a/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs
index a5f4cf957..136af8a1a 100644
--- a/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecP521R1Curve.cs
@@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected readonly SecP521R1Point m_infinity;
 
         public SecP521R1Curve()
-            : base(q, true)
+            : base(q, isInternal: true)
         {
             this.m_infinity = new SecP521R1Point(this, null, null);