using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
namespace Org.BouncyCastle.Crypto.Agreement{
public class ECMqvBasicAgreement
: IBasicAgreement
{
protected internal MqvPrivateParameters privParams;
public void Init(
ICipherParameters parameters)
{
if (parameters is ParametersWithRandom)
{
parameters = ((ParametersWithRandom)parameters).Parameters;
}
this.privParams = (MqvPrivateParameters)parameters;
}
public virtual BigInteger CalculateAgreement(
ICipherParameters pubKey)
{
MqvPublicParameters pubParams = (MqvPublicParameters)pubKey;
ECPrivateKeyParameters staticPrivateKey = privParams.StaticPrivateKey;
ECPoint agreement = calculateMqvAgreement(staticPrivateKey.Parameters, staticPrivateKey,
privParams.EphemeralPrivateKey, privParams.EphemeralPublicKey,
pubParams.StaticPublicKey, pubParams.EphemeralPublicKey);
return agreement.X.ToBigInteger();
}
// The ECMQV Primitive as described in SEC-1, 3.4
private static ECPoint calculateMqvAgreement(
ECDomainParameters parameters,
ECPrivateKeyParameters d1U,
ECPrivateKeyParameters d2U,
ECPublicKeyParameters Q2U,
ECPublicKeyParameters Q1V,
ECPublicKeyParameters Q2V)
{
BigInteger n = parameters.N;
int e = (n.BitLength + 1) / 2;
BigInteger powE = BigInteger.One.ShiftLeft(e);
// The Q2U public key is optional
ECPoint q;
if (Q2U == null)
{
q = parameters.G.Multiply(d2U.D);
}
else
{
q = Q2U.Q;
}
BigInteger x = q.X.ToBigInteger();
BigInteger xBar = x.Mod(powE);
BigInteger Q2UBar = xBar.SetBit(e);
BigInteger s = d1U.D.Multiply(Q2UBar).Mod(n).Add(d2U.D).Mod(n);
BigInteger xPrime = Q2V.Q.X.ToBigInteger();
BigInteger xPrimeBar = xPrime.Mod(powE);
BigInteger Q2VBar = xPrimeBar.SetBit(e);
BigInteger hs = parameters.H.Multiply(s).Mod(n);
//ECPoint p = Q1V.Q.Multiply(Q2VBar).Add(Q2V.Q).Multiply(hs);
ECPoint p = ECAlgorithms.SumOfTwoMultiplies(
Q1V.Q, Q2VBar.Multiply(hs).Mod(n), Q2V.Q, hs);
if (p.IsInfinity)
throw new InvalidOperationException("Infinity is not a valid agreement value for MQV");
return p;
}
}
}
|