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

ECDHBasicAgreement

using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Math.EC; using System; namespace Org.BouncyCastle.Crypto.Agreement { public class ECDHBasicAgreement : IBasicAgreement { protected internal ECPrivateKeyParameters privKey; public virtual void Init(ICipherParameters parameters) { ParametersWithRandom parametersWithRandom = parameters as ParametersWithRandom; if (parametersWithRandom != null) parameters = parametersWithRandom.Parameters; ECPrivateKeyParameters eCPrivateKeyParameters = parameters as ECPrivateKeyParameters; if (eCPrivateKeyParameters == null) throw new ArgumentException("ECDHBasicAgreement expects ECPrivateKeyParameters"); privKey = eCPrivateKeyParameters; } public virtual int GetFieldSize() { return privKey.Parameters.Curve.FieldElementEncodingLength; } public virtual BigInteger CalculateAgreement(ICipherParameters pubKey) { ECPublicKeyParameters eCPublicKeyParameters = (ECPublicKeyParameters)pubKey; ECDomainParameters parameters = privKey.Parameters; if (!parameters.Equals(eCPublicKeyParameters.Parameters)) throw new InvalidOperationException("ECDH public key has wrong domain parameters"); BigInteger bigInteger = privKey.D; ECPoint eCPoint = ECAlgorithms.CleanPoint(parameters.Curve, eCPublicKeyParameters.Q); if (eCPoint.IsInfinity) throw new InvalidOperationException("Infinity is not a valid public key for ECDH"); BigInteger h = parameters.H; if (!h.Equals(BigInteger.One)) { bigInteger = parameters.HInv.Multiply(bigInteger).Mod(parameters.N); eCPoint = ECAlgorithms.ReferenceMultiply(eCPoint, h); } ECPoint eCPoint2 = eCPoint.Multiply(bigInteger).Normalize(); if (eCPoint2.IsInfinity) throw new InvalidOperationException("Infinity is not a valid agreement value for ECDH"); return eCPoint2.AffineXCoord.ToBigInteger(); } } }