54 lines
1.6 KiB
C#
54 lines
1.6 KiB
C#
using System;
|
|
using Org.BouncyCastle.Crypto.Parameters;
|
|
using Org.BouncyCastle.Math;
|
|
using Org.BouncyCastle.Math.EC;
|
|
|
|
namespace Org.BouncyCastle.Crypto.Agreement;
|
|
|
|
public class ECDHBasicAgreement : IBasicAgreement
|
|
{
|
|
protected internal ECPrivateKeyParameters privKey;
|
|
|
|
public virtual void Init(ICipherParameters parameters)
|
|
{
|
|
if (parameters is ParametersWithRandom)
|
|
{
|
|
parameters = ((ParametersWithRandom)parameters).Parameters;
|
|
}
|
|
privKey = (ECPrivateKeyParameters)parameters;
|
|
}
|
|
|
|
public virtual int GetFieldSize()
|
|
{
|
|
return (privKey.Parameters.Curve.FieldSize + 7) / 8;
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|