DHGEX.java

Go to the documentation of this file.
00001 /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
00002 /*
00003 Copyright (c) 2002-2011 ymnk, JCraft,Inc. All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007 
00008   1. Redistributions of source code must retain the above copyright notice,
00009      this list of conditions and the following disclaimer.
00010 
00011   2. Redistributions in binary form must reproduce the above copyright 
00012      notice, this list of conditions and the following disclaimer in 
00013      the documentation and/or other materials provided with the distribution.
00014 
00015   3. The names of the authors may not be used to endorse or promote products
00016      derived from this software without specific prior written permission.
00017 
00018 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
00019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
00020 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
00021 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
00022 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00023 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00024 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00025 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00026 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00027 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028 */
00029 
00030 package com.jcraft.jsch;
00031 
00048 public class DHGEX extends KeyExchange{
00049 
00050   private static final int SSH_MSG_KEX_DH_GEX_GROUP=               31;
00051   private static final int SSH_MSG_KEX_DH_GEX_INIT=                32;
00052   private static final int SSH_MSG_KEX_DH_GEX_REPLY=               33;
00053   private static final int SSH_MSG_KEX_DH_GEX_REQUEST=             34;
00054 
00055   static int min=1024;
00056 
00057 //  static int min=512;
00058   static int preferred=1024;
00059   static int max=1024;
00060 
00061 //  static int preferred=1024;
00062 //  static int max=2000;
00063 
00064   static final int RSA=0;
00065   static final int DSS=1;
00066   private int type=0;
00067 
00068   private int state;
00069 
00070 //  com.jcraft.jsch.DH dh;
00071   DH dh;
00072 
00073   byte[] V_S;
00074   byte[] V_C;
00075   byte[] I_S;
00076   byte[] I_C;
00077 
00078   private Buffer buf;
00079   private Packet packet;
00080 
00081   private byte[] p;
00082   private byte[] g;
00083   private byte[] e;
00084   //private byte[] f;
00085 
00086   // javadoc inherited from superclass -- P.E.
00087 
00088   public void init(Session session,
00089            byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{
00090     this.session=session;
00091     this.V_S=V_S;      
00092     this.V_C=V_C;      
00093     this.I_S=I_S;      
00094     this.I_C=I_C;      
00095 
00096     try{
00097       Class c=Class.forName(session.getConfig("sha-1"));
00098       sha=(HASH)(c.newInstance());
00099       sha.init();
00100     }
00101     catch(Exception e){
00102       System.err.println(e);
00103     }
00104 
00105     buf=new Buffer();
00106     packet=new Packet(buf);
00107 
00108     try{
00109       Class c=Class.forName(session.getConfig("dh"));
00110       dh=(com.jcraft.jsch.DH)(c.newInstance());
00111       dh.init();
00112     }
00113     catch(Exception e){
00114 //      System.err.println(e);
00115       throw e;
00116     }
00117 
00118     packet.reset();
00119     buf.putByte((byte)SSH_MSG_KEX_DH_GEX_REQUEST);
00120     buf.putInt(min);
00121     buf.putInt(preferred);
00122     buf.putInt(max);
00123     session.write(packet); 
00124 
00125     if(JSch.getLogger().isEnabled(Logger.INFO)){
00126       JSch.getLogger().log(Logger.INFO, 
00127                            "SSH_MSG_KEX_DH_GEX_REQUEST("+min+"<"+preferred+"<"+max+") sent");
00128       JSch.getLogger().log(Logger.INFO, 
00129                            "expecting SSH_MSG_KEX_DH_GEX_GROUP");
00130     }
00131 
00132     state=SSH_MSG_KEX_DH_GEX_GROUP;
00133   }
00134 
00135   public boolean next(Buffer _buf) throws Exception{
00136     int i,j;
00137     switch(state){
00138     case SSH_MSG_KEX_DH_GEX_GROUP:
00139       // byte  SSH_MSG_KEX_DH_GEX_GROUP(31)
00140       // mpint p, safe prime
00141       // mpint g, generator for subgroup in GF (p)
00142       _buf.getInt();
00143       _buf.getByte();
00144       j=_buf.getByte();
00145       if(j!=SSH_MSG_KEX_DH_GEX_GROUP){
00146     System.err.println("type: must be SSH_MSG_KEX_DH_GEX_GROUP "+j);
00147     return false;
00148       }
00149 
00150       p=_buf.getMPInt();
00151       g=_buf.getMPInt();
00152       /*
00153 for(int iii=0; iii<p.length; iii++){
00154 System.err.println("0x"+Integer.toHexString(p[iii]&0xff)+",");
00155 }
00156 System.err.println("");
00157 for(int iii=0; iii<g.length; iii++){
00158 System.err.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
00159 }
00160       */
00161       dh.setP(p);
00162       dh.setG(g);
00163 
00164       // The client responds with:
00165       // byte  SSH_MSG_KEX_DH_GEX_INIT(32)
00166       // mpint e <- g^x mod p
00167       //         x is a random number (1 < x < (p-1)/2)
00168 
00169       e=dh.getE();
00170 
00171       packet.reset();
00172       buf.putByte((byte)SSH_MSG_KEX_DH_GEX_INIT);
00173       buf.putMPInt(e);
00174       session.write(packet);
00175 
00176       if(JSch.getLogger().isEnabled(Logger.INFO)){
00177         JSch.getLogger().log(Logger.INFO, 
00178                              "SSH_MSG_KEX_DH_GEX_INIT sent");
00179         JSch.getLogger().log(Logger.INFO, 
00180                              "expecting SSH_MSG_KEX_DH_GEX_REPLY");
00181       }
00182 
00183       state=SSH_MSG_KEX_DH_GEX_REPLY;
00184       return true;
00185       //break;
00186 
00187     case SSH_MSG_KEX_DH_GEX_REPLY:
00188       // The server responds with:
00189       // byte      SSH_MSG_KEX_DH_GEX_REPLY(33)
00190       // string    server public host key and certificates (K_S)
00191       // mpint     f
00192       // string    signature of H
00193       j=_buf.getInt();
00194       j=_buf.getByte();
00195       j=_buf.getByte();
00196       if(j!=SSH_MSG_KEX_DH_GEX_REPLY){
00197     System.err.println("type: must be SSH_MSG_KEX_DH_GEX_REPLY "+j);
00198     return false;
00199       }
00200 
00201       K_S=_buf.getString();
00202       // K_S is server_key_blob, which includes ....
00203       // string ssh-dss
00204       // impint p of dsa
00205       // impint q of dsa
00206       // impint g of dsa
00207       // impint pub_key of dsa
00208       //System.err.print("K_S: "); dump(K_S, 0, K_S.length);
00209 
00210       byte[] f=_buf.getMPInt();
00211       byte[] sig_of_H=_buf.getString();
00212 
00213       dh.setF(f);
00214       K=dh.getK();
00215 
00216       //The hash H is computed as the HASH hash of the concatenation of the
00217       //following:
00218       // string    V_C, the client's version string (CR and NL excluded)
00219       // string    V_S, the server's version string (CR and NL excluded)
00220       // string    I_C, the payload of the client's SSH_MSG_KEXINIT
00221       // string    I_S, the payload of the server's SSH_MSG_KEXINIT
00222       // string    K_S, the host key
00223       // uint32    min, minimal size in bits of an acceptable group
00224       // uint32   n, preferred size in bits of the group the server should send
00225       // uint32    max, maximal size in bits of an acceptable group
00226       // mpint     p, safe prime
00227       // mpint     g, generator for subgroup
00228       // mpint     e, exchange value sent by the client
00229       // mpint     f, exchange value sent by the server
00230       // mpint     K, the shared secret
00231       // This value is called the exchange hash, and it is used to authenti-
00232       // cate the key exchange.
00233 
00234       buf.reset();
00235       buf.putString(V_C); buf.putString(V_S);
00236       buf.putString(I_C); buf.putString(I_S);
00237       buf.putString(K_S);
00238       buf.putInt(min); buf.putInt(preferred); buf.putInt(max);
00239       buf.putMPInt(p); buf.putMPInt(g); buf.putMPInt(e); buf.putMPInt(f);
00240       buf.putMPInt(K);
00241 
00242       byte[] foo=new byte[buf.getLength()];
00243       buf.getByte(foo);
00244       sha.update(foo, 0, foo.length);
00245 
00246       H=sha.digest();
00247 
00248       // System.err.print("H -> "); dump(H, 0, H.length);
00249 
00250       i=0;
00251       j=0;
00252       j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
00253     ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
00254       String alg=Util.byte2str(K_S, i, j);
00255       i+=j;
00256 
00257       boolean result=false;
00258       if(alg.equals("ssh-rsa")){
00259     byte[] tmp;
00260     byte[] ee;
00261     byte[] n;
00262     
00263     type=RSA;
00264 
00265     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
00266       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
00267     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
00268     ee=tmp;
00269     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
00270       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
00271     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
00272     n=tmp;
00273 
00274 //  SignatureRSA sig=new SignatureRSA();
00275 //  sig.init();
00276 
00277     SignatureRSA sig=null;
00278     try{
00279       Class c=Class.forName(session.getConfig("signature.rsa"));
00280       sig=(SignatureRSA)(c.newInstance());
00281       sig.init();
00282     }
00283     catch(Exception e){
00284       System.err.println(e);
00285     }
00286 
00287     sig.setPubKey(ee, n);   
00288     sig.update(H);
00289     result=sig.verify(sig_of_H);
00290 
00291         if(JSch.getLogger().isEnabled(Logger.INFO)){
00292           JSch.getLogger().log(Logger.INFO, 
00293                                "ssh_rsa_verify: signature "+result);
00294         }
00295 
00296       }
00297       else if(alg.equals("ssh-dss")){
00298     byte[] q=null;
00299     byte[] tmp;
00300 
00301     type=DSS;
00302 
00303     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
00304       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
00305     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
00306     p=tmp;
00307     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
00308       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
00309     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
00310     q=tmp;
00311     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
00312       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
00313     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
00314     g=tmp;
00315     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
00316       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
00317     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
00318     f=tmp;
00319     
00320 //  SignatureDSA sig=new SignatureDSA();
00321 //  sig.init();
00322 
00323     SignatureDSA sig=null;
00324     try{
00325       Class c=Class.forName(session.getConfig("signature.dss"));
00326       sig=(SignatureDSA)(c.newInstance());
00327       sig.init();
00328     }
00329     catch(Exception e){
00330       System.err.println(e);
00331     }
00332 
00333     sig.setPubKey(f, p, q, g);   
00334     sig.update(H);
00335     result=sig.verify(sig_of_H);
00336 
00337         if(JSch.getLogger().isEnabled(Logger.INFO)){
00338           JSch.getLogger().log(Logger.INFO, 
00339                                "ssh_dss_verify: signature "+result);
00340         }
00341 
00342       }
00343       else{
00344     System.err.println("unknown alg");
00345       }     
00346       state=STATE_END;
00347       return result;
00348     }
00349     return false;
00350   }
00351 
00352   public String getKeyType(){
00353     if(type==DSS) return "DSA";
00354     return "RSA";
00355   }
00356 
00357   public int getState(){return state; }
00358 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1