Common secret
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/f9bf8077 Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/f9bf8077 Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/f9bf8077 Branch: refs/heads/feature/GEODE-420 Commit: f9bf8077ddb3944e55dd07d108c56641ace6a746 Parents: d6e7175 Author: Hitesh Khamesra <[email protected]> Authored: Thu May 19 09:40:11 2016 -0700 Committer: Hitesh Khamesra <[email protected]> Committed: Mon Aug 29 10:39:17 2016 -0700 ---------------------------------------------------------------------- .../membership/gms/messenger/GMSEncrypt.java | 327 ++++++++++---- .../gms/messenger/JGroupsMessenger.java | 14 +- .../gms/messenger/GMSEncryptJUnitTest.java | 428 ++++++++++++++++++- 3 files changed, 686 insertions(+), 83 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f9bf8077/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/GMSEncrypt.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/GMSEncrypt.java b/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/GMSEncrypt.java index 4cc9224..bf8f7bc 100755 --- a/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/GMSEncrypt.java +++ b/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/GMSEncrypt.java @@ -17,14 +17,21 @@ package com.gemstone.gemfire.distributed.internal.membership.gms.messenger; +import io.codearte.catchexception.shade.mockito.cglib.core.Local; + import java.math.BigInteger; import java.security.*; import java.security.spec.EncodedKeySpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.crypto.Cipher; @@ -74,22 +81,38 @@ public class GMSEncrypt implements Cloneable{ private String dhSKAlgo = null; private Services services; + + private InternalDistributedMember localMember; private NetView view; private Map<InternalDistributedMember, PeerEncryptor> memberToPeerEncryptor = new ConcurrentHashMap<>(); + + private ClusterEncryptor clusterEncryptor; - protected void installView(NetView view) { + protected void installView(NetView view) throws Exception { this.view = view; this.view.setPublicKey(services.getJoinLeave().getMemberID(), getPublicKeyBytes()); - // TODO remove ciphers for departed members } - protected void installView(NetView view, InternalDistributedMember mbr) { + protected void installView(NetView view, InternalDistributedMember mbr) throws Exception { this.view = view; - this.view.setPublicKey(mbr, getPublicKeyBytes()); + // this.view.setPublicKey(mbr, getPublicKeyBytes()); // TODO remove ciphers for departed members + //addClusterKey(); + } + + protected byte[] getSecretBytes() { + return this.clusterEncryptor.secretBytes; + } + + protected synchronized void addClusterKey() throws Exception { + this.clusterEncryptor = new ClusterEncryptor(this); + } + + protected synchronized void addClusterKey(byte[] secretBytes) throws Exception { + this.clusterEncryptor = new ClusterEncryptor(secretBytes); } protected GMSEncrypt() { @@ -100,6 +123,12 @@ public class GMSEncrypt implements Cloneable{ this.services = services; initDHKeys(services.getConfig().getDistributionConfig()); } + + public GMSEncrypt(Services services, InternalDistributedMember mbr) throws Exception { + this.services = services; + this.localMember = mbr; + initDHKeys(services.getConfig().getDistributionConfig()); + } public byte[] decryptData(byte[] data, InternalDistributedMember member) throws Exception { return getPeerEncryptor(member).decryptBytes(data); @@ -108,6 +137,15 @@ public class GMSEncrypt implements Cloneable{ public byte[] encryptData(byte[] data, InternalDistributedMember member) throws Exception { return getPeerEncryptor(member).encryptBytes(data); } + + + public byte[] decryptData(byte[] data) throws Exception { + return this.clusterEncryptor.decryptBytes(data); + } + + public byte[] encryptData(byte[] data) throws Exception { + return this.clusterEncryptor.encryptBytes(data); + } protected byte[] getPublicKeyBytes() { return dhPublicKey.getEncoded(); @@ -117,6 +155,7 @@ public class GMSEncrypt implements Cloneable{ protected GMSEncrypt clone() throws CloneNotSupportedException { try { GMSEncrypt gmsEncrypt = new GMSEncrypt(); + gmsEncrypt.localMember = this.localMember; gmsEncrypt.dhSKAlgo = this.dhSKAlgo; X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(this.dhPublicKey.getEncoded()); @@ -138,7 +177,6 @@ public class GMSEncrypt implements Cloneable{ } } - /** * Initialize the Diffie-Hellman keys. This method is not thread safe */ @@ -256,13 +294,12 @@ public class GMSEncrypt implements Cloneable{ private String peerSKAlgo = null; - private Cipher _encrypt; + private Cipher encrypt; + + private Cipher decrypt = null; - protected PeerEncryptor(byte[] peerPublicKeyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException { - X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(peerPublicKeyBytes); - KeyFactory keyFact = KeyFactory.getInstance("DH"); - //PublicKey pubKey = keyFact.generatePublic(x509KeySpec); - this.peerPublicKey = keyFact.generatePublic(x509KeySpec); + protected PeerEncryptor(byte[] peerPublicKeyBytes) throws Exception { + this.peerPublicKey = getPublicKey(peerPublicKeyBytes); } public byte [] encryptBytes(byte[] data) throws Exception { @@ -272,46 +309,21 @@ public class GMSEncrypt implements Cloneable{ } else { algo = dhSKAlgo; } - return GMSEncrypt.encryptBytes(data, getEncryptCipher(algo, this.peerPublicKey)); + return GMSEncrypt.encryptBytes(data, getEncryptCipher(algo)); } - private Cipher getEncryptCipher(String dhSKAlgo, PublicKey publicKey) + private Cipher getEncryptCipher(String dhSKAlgo) throws Exception{ try { - if(_encrypt == null) { - KeyAgreement ka = KeyAgreement.getInstance("DH"); - ka.init(dhPrivateKey); - ka.doPhase(publicKey, true); - - Cipher encrypt; - - int keysize = getKeySize(dhSKAlgo); - int blocksize = getBlockSize(dhSKAlgo); - - if (keysize == -1 || blocksize == -1) { - SecretKey sKey = ka.generateSecret(dhSKAlgo); - encrypt = Cipher.getInstance(dhSKAlgo); - encrypt.init(Cipher.ENCRYPT_MODE, sKey); - } - else { - String dhAlgoStr = getDhAlgoStr(dhSKAlgo); - - byte[] sKeyBytes = ka.generateSecret(); - SecretKeySpec sks = new SecretKeySpec(sKeyBytes, 0, keysize, dhAlgoStr); - IvParameterSpec ivps = new IvParameterSpec(sKeyBytes, keysize, blocksize); - - encrypt = Cipher.getInstance(dhAlgoStr + "/CBC/PKCS5Padding"); - encrypt.init(Cipher.ENCRYPT_MODE, sks, ivps); - } - _encrypt = encrypt; + if(encrypt == null) { + encrypt = GMSEncrypt.getEncryptCipher(dhSKAlgo, dhPrivateKey, this.peerPublicKey); } }catch(Exception ex) { throw ex; } - return _encrypt; + return encrypt; } - - + public byte[] decryptBytes(byte[] data) throws Exception { String algo = null; @@ -323,48 +335,213 @@ public class GMSEncrypt implements Cloneable{ Cipher c = getDecryptCipher(algo, this.peerPublicKey); return GMSEncrypt.decryptBytes(data, c); + } + + private Cipher getDecryptCipher( String dhSKAlgo, PublicKey publicKey) + throws Exception{ + if(decrypt == null) { + decrypt = GMSEncrypt.getDecryptCipher(dhSKAlgo, dhPrivateKey, this.peerPublicKey); + } + return decrypt; } + } + + protected static Cipher getEncryptCipher(String dhSKAlgo, PrivateKey privateKey, PublicKey peerPublicKey) + throws Exception{ + KeyAgreement ka = KeyAgreement.getInstance("DH"); + ka.init(privateKey); + ka.doPhase(peerPublicKey, true); + + Cipher encrypt; + + int keysize = getKeySize(dhSKAlgo); + int blocksize = getBlockSize(dhSKAlgo); + if (keysize == -1 || blocksize == -1) { + SecretKey sKey = ka.generateSecret(dhSKAlgo); + encrypt = Cipher.getInstance(dhSKAlgo); + encrypt.init(Cipher.ENCRYPT_MODE, sKey); + } + else { + String dhAlgoStr = getDhAlgoStr(dhSKAlgo); - private Cipher _decrypt = null; + byte[] sKeyBytes = ka.generateSecret(); + SecretKeySpec sks = new SecretKeySpec(sKeyBytes, 0, keysize, dhAlgoStr); + IvParameterSpec ivps = new IvParameterSpec(sKeyBytes, keysize, blocksize); - private Cipher getDecryptCipher( String dhSKAlgo, PublicKey publicKey) + encrypt = Cipher.getInstance(dhAlgoStr + "/CBC/PKCS5Padding"); + encrypt.init(Cipher.ENCRYPT_MODE, sks, ivps); + } + + return encrypt; + } + + protected static Cipher getEncryptCipher(String dhSKAlgo, byte[] secretBytes) throws Exception{ - if(_decrypt == null) { - try { - KeyAgreement ka = KeyAgreement.getInstance("DH"); - ka.init(dhPrivateKey); - ka.doPhase(publicKey, true); - - Cipher decrypt; - - int keysize = getKeySize(dhSKAlgo); - int blocksize = getBlockSize(dhSKAlgo); - - if (keysize == -1 || blocksize == -1) { - SecretKey sKey = ka.generateSecret(dhSKAlgo); - decrypt = Cipher.getInstance(dhSKAlgo); - decrypt.init(Cipher.DECRYPT_MODE, sKey); - } - else { - String algoStr = getDhAlgoStr(dhSKAlgo); - - byte[] sKeyBytes = ka.generateSecret(); - SecretKeySpec sks = new SecretKeySpec(sKeyBytes, 0, keysize, algoStr); - IvParameterSpec ivps = new IvParameterSpec(sKeyBytes, keysize, blocksize); - - decrypt = Cipher.getInstance(algoStr + "/CBC/PKCS5Padding"); - decrypt.init(Cipher.DECRYPT_MODE, sks, ivps); - } - - _decrypt = decrypt; - }catch(Exception ex) { - throw ex; + + Cipher encrypt = null; + + int keysize = getKeySize(dhSKAlgo); + int blocksize = getBlockSize(dhSKAlgo); + + if (keysize == -1 || blocksize == -1) { + //TODO how should we do here + /*SecretKey sKey = ka.generateSecret(dhSKAlgo); + encrypt = Cipher.getInstance(dhSKAlgo); + encrypt.init(Cipher.ENCRYPT_MODE, sKey);*/ + } + else { + String dhAlgoStr = getDhAlgoStr(dhSKAlgo); + + SecretKeySpec sks = new SecretKeySpec(secretBytes, 0, keysize, dhAlgoStr); + IvParameterSpec ivps = new IvParameterSpec(secretBytes, keysize, blocksize); + + encrypt = Cipher.getInstance(dhAlgoStr + "/CBC/PKCS5Padding"); + encrypt.init(Cipher.ENCRYPT_MODE, sks, ivps); + } + + return encrypt; + } + + protected static Cipher getDecryptCipher(String dhSKAlgo, PrivateKey privateKey, PublicKey publicKey) throws Exception { + KeyAgreement ka = KeyAgreement.getInstance("DH"); + ka.init(privateKey); + ka.doPhase(publicKey, true); + + Cipher decrypt; + + int keysize = getKeySize(dhSKAlgo); + int blocksize = getBlockSize(dhSKAlgo); + + if (keysize == -1 || blocksize == -1) { + SecretKey sKey = ka.generateSecret(dhSKAlgo); + decrypt = Cipher.getInstance(dhSKAlgo); + decrypt.init(Cipher.DECRYPT_MODE, sKey); + } else { + String algoStr = getDhAlgoStr(dhSKAlgo); + + byte[] sKeyBytes = ka.generateSecret(); + SecretKeySpec sks = new SecretKeySpec(sKeyBytes, 0, keysize, algoStr); + IvParameterSpec ivps = new IvParameterSpec(sKeyBytes, keysize, blocksize); + + decrypt = Cipher.getInstance(algoStr + "/CBC/PKCS5Padding"); + decrypt.init(Cipher.DECRYPT_MODE, sks, ivps); + } + return decrypt; + } + + protected static Cipher getDecryptCipher(String dhSKAlgo, byte[] secretBytes) throws Exception { + Cipher decrypt = null; + + int keysize = getKeySize(dhSKAlgo); + int blocksize = getBlockSize(dhSKAlgo); + + if (keysize == -1 || blocksize == -1) { + //TODO: how to do here + /*SecretKey sKey = ka.generateSecret(dhSKAlgo); + decrypt = Cipher.getInstance(dhSKAlgo); + decrypt.init(Cipher.DECRYPT_MODE, sKey);*/ + } else { + String algoStr = getDhAlgoStr(dhSKAlgo); + + SecretKeySpec sks = new SecretKeySpec(secretBytes, 0, keysize, algoStr); + IvParameterSpec ivps = new IvParameterSpec(secretBytes, keysize, blocksize); + + decrypt = Cipher.getInstance(algoStr + "/CBC/PKCS5Padding"); + decrypt.init(Cipher.DECRYPT_MODE, sks, ivps); + } + return decrypt; + } + protected static byte[] generateSecret(String dhSKAlgo, PrivateKey privateKey, PublicKey otherPublicKey) throws Exception { + KeyAgreement ka = KeyAgreement.getInstance("DH"); + ka.init(privateKey); + ka.doPhase(otherPublicKey, true); + + int keysize = getKeySize(dhSKAlgo); + int blocksize = getBlockSize(dhSKAlgo); + + if (keysize == -1 || blocksize == -1) { + SecretKey sKey = ka.generateSecret(dhSKAlgo); + return sKey.getEncoded(); + } else { + String algoStr = getDhAlgoStr(dhSKAlgo); + + return ka.generateSecret(); + } + } + + protected static PublicKey getPublicKey(byte[] publicKeyBytes) throws Exception { + X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes); + KeyFactory keyFact = KeyFactory.getInstance("DH"); + //PublicKey pubKey = keyFact.generatePublic(x509KeySpec); + return keyFact.generatePublic(x509KeySpec); + } + + protected static void initEncryptCipher(KeyAgreement ka, List<PublicKey> publicKeys) throws Exception{ + Iterator<PublicKey> itr = publicKeys.iterator(); + while(itr.hasNext()) { + ka.doPhase(itr.next(), !itr.hasNext()); + } + } + /*** + * this will hold the common key for cluster + * that will be created using publickey of all the members.. + * + */ + protected class ClusterEncryptor{ + byte[] secretBytes; + Cipher encrypt; + Cipher decrypt; + int viewId; + Set<InternalDistributedMember> mbrs; + + public ClusterEncryptor(GMSEncrypt other) throws Exception { + GMSEncrypt mine = new GMSEncrypt(other.services); + this.secretBytes = GMSEncrypt.generateSecret(mine.dhSKAlgo, mine.dhPrivateKey, other.dhPublicKey); + } + + public ClusterEncryptor(byte[] sb) { + this.secretBytes = sb; + } + + public byte [] encryptBytes(byte[] data) throws Exception { + String algo = dhSKAlgo; + return GMSEncrypt.encryptBytes(data, getEncryptCipher(algo)); + } + + private Cipher getEncryptCipher(String dhSKAlgo) + throws Exception{ + try { + if(encrypt == null) { + synchronized (this) { + if(encrypt == null) + encrypt = GMSEncrypt.getEncryptCipher(dhSKAlgo, secretBytes); + } } + }catch(Exception ex) { + throw ex; } - return _decrypt; + return encrypt; + } + + public byte[] decryptBytes(byte[] data) throws Exception + { + String algo = dhSKAlgo; + Cipher c = getDecryptCipher(algo); + return GMSEncrypt.decryptBytes(data, c); } + private Cipher getDecryptCipher( String dhSKAlgo) + throws Exception{ + if(decrypt == null) { + synchronized (this) { + if(decrypt == null) + decrypt = GMSEncrypt.getDecryptCipher(dhSKAlgo, secretBytes); + } + } + return decrypt; + } } } + http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f9bf8077/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/JGroupsMessenger.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/JGroupsMessenger.java b/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/JGroupsMessenger.java index 89f7dec..331d672 100644 --- a/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/JGroupsMessenger.java +++ b/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/JGroupsMessenger.java @@ -355,7 +355,12 @@ public class JGroupsMessenger implements Messenger { addressesWithIoExceptionsProcessed.clear(); if (encrypt != null) { -// encrypt.installView(v); + try { + encrypt.installView(v); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } } @@ -572,7 +577,12 @@ public class JGroupsMessenger implements Messenger { @Override public Set<InternalDistributedMember> send(DistributionMessage msg, NetView alternateView) { if (this.encrypt != null) { - // this.encrypt.installView(alternateView); + try { + this.encrypt.installView(alternateView); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } return send(msg, true); } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f9bf8077/geode-core/src/test/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/GMSEncryptJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/GMSEncryptJUnitTest.java b/geode-core/src/test/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/GMSEncryptJUnitTest.java index de90328..8652b67 100755 --- a/geode-core/src/test/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/GMSEncryptJUnitTest.java +++ b/geode-core/src/test/java/com/gemstone/gemfire/distributed/internal/membership/gms/messenger/GMSEncryptJUnitTest.java @@ -1,5 +1,6 @@ package com.gemstone.gemfire.distributed.internal.membership.gms.messenger; import static org.mockito.Mockito.*; + import com.gemstone.gemfire.distributed.internal.DistributionConfig; import com.gemstone.gemfire.distributed.internal.DistributionConfigImpl; import com.gemstone.gemfire.distributed.internal.DistributionManager; @@ -8,14 +9,26 @@ import com.gemstone.gemfire.distributed.internal.membership.NetView; import com.gemstone.gemfire.distributed.internal.membership.gms.ServiceConfig; import com.gemstone.gemfire.distributed.internal.membership.gms.Services; import com.gemstone.gemfire.internal.admin.remote.RemoteTransportConfig; + import org.junit.Assert; import org.junit.Test; +import java.math.BigInteger; +import java.security.Key; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Properties; +import javax.crypto.KeyAgreement; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DHParameterSpec; + /** * Created by bschuchardt on 5/6/2016. */ @@ -45,12 +58,13 @@ public class GMSEncryptJUnitTest { } int viewId = 1; List<InternalDistributedMember> mbrs = new LinkedList<>(); - mbrs.add(mockMembers[0]); + //mbrs.add(mockMembers[0]); mbrs.add(mockMembers[1]); mbrs.add(mockMembers[2]); + mbrs.add(mockMembers[3]); //prepare the view - netView = new NetView(mockMembers[0], viewId, mbrs); + netView = new NetView(mockMembers[1], viewId, mbrs); } @@ -59,8 +73,8 @@ public class GMSEncryptJUnitTest { public void testOneMemberCanDecryptAnothersMessage() throws Exception{ initMocks(); - GMSEncrypt gmsEncrypt1 = new GMSEncrypt(services); // this will be the sender - GMSEncrypt gmsEncrypt2 = new GMSEncrypt(services); // this will be the receiver + GMSEncrypt gmsEncrypt1 = new GMSEncrypt(services, mockMembers[1]); // this will be the sender + GMSEncrypt gmsEncrypt2 = new GMSEncrypt(services, mockMembers[2]); // this will be the receiver // establish the public keys for the sender and receiver netView.setPublicKey(mockMembers[1], gmsEncrypt1.getPublicKeyBytes()); @@ -99,8 +113,8 @@ public class GMSEncryptJUnitTest { public void testPublicKeyPrivateKeyFromSameMember() throws Exception{ initMocks(); - GMSEncrypt gmsEncrypt1 = new GMSEncrypt(services); // this will be the sender - GMSEncrypt gmsEncrypt2 = new GMSEncrypt(services); // this will be the receiver + GMSEncrypt gmsEncrypt1 = new GMSEncrypt(services, mockMembers[1]); // this will be the sender + GMSEncrypt gmsEncrypt2 = new GMSEncrypt(services, mockMembers[2]); // this will be the receiver gmsEncrypt1 = gmsEncrypt1.clone(); gmsEncrypt2 = gmsEncrypt2.clone(); @@ -137,4 +151,406 @@ public class GMSEncryptJUnitTest { Assert.assertTrue(Arrays.equals(responseBytes, decryptedResponse)); } + + @Test + public void testForClusterSecretKey() throws Exception{ + initMocks(); + + GMSEncrypt gmsEncrypt1 = new GMSEncrypt(services, mockMembers[1]); // this will be the sender + gmsEncrypt1.addClusterKey(); + // establish the public keys for the sender and receiver + netView.setPublicKey(mockMembers[1], gmsEncrypt1.getPublicKeyBytes()); + + gmsEncrypt1.installView(netView, mockMembers[1]); + + // sender encrypts a message, so use receiver's public key + String ch = "Hello world"; + byte[] challenge = ch.getBytes(); + byte[] encryptedChallenge = gmsEncrypt1.encryptData(challenge); + + // receiver decrypts the message using the sender's public key + byte[] decryptBytes = gmsEncrypt1.decryptData(encryptedChallenge); + + Assert.assertFalse(Arrays.equals(challenge, encryptedChallenge)); + + Assert.assertTrue(Arrays.equals(challenge, decryptBytes)); + } + + @Test + public void testForClusterSecretKeyFromOtherMember() throws Exception{ + initMocks(); + + GMSEncrypt gmsEncrypt1 = new GMSEncrypt(services, mockMembers[1]); // this will be the sender + gmsEncrypt1.addClusterKey(); + GMSEncrypt gmsEncrypt2 = new GMSEncrypt(services, mockMembers[2]); // this will be the sender + + // establish the public keys for the sender and receiver + netView.setPublicKey(mockMembers[1], gmsEncrypt1.getPublicKeyBytes()); + netView.setPublicKey(mockMembers[2], gmsEncrypt2.getPublicKeyBytes()); + + gmsEncrypt1.installView(netView, mockMembers[1]); + + byte[] secretBytes = gmsEncrypt1.getSecretBytes(); + gmsEncrypt2.addClusterKey(secretBytes); + + gmsEncrypt2.installView(netView, mockMembers[1]); + + // sender encrypts a message, so use receiver's public key + String ch = "Hello world"; + byte[] challenge = ch.getBytes(); + byte[] encryptedChallenge = gmsEncrypt1.encryptData(challenge); + + // receiver decrypts the message using the sender's public key + byte[] decryptBytes = gmsEncrypt2.decryptData(encryptedChallenge); + + // now send a response + String response = "Hello yourself!"; + byte[] responseBytes = response.getBytes(); + byte[] encryptedResponse = gmsEncrypt2.encryptData(responseBytes); + + // receiver decodes the response + byte[] decryptedResponse = gmsEncrypt1.decryptData(encryptedResponse); + + Assert.assertFalse(Arrays.equals(challenge, encryptedChallenge)); + + Assert.assertTrue(Arrays.equals(challenge, decryptBytes)); + + Assert.assertFalse(Arrays.equals(responseBytes, encryptedResponse)); + + Assert.assertTrue(Arrays.equals(responseBytes, decryptedResponse)); + } + + + @Test + public void testDHAlgo() throws Exception { + + DHParameterSpec dhSkipParamSpec; + + System.out.println("Using SKIP Diffie-Hellman parameters"); + dhSkipParamSpec = new DHParameterSpec(skip1024Modulus, skip1024Base); + + // Alice creates her own DH key pair + System.out.println("ALICE: Generate DH keypair ..."); + KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH"); + aliceKpairGen.initialize(dhSkipParamSpec); + KeyPair aliceKpair = aliceKpairGen.generateKeyPair(); + + // Bob creates his own DH key pair + System.out.println("BOB: Generate DH keypair ..."); + KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH"); + bobKpairGen.initialize(dhSkipParamSpec); + KeyPair bobKpair = bobKpairGen.generateKeyPair(); + + // Carol creates her own DH key pair + System.out.println("CAROL: Generate DH keypair ..."); + KeyPairGenerator carolKpairGen = KeyPairGenerator.getInstance("DH"); + carolKpairGen.initialize(dhSkipParamSpec); + KeyPair carolKpair = carolKpairGen.generateKeyPair(); + + + // Alice initialize + System.out.println("ALICE: Initialize ..."); + KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH"); + aliceKeyAgree.init(aliceKpair.getPrivate()); + + // Bob initialize + System.out.println("BOB: Initialize ..."); + KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH"); + bobKeyAgree.init(bobKpair.getPrivate()); + + // Carol initialize + System.out.println("CAROL: Initialize ..."); + KeyAgreement carolKeyAgree = KeyAgreement.getInstance("DH"); + carolKeyAgree.init(carolKpair.getPrivate()); + + + // Alice uses Carol's public key + Key ac = aliceKeyAgree.doPhase(carolKpair.getPublic(), false); + + // Bob uses Alice's public key + Key ba = bobKeyAgree.doPhase(aliceKpair.getPublic(), false); + + // Carol uses Bob's public key + Key cb = carolKeyAgree.doPhase(bobKpair.getPublic(), false); + + + // Alice uses Carol's result from above + aliceKeyAgree.doPhase(cb, true); + + // Bob uses Alice's result from above + bobKeyAgree.doPhase(ac, true); + + // Carol uses Bob's result from above + carolKeyAgree.doPhase(ba, true); + + + // Alice, Bob and Carol compute their secrets + byte[] aliceSharedSecret = aliceKeyAgree.generateSecret(); + System.out.println("Alice secret: " + toHexString(aliceSharedSecret)); + + byte[] bobSharedSecret = bobKeyAgree.generateSecret(); + System.out.println("Bob secret: " + toHexString(bobSharedSecret)); + + byte[] carolSharedSecret = carolKeyAgree.generateSecret(); + System.out.println("Carol secret: " + toHexString(carolSharedSecret)); + + + // Compare Alice and Bob + if (!java.util.Arrays.equals(aliceSharedSecret, bobSharedSecret)) + throw new Exception("Alice and Bob differ"); + System.out.println("Alice and Bob are the same"); + + // Compare Bob and Carol + if (!java.util.Arrays.equals(bobSharedSecret, carolSharedSecret)) + throw new Exception("Bob and Carol differ"); + System.out.println("Bob and Carol are the same"); + } + + @Test + public void testDHAlgo2() throws Exception { + + DHParameterSpec dhSkipParamSpec; + + System.out.println("Using SKIP Diffie-Hellman parameters"); + dhSkipParamSpec = new DHParameterSpec(skip1024Modulus, skip1024Base); + + // Alice creates her own DH key pair + System.out.println("ALICE: Generate DH keypair ..."); + KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH"); + aliceKpairGen.initialize(dhSkipParamSpec); + KeyPair aliceKpair = aliceKpairGen.generateKeyPair(); + + + // Bob creates his own DH key pair + System.out.println("BOB: Generate DH keypair ..."); + KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH"); + bobKpairGen.initialize(dhSkipParamSpec); + KeyPair bobKpair = bobKpairGen.generateKeyPair(); + + + // Alice initialize + System.out.println("ALICE: Initialize ..."); + KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH"); + aliceKeyAgree.init(aliceKpair.getPrivate()); + + // Bob initialize + System.out.println("BOB : Initialize ..."); + KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH"); + bobKeyAgree.init(bobKpair.getPrivate()); + + // Alice uses Carol's public key + aliceKeyAgree.doPhase(bobKpair.getPublic(), true); + + // Bob uses Alice's public key + bobKeyAgree.doPhase(aliceKpair.getPublic(), true); + + // Alice, Bob and Carol compute their secrets + byte[] aliceSharedSecret = aliceKeyAgree.generateSecret(); + System.out.println("Alice secret: " + toHexString(aliceSharedSecret)); + + + byte[] bobSharedSecret = bobKeyAgree.generateSecret(); + System.out.println("Bob secret: " + toHexString(bobSharedSecret)); + + + // Compare Alice and Bob + if (!java.util.Arrays.equals(aliceSharedSecret, bobSharedSecret)) + throw new Exception("Alice and Bob differ"); + System.out.println("Alice and Bob are the same"); + + } + + @Test + public void testDHAlgo3() throws Exception { + + DHParameterSpec dhSkipParamSpec; + + System.out.println("Using SKIP Diffie-Hellman parameters"); + dhSkipParamSpec = new DHParameterSpec(skip1024Modulus, skip1024Base); + + // Alice creates her own DH key pair + System.out.println("ALICE: Generate DH keypair ..."); + KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH"); + aliceKpairGen.initialize(dhSkipParamSpec); + KeyPair aliceKpair = aliceKpairGen.generateKeyPair(); + + + // Bob creates his own DH key pair + System.out.println("BOB: Generate DH keypair ..."); + KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH"); + bobKpairGen.initialize(dhSkipParamSpec); + KeyPair bobKpair = bobKpairGen.generateKeyPair(); + + + // Alice initialize + System.out.println("ALICE: Initialize ..."); + KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH"); + aliceKeyAgree.init(aliceKpair.getPrivate()); + + // Bob initialize + System.out.println("BOB : Initialize ..."); + KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH"); + bobKeyAgree.init(bobKpair.getPrivate()); + + // Alice uses Carol's public key + aliceKeyAgree.doPhase(bobKpair.getPublic(), true); + + // Bob uses Alice's public key + bobKeyAgree.doPhase(aliceKpair.getPublic(), true); + + String dhKalgo = "AES"; + // Alice, Bob and Carol compute their secrets + SecretKey aliceSharedSecret = aliceKeyAgree.generateSecret(dhKalgo); + System.out.println("Alice secret: " + toHexString(aliceSharedSecret.getEncoded())); + + + + SecretKey bobSharedSecret = bobKeyAgree.generateSecret(dhKalgo); + System.out.println("Bob secret: " + toHexString(bobSharedSecret.getEncoded())); + + applyMAC(aliceSharedSecret); + applyMAC(bobSharedSecret); + + // Compare Alice and Bob + if (!java.util.Arrays.equals(aliceSharedSecret.getEncoded(), bobSharedSecret.getEncoded())) + throw new Exception("Alice and Bob differ"); + System.out.println("Alice and Bob are the same"); + } + + private void applyMAC(Key key) throws Exception { + SecretKey key2 = new SecretKey() { + + @Override + public String getFormat() { + // TODO Auto-generated method stub + return key.getFormat(); + } + + @Override + public byte[] getEncoded() { + // TODO Auto-generated method stub + String hitesh = "This is from Hitesh"; + byte[] secbytes = hitesh.getBytes(); + byte[] origsecret = key.getEncoded(); + byte[] ns = new byte[origsecret.length + secbytes.length]; + System.arraycopy(origsecret, 0, ns, 0, origsecret.length); + System.arraycopy(secbytes, 0, ns, origsecret.length, secbytes.length); + return ns; + } + + @Override + public String getAlgorithm() { + // TODO Auto-generated method stub + return key.getAlgorithm(); + } + }; + // Generate secret key for HMAC-MD5 + //KeyGenerator kg = KeyGenerator.getInstance("HmacMD5"); + //SecretKey sk = kg.generateKey(); + + // Get instance of Mac object implementing HMAC-MD5, and + // initialize it with the above secret key + + System.out.println("Key2 secret " + toHexString(key2.getEncoded())); + + Mac mac = Mac.getInstance("HmacMD5"); + mac.init(key2); + byte[] result = mac.doFinal("Hi There".getBytes()); + + + System.out.println("Message Authentication code length: " + mac.getMacLength()); + System.out.println("Message Authentication code : " + toHexString(result)); + + verifyMacBody(mac, result); + } + + private byte[] verifyMacBody(Mac hmac, byte[] encryptedAndMac) throws Exception { + byte[] encrypted = new byte[encryptedAndMac.length - hmac.getMacLength()]; + System.arraycopy(encryptedAndMac, 0, encrypted, 0, encrypted.length); + + byte[] remoteMac = new byte[hmac.getMacLength()]; + System.arraycopy(encryptedAndMac, encryptedAndMac.length - remoteMac.length, remoteMac, 0, remoteMac.length); + + byte[] localMac = hmac.doFinal(encrypted); + + System.out.println("Message Authentication code remoteMac : " + toHexString(remoteMac)); + System.out.println("Message Authentication code localMac : " + toHexString(localMac)); + if (!Arrays.equals(remoteMac, localMac)) + throw new Exception("MAC doesen't match."); + + return encrypted; + } + // The 1024 bit Diffie-Hellman modulus values used by SKIP + private static final byte skip1024ModulusBytes[] = { + (byte)0xF4, (byte)0x88, (byte)0xFD, (byte)0x58, + (byte)0x4E, (byte)0x49, (byte)0xDB, (byte)0xCD, + (byte)0x20, (byte)0xB4, (byte)0x9D, (byte)0xE4, + (byte)0x91, (byte)0x07, (byte)0x36, (byte)0x6B, + (byte)0x33, (byte)0x6C, (byte)0x38, (byte)0x0D, + (byte)0x45, (byte)0x1D, (byte)0x0F, (byte)0x7C, + (byte)0x88, (byte)0xB3, (byte)0x1C, (byte)0x7C, + (byte)0x5B, (byte)0x2D, (byte)0x8E, (byte)0xF6, + (byte)0xF3, (byte)0xC9, (byte)0x23, (byte)0xC0, + (byte)0x43, (byte)0xF0, (byte)0xA5, (byte)0x5B, + (byte)0x18, (byte)0x8D, (byte)0x8E, (byte)0xBB, + (byte)0x55, (byte)0x8C, (byte)0xB8, (byte)0x5D, + (byte)0x38, (byte)0xD3, (byte)0x34, (byte)0xFD, + (byte)0x7C, (byte)0x17, (byte)0x57, (byte)0x43, + (byte)0xA3, (byte)0x1D, (byte)0x18, (byte)0x6C, + (byte)0xDE, (byte)0x33, (byte)0x21, (byte)0x2C, + (byte)0xB5, (byte)0x2A, (byte)0xFF, (byte)0x3C, + (byte)0xE1, (byte)0xB1, (byte)0x29, (byte)0x40, + (byte)0x18, (byte)0x11, (byte)0x8D, (byte)0x7C, + (byte)0x84, (byte)0xA7, (byte)0x0A, (byte)0x72, + (byte)0xD6, (byte)0x86, (byte)0xC4, (byte)0x03, + (byte)0x19, (byte)0xC8, (byte)0x07, (byte)0x29, + (byte)0x7A, (byte)0xCA, (byte)0x95, (byte)0x0C, + (byte)0xD9, (byte)0x96, (byte)0x9F, (byte)0xAB, + (byte)0xD0, (byte)0x0A, (byte)0x50, (byte)0x9B, + (byte)0x02, (byte)0x46, (byte)0xD3, (byte)0x08, + (byte)0x3D, (byte)0x66, (byte)0xA4, (byte)0x5D, + (byte)0x41, (byte)0x9F, (byte)0x9C, (byte)0x7C, + (byte)0xBD, (byte)0x89, (byte)0x4B, (byte)0x22, + (byte)0x19, (byte)0x26, (byte)0xBA, (byte)0xAB, + (byte)0xA2, (byte)0x5E, (byte)0xC3, (byte)0x55, + (byte)0xE9, (byte)0x2F, (byte)0x78, (byte)0xC7 + }; + + + + // The SKIP 1024 bit modulus + private static final BigInteger skip1024Modulus + = new BigInteger(1, skip1024ModulusBytes); + + // The base used with the SKIP 1024 bit modulus + private static final BigInteger skip1024Base = BigInteger.valueOf(2); + + /* + * Converts a byte to hex digit and writes to the supplied buffer + */ + private void byte2hex(byte b, StringBuffer buf) { + char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + int high = ((b & 0xf0) >> 4); + int low = (b & 0x0f); + buf.append(hexChars[high]); + buf.append(hexChars[low]); + } + + /* + * Converts a byte array to hex string + */ + private String toHexString(byte[] block) { + StringBuffer buf = new StringBuffer(); + + int len = block.length; + + for (int i = 0; i < len; i++) { + byte2hex(block[i], buf); + if (i < len-1) { + buf.append(":"); + } + } + return buf.toString(); + } }
