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

DHPublicKeyParameters

using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Math; using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crypto.Parameters { public class DHPublicKeyParameters : DHKeyParameters { private readonly BigInteger m_y; public virtual BigInteger Y => m_y; private static BigInteger Validate(BigInteger y, DHParameters dhParams) { if (y == null) throw new ArgumentNullException("y"); BigInteger p = dhParams.P; if (y.CompareTo(BigInteger.Two) < 0 || y.CompareTo(p.Subtract(BigInteger.Two)) > 0) throw new ArgumentException("invalid DH public key", "y"); BigInteger q = dhParams.Q; if (q == null) return y; if (p.TestBit(0) && p.BitLength - 1 == q.BitLength && p.ShiftRight(1).Equals(q)) { if (1 == Legendre(y, p)) return y; } else if (BigInteger.One.Equals(y.ModPow(q, p))) { return y; } throw new ArgumentException("value does not appear to be in correct group", "y"); } public DHPublicKeyParameters(BigInteger y, DHParameters parameters) : base(false, parameters) { m_y = Validate(y, parameters); } public DHPublicKeyParameters(BigInteger y, DHParameters parameters, DerObjectIdentifier algorithmOid) : base(false, parameters, algorithmOid) { m_y = Validate(y, parameters); } public override bool Equals(object obj) { if (obj == this) return true; DHPublicKeyParameters dHPublicKeyParameters = obj as DHPublicKeyParameters; if (dHPublicKeyParameters == null) return false; return Equals(dHPublicKeyParameters); } protected bool Equals(DHPublicKeyParameters other) { if (m_y.Equals(other.m_y)) return Equals((DHKeyParameters)other); return false; } public override int GetHashCode() { return m_y.GetHashCode() ^ base.GetHashCode(); } private unsafe static int Legendre(BigInteger a, BigInteger b) { int bitLength = b.BitLength; int num = Nat.GetLengthForBits(bitLength); Span<uint> span; if (num <= 64) { int num2 = num; span = new Span<uint>(stackalloc byte[(int)checked(unchecked((ulong)(uint)num2) * 4)], num2); } else span = new uint[num]; Span<uint> span2 = span; Nat.FromBigInteger(bitLength, a, span2); if (num <= 64) { int num2 = num; span = new Span<uint>(stackalloc byte[(int)checked(unchecked((ulong)(uint)num2) * 4)], num2); } else span = new uint[num]; Span<uint> span3 = span; Nat.FromBigInteger(bitLength, b, span3); int num3 = 0; while (true) { if (span2[0] == 0) Nat.ShiftDownWord(num, span2, 0); else { int num4 = Integers.NumberOfTrailingZeros((int)span2[0]); if (num4 > 0) { Nat.ShiftDownBits(num, span2, num4, 0); int num5 = (int)span3[0]; num3 ^= ((num5 ^ (num5 >> 1)) & (num4 << 1)); } int num6 = Nat.Compare(num, span2, span3); if (num6 == 0) break; if (num6 < 0) { num3 ^= (int)(span2[0] & span3[0]); Span<uint> span4 = span2; span2 = span3; span3 = span4; } while (span2[num - 1] == 0) { num--; } Nat.Sub(num, span2, span3, span2); } } if (!Nat.IsOne(num, span3)) return 0; return 1 - (num3 & 2); } } }