in sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java [153:247]
public boolean next(int cmd, Buffer buffer) throws Exception {
AbstractClientSession session = getClientSession();
boolean debugEnabled = log.isDebugEnabled();
if (debugEnabled) {
log.debug("next({})[{}] process command={} (expected={})",
this, session, KeyExchange.getGroupKexOpcodeName(cmd),
KeyExchange.getGroupKexOpcodeName(expected));
}
if (cmd != expected) {
throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
"Protocol error: expected packet " + KeyExchange.getGroupKexOpcodeName(expected)
+ ", got "
+ KeyExchange.getGroupKexOpcodeName(cmd));
}
if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_GROUP) {
setP(buffer.getMPIntAsBytes());
g = buffer.getMPIntAsBytes();
dh = getDH(getPValue(), new BigInteger(g));
hash = dh.getHash();
hash.init();
byte[] e = updateE(dh.getE());
validateEValue();
if (debugEnabled) {
log.debug("next({})[{}] Send SSH_MSG_KEX_DH_GEX_INIT", this, session);
}
buffer = session.createBuffer(
SshConstants.SSH_MSG_KEX_DH_GEX_INIT, e.length + Byte.SIZE);
buffer.putMPInt(e);
session.writePacket(buffer);
expected = SshConstants.SSH_MSG_KEX_DH_GEX_REPLY;
return false;
}
if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REPLY) {
if (debugEnabled) {
log.debug("next({})[{}] validate SSH_MSG_KEX_DH_GEX_REPLY - min={}, prf={}, max={}",
this, session, min, prf, max);
}
byte[] k_s = buffer.getBytes();
byte[] f = updateF(buffer);
byte[] sig = buffer.getBytes();
validateFValue();
dh.setF(f);
k = normalize(dh.getK());
buffer = new ByteArrayBuffer(k_s);
PublicKey serverKey = buffer.getRawPublicKey();
String keyAlg = session.getNegotiatedKexParameter(KexProposalOption.SERVERKEYS);
if (GenericUtils.isEmpty(keyAlg)) {
throw new SshException("Unsupported server key type: " + serverKey.getAlgorithm()
+ " [" + serverKey.getFormat() + "]");
}
buffer = new ByteArrayBuffer();
buffer.putBytes(v_c);
buffer.putBytes(v_s);
buffer.putBytes(i_c);
buffer.putBytes(i_s);
buffer.putBytes(k_s);
buffer.putInt(min);
buffer.putInt(prf);
buffer.putInt(max);
buffer.putMPInt(getP());
buffer.putMPInt(g);
buffer.putMPInt(getE());
buffer.putMPInt(f);
buffer.putBytes(k);
hash.update(buffer.array(), 0, buffer.available());
h = hash.digest();
Signature verif = ValidateUtils.checkNotNull(
NamedFactory.create(session.getSignatureFactories(), keyAlg),
"No verifier located for algorithm=%s", keyAlg);
verif.initVerifier(session, serverKey);
verif.update(session, h);
if (!verif.verify(session, sig)) {
throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
"KeyExchange signature verification failed for key type=" + keyAlg);
}
session.setServerKey(serverKey);
return true;
}
throw new IllegalStateException("Unknown command value: " + KeyExchange.getGroupKexOpcodeName(cmd));
}