in RFC 4253 "SSH Transport Layer Protocol", section 7.2 specifies how session encryption and integrity keys (and IVs) are derived from the shared secret (K) and the exchange hash value (H). It uses, a part from these values and constants, a session_id. E.g.

Initial IV server to client: HASH(K || H || "B" || session_id)

I am confused since I though that H was actually the session identifier. What is session_id and how is it obtained?

1 Answer 1


It is in the source code of openssh as described in the RFC and we can simply trace its source from there:

/* K1 = HASH(K || H || "A" || session_id) */
if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
    ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
    ssh_digest_update(hashctx, hash, hashlen) != 0 ||
    ssh_digest_update(hashctx, &c, 1) != 0 ||
    ssh_digest_update(hashctx, kex->session_id,
    kex->session_id_len) != 0 ||
    ssh_digest_final(hashctx, digest, mdsz) != 0) {

From the RFC:

The exchange hash H from the first key exchange is additionally used as the session identifier, which is a unique identifier for this connection.

This means, that the session_id is equal to hash (H) for the first key exchange. If there is another key exchange later, it is always the hash from the first key exchange.

Checking also code of DH:

/* calc and verify H */
hashlen = sizeof(hash);
if ((r = kex_dh_hash(

if (kex->session_id == NULL) {
    memcpy(kex->session_id, hash, kex->session_id_len);

if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)

confirms this idea. First we calculate H, then we update session_id (if not set already) and then we derive the keys (code above).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .