KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgroups > protocols > ENCRYPT1_4


1 // changes made by mandar
2

3 // Added .* imports
4
// replacing SecretKey with SecretKey
5

6
7 // $Id: ENCRYPT1_4.java,v 1.6 2004/09/23 16:29:41 belaban Exp $
8

9 package org.jgroups.protocols;
10
11 import org.jgroups.Address;
12 import org.jgroups.Event;
13 import org.jgroups.Message;
14 import org.jgroups.View;
15 import org.jgroups.stack.Protocol;
16
17 import javax.crypto.Cipher;
18 import javax.crypto.KeyGenerator;
19 import javax.crypto.SecretKey;
20 import javax.crypto.SecretKeyFactory;
21 import javax.crypto.spec.SecretKeySpec;
22 import java.io.IOException JavaDoc;
23 import java.security.*;
24 import java.security.spec.X509EncodedKeySpec JavaDoc;
25 import java.util.Properties JavaDoc;
26 import java.util.Vector JavaDoc;
27
28 /**
29  * ENCRYPT1_4 layer. Encrypt and decrypt the group communication in JGroups
30  */

31 public class ENCRYPT1_4 extends Protocol {
32
33 public static class EncryptHeader extends org.jgroups.Header {
34     int type;
35     static final int ENCRYPT=0;
36     static final int KEY_REQUEST=1;
37     static final int SERVER_PUBKEY=2;
38     static final int SECRETKEY=3;
39     static final int SECRETKEY_READY=4;
40
41     // adding key for Message object purpose
42
static final String JavaDoc KEY="encrypt";
43
44     public EncryptHeader(){}
45
46     public EncryptHeader(int type) {
47         this.type=type;
48     }
49
50     public void writeExternal(java.io.ObjectOutput JavaDoc out) throws IOException JavaDoc {
51         out.writeInt(type);
52     }
53
54     public void readExternal(java.io.ObjectInput JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
55         type=in.readInt();
56     }
57
58     public String JavaDoc toString() {
59         return "[ENCTYPT: <variables> ]";
60     }
61 }
62
63
64     Address local_addr=null;
65     Address keyServerAddr=null;
66     boolean keyServer=false;
67     String JavaDoc asymAlgorithm="RSA";
68     String JavaDoc symAlgorithm="DES/ECB/PKCS5Padding";
69     int asymInit=512; // initial public/private key length
70
int symInit=56; // initial shared key length
71
// for public/private Key
72
KeyPair Kpair; // to store own's public/private Key
73
SecretKey desKey=null;
74     final PublicKey pubKey=null; // for server to store the temporary client public key
75
PublicKey serverPubKey=null; // for client to store server's public Key
76
Cipher cipher;
77     Cipher rsa;
78     final Vector JavaDoc members=new Vector JavaDoc();
79     final Vector JavaDoc notReady=new Vector JavaDoc();
80
81     public ENCRYPT1_4() {
82         //Provider prov = Security.getProvider("SUN");
83
//Security.addProvider(prov);
84
}
85
86
87     public String JavaDoc getName() {
88         return "ENCRYPT1_4";
89     }
90
91
92     /*
93      * GetAlgorithm: Get the algorithm name from "algorithm/mode/padding"
94      */

95     private String JavaDoc getAlgorithm(String JavaDoc s) {
96         int index=s.indexOf("/");
97         if(index == -1)
98             return s;
99
100         return s.substring(0, index);
101     }
102
103
104     public boolean setProperties(Properties JavaDoc props) {
105         String JavaDoc str;
106
107         super.setProperties(props);
108         // asymmetric key length
109
str=props.getProperty("asymInit");
110         if(str != null) {
111             asymInit=Integer.parseInt(str);
112             props.remove("asymInit");
113
114         if(log.isInfoEnabled()) log.info("Asym algo bits used is " + asymInit);
115         }
116
117         // symmetric key length
118
str=props.getProperty("symInit");
119         if(str != null) {
120             symInit=Integer.parseInt(str);
121             props.remove("symInit");
122
123         if(log.isInfoEnabled()) log.info("Sym algo bits used is " + symInit);
124         }
125
126         // asymmetric algorithm name
127
str=props.getProperty("asymAlgorithm");
128         if(str != null) {
129             asymAlgorithm=str;
130             props.remove("asymAlgorithm");
131
132         if(log.isInfoEnabled()) log.info("Asym algo used is " + asymAlgorithm);
133         }
134
135         // symmetric algorithm name
136
str=props.getProperty("symAlgorithm");
137         if(str != null) {
138             symAlgorithm=str;
139             props.remove("symAlgorithm");
140
141         if(log.isInfoEnabled()) log.info("Sym algo used is " + symAlgorithm);
142         }
143         if(props.size() > 0) {
144
145         if(log.isErrorEnabled()) log.error("these properties are not recognized:"+ props);
146             return false;
147         }
148
149
150         return true;
151     }
152
153     public void init() throws Exception JavaDoc {
154         // generate keys according to the specified algorithms
155
// generate publicKey and Private Key using RSA
156
KeyPairGenerator KpairGen=KeyPairGenerator.getInstance(getAlgorithm(asymAlgorithm));
157         KpairGen.initialize(asymInit, new SecureRandom());
158         Kpair=KpairGen.generateKeyPair();
159
160         // generate secret key
161
KeyGenerator keyGen=KeyGenerator.getInstance(getAlgorithm(symAlgorithm));
162         keyGen.init(symInit);
163         desKey=keyGen.generateKey();
164
165         // initialize for rsa, cipher encryption/decryption
166
rsa=Cipher.getInstance(asymAlgorithm);
167         cipher=Cipher.getInstance(symAlgorithm);
168
169
170         if(log.isInfoEnabled()) log.info(" Both asym and sym algo initialized with the single shared key");
171     }
172
173     /** Just remove if you don't need to reset any state */
174     public void reset() {
175     }
176
177     public void up(Event evt) {
178         Message msg;
179         Message newMsg;
180         EncryptHeader hdr;
181
182
183         if(log.isInfoEnabled()) log.info("Event going up is " + evt);
184
185         switch(evt.getType()) {
186             case Event.SET_LOCAL_ADDRESS:
187
188             if(log.isInfoEnabled()) log.info("Set address call");
189                 local_addr=(Address)evt.getArg();
190                 break;
191             case Event.FIND_INITIAL_MBRS_OK:
192                 Vector JavaDoc member=(Vector JavaDoc)evt.getArg();
193
194             if(log.isInfoEnabled()) log.info("FIND_INIT members call, left members are " + member.size());
195
196         
197         // this check is required, to prevent keyServer= false when adding itself
198
if (!keyServer)
199             keyServer=member.size() > 0 ? false : true;
200         
201                 if(member != null && member.size() > 0)
202                     keyServerAddr=((PingRsp) member.firstElement()).coord_addr;
203                 else
204                     keyServerAddr=local_addr;
205
206                 if(!keyServer)
207             {
208             
209             desKey=null;
210
211                 if(log.isDebugEnabled()) log.debug("This is not keyserver, deskey set to null");
212             // client send clien's public key to server and request server's public key
213
newMsg=new Message(keyServerAddr, local_addr, Kpair.getPublic().getEncoded());
214             // making changes (MANDAR)
215
newMsg.putHeader(EncryptHeader.KEY, new EncryptHeader(EncryptHeader.KEY_REQUEST));
216             passDown(new Event(Event.MSG, newMsg));
217             }
218
219             if(log.isInfoEnabled()) log.info("Done parsing for encrypt headers, sending upwards" + evt);
220         passUp(evt);
221                 return;
222
223             case Event.MSG:
224                 msg=(Message) evt.getArg();
225
226             if(log.isInfoEnabled()) log.info("This is a message from peer, not control header" + msg);
227
228                 // making changes (MANDAR)
229
if(msg == null) {
230
231             if(log.isDebugEnabled()) log.debug("Null message");
232                     passUp(evt);
233                     return;
234                 }
235
236                 // making changes (MANDAR)
237
//Object obj=msg.peekHeader();
238
Object JavaDoc obj=msg.removeHeader(EncryptHeader.KEY);
239
240             if(log.isInfoEnabled()) log.info("Stripping the required protocol header");
241
242                 // if not encrypted message, pass up
243
if(obj == null || !(obj instanceof EncryptHeader)) {
244
245             if(log.isInfoEnabled()) log.info("Dropping package as ENCRYPT1_4 protocol is not been recognized, msg will not be passed up");
246
247             // BELA comment this out in case U think otherwise
248
//passUp(evt);
249
return;
250                 }
251
252                 // making changes (MANDAR)
253
//hdr = (EncryptHeader)msg.removeHeader();
254
hdr=(EncryptHeader) obj;
255
256             if(log.isInfoEnabled()) log.info("Header received " + hdr + ':' + hdr.type);
257                 switch(hdr.type) {
258                     // key request from client and send server's public key to client
259
case EncryptHeader.KEY_REQUEST:
260                         try {
261
262                 if(log.isDebugEnabled()) log.debug("Request for key");
263                             // store the this client to notReady list using client's address
264
notReady.addElement(msg.getSrc());
265                             // store the client's public key for temporary
266
PublicKey pubKey=generatePubKey(msg.getBuffer());
267
268                 if(log.isDebugEnabled()) log.debug("Generated requestors public key");
269
270                             // send server's publicKey
271
newMsg=new Message(msg.getSrc(), local_addr, Kpair.getPublic().getEncoded());
272                             // making changes (MANDAR)
273
newMsg.putHeader(EncryptHeader.KEY, new EncryptHeader(EncryptHeader.SERVER_PUBKEY));
274
275                 if(log.isDebugEnabled()) log.debug("Encoded servers public key using clients public key, only client can debug it using its private key and sending it back");
276                             passDown(new Event(Event.MSG, newMsg));
277
278                 // my changes (MANDAR)
279
rsa.init(Cipher.ENCRYPT_MODE, pubKey);
280                 byte[] encryptedKey = rsa.doFinal(desKey.getEncoded());
281
282                 if(log.isDebugEnabled()) log.debug(" Generated encoded key which only client can decode");
283                 
284                             // send shared DesKey to client
285
// 1. Decrypt desKey with server's own private Key
286
// 2. Encrypt decrypted desKey with client's own public Key
287
// encrypt encoded desKey using server's private key
288
/*
289                             rsa.init(Cipher.ENCRYPT_MODE, Kpair.getPrivate());
290                             byte[] decryptedKey=rsa.doFinal(desKey.getEncoded());
291
292                             // encrypt decrypted key using client's public key
293                             rsa.init(Cipher.ENCRYPT_MODE, pubKey);
294                             byte[] encryptedKey=rsa.doFinal(decryptedKey);
295                 */

296                             //send encrypted deskey to client
297
newMsg=new Message(msg.getSrc(), local_addr, encryptedKey);
298                             // making changes (MANDAR)
299
newMsg.putHeader(EncryptHeader.KEY, new EncryptHeader(EncryptHeader.SECRETKEY));
300
301                 if(log.isDebugEnabled()) log.debug(" Sending encoded key to client");
302                             passDown(new Event(Event.MSG, newMsg));
303                         }
304                         catch(Exception JavaDoc e) {
305                             e.printStackTrace();
306                             System.out.println(e + "0");
307                         }
308                         return;
309                     case EncryptHeader.SECRETKEY_READY:
310                         //server get client's public key and generate the secret key
311
notReady.removeElement(msg.getSrc());
312
313                 if(log.isDebugEnabled()) log.debug("Removed client " + msg.getSrc() + "from notready list");
314                         return;
315                     case EncryptHeader.SERVER_PUBKEY:
316                         serverPubKey=generatePubKey(msg.getBuffer());
317
318                 if(log.isDebugEnabled()) log.debug(" Obtained the servers public key");
319                         return;
320
321                     case EncryptHeader.SECRETKEY:
322                         try {
323                             // decrypt using client's private Key
324
rsa.init(Cipher.DECRYPT_MODE, Kpair.getPrivate());
325                 // my changes (MANDAR)
326
byte[] encodedKey = rsa.doFinal(msg.getBuffer());
327
328
329                 if(log.isDebugEnabled()) log.debug("generating encoded key obtained from server-admin");
330                 
331                 /* Piece commented out by MANDAR
332                             byte[] decryptedKey=rsa.doFinal(msg.getBuffer());
333                             // decrypt using server's public Key
334                             rsa.init(Cipher.DECRYPT_MODE, serverPubKey);
335                             byte[] encodedKey=rsa.doFinal(decryptedKey);
336                 */

337
338                             // decode secretKey
339
desKey=decodedKey(encodedKey);
340                             if(desKey == null)
341                                 log.error("ohh oh !! DES key is null");
342                     
343
344                             // send ready message (MANDAR) null -> ""
345
newMsg=new Message(msg.getSrc(), local_addr, null);
346                             // making changes (MANDAR)
347
newMsg.putHeader(EncryptHeader.KEY, new EncryptHeader(EncryptHeader.SECRETKEY_READY));
348                             passDown(new Event(Event.MSG, newMsg));
349
350                 if(log.isDebugEnabled()) log.debug("Got the deskey, sending down sec_Ready header");
351                         }
352                         catch(Exception JavaDoc e) {
353                             e.printStackTrace();
354                             System.out.println(e + "5");
355                         }
356                         return;
357
358                     default:
359                         break;
360                 }
361
362                 if (hdr.type != 0)
363                     log.error("Error , header is not 0");
364
365                 // not have shared key yet
366
// this encrypted message is of no use, drop it
367
if(desKey == null) return;
368
369
370             if(log.isInfoEnabled()) log.info(" Starting to decypher messages");
371
372                 // if both the shared key and incoming message are not null
373
// decrypt the message
374
if(msg.getBuffer() != null) {
375                     try {
376                         cipher.init(Cipher.DECRYPT_MODE, desKey);
377                         msg.setBuffer(cipher.doFinal(msg.getBuffer()));
378                     }
379                     catch(Exception JavaDoc e) {
380             e.printStackTrace();
381                     }
382                 }
383                 break;
384         }
385
386         if(log.isInfoEnabled()) log.info("Passing up event");
387         passUp(evt); // Pass up to the layer above us
388
}
389
390     public void down(Event evt) {
391         Message msg;
392         Message newMsg;
393         boolean leave=false;
394
395
396         if(log.isInfoEnabled()) log.info("down:evt is " + evt + ':' + evt.getType());
397
398         switch(evt.getType()) {
399         
400             case Event.VIEW_CHANGE:
401
402             if(log.isInfoEnabled()) log.info("View change call, new member coming in");
403                 Vector JavaDoc new_members=((View)evt.getArg()).getMembers();
404
405                 // member size decreases: member leaves, need a new key
406
if(members.size() > new_members.size()) leave=true;
407
408                 // copy member list
409
synchronized(members) {
410                     members.removeAllElements();
411                     if(new_members != null && new_members.size() > 0)
412                         for(int i=0; i < new_members.size(); i++)
413                             members.addElement(new_members.elementAt(i));
414                 }// end of sync
415

416                 // redistribute/regain the new key because old member leaves
417
if(leave) {
418                     // get coordinator address
419
Object JavaDoc obj=members.firstElement();
420
421                     // if I'm the coordinator/key-server
422
if(obj.equals(local_addr)) {
423                         //create the new shared key and distribute
424
keyServer=true;
425                         keyServerAddr=local_addr;
426
427                         // reset shared key
428
desKey=null;
429
430                 if(log.isInfoEnabled()) log.info(" leave caused deskey to be null ");
431
432                         try {
433                             //generate new shared key
434
KeyGenerator keyGen=KeyGenerator.getInstance(getAlgorithm(symAlgorithm));
435                             keyGen.init(symInit);
436                             desKey=keyGen.generateKey();
437                         }
438                         catch(Exception JavaDoc e) {
439                             e.printStackTrace();
440                         }
441                     }//end of local_addr == obj
442
// if I'm not the coordinator/key-server
443
else {
444                         keyServer=false;
445                         keyServerAddr=(Address)obj;
446
447                         // reset shared key
448
desKey=null;
449
450                         // client send clien's public key to server and request server's public key
451
newMsg=new Message(keyServerAddr, local_addr, Kpair.getPublic().getEncoded());
452                         // making changes (MANDAR)
453
newMsg.putHeader(EncryptHeader.KEY, new EncryptHeader(EncryptHeader.KEY_REQUEST));
454                         passDown(new Event(Event.MSG, newMsg));
455
456                 if(log.isDebugEnabled()) log.debug("Requesting new key to be part of group");
457                     } // end of else
458
}
459                 break;
460
461             case Event.MSG:
462                 msg= (Message) evt.getArg();
463
464             if(log.isDebugEnabled()) log.debug("Its a message call " + msg);
465         int i;
466         
467         // For Server:
468
// if some members don't have the shared key yet
469
if(!notReady.isEmpty())
470             {
471             System.out.println("not Ready list :" + notReady.toString());
472             if(msg.getDest() == null) {
473             for(i=0; i < notReady.size(); i++) {
474                 // making changes (MANDAR)
475
newMsg=new Message((Address)notReady.elementAt(i), local_addr, msg.getBuffer());
476                 passDown(new Event(Event.MSG, newMsg));
477             }
478             break;
479             }
480             else
481             {
482                 for(i=0; i < notReady.size(); i++) {
483                     if(msg.getDest() == notReady.elementAt(i)) {
484                     passDown(evt);
485                     return;
486                     }// end of if..
487
}// end of for..
488
}// end of else
489
}
490         
491         // I already know the shared key
492
if(desKey != null)
493             {
494
495
496                 if(log.isInfoEnabled()) log.info("DESkey is not null, I know it ");
497             try
498                 {
499                 // if the message is not empty, encrypt it
500
if(msg.getBuffer() != null)
501                     {
502                     cipher.init(Cipher.ENCRYPT_MODE, desKey);
503                     msg.setBuffer(cipher.doFinal(msg.getBuffer()));
504                     msg.putHeader(EncryptHeader.KEY, new EncryptHeader(0));
505
506                         if(log.isInfoEnabled()) log.info(" have DES key , package sent");
507                     }
508                 else
509                     {
510                     msg.setBuffer(null);
511                     msg.putHeader(EncryptHeader.KEY, new EncryptHeader(0));
512
513                         if(log.isInfoEnabled()) log.info(" buffer null, added header");
514                     }
515                 }catch(Exception JavaDoc e)
516                 {
517                     e.printStackTrace();
518                 }
519             }
520         break;
521     }// check des key..
522

523         if(log.isInfoEnabled()) log.info("Pass Down: " + evt.toString());
524     passDown(evt); // Pass on to the layer below us
525
}
526
527     private SecretKey decodedKey(byte[] encodedKey) {
528         SecretKey key=null;
529         try {
530             //change needed mandar
531
SecretKeyFactory KeyFac=SecretKeyFactory.getInstance(getAlgorithm(symAlgorithm));
532             SecretKeySpec desKeySpec=new SecretKeySpec(encodedKey, getAlgorithm(symAlgorithm));
533             key=KeyFac.generateSecret(desKeySpec);
534         }
535         catch(Exception JavaDoc e) {
536             e.printStackTrace();
537         }
538         return key;
539     }
540
541     private PublicKey generatePubKey(byte[] encodedKey) {
542         PublicKey pubKey=null;
543         try {
544             KeyFactory KeyFac=KeyFactory.getInstance(getAlgorithm(asymAlgorithm));
545             X509EncodedKeySpec JavaDoc x509KeySpec=new X509EncodedKeySpec JavaDoc(encodedKey);
546             pubKey=KeyFac.generatePublic(x509KeySpec);
547         }
548         catch(Exception JavaDoc e) {
549             e.printStackTrace();
550         }
551         return pubKey;
552     }
553 }
554
Popular Tags