<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.1" />

AbstractFpCurve

public abstract class AbstractFpCurve : ECCurve
using Org.BouncyCastle.Math.Field; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using System; using System.Collections.Concurrent; namespace Org.BouncyCastle.Math.EC { public abstract class AbstractFpCurve : ECCurve { private static readonly ConcurrentDictionary<BigInteger, bool> KnownPrimes = new ConcurrentDictionary<BigInteger, bool>(); protected AbstractFpCurve(BigInteger q) : this(q, false) { } internal AbstractFpCurve(BigInteger q, bool isInternal) : base(FiniteFields.GetPrimeField(q)) { if (isInternal) KnownPrimes.AddOrUpdate(q, true, (BigInteger key, bool value) => true); else if (!KnownPrimes.ContainsKey(q)) { ImplCheckQ(q); KnownPrimes.TryAdd(q, false); } } public override bool IsValidFieldElement(BigInteger x) { if (x != null && x.SignValue >= 0) return x.CompareTo(Field.Characteristic) < 0; return false; } public override ECFieldElement RandomFieldElement(SecureRandom r) { BigInteger characteristic = Field.Characteristic; ECFieldElement eCFieldElement = FromBigInteger(ImplRandomFieldElement(r, characteristic)); ECFieldElement b = FromBigInteger(ImplRandomFieldElement(r, characteristic)); return eCFieldElement.Multiply(b); } public override ECFieldElement RandomFieldElementMult(SecureRandom r) { BigInteger characteristic = Field.Characteristic; ECFieldElement eCFieldElement = FromBigInteger(ImplRandomFieldElementMult(r, characteristic)); ECFieldElement b = FromBigInteger(ImplRandomFieldElementMult(r, characteristic)); return eCFieldElement.Multiply(b); } protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) { ECFieldElement eCFieldElement = FromBigInteger(X1); ECFieldElement eCFieldElement2 = eCFieldElement.Square().Add(A).Multiply(eCFieldElement) .Add(B) .Sqrt(); if (eCFieldElement2 == null) throw new ArgumentException("Invalid point compression"); if (eCFieldElement2.TestBitZero() != (yTilde == 1)) eCFieldElement2 = eCFieldElement2.Negate(); return CreateRawPoint(eCFieldElement, eCFieldElement2); } private static void ImplCheckQ(BigInteger q) { int num = ECCurve.ImplGetInteger("Org.BouncyCastle.EC.Fp_MaxSize", 1042); if (q.BitLength > num) throw new ArgumentException("Fp q value out of range"); if (!ImplIsPrime(q)) throw new ArgumentException("Fp q value not prime"); } private static int ImplGetIterations(int bits, int certainty) { if (bits >= 1536) { if (certainty > 100) { if (certainty > 128) return 4 + (certainty - 128 + 1) / 2; return 4; } return 3; } if (bits >= 1024) { if (certainty > 100) { if (certainty > 112) return 5 + (certainty - 112 + 1) / 2; return 5; } return 4; } if (bits >= 512) { if (certainty > 80) { if (certainty > 100) return 7 + (certainty - 100 + 1) / 2; return 7; } return 5; } if (certainty > 80) return 40 + (certainty - 80 + 1) / 2; return 40; } private static bool ImplIsPrime(BigInteger q) { if (Primes.HasAnySmallFactors(q)) return false; int certainty = ECCurve.ImplGetInteger("Org.BouncyCastle.EC.Fp_Certainty", 100); int iterations = ImplGetIterations(q.BitLength, certainty); return Primes.IsMRProbablePrime(q, SecureRandom.ArbitraryRandom, iterations); } private static BigInteger ImplRandomFieldElement(SecureRandom r, BigInteger p) { BigInteger bigInteger; do { bigInteger = BigIntegers.CreateRandomBigInteger(p.BitLength, r); } while (bigInteger.CompareTo(p) >= 0); return bigInteger; } private static BigInteger ImplRandomFieldElementMult(SecureRandom r, BigInteger p) { BigInteger bigInteger; do { bigInteger = BigIntegers.CreateRandomBigInteger(p.BitLength, r); } while (bigInteger.SignValue <= 0 || bigInteger.CompareTo(p) >= 0); return bigInteger; } } }