* @param kex to use for generating key values
* @throws JSchException if any errors occur
*/
void initNewKeys(KeyExchange kex) throws JSchException {
KexProposal proposal = kex.getKexProposal();
Hash hash = kex.getKexAlgorithm().getHash();
byte[] H = kex.getKexAlgorithm().getH();
byte[] K = kex.getKexAlgorithm().getK();
try {
// Initial IV client to server: HASH (K || H || "A" || session_id)
// Initial IV server to client: HASH (K || H || "B" || session_id)
// Encryption key client to server: HASH (K || H || "C" || session_id)
// Encryption key server to client: HASH (K || H || "D" || session_id)
// Integrity key client to server: HASH (K || H || "E" || session_id)
// Integrity key server to client: HASH (K || H || "F" || session_id)
Buffer buffer = new Buffer();
buffer.putMPInt(K);
buffer.putBytes(H);
int letterIndex = buffer.index;
buffer.putByte((byte) 0x41); // 0x41 = 'A'
buffer.putBytes(_session.getSessionId());
hash.update(buffer.buffer, 0, buffer.index);
byte[] c2sCipherIV = hash.digest();
buffer.buffer[letterIndex]++; // Increment to 'B'
hash.update(buffer.buffer, 0, buffer.index);
byte[] s2cCipherIV = hash.digest();
buffer.buffer[letterIndex]++; // Increment to 'C'
hash.update(buffer.buffer, 0, buffer.index);
byte[] c2sCipherKey = hash.digest();
buffer.buffer[letterIndex]++; // Increment to 'D'
hash.update(buffer.buffer, 0, buffer.index);
byte[] s2cCipherKey = hash.digest();
buffer.buffer[letterIndex]++; // Increment to 'E'
hash.update(buffer.buffer, 0, buffer.index);
byte[] c2sMacIV = hash.digest();
buffer.buffer[letterIndex]++; // Increment to 'F'
hash.update(buffer.buffer, 0, buffer.index);
byte[] s2cMacIV = hash.digest();
// Generate server-to-client cipher instance
_readCipher = CipherManager.getManager().createCipher(proposal.getCipherAlgStoC(), _session);
while( _readCipher.getBlockSize() > s2cCipherKey.length ) {
buffer.reset();
buffer.skip(letterIndex);
buffer.putBytes(s2cCipherKey);
hash.update(buffer.buffer, 0, buffer.index);
s2cCipherKey = Util.join(s2cCipherKey, hash.digest());
}
_readCipher.init(Cipher.DECRYPT_MODE, s2cCipherKey, s2cCipherIV);
_readCipherSize = _readCipher.getIVSize();
// Generate server-to-client MAC instance
_readMac = HashManager.getManager().createMAC(proposal.getMACAlgStoC());
_readMac.init(s2cMacIV);
_clientMacDigest = new byte[_readMac.getBlockSize()];
_serverMacDigest = new byte[_readMac.getBlockSize()];
// Generate client-to-server cipher instance
_writeCipher = CipherManager.getManager().createCipher(proposal.getCipherAlgCtoS(), _session);
while( _writeCipher.getBlockSize() > c2sCipherKey.length ) {
buffer.reset();
buffer.skip(letterIndex);
buffer.putBytes(c2sCipherKey);
hash.update(buffer.buffer, 0, buffer.index);
c2sCipherKey = Util.join(c2sCipherKey, hash.digest());
}
_writeCipher.init(Cipher.ENCRYPT_MODE, c2sCipherKey, c2sCipherIV);
_writeCipherSize = _writeCipher.getIVSize();
// Generate client-to-server MAC instance