public override bool next(Buffer _buf)
        {
            int i,j;
            bool result = false;
            switch(state)
            {
                case SSH_MSG_KEXDH_REPLY:
                    // The server responds with:
                    // byte      SSH_MSG_KEXDH_REPLY(31)
                    // string    server public host key and certificates (K_S)
                    // mpint     f
                    // string    signature of H
                    j=_buf.getInt();
                    j=_buf.getByte();
                    j=_buf.getByte();
                    if(j!=31)
                    {
                        Console.WriteLine("type: must be 31 "+j);
                        result = false;
                        break;
                    }

                    K_S=_buf.getString();
                    // K_S is server_key_blob, which includes ....
                    // string ssh-dss
                    // impint p of dsa
                    // impint q of dsa
                    // impint g of dsa
                    // impint pub_key of dsa
                    //System.out.print("K_S: "); //dump(K_S, 0, K_S.length);
                    byte[] f=_buf.getMPInt();
                    byte[] sig_of_H=_buf.getString();
                    /*
              for(int ii=0; ii<sig_of_H.length;ii++){
                System.out.print(Integer.toHexString(sig_of_H[ii]&0xff));
                System.out.print(": ");
              }
              Console.WriteLine("");
                    */

                    dh.setF(f);
                    K=dh.getK();

                    //The hash H is computed as the HASH hash of the concatenation of the
                    //following:
                    // string    V_C, the client's version string (CR and NL excluded)
                    // string    V_S, the server's version string (CR and NL excluded)
                    // string    I_C, the payload of the client's SSH_MSG_KEXINIT
                    // string    I_S, the payload of the server's SSH_MSG_KEXINIT
                    // string    K_S, the host key
                    // mpint     e, exchange value sent by the client
                    // mpint     f, exchange value sent by the server
                    // mpint     K, the shared secret
                    // This value is called the exchange hash, and it is used to authenti-
                    // cate the key exchange.
                    buf.reset();
                    buf.putString(V_C); buf.putString(V_S);
                    buf.putString(I_C); buf.putString(I_S);
                    buf.putString(K_S);
                    buf.putMPInt(e); buf.putMPInt(f);
                    buf.putMPInt(K);
                    byte[] foo=new byte[buf.getLength()];
                    buf.getByte(foo);
                    sha.update(foo, 0, foo.Length);
                    H=sha.digest();
                    //System.out.print("H -> "); //dump(H, 0, H.length);

                    i=0;
                    j=0;
                    j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                    String alg=Util.getString(K_S, i, j);
                    i+=j;

                    result=false;

                    if(alg.Equals("ssh-rsa"))
                    {
                        byte[] tmp;
                        byte[] ee;
                        byte[] n;

                        type=RSA;

                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        ee=tmp;
                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        n=tmp;

                        //	SignatureRSA sig=new SignatureRSA();
                        //	sig.init();

                        SignatureRSA sig=null;
                        try
                        {
                            Type t=Type.GetType(session.getConfig("signature.rsa"));
                            sig=(SignatureRSA)(Activator.CreateInstance(t));
                            sig.init();
                        }
                        catch(Exception eee)
                        {
                            Console.WriteLine(eee);
                        }

                        sig.setPubKey(ee, n);
                        sig.update(H);
                        result=sig.verify(sig_of_H);
                        //MainClass.dump(ee, n, sig_of_H, H);
                    }
                    else if(alg.Equals("ssh-dss"))
                    {
                        byte[] q=null;
                        byte[] tmp;
                        byte[] p;
                        byte[] g;

                        type=DSS;

                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        p=tmp;
                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        q=tmp;
                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        g=tmp;
                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        f=tmp;
                        //	SignatureDSA sig=new SignatureDSA();
                        //	sig.init();
                        SignatureDSA sig=null;
                        try
                        {
                            Type t=Type.GetType(session.getConfig("signature.dss"));
                            sig=(SignatureDSA)(Activator.CreateInstance(t));
                            sig.init();
                        }
                        catch(Exception ee)
                        {
                            Console.WriteLine(ee);
                        }
                        sig.setPubKey(f, p, q, g);
                        sig.update(H);
                        result=sig.verify(sig_of_H);
                    }
                    else
                    {
                        Console.WriteLine("unknow alg");
                    }
                    state=STATE_END;
                    break;
            }
            return result;
        }
        public override bool next(Buffer _buf)
        {
            int i,j;
            bool result=false;
            switch(state)
            {
                case SSH_MSG_KEX_DH_GEX_GROUP:
                    // byte  SSH_MSG_KEX_DH_GEX_GROUP(31)
                    // mpint p, safe prime
                    // mpint g, generator for subgroup in GF (p)
                    _buf.getInt();
                    _buf.getByte();
                    j=_buf.getByte();
                    if(j!=31)
                    {
                        Console.WriteLine("type: must be 31 "+j);
                        result = false;
                    }

                    p=_buf.getMPInt();
                    g=_buf.getMPInt();
                    /*
              for(int iii=0; iii<p.length; iii++){
              System.out.println("0x"+Integer.toHexString(p[iii]&0xff)+",");
              }
              System.out.println("");
              for(int iii=0; iii<g.length; iii++){
              System.out.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
              }
                    */
                    dh.setP(p);
                    dh.setG(g);

                    // The client responds with:
                    // byte  SSH_MSG_KEX_DH_GEX_INIT(32)
                    // mpint e <- g^x mod p
                    //         x is a random number (1 < x < (p-1)/2)

                    e=dh.getE();

                    packet.reset();
                    buf.putByte((byte)0x20);
                    buf.putMPInt(e);
                    session.write(packet);

                    state=SSH_MSG_KEX_DH_GEX_REPLY;
                    result = true;
                    break;

                case SSH_MSG_KEX_DH_GEX_REPLY:
                    // The server responds with:
                    // byte      SSH_MSG_KEX_DH_GEX_REPLY(33)
                    // string    server public host key and certificates (K_S)
                    // mpint     f
                    // string    signature of H
                    j=_buf.getInt();
                    j=_buf.getByte();
                    j=_buf.getByte();
                    if(j!=33)
                    {
                        Console.WriteLine("type: must be 33 "+j);
                        result = false;
                    }

                    K_S=_buf.getString();
                    // K_S is server_key_blob, which includes ....
                    // string ssh-dss
                    // impint p of dsa
                    // impint q of dsa
                    // impint g of dsa
                    // impint pub_key of dsa
                    //System.out.print("K_S: "); dump(K_S, 0, K_S.length);

                    byte[] f=_buf.getMPInt();
                    byte[] sig_of_H=_buf.getString();

                    dh.setF(f);
                    K=dh.getK();

                    //The hash H is computed as the HASH hash of the concatenation of the
                    //following:
                    // string    V_C, the client's version string (CR and NL excluded)
                    // string    V_S, the server's version string (CR and NL excluded)
                    // string    I_C, the payload of the client's SSH_MSG_KEXINIT
                    // string    I_S, the payload of the server's SSH_MSG_KEXINIT
                    // string    K_S, the host key
                    // uint32    min, minimal size in bits of an acceptable group
                    // uint32   n, preferred size in bits of the group the server should send
                    // uint32    max, maximal size in bits of an acceptable group
                    // mpint     p, safe prime
                    // mpint     g, generator for subgroup
                    // mpint     e, exchange value sent by the client
                    // mpint     f, exchange value sent by the server
                    // mpint     K, the shared secret
                    // This value is called the exchange hash, and it is used to authenti-
                    // cate the key exchange.

                    buf.reset();
                    buf.putString(V_C); buf.putString(V_S);
                    buf.putString(I_C); buf.putString(I_S);
                    buf.putString(K_S);
                    buf.putInt(min); buf.putInt(preferred); buf.putInt(max);
                    buf.putMPInt(p); buf.putMPInt(g); buf.putMPInt(e); buf.putMPInt(f);
                    buf.putMPInt(K);

                    byte[] foo=new byte[buf.getLength()];
                    buf.getByte(foo);
                    sha.update(foo, 0, foo.Length);

                    H=sha.digest();

                    // System.out.print("H -> "); dump(H, 0, H.length);

                    i=0;
                    j=0;
                    j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                        ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                    String alg=Util.getString(K_S, i, j);
                    i+=j;

                    if(alg.Equals("ssh-rsa"))
                    {
                        byte[] tmp;
                        byte[] ee;
                        byte[] n;

                        type=RSA;

                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        ee=tmp;
                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        n=tmp;

                        //	SignatureRSA sig=new SignatureRSA();
                        //	sig.init();

                        SignatureRSA sig=null;
                        try
                        {
                            Type t=Type.GetType(session.getConfig("signature.rsa"));
                            sig=(SignatureRSA)(Activator.CreateInstance(t));
                            sig.init();
                        }
                        catch(Exception eee)
                        {
                            Console.WriteLine(eee);
                        }

                        sig.setPubKey(ee, n);
                        sig.update(H);
                        result=sig.verify(sig_of_H);
                    }
                    else if(alg.Equals("ssh-dss"))
                    {
                        byte[] q=null;
                        byte[] tmp;

                        type=DSS;

                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        p=tmp;
                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        q=tmp;
                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        g=tmp;
                        j=(int)((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
                            ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
                        tmp=new byte[j]; Array.Copy(K_S, i, tmp, 0, j); i+=j;
                        f=tmp;

                        //	SignatureDSA sig=new SignatureDSA();
                        //	sig.init();

                        SignatureDSA sig=null;
                        try
                        {
                            Type t=Type.GetType(session.getConfig("signature.dss"));
                            sig=(SignatureDSA)(Activator.CreateInstance(t));
                            sig.init();
                        }
                        catch(Exception ee)
                        {
                            Console.WriteLine(ee);
                        }

                        sig.setPubKey(f, p, q, g);
                        sig.update(H);
                        result=sig.verify(sig_of_H);
                    }
                    else
                    {
                        Console.WriteLine("unknow alg");
                    }
                    state=STATE_END;
                    break;
            }
            return result;
        }