{
// clientHash = H(N) xor H(g) | H(U) | s | A | B
clientHash.update(Bbytes);
if( log.isTraceEnabled() )
{
MessageDigest tmp = CryptoUtil.copy(clientHash);
log.trace("H[H(N) xor H(g) | H(U) | s | A | B]: "+CryptoUtil.tob64(tmp.digest()));
}
// Calculate u as the first 32 bits of H(B)
byte[] hB = CryptoUtil.newDigest().digest(Bbytes);
byte[] ub =
{hB[0], hB[1], hB[2], hB[3]};
// Calculate S = (B - g^x) ^ (a + u * x) % N
BigInteger B = new BigInteger(1, Bbytes);
if( log.isTraceEnabled() )
log.trace("B: "+CryptoUtil.tob64(B.toByteArray()));
if( B.compareTo(v) < 0 )
B = B.add(N);
if( log.isTraceEnabled() )
log.trace("B': "+CryptoUtil.tob64(B.toByteArray()));
if( log.isTraceEnabled() )
log.trace("v: "+CryptoUtil.tob64(v.toByteArray()));
BigInteger u = new BigInteger(1, ub);
if( log.isTraceEnabled() )
log.trace("u: "+CryptoUtil.tob64(u.toByteArray()));
BigInteger B_v = B.subtract(v);
if( log.isTraceEnabled() )
log.trace("B - v: "+CryptoUtil.tob64(B_v.toByteArray()));
BigInteger a_ux = a.add(u.multiply(x));
if( log.isTraceEnabled() )
log.trace("a + u * x: "+CryptoUtil.tob64(a_ux.toByteArray()));
BigInteger S = B_v.modPow(a_ux, N);
if( log.isTraceEnabled() )
log.trace("S: "+CryptoUtil.tob64(S.toByteArray()));
// K = SessionHash(S)
MessageDigest sessionDigest = MessageDigest.getInstance(params.hashAlgorithm);
K = sessionDigest.digest(S.toByteArray());
if( log.isTraceEnabled() )
log.trace("K: "+CryptoUtil.tob64(K));
// clientHash = H(N) xor H(g) | H(U) | A | B | K
clientHash.update(K);
byte[] M1 = clientHash.digest();
if( log.isTraceEnabled() )
log.trace("M1: H[H(N) xor H(g) | H(U) | s | A | B | K]: "+CryptoUtil.tob64(M1));
serverHash.update(M1);
serverHash.update(K);
if( log.isTraceEnabled() )
{
MessageDigest tmp = CryptoUtil.copy(serverHash);
log.trace("H[A | M1 | K]: "+CryptoUtil.tob64(tmp.digest()));
}
return M1;
}