Skip to content

Commit

Permalink
[ADD] metadata sent with signature
Browse files Browse the repository at this point in the history
  • Loading branch information
ostumpf committed Jan 14, 2015
1 parent 09d516e commit 1339dd2
Show file tree
Hide file tree
Showing 13 changed files with 242 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,9 @@ public void registerReplicaListener(ReplicaListener listener) {
* of the replica being registered
*/
public Collection<KnowledgeManager> createReplica(String id) {
if (locals.containsKey(id)) {
if (hasLocal(id)) {
throw new RuntimeException("Cannot create replica for a local knowledge manager (id: " + id + ").");
} else if (replicas.containsKey(id)) {
} else if (hasReplica(id)) {
return replicas.get(id).values();
} else {
replicas.put(id, new HashMap<>());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,14 @@ protected List<KnowledgeData> prepareLocalKnowledgeData(KnowledgeManager km)
throws KnowledgeNotFoundException {
// extract local knowledge
ValueSet basicValueSet = getNonLocalKnowledge(km.get(emptyPath), km);
KnowledgeMetaData metaData = new KnowledgeMetaData(km.getId(), localVersion, host, timeProvider.getCurrentMilliseconds(), 1);
KnowledgeMetaData metaData = createMetaData(km);
return knowledgeEncryptor.encryptValueSet(basicValueSet, km, metaData);
}

protected KnowledgeMetaData createMetaData(KnowledgeManager km) {
return new KnowledgeMetaData(km.getId(), localVersion, host, timeProvider.getCurrentMilliseconds(), 1);
}

protected ValueSet getNonLocalKnowledge(ValueSet toFilter, KnowledgeManager km) {
ValueSet result = new ValueSet();
for (KnowledgePath kp: toFilter.getKnowledgePaths()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ public class KnowledgeMetaData implements Serializable {
public byte[] encryptedKey;
public String encryptedKeyAlgorithm;
public KnowledgeSecurityAnnotation targetRole;
public byte[] signature;

public KnowledgeMetaData(String componentId, long versionId, String sender, long createdAt, int hopCount) {
this(componentId, versionId, sender, createdAt, hopCount, null, null, null);
this(componentId, versionId, sender, createdAt, hopCount, null, null, null, null);
}

public KnowledgeMetaData(String componentId, long versionId, String sender, long createdAt, int hopCount,
byte[] encryptedKey, String encryptedKeyAlgorithm, KnowledgeSecurityAnnotation targetRole) {
byte[] encryptedKey, String encryptedKeyAlgorithm, KnowledgeSecurityAnnotation targetRole, byte[] signature) {
super();
this.componentId = componentId;
this.versionId = versionId;
Expand All @@ -35,10 +36,11 @@ public KnowledgeMetaData(String componentId, long versionId, String sender, long
this.encryptedKey = encryptedKey;
this.encryptedKeyAlgorithm = encryptedKeyAlgorithm;
this.targetRole = targetRole;
this.signature = signature;
}

public KnowledgeMetaData clone() {
return new KnowledgeMetaData(componentId, versionId, sender, createdAt, hopCount, encryptedKey, encryptedKeyAlgorithm, targetRole);
return new KnowledgeMetaData(componentId, versionId, sender, createdAt, hopCount, encryptedKey, encryptedKeyAlgorithm, targetRole, signature);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,18 @@ public List<KnowledgeData> encryptValueSet(ValueSet basicValueSet, KnowledgeMana
}

private Object accessValue(SealedObject sealedObject, KnowledgeManager replica, KnowledgeMetaData metaData) throws KnowledgeNotFoundException {
// verify signature on metadata
boolean verificationSucceeded = false;
try {
verificationSucceeded = securityHelper.verify(metaData.signature, keyManager.getIntegrityPublicKey(), metaData.componentId, metaData.versionId, metaData.targetRole);
} catch (InvalidKeyException | CertificateEncodingException
| SignatureException | NoSuchAlgorithmException
| KeyStoreException | SecurityException | IllegalStateException e1) { }

if (!verificationSucceeded) {
throw new SecurityException();
}

Object value = null;
boolean encryptionSucceeded = false;

Expand All @@ -131,9 +143,7 @@ private Object accessValue(SealedObject sealedObject, KnowledgeManager replica,
| IllegalBlockSizeException | BadPaddingException
| NoSuchAlgorithmException | NoSuchPaddingException
| IOException | ShortBufferException | CertificateEncodingException | KeyStoreException | SecurityException
| SignatureException | IllegalStateException e) {

}
| SignatureException | IllegalStateException e) { }
}

if (!encryptionSucceeded) {
Expand Down Expand Up @@ -167,6 +177,7 @@ private void sealKnowledge(KnowledgeManager km, ValueSet valueSet, KnowledgeSecu
metaData.encryptedKey = encryptedKey;
metaData.encryptedKeyAlgorithm = symmetricKey.getAlgorithm();
metaData.targetRole = new KnowledgeSecurityAnnotation(roleName, arguments);
metaData.signature = securityHelper.sign(keyManager.getIntegrityPrivateKey(), metaData.componentId, metaData.versionId, metaData.targetRole);

valueSet.setValue(kp, encryptedKnowledge);
} catch (IllegalBlockSizeException | IOException | InvalidKeyException | BadPaddingException | NoSuchAlgorithmException | NoSuchPaddingException
Expand Down
48 changes: 48 additions & 0 deletions jdeeco-core/src/cz/cuni/mff/d3s/deeco/security/SecurityHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.SignatureException;
import java.util.Arrays;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
Expand All @@ -24,6 +32,7 @@
public class SecurityHelper {

private final int BLOCK_SIZE = 16;
private static SecureRandom secureRandom = new SecureRandom();

static {
Security.addProvider(new BouncyCastleProvider());
Expand Down Expand Up @@ -90,7 +99,46 @@ public Key generateKey() throws NoSuchAlgorithmException {
public Key generateKey(String algorithm, int keySize) throws NoSuchAlgorithmException {
KeyGenerator generator = KeyGenerator.getInstance(algorithm);
generator.init(keySize);
generator.init(secureRandom);
return generator.generateKey();
}

public KeyPair generateKeyPair() throws NoSuchAlgorithmException {
return generateKeyPair("RSA", 1024);
}

public KeyPair generateKeyPair(String algorithm, int keySize) throws NoSuchAlgorithmException {
KeyPairGenerator generator = KeyPairGenerator.getInstance(algorithm);
generator.initialize(keySize, secureRandom);
return generator.generateKeyPair();
}

public byte[] sign(PrivateKey key, Object... data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, SignatureException {
if (data == null || data.length == 0) {
throw new IllegalArgumentException("No data to sign.");
}

int hash = Arrays.hashCode(data);
byte[] hashArray = new byte[] { (byte)(hash >>> 24), (byte)(hash >>> 16), (byte)(hash >>> 8), (byte)hash};

Signature signature = Signature.getInstance(key.getAlgorithm());
signature.initSign(key);
signature.update(hashArray);
return signature.sign();
}

public boolean verify(byte[] signatureHash, PublicKey key, Object... data) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
if (data == null || data.length == 0) {
throw new IllegalArgumentException("No data to verify.");
}

int hash = Arrays.hashCode(data);
byte[] hashArray = new byte[] { (byte)(hash >>> 24), (byte)(hash >>> 16), (byte)(hash >>> 8), (byte)hash};

Signature signature = Signature.getInstance(key.getAlgorithm());
signature.initVerify(key);
signature.update(hashArray);
return signature.verify(signatureHash);
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package cz.cuni.mff.d3s.deeco.security;

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.util.Map;
Expand All @@ -13,7 +14,11 @@
*/
public interface SecurityKeyManager {

Key getPublicKeyFor(String roleName, Map<String, Object> arguments) throws KeyStoreException, NoSuchAlgorithmException, InvalidKeyException, CertificateEncodingException, SecurityException, SignatureException, IllegalStateException;
PublicKey getPublicKeyFor(String roleName, Map<String, Object> arguments) throws KeyStoreException, NoSuchAlgorithmException, InvalidKeyException, CertificateEncodingException, SecurityException, SignatureException, IllegalStateException;

Key getPrivateKeyFor(String roleName, Map<String, Object> arguments) throws InvalidKeyException, CertificateEncodingException, KeyStoreException, NoSuchAlgorithmException, SecurityException, SignatureException, IllegalStateException;
PrivateKey getPrivateKeyFor(String roleName, Map<String, Object> arguments) throws InvalidKeyException, CertificateEncodingException, KeyStoreException, NoSuchAlgorithmException, SecurityException, SignatureException, IllegalStateException;

PrivateKey getIntegrityPrivateKey() throws InvalidKeyException, CertificateEncodingException, NoSuchAlgorithmException, KeyStoreException, SecurityException, SignatureException, IllegalStateException;

PublicKey getIntegrityPublicKey() throws InvalidKeyException, CertificateEncodingException, KeyStoreException, NoSuchAlgorithmException, SecurityException, SignatureException, IllegalStateException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.SignatureException;
import java.security.cert.Certificate;
Expand All @@ -32,11 +32,15 @@ public class SecurityKeyManagerImpl implements SecurityKeyManager {
private KeyStore keyStore;
private Map<Integer, PrivateKey> privateKeys;
private SecureRandom secureRandom;
private SecurityHelper securityHelper;

private final Integer INTEGRITY_KEY = 95423814;

public SecurityKeyManagerImpl() throws KeyStoreException {
this.keyStore = KeyStore.getInstance("JKS");
this.secureRandom = new SecureRandom();
this.privateKeys = new HashMap<>();
this.securityHelper = new SecurityHelper();

try {
initialize();
Expand All @@ -51,7 +55,7 @@ private void initialize() throws NoSuchAlgorithmException, CertificateException,
}

@Override
public Key getPublicKeyFor(String roleName, Map<String, Object> arguments) throws KeyStoreException, NoSuchAlgorithmException, InvalidKeyException, CertificateEncodingException, SecurityException, SignatureException, IllegalStateException {
public PublicKey getPublicKeyFor(String roleName, Map<String, Object> arguments) throws KeyStoreException, NoSuchAlgorithmException, InvalidKeyException, CertificateEncodingException, SecurityException, SignatureException, IllegalStateException {
Integer roleKey = getRoleKey(roleName, arguments);

if (!keyStore.containsAlias(roleKey.toString())) {
Expand All @@ -61,17 +65,8 @@ public Key getPublicKeyFor(String roleName, Map<String, Object> arguments) throw
return keyStore.getCertificate(roleKey.toString()).getPublicKey();
}

private void generateKeyPairFor(Integer roleKey) throws NoSuchAlgorithmException, InvalidKeyException, CertificateEncodingException, KeyStoreException, SecurityException, SignatureException, IllegalStateException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024, secureRandom);
KeyPair keypair = keyGen.generateKeyPair();

keyStore.setCertificateEntry(roleKey.toString(), generateCertificate(roleKey, keypair));
privateKeys.put(roleKey, keypair.getPrivate());
}

@Override
public Key getPrivateKeyFor(String roleName, Map<String, Object> arguments) throws InvalidKeyException, CertificateEncodingException, KeyStoreException, NoSuchAlgorithmException, SecurityException, SignatureException, IllegalStateException {
public PrivateKey getPrivateKeyFor(String roleName, Map<String, Object> arguments) throws InvalidKeyException, CertificateEncodingException, KeyStoreException, NoSuchAlgorithmException, SecurityException, SignatureException, IllegalStateException {
Integer roleKey = getRoleKey(roleName, arguments);

if (!keyStore.containsAlias(roleKey.toString())) {
Expand All @@ -81,6 +76,31 @@ public Key getPrivateKeyFor(String roleName, Map<String, Object> arguments) thro
return privateKeys.get(roleKey);
}

@Override
public PrivateKey getIntegrityPrivateKey() throws InvalidKeyException, CertificateEncodingException, NoSuchAlgorithmException, KeyStoreException, SecurityException, SignatureException, IllegalStateException {
if (!keyStore.containsAlias(INTEGRITY_KEY.toString())) {
generateKeyPairFor(INTEGRITY_KEY);
}

return privateKeys.get(INTEGRITY_KEY);
}

@Override
public PublicKey getIntegrityPublicKey() throws InvalidKeyException, CertificateEncodingException, KeyStoreException, NoSuchAlgorithmException, SecurityException, SignatureException, IllegalStateException {
if (!keyStore.containsAlias(INTEGRITY_KEY.toString())) {
generateKeyPairFor(INTEGRITY_KEY);
}

return keyStore.getCertificate(INTEGRITY_KEY.toString()).getPublicKey();
}

private void generateKeyPairFor(Integer roleKey) throws NoSuchAlgorithmException, InvalidKeyException, CertificateEncodingException, KeyStoreException, SecurityException, SignatureException, IllegalStateException {
KeyPair keypair = securityHelper.generateKeyPair();

keyStore.setCertificateEntry(roleKey.toString(), generateCertificate(roleKey, keypair));
privateKeys.put(roleKey, keypair.getPrivate());
}

@SuppressWarnings("deprecation")
private Certificate generateCertificate(Integer roleKey, KeyPair keypair) throws NoSuchAlgorithmException, InvalidKeyException, SecurityException, SignatureException, CertificateEncodingException, IllegalStateException {
X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public void receiveKnowledge_OldKnowledgeTest2() {
// given knowledge of various roles is received
List<KnowledgeData> data = new LinkedList<>();
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 456, 1)));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 122, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"))));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 122, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"), null)));

// when receiveKnowledge() is called
runtimeModel.knowledgeDataManager.receiveKnowledge(data);
Expand All @@ -141,7 +141,7 @@ public void receiveKnowledge_OldKnowledgeTest2() {
public void receiveKnowledge_OldKnowledgeTest3() {
// given knowledge of various roles is received
List<KnowledgeData> data = new LinkedList<>();
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 456, 1, null, null, createKnowledgeAnnotation("role"))));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 456, 1, null, null, createKnowledgeAnnotation("role"), null)));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 122, "4.56", 450, 1)));

// when receiveKnowledge() is called
Expand All @@ -156,8 +156,8 @@ public void receiveKnowledge_OldKnowledgeTest4() {
// given knowledge of various roles is received
List<KnowledgeData> data = new LinkedList<>();
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 456, 1)));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 122, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"))));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"))));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 122, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"), null)));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"), null)));

// when receiveKnowledge() is called
runtimeModel.knowledgeDataManager.receiveKnowledge(data);
Expand All @@ -171,7 +171,7 @@ public void receiveKnowledge_OldKnowledgeTest5() {
// given knowledge of various roles is received
List<KnowledgeData> data = new LinkedList<>();
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 456, 1)));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"))));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"), null)));

// when receiveKnowledge() is called
runtimeModel.knowledgeDataManager.receiveKnowledge(data);
Expand All @@ -186,9 +186,9 @@ public void receiveKnowledge_OldKnowledgeTest6() {
List<KnowledgeData> data = new LinkedList<>();
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 456, 1)));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 122, "4.56", 450, 1)));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"))));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 122, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"))));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 125, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"))));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 123, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"), null)));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 122, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"), null)));
data.add(new KnowledgeData(new ValueSet(), new KnowledgeMetaData("V_remote", 125, "4.56", 450, 1, null, null, createKnowledgeAnnotation("role"), null)));

// when receiveKnowledge() is called
runtimeModel.knowledgeDataManager.receiveKnowledge(data);
Expand Down
Loading

0 comments on commit 1339dd2

Please sign in to comment.