aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/ECMQVBasicAgreement.java
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/ECMQVBasicAgreement.java')
-rw-r--r--libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/ECMQVBasicAgreement.java91
1 files changed, 91 insertions, 0 deletions
diff --git a/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/ECMQVBasicAgreement.java b/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/ECMQVBasicAgreement.java
new file mode 100644
index 000000000..9faa50068
--- /dev/null
+++ b/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/ECMQVBasicAgreement.java
@@ -0,0 +1,91 @@
+package org.spongycastle.crypto.agreement;
+
+import java.math.BigInteger;
+
+import org.spongycastle.crypto.BasicAgreement;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.params.ECDomainParameters;
+import org.spongycastle.crypto.params.ECPrivateKeyParameters;
+import org.spongycastle.crypto.params.ECPublicKeyParameters;
+import org.spongycastle.crypto.params.MQVPrivateParameters;
+import org.spongycastle.crypto.params.MQVPublicParameters;
+import org.spongycastle.math.ec.ECAlgorithms;
+import org.spongycastle.math.ec.ECConstants;
+import org.spongycastle.math.ec.ECCurve;
+import org.spongycastle.math.ec.ECPoint;
+
+public class ECMQVBasicAgreement
+ implements BasicAgreement
+{
+ MQVPrivateParameters privParams;
+
+ public void init(
+ CipherParameters key)
+ {
+ this.privParams = (MQVPrivateParameters)key;
+ }
+
+ public int getFieldSize()
+ {
+ return (privParams.getStaticPrivateKey().getParameters().getCurve().getFieldSize() + 7) / 8;
+ }
+
+ public BigInteger calculateAgreement(CipherParameters pubKey)
+ {
+ MQVPublicParameters pubParams = (MQVPublicParameters)pubKey;
+
+ ECPrivateKeyParameters staticPrivateKey = privParams.getStaticPrivateKey();
+
+ ECPoint agreement = calculateMqvAgreement(staticPrivateKey.getParameters(), staticPrivateKey,
+ privParams.getEphemeralPrivateKey(), privParams.getEphemeralPublicKey(),
+ pubParams.getStaticPublicKey(), pubParams.getEphemeralPublicKey()).normalize();
+
+ if (agreement.isInfinity())
+ {
+ throw new IllegalStateException("Infinity is not a valid agreement value for MQV");
+ }
+
+ return agreement.getAffineXCoord().toBigInteger();
+ }
+
+ // The ECMQV Primitive as described in SEC-1, 3.4
+ private ECPoint calculateMqvAgreement(
+ ECDomainParameters parameters,
+ ECPrivateKeyParameters d1U,
+ ECPrivateKeyParameters d2U,
+ ECPublicKeyParameters Q2U,
+ ECPublicKeyParameters Q1V,
+ ECPublicKeyParameters Q2V)
+ {
+ BigInteger n = parameters.getN();
+ int e = (n.bitLength() + 1) / 2;
+ BigInteger powE = ECConstants.ONE.shiftLeft(e);
+
+ ECCurve curve = parameters.getCurve();
+
+ ECPoint[] points = new ECPoint[]{
+ // The Q2U public key is optional
+ ECAlgorithms.importPoint(curve, Q2U == null ? parameters.getG().multiply(d2U.getD()) : Q2U.getQ()),
+ ECAlgorithms.importPoint(curve, Q1V.getQ()),
+ ECAlgorithms.importPoint(curve, Q2V.getQ())
+ };
+
+ curve.normalizeAll(points);
+
+ ECPoint q2u = points[0], q1v = points[1], q2v = points[2];
+
+ BigInteger x = q2u.getAffineXCoord().toBigInteger();
+ BigInteger xBar = x.mod(powE);
+ BigInteger Q2UBar = xBar.setBit(e);
+ BigInteger s = d1U.getD().multiply(Q2UBar).add(d2U.getD()).mod(n);
+
+ BigInteger xPrime = q2v.getAffineXCoord().toBigInteger();
+ BigInteger xPrimeBar = xPrime.mod(powE);
+ BigInteger Q2VBar = xPrimeBar.setBit(e);
+
+ BigInteger hs = parameters.getH().multiply(s).mod(n);
+
+ return ECAlgorithms.sumOfTwoMultiplies(
+ q1v, Q2VBar.multiply(hs).mod(n), q2v, hs);
+ }
+}