org.bouncycastle.crypto.agreement.ECMQVBasicAgreement Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-ext-debug-jdk18on Show documentation
Show all versions of bcprov-ext-debug-jdk18on Show documentation
The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for Java 1.8 and later with debug enabled.
The newest version!
package org.bouncycastle.crypto.agreement;
import java.math.BigInteger;
import org.bouncycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.MQVPrivateParameters;
import org.bouncycastle.crypto.params.MQVPublicParameters;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECConstants;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.Properties;
public class ECMQVBasicAgreement
implements BasicAgreement
{
MQVPrivateParameters privParams;
public void init(
CipherParameters key)
{
this.privParams = (MQVPrivateParameters)key;
CryptoServicesRegistrar.checkConstraints(Utils.getDefaultProperties("ECMQV", this.privParams.getStaticPrivateKey()));
}
public int getFieldSize()
{
return (privParams.getStaticPrivateKey().getParameters().getCurve().getFieldSize() + 7) / 8;
}
public BigInteger calculateAgreement(CipherParameters pubKey)
{
if (Properties.isOverrideSet("org.bouncycastle.ec.disable_mqv"))
{
throw new IllegalStateException("ECMQV explicitly disabled");
}
MQVPublicParameters pubParams = (MQVPublicParameters)pubKey;
ECPrivateKeyParameters staticPrivateKey = privParams.getStaticPrivateKey();
ECDomainParameters parameters = staticPrivateKey.getParameters();
if (!parameters.equals(pubParams.getStaticPublicKey().getParameters()))
{
throw new IllegalStateException("ECMQV public key components have wrong domain parameters");
}
ECPoint agreement = calculateMqvAgreement(parameters, 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();
// The Q2U public key is optional - but will be calculated for us if it wasn't present
ECPoint q2u = ECAlgorithms.cleanPoint(curve, Q2U.getQ());
ECPoint q1v = ECAlgorithms.cleanPoint(curve, Q1V.getQ());
ECPoint q2v = ECAlgorithms.cleanPoint(curve, Q2V.getQ());
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);
}
}