KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcraft > jsch > DHGEX


1 /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
2 /*
3 Copyright (c) 2002,2003,2004,2005,2006 ymnk, JCraft,Inc. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8   1. Redistributions of source code must retain the above copyright notice,
9      this list of conditions and the following disclaimer.
10
11   2. Redistributions in binary form must reproduce the above copyright
12      notice, this list of conditions and the following disclaimer in
13      the documentation and/or other materials provided with the distribution.
14
15   3. The names of the authors may not be used to endorse or promote products
16      derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
19 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
21 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */

29
30 package com.jcraft.jsch;
31
32 public class DHGEX extends KeyExchange{
33
34   private static final int SSH_MSG_KEX_DH_GEX_GROUP= 31;
35   private static final int SSH_MSG_KEX_DH_GEX_INIT= 32;
36   private static final int SSH_MSG_KEX_DH_GEX_REPLY= 33;
37   private static final int SSH_MSG_KEX_DH_GEX_REQUEST= 34;
38
39   static int min=1024;
40
41 // static int min=512;
42
static int preferred=1024;
43   static int max=1024;
44
45 // static int preferred=1024;
46
// static int max=2000;
47

48   static final int RSA=0;
49   static final int DSS=1;
50   private int type=0;
51
52   private int state;
53
54 // com.jcraft.jsch.DH dh;
55
DH dh;
56
57   byte[] V_S;
58   byte[] V_C;
59   byte[] I_S;
60   byte[] I_C;
61
62   private Buffer buf;
63   private Packet packet;
64
65   private byte[] p;
66   private byte[] g;
67   private byte[] e;
68   //private byte[] f;
69

70   public void init(Session session,
71            byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception JavaDoc{
72     this.session=session;
73     this.V_S=V_S;
74     this.V_C=V_C;
75     this.I_S=I_S;
76     this.I_C=I_C;
77
78     try{
79       Class JavaDoc c=Class.forName(session.getConfig("sha-1"));
80       sha=(HASH)(c.newInstance());
81       sha.init();
82     }
83     catch(Exception JavaDoc e){
84       System.err.println(e);
85     }
86
87     buf=new Buffer();
88     packet=new Packet(buf);
89
90     try{
91       Class JavaDoc c=Class.forName(session.getConfig("dh"));
92       dh=(com.jcraft.jsch.DH)(c.newInstance());
93       dh.init();
94     }
95     catch(Exception JavaDoc e){
96 // System.err.println(e);
97
throw e;
98     }
99
100     packet.reset();
101     buf.putByte((byte)SSH_MSG_KEX_DH_GEX_REQUEST);
102     buf.putInt(min);
103     buf.putInt(preferred);
104     buf.putInt(max);
105     session.write(packet);
106
107     if(JSch.getLogger().isEnabled(Logger.INFO)){
108       JSch.getLogger().log(Logger.INFO,
109                            "SSH_MSG_KEX_DH_GEX_REQUEST("+min+"<"+preferred+"<"+max+") sent");
110       JSch.getLogger().log(Logger.INFO,
111                            "expecting SSH_MSG_KEX_DH_GEX_GROUP");
112     }
113
114     state=SSH_MSG_KEX_DH_GEX_GROUP;
115   }
116
117   public boolean next(Buffer _buf) throws Exception JavaDoc{
118     int i,j;
119     switch(state){
120     case SSH_MSG_KEX_DH_GEX_GROUP:
121       // byte SSH_MSG_KEX_DH_GEX_GROUP(31)
122
// mpint p, safe prime
123
// mpint g, generator for subgroup in GF (p)
124
_buf.getInt();
125       _buf.getByte();
126       j=_buf.getByte();
127       if(j!=SSH_MSG_KEX_DH_GEX_GROUP){
128     System.err.println("type: must be SSH_MSG_KEX_DH_GEX_GROUP "+j);
129     return false;
130       }
131
132       p=_buf.getMPInt();
133       g=_buf.getMPInt();
134       /*
135 for(int iii=0; iii<p.length; iii++){
136 System.err.println("0x"+Integer.toHexString(p[iii]&0xff)+",");
137 }
138 System.err.println("");
139 for(int iii=0; iii<g.length; iii++){
140 System.err.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
141 }
142       */

143       dh.setP(p);
144       dh.setG(g);
145
146       // The client responds with:
147
// byte SSH_MSG_KEX_DH_GEX_INIT(32)
148
// mpint e <- g^x mod p
149
// x is a random number (1 < x < (p-1)/2)
150

151       e=dh.getE();
152
153       packet.reset();
154       buf.putByte((byte)SSH_MSG_KEX_DH_GEX_INIT);
155       buf.putMPInt(e);
156       session.write(packet);
157
158       if(JSch.getLogger().isEnabled(Logger.INFO)){
159         JSch.getLogger().log(Logger.INFO,
160                              "SSH_MSG_KEX_DH_GEX_INIT sent");
161         JSch.getLogger().log(Logger.INFO,
162                              "expecting SSH_MSG_KEX_DH_GEX_REPLY");
163       }
164
165       state=SSH_MSG_KEX_DH_GEX_REPLY;
166       return true;
167       //break;
168

169     case SSH_MSG_KEX_DH_GEX_REPLY:
170       // The server responds with:
171
// byte SSH_MSG_KEX_DH_GEX_REPLY(33)
172
// string server public host key and certificates (K_S)
173
// mpint f
174
// string signature of H
175
j=_buf.getInt();
176       j=_buf.getByte();
177       j=_buf.getByte();
178       if(j!=SSH_MSG_KEX_DH_GEX_REPLY){
179     System.err.println("type: must be SSH_MSG_KEX_DH_GEX_REPLY "+j);
180     return false;
181       }
182
183       K_S=_buf.getString();
184       // K_S is server_key_blob, which includes ....
185
// string ssh-dss
186
// impint p of dsa
187
// impint q of dsa
188
// impint g of dsa
189
// impint pub_key of dsa
190
//System.err.print("K_S: "); dump(K_S, 0, K_S.length);
191

192       byte[] f=_buf.getMPInt();
193       byte[] sig_of_H=_buf.getString();
194
195       dh.setF(f);
196       K=dh.getK();
197
198       //The hash H is computed as the HASH hash of the concatenation of the
199
//following:
200
// string V_C, the client's version string (CR and NL excluded)
201
// string V_S, the server's version string (CR and NL excluded)
202
// string I_C, the payload of the client's SSH_MSG_KEXINIT
203
// string I_S, the payload of the server's SSH_MSG_KEXINIT
204
// string K_S, the host key
205
// uint32 min, minimal size in bits of an acceptable group
206
// uint32 n, preferred size in bits of the group the server should send
207
// uint32 max, maximal size in bits of an acceptable group
208
// mpint p, safe prime
209
// mpint g, generator for subgroup
210
// mpint e, exchange value sent by the client
211
// mpint f, exchange value sent by the server
212
// mpint K, the shared secret
213
// This value is called the exchange hash, and it is used to authenti-
214
// cate the key exchange.
215

216       buf.reset();
217       buf.putString(V_C); buf.putString(V_S);
218       buf.putString(I_C); buf.putString(I_S);
219       buf.putString(K_S);
220       buf.putInt(min); buf.putInt(preferred); buf.putInt(max);
221       buf.putMPInt(p); buf.putMPInt(g); buf.putMPInt(e); buf.putMPInt(f);
222       buf.putMPInt(K);
223
224       byte[] foo=new byte[buf.getLength()];
225       buf.getByte(foo);
226       sha.update(foo, 0, foo.length);
227
228       H=sha.digest();
229
230       // System.err.print("H -> "); dump(H, 0, H.length);
231

232       i=0;
233       j=0;
234       j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
235     ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
236       String JavaDoc alg=new String JavaDoc(K_S, i, j);
237       i+=j;
238
239       boolean result=false;
240       if(alg.equals("ssh-rsa")){
241     byte[] tmp;
242     byte[] ee;
243     byte[] n;
244     
245     type=RSA;
246
247     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
248       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
249     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
250     ee=tmp;
251     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
252       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
253     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
254     n=tmp;
255
256 // SignatureRSA sig=new SignatureRSA();
257
// sig.init();
258

259     SignatureRSA sig=null;
260     try{
261       Class JavaDoc c=Class.forName(session.getConfig("signature.rsa"));
262       sig=(SignatureRSA)(c.newInstance());
263       sig.init();
264     }
265     catch(Exception JavaDoc e){
266       System.err.println(e);
267     }
268
269     sig.setPubKey(ee, n);
270     sig.update(H);
271     result=sig.verify(sig_of_H);
272
273         if(JSch.getLogger().isEnabled(Logger.INFO)){
274           JSch.getLogger().log(Logger.INFO,
275                                "ssh_rsa_verify: signature "+result);
276         }
277
278       }
279       else if(alg.equals("ssh-dss")){
280     byte[] q=null;
281     byte[] tmp;
282
283     type=DSS;
284
285     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
286       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
287     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
288     p=tmp;
289     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
290       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
291     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
292     q=tmp;
293     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
294       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
295     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
296     g=tmp;
297     j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
298       ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
299     tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
300     f=tmp;
301     
302 // SignatureDSA sig=new SignatureDSA();
303
// sig.init();
304

305     SignatureDSA sig=null;
306     try{
307       Class JavaDoc c=Class.forName(session.getConfig("signature.dss"));
308       sig=(SignatureDSA)(c.newInstance());
309       sig.init();
310     }
311     catch(Exception JavaDoc e){
312       System.err.println(e);
313     }
314
315     sig.setPubKey(f, p, q, g);
316     sig.update(H);
317     result=sig.verify(sig_of_H);
318
319         if(JSch.getLogger().isEnabled(Logger.INFO)){
320           JSch.getLogger().log(Logger.INFO,
321                                "ssh_dss_verify: signature "+result);
322         }
323
324       }
325       else{
326     System.err.println("unknown alg");
327       }
328       state=STATE_END;
329       return result;
330     }
331     return false;
332   }
333
334   public String JavaDoc getKeyType(){
335     if(type==DSS) return "DSA";
336     return "RSA";
337   }
338
339   public int getState(){return state; }
340 }
341
Popular Tags