diff options
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.java | 91 |
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); + } +} |