byte[] nb = CryptoUtil.trim(B.toByteArray());
// clientHash = H(N) xor H(g) | H(U) | s | A
clientHash.update(ab);
if( log.isTraceEnabled() )
{
MessageDigest tmp = CryptoUtil.copy(clientHash);
log.trace("H[H(N) xor H(g) | H(U) | s | A]: "+CryptoUtil.tob64(tmp.digest()));
}
// clientHash = H(N) xor H(g) | H(U) | A | B
clientHash.update(nb);
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()));
}
// serverHash = A
serverHash.update(ab);
// Calculate u as the first 32 bits of H(B)
byte[] hB = CryptoUtil.newDigest().digest(nb);
byte[] ub =
{hB[0], hB[1], hB[2], hB[3]};
// Calculate S = (A * v^u) ^ b % N
BigInteger A = new BigInteger(1, ab);
if( log.isTraceEnabled() )
log.trace("A: "+CryptoUtil.tob64(A.toByteArray()));
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 A_v2u = A.multiply(v.modPow(u, N)).mod(N);
if( log.isTraceEnabled() )
log.trace("A * v^u: "+CryptoUtil.tob64(A_v2u.toByteArray()));
BigInteger S = A_v2u.modPow(b, 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);
if( log.isTraceEnabled() )
{
MessageDigest tmp = CryptoUtil.copy(clientHash);
log.trace("H[H(N) xor H(g) | H(U) | s | A | B | K]: "+CryptoUtil.tob64(tmp.digest()));
}
}