BigInteger n = parameters.getN();
int e = (n.bitLength() + 1) / 2;
BigInteger powE = ECConstants.ONE.shiftLeft(e);
// The Q2U public key is optional
ECPoint q;
if (Q2U == null)
{
q = parameters.getG().multiply(d2U.getD());
}
else
{
q = Q2U.getQ();
}
BigInteger x = q.getX().toBigInteger();
BigInteger xBar = x.mod(powE);
BigInteger Q2UBar = xBar.setBit(e);
BigInteger s = d1U.getD().multiply(Q2UBar).mod(n).add(d2U.getD()).mod(n);
BigInteger xPrime = Q2V.getQ().getX().toBigInteger();
BigInteger xPrimeBar = xPrime.mod(powE);
BigInteger Q2VBar = xPrimeBar.setBit(e);
BigInteger hs = parameters.getH().multiply(s).mod(n);
// ECPoint p = Q1V.getQ().multiply(Q2VBar).add(Q2V.getQ()).multiply(hs);
ECPoint p = ECAlgorithms.sumOfTwoMultiplies(
Q1V.getQ(), Q2VBar.multiply(hs).mod(n), Q2V.getQ(), hs);
if (p.isInfinity())
{
throw new IllegalStateException("Infinity is not a valid agreement value for MQV");
}
return p;