001: // changes made by mandar
002:
003: // Added .* imports
004: // replacing SecretKey with SecretKey
005:
006: // $Id: ENCRYPT1_4.java,v 1.1 2006/03/10 15:09:46 belaban Exp $
007:
008: package org.jgroups.protocols.obsolete;
009:
010: import org.jgroups.Address;
011: import org.jgroups.Event;
012: import org.jgroups.Message;
013: import org.jgroups.View;
014: import org.jgroups.protocols.PingRsp;
015: import org.jgroups.stack.Protocol;
016:
017: import javax.crypto.Cipher;
018: import javax.crypto.KeyGenerator;
019: import javax.crypto.SecretKey;
020: import javax.crypto.SecretKeyFactory;
021: import javax.crypto.spec.SecretKeySpec;
022: import java.io.IOException;
023: import java.security.*;
024: import java.security.spec.X509EncodedKeySpec;
025: import java.util.Properties;
026: import java.util.Vector;
027:
028: /**
029: * ENCRYPT1_4 layer. Encrypt and decrypt the group communication in JGroups
030: */
031: public class ENCRYPT1_4 extends Protocol {
032:
033: public static class EncryptHeader extends org.jgroups.Header {
034: int type;
035: static final int ENCRYPT = 0;
036: static final int KEY_REQUEST = 1;
037: static final int SERVER_PUBKEY = 2;
038: static final int SECRETKEY = 3;
039: static final int SECRETKEY_READY = 4;
040:
041: // adding key for Message object purpose
042: static final String KEY = "encrypt";
043:
044: public EncryptHeader() {
045: }
046:
047: public EncryptHeader(int type) {
048: this .type = type;
049: }
050:
051: public void writeExternal(java.io.ObjectOutput out)
052: throws IOException {
053: out.writeInt(type);
054: }
055:
056: public void readExternal(java.io.ObjectInput in)
057: throws IOException, ClassNotFoundException {
058: type = in.readInt();
059: }
060:
061: public String toString() {
062: return "[ENCTYPT: <variables> ]";
063: }
064: }
065:
066: Address local_addr = null;
067: Address keyServerAddr = null;
068: boolean keyServer = false;
069: String asymAlgorithm = "RSA";
070: String symAlgorithm = "DES/ECB/PKCS5Padding";
071: int asymInit = 512; // initial public/private key length
072: int symInit = 56; // initial shared key length
073: // for public/private Key
074: KeyPair Kpair; // to store own's public/private Key
075: SecretKey desKey = null;
076: final PublicKey pubKey = null; // for server to store the temporary client public key
077: PublicKey serverPubKey = null; // for client to store server's public Key
078: Cipher cipher;
079: Cipher rsa;
080: final Vector members = new Vector();
081: final Vector notReady = new Vector();
082:
083: public ENCRYPT1_4() {
084: //Provider prov = Security.getProvider("SUN");
085: //Security.addProvider(prov);
086: }
087:
088: public String getName() {
089: return "ENCRYPT1_4";
090: }
091:
092: /*
093: * GetAlgorithm: Get the algorithm name from "algorithm/mode/padding"
094: */
095: private static String getAlgorithm(String s) {
096: int index = s.indexOf("/");
097: if (index == -1)
098: return s;
099:
100: return s.substring(0, index);
101: }
102:
103: public boolean setProperties(Properties props) {
104: String str;
105:
106: super .setProperties(props);
107: // asymmetric key length
108: str = props.getProperty("asymInit");
109: if (str != null) {
110: asymInit = Integer.parseInt(str);
111: props.remove("asymInit");
112:
113: if (log.isInfoEnabled())
114: 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())
124: log.info("Sym algo bits used is " + symInit);
125: }
126:
127: // asymmetric algorithm name
128: str = props.getProperty("asymAlgorithm");
129: if (str != null) {
130: asymAlgorithm = str;
131: props.remove("asymAlgorithm");
132:
133: if (log.isInfoEnabled())
134: log.info("Asym algo used is " + asymAlgorithm);
135: }
136:
137: // symmetric algorithm name
138: str = props.getProperty("symAlgorithm");
139: if (str != null) {
140: symAlgorithm = str;
141: props.remove("symAlgorithm");
142:
143: if (log.isInfoEnabled())
144: log.info("Sym algo used is " + symAlgorithm);
145: }
146: if (props.size() > 0) {
147:
148: if (log.isErrorEnabled())
149: log.error("these properties are not recognized: "
150: + props);
151: return false;
152: }
153:
154: return true;
155: }
156:
157: public void init() throws Exception {
158: // generate keys according to the specified algorithms
159: // generate publicKey and Private Key using RSA
160: KeyPairGenerator KpairGen = KeyPairGenerator
161: .getInstance(getAlgorithm(asymAlgorithm));
162: KpairGen.initialize(asymInit, new SecureRandom());
163: Kpair = KpairGen.generateKeyPair();
164:
165: // generate secret key
166: KeyGenerator keyGen = KeyGenerator
167: .getInstance(getAlgorithm(symAlgorithm));
168: keyGen.init(symInit);
169: desKey = keyGen.generateKey();
170:
171: // initialize for rsa, cipher encryption/decryption
172: rsa = Cipher.getInstance(asymAlgorithm);
173: cipher = Cipher.getInstance(symAlgorithm);
174:
175: if (log.isInfoEnabled())
176: log
177: .info(" Both asym and sym algo initialized with the single shared key");
178: }
179:
180: /** Just remove if you don't need to reset any state */
181: public static void reset() {
182: }
183:
184: public void up(Event evt) {
185: Message msg;
186: Message newMsg;
187: EncryptHeader hdr;
188:
189: if (log.isInfoEnabled())
190: log.info("Event going up is " + evt);
191:
192: switch (evt.getType()) {
193: case Event.SET_LOCAL_ADDRESS:
194:
195: if (log.isInfoEnabled())
196: log.info("Set address call");
197: local_addr = (Address) evt.getArg();
198: break;
199: case Event.FIND_INITIAL_MBRS_OK:
200: Vector member = (Vector) evt.getArg();
201:
202: if (log.isInfoEnabled())
203: log.info("FIND_INIT members call, left members are "
204: + member.size());
205:
206: // this check is required, to prevent keyServer= false when adding itself
207: if (!keyServer)
208: keyServer = member.size() <= 0;
209:
210: if (member != null && member.size() > 0)
211: keyServerAddr = ((PingRsp) member.firstElement()).coord_addr;
212: else
213: keyServerAddr = local_addr;
214:
215: if (!keyServer) {
216:
217: desKey = null;
218:
219: if (log.isDebugEnabled())
220: log
221: .debug("This is not keyserver, deskey set to null");
222: // client send clien's public key to server and request server's public key
223: newMsg = new Message(keyServerAddr, local_addr, Kpair
224: .getPublic().getEncoded());
225: // making changes (MANDAR)
226: newMsg.putHeader(EncryptHeader.KEY, new EncryptHeader(
227: EncryptHeader.KEY_REQUEST));
228: passDown(new Event(Event.MSG, newMsg));
229: }
230:
231: if (log.isInfoEnabled())
232: log
233: .info("Done parsing for encrypt headers, sending upwards"
234: + evt);
235: passUp(evt);
236: return;
237:
238: case Event.MSG:
239: msg = (Message) evt.getArg();
240:
241: if (log.isInfoEnabled())
242: log
243: .info("This is a message from peer, not control header"
244: + msg);
245:
246: // making changes (MANDAR)
247: if (msg == null) {
248:
249: if (log.isDebugEnabled())
250: log.debug("Null message");
251: passUp(evt);
252: return;
253: }
254:
255: // making changes (MANDAR)
256: //Object obj=msg.peekHeader();
257: Object obj = msg.removeHeader(EncryptHeader.KEY);
258:
259: if (log.isInfoEnabled())
260: log.info("Stripping the required protocol header");
261:
262: // if not encrypted message, pass up
263: if (obj == null || !(obj instanceof EncryptHeader)) {
264:
265: if (log.isInfoEnabled())
266: log
267: .info("Dropping package as ENCRYPT1_4 protocol is not been recognized, msg will not be passed up");
268:
269: // BELA comment this out in case U think otherwise
270: //passUp(evt);
271: return;
272: }
273:
274: // making changes (MANDAR)
275: //hdr = (EncryptHeader)msg.removeHeader();
276: hdr = (EncryptHeader) obj;
277:
278: if (log.isInfoEnabled())
279: log.info("Header received " + hdr + ':' + hdr.type);
280: switch (hdr.type) {
281: // key request from client and send server's public key to client
282: case EncryptHeader.KEY_REQUEST:
283: try {
284:
285: if (log.isDebugEnabled())
286: log.debug("Request for key");
287: // store the this client to notReady list using client's address
288: notReady.addElement(msg.getSrc());
289: // store the client's public key for temporary
290: PublicKey tmpPubKey = generatePubKey(msg
291: .getBuffer());
292:
293: if (log.isDebugEnabled())
294: log.debug("Generated requestors public key");
295:
296: // send server's publicKey
297: newMsg = new Message(msg.getSrc(), local_addr,
298: Kpair.getPublic().getEncoded());
299: // making changes (MANDAR)
300: newMsg.putHeader(EncryptHeader.KEY,
301: new EncryptHeader(
302: EncryptHeader.SERVER_PUBKEY));
303:
304: if (log.isDebugEnabled())
305: log
306: .debug("Encoded servers public key using clients public key, only client can debug it using its private key and sending it back");
307: passDown(new Event(Event.MSG, newMsg));
308:
309: // my changes (MANDAR)
310: rsa.init(Cipher.ENCRYPT_MODE, tmpPubKey);
311: byte[] encryptedKey = rsa.doFinal(desKey
312: .getEncoded());
313:
314: if (log.isDebugEnabled())
315: log
316: .debug(" Generated encoded key which only client can decode");
317:
318: // send shared DesKey to client
319: // 1. Decrypt desKey with server's own private Key
320: // 2. Encrypt decrypted desKey with client's own public Key
321: // encrypt encoded desKey using server's private key
322: /*
323: rsa.init(Cipher.ENCRYPT_MODE, Kpair.getPrivate());
324: byte[] decryptedKey=rsa.doFinal(desKey.getEncoded());
325:
326: // encrypt decrypted key using client's public key
327: rsa.init(Cipher.ENCRYPT_MODE, pubKey);
328: byte[] encryptedKey=rsa.doFinal(decryptedKey);
329: */
330: //send encrypted deskey to client
331: newMsg = new Message(msg.getSrc(), local_addr,
332: encryptedKey);
333: // making changes (MANDAR)
334: newMsg.putHeader(EncryptHeader.KEY,
335: new EncryptHeader(EncryptHeader.SECRETKEY));
336:
337: if (log.isDebugEnabled())
338: log.debug(" Sending encoded key to client");
339: passDown(new Event(Event.MSG, newMsg));
340: } catch (Exception e) {
341: e.printStackTrace();
342: System.out.println(e + "0");
343: }
344: return;
345: case EncryptHeader.SECRETKEY_READY:
346: //server get client's public key and generate the secret key
347: notReady.removeElement(msg.getSrc());
348:
349: if (log.isDebugEnabled())
350: log.debug("Removed client " + msg.getSrc()
351: + "from notready list");
352: return;
353: case EncryptHeader.SERVER_PUBKEY:
354: serverPubKey = generatePubKey(msg.getBuffer());
355:
356: if (log.isDebugEnabled())
357: log.debug(" Obtained the servers public key");
358: return;
359:
360: case EncryptHeader.SECRETKEY:
361: try {
362: // decrypt using client's private Key
363: rsa.init(Cipher.DECRYPT_MODE, Kpair.getPrivate());
364: // my changes (MANDAR)
365: byte[] encodedKey = rsa.doFinal(msg.getBuffer());
366:
367: if (log.isDebugEnabled())
368: log
369: .debug("generating encoded key obtained from server-admin");
370:
371: /* Piece commented out by MANDAR
372: byte[] decryptedKey=rsa.doFinal(msg.getBuffer());
373: // decrypt using server's public Key
374: rsa.init(Cipher.DECRYPT_MODE, serverPubKey);
375: byte[] encodedKey=rsa.doFinal(decryptedKey);
376: */
377:
378: // decode secretKey
379: desKey = decodedKey(encodedKey);
380: if (desKey == null)
381: log.error("ohh oh !! DES key is null");
382:
383: // send ready message (MANDAR) null -> ""
384: newMsg = new Message(msg.getSrc(), local_addr, null);
385: // making changes (MANDAR)
386: newMsg.putHeader(EncryptHeader.KEY,
387: new EncryptHeader(
388: EncryptHeader.SECRETKEY_READY));
389: passDown(new Event(Event.MSG, newMsg));
390:
391: if (log.isDebugEnabled())
392: log
393: .debug("Got the deskey, sending down sec_Ready header");
394: } catch (Exception e) {
395: e.printStackTrace();
396: System.out.println(e + "5");
397: }
398: return;
399:
400: default:
401: break;
402: }
403:
404: if (hdr.type != 0)
405: log.error("Error , header is not 0");
406:
407: // not have shared key yet
408: // this encrypted message is of no use, drop it
409: if (desKey == null)
410: return;
411:
412: if (log.isInfoEnabled())
413: log.info(" Starting to decypher messages");
414:
415: // if both the shared key and incoming message are not null
416: // decrypt the message
417: if (msg.getBuffer() != null) {
418: try {
419: cipher.init(Cipher.DECRYPT_MODE, desKey);
420: msg.setBuffer(cipher.doFinal(msg.getBuffer()));
421: } catch (Exception e) {
422: e.printStackTrace();
423: }
424: }
425: break;
426: }
427:
428: if (log.isInfoEnabled())
429: log.info("Passing up event");
430: passUp(evt); // Pass up to the layer above us
431: }
432:
433: public void down(Event evt) {
434: Message msg;
435: Message newMsg;
436: boolean leave = false;
437:
438: if (log.isInfoEnabled())
439: log.info("down:evt is " + evt + ':' + evt.getType());
440:
441: switch (evt.getType()) {
442:
443: case Event.VIEW_CHANGE:
444:
445: if (log.isInfoEnabled())
446: log.info("View change call, new member coming in");
447: Vector new_members = ((View) evt.getArg()).getMembers();
448:
449: // member size decreases: member leaves, need a new key
450: if (members.size() > new_members.size())
451: leave = true;
452:
453: // copy member list
454: synchronized (members) {
455: members.removeAllElements();
456: if (new_members != null && new_members.size() > 0)
457: for (int i = 0; i < new_members.size(); i++)
458: members.addElement(new_members.elementAt(i));
459: }// end of sync
460:
461: // redistribute/regain the new key because old member leaves
462: if (leave) {
463: // get coordinator address
464: Object obj = members.firstElement();
465:
466: // if I'm the coordinator/key-server
467: if (obj.equals(local_addr)) {
468: //create the new shared key and distribute
469: keyServer = true;
470: keyServerAddr = local_addr;
471:
472: // reset shared key
473: desKey = null;
474:
475: if (log.isInfoEnabled())
476: log.info(" leave caused deskey to be null ");
477:
478: try {
479: //generate new shared key
480: KeyGenerator keyGen = KeyGenerator
481: .getInstance(getAlgorithm(symAlgorithm));
482: keyGen.init(symInit);
483: desKey = keyGen.generateKey();
484: } catch (Exception e) {
485: e.printStackTrace();
486: }
487: }//end of local_addr == obj
488: // if I'm not the coordinator/key-server
489: else {
490: keyServer = false;
491: keyServerAddr = (Address) obj;
492:
493: // reset shared key
494: desKey = null;
495:
496: // client send clien's public key to server and request server's public key
497: newMsg = new Message(keyServerAddr, local_addr,
498: Kpair.getPublic().getEncoded());
499: // making changes (MANDAR)
500: newMsg
501: .putHeader(EncryptHeader.KEY,
502: new EncryptHeader(
503: EncryptHeader.KEY_REQUEST));
504: passDown(new Event(Event.MSG, newMsg));
505:
506: if (log.isDebugEnabled())
507: log
508: .debug("Requesting new key to be part of group");
509: } // end of else
510: }
511: break;
512:
513: case Event.MSG:
514: msg = (Message) evt.getArg();
515:
516: if (log.isDebugEnabled())
517: log.debug("Its a message call " + msg);
518: int i;
519:
520: // For Server:
521: // if some members don't have the shared key yet
522: if (!notReady.isEmpty()) {
523: System.out.println("not Ready list :"
524: + notReady.toString());
525: if (msg.getDest() == null) {
526: for (i = 0; i < notReady.size(); i++) {
527: // making changes (MANDAR)
528: newMsg = new Message((Address) notReady
529: .elementAt(i), local_addr, msg
530: .getBuffer());
531: passDown(new Event(Event.MSG, newMsg));
532: }
533: break;
534: } else {
535: for (i = 0; i < notReady.size(); i++) {
536: if (msg.getDest().equals(notReady.elementAt(i))) {
537: passDown(evt);
538: return;
539: }// end of if..
540: }// end of for..
541: }// end of else
542: }
543:
544: // I already know the shared key
545: if (desKey != null) {
546:
547: if (log.isInfoEnabled())
548: log.info("DESkey is not null, I know it ");
549: try {
550: // if the message is not empty, encrypt it
551: if (msg.getBuffer() != null) {
552: cipher.init(Cipher.ENCRYPT_MODE, desKey);
553: msg.setBuffer(cipher.doFinal(msg.getBuffer()));
554: msg.putHeader(EncryptHeader.KEY,
555: new EncryptHeader(0));
556:
557: if (log.isInfoEnabled())
558: log.info(" have DES key , package sent");
559: } else {
560: msg.setBuffer(null);
561: msg.putHeader(EncryptHeader.KEY,
562: new EncryptHeader(0));
563:
564: if (log.isInfoEnabled())
565: log.info(" buffer null, added header");
566: }
567: } catch (Exception e) {
568: e.printStackTrace();
569: }
570: }
571: break;
572: }// check des key..
573:
574: if (log.isInfoEnabled())
575: log.info("Pass Down: " + evt.toString());
576: passDown(evt); // Pass on to the layer below us
577: }
578:
579: private SecretKey decodedKey(byte[] encodedKey) {
580: SecretKey key = null;
581: try {
582: //change needed mandar
583: SecretKeyFactory KeyFac = SecretKeyFactory
584: .getInstance(getAlgorithm(symAlgorithm));
585: SecretKeySpec desKeySpec = new SecretKeySpec(encodedKey,
586: getAlgorithm(symAlgorithm));
587: key = KeyFac.generateSecret(desKeySpec);
588: } catch (Exception e) {
589: e.printStackTrace();
590: }
591: return key;
592: }
593:
594: private PublicKey generatePubKey(byte[] encodedKey) {
595: PublicKey tmpPubKey = null;
596: try {
597: KeyFactory KeyFac = KeyFactory
598: .getInstance(getAlgorithm(asymAlgorithm));
599: X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(
600: encodedKey);
601: tmpPubKey = KeyFac.generatePublic(x509KeySpec);
602: } catch (Exception e) {
603: e.printStackTrace();
604: }
605: return tmpPubKey;
606: }
607: }
|