summary refs log tree commit diff
path: root/Crypto/src/crypto/agreement/ECMqvBasicAgreement.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/crypto/agreement/ECMqvBasicAgreement.cs')
-rw-r--r--Crypto/src/crypto/agreement/ECMqvBasicAgreement.cs85
1 files changed, 85 insertions, 0 deletions
diff --git a/Crypto/src/crypto/agreement/ECMqvBasicAgreement.cs b/Crypto/src/crypto/agreement/ECMqvBasicAgreement.cs
new file mode 100644

index 000000000..51faa8e49 --- /dev/null +++ b/Crypto/src/crypto/agreement/ECMqvBasicAgreement.cs
@@ -0,0 +1,85 @@ +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; + } + } +}