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;
+ }
+ }
+}
|