public boolean next()

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));
    }