diff --git a/bootstrap/src/main/java/io/bitsquare/p2p/seed/SeedNodeMain.java b/bootstrap/src/main/java/io/bitsquare/p2p/seed/SeedNodeMain.java
index 8d722278ea..68feef2666 100644
--- a/bootstrap/src/main/java/io/bitsquare/p2p/seed/SeedNodeMain.java
+++ b/bootstrap/src/main/java/io/bitsquare/p2p/seed/SeedNodeMain.java
@@ -1,6 +1,9 @@
package io.bitsquare.p2p.seed;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
import java.security.NoSuchAlgorithmException;
+import java.security.Security;
public class SeedNodeMain {
@@ -8,6 +11,8 @@ public class SeedNodeMain {
// eg. 4444 true localhost:7777 localhost:8888
// To stop enter: q
public static void main(String[] args) throws NoSuchAlgorithmException {
+ Security.addProvider(new BouncyCastleProvider());
+
SeedNode seedNode = new SeedNode();
seedNode.processArgs(args);
seedNode.createAndStartP2PService();
diff --git a/common/src/main/java/io/bitsquare/common/crypto/CryptoUtil.java b/common/src/main/java/io/bitsquare/common/crypto/CryptoUtil.java
deleted file mode 100644
index 2f36198076..0000000000
--- a/common/src/main/java/io/bitsquare/common/crypto/CryptoUtil.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * This file is part of Bitsquare.
- *
- * Bitsquare is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or (at
- * your option) any later version.
- *
- * Bitsquare is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with Bitsquare. If not, see .
- */
-
-package io.bitsquare.common.crypto;
-
-import io.bitsquare.common.util.Utilities;
-import org.bitcoinj.core.Sha256Hash;
-import org.bitcoinj.core.Utils;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Base64;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.nio.ByteBuffer;
-import java.security.*;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.X509EncodedKeySpec;
-
-public class CryptoUtil {
- private static final Logger log = LoggerFactory.getLogger(CryptoUtil.class);
- public static final String STORAGE_SIGN_KEY_ALGO = "DSA";
- public static final String MSG_SIGN_KEY_ALGO = "DSA";
- public static final String MSG_ENCR_KEY_ALGO = "RSA";
-
- public static final String SYM_ENCR_KEY_ALGO = "AES";
- public static final String SYM_CIPHER = "AES";
- public static final String ASYM_CIPHER = "RSA"; //RSA/ECB/PKCS1Padding
- public static final String MSG_SIGN_ALGO = "SHA1withDSA";
-
-
- public static KeyPair generateStorageSignatureKeyPair() throws NoSuchAlgorithmException {
- long ts = System.currentTimeMillis();
- final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(STORAGE_SIGN_KEY_ALGO);
- keyPairGenerator.initialize(1024);
- KeyPair keyPair = keyPairGenerator.genKeyPair();
- log.trace("Generate storageSignatureKeyPair needed {} ms", System.currentTimeMillis() - ts);
- return keyPair;
- }
-
- public static KeyPair generateMsgSignatureKeyPair() throws NoSuchAlgorithmException {
- long ts = System.currentTimeMillis();
- final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(MSG_SIGN_KEY_ALGO);
- keyPairGenerator.initialize(1024);
- KeyPair keyPair = keyPairGenerator.genKeyPair();
- log.trace("Generate msgSignatureKeyPair needed {} ms", System.currentTimeMillis() - ts);
- return keyPair;
- }
-
- public static KeyPair generateMsgEncryptionKeyPair() throws NoSuchAlgorithmException {
- long ts = System.currentTimeMillis();
- KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(MSG_ENCR_KEY_ALGO);
- keyPairGenerator.initialize(2048);
- KeyPair keyPair = keyPairGenerator.genKeyPair();
- log.trace("Generate msgEncryptionKeyPair needed {} ms", System.currentTimeMillis() - ts);
- return keyPair;
- }
-
- static {
- Security.addProvider(new BouncyCastleProvider());
- }
-
- public static String signMessage(PrivateKey privateKey, String message)
- throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
- Signature sig = Signature.getInstance(MSG_SIGN_ALGO);
- sig.initSign(privateKey);
- sig.update(message.getBytes());
- return Base64.toBase64String(sig.sign());
- }
-
- public static boolean verifyMessage(PublicKey publicKey, String message, String signature)
- throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
- Signature sig = Signature.getInstance(MSG_SIGN_ALGO);
- sig.initVerify(publicKey);
- sig.update(message.getBytes());
- return sig.verify(Base64.decode(signature));
- }
-
- public static byte[] signStorageData(PrivateKey privateKey, byte[] data)
- throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
- Signature sig = Signature.getInstance(MSG_SIGN_ALGO);
- sig.initSign(privateKey);
- sig.update(data);
- return sig.sign();
- }
-
- public static boolean verifyStorageData(PublicKey publicKey, byte[] data, byte[] signature)
- throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
- Signature sig = Signature.getInstance(MSG_SIGN_ALGO);
- sig.initVerify(publicKey);
- sig.update(data);
- return sig.verify(signature);
- }
-
- public static byte[] getHash(Integer data) {
- return Sha256Hash.hash(ByteBuffer.allocate(4).putInt(data).array());
- }
-
- public static byte[] getHash(Object data) {
- return Sha256Hash.hash(Utilities.objectToByteArray(data));
- }
-
- public static byte[] getHash(String message) {
- return Sha256Hash.hash(Utils.formatMessageForSigning(message));
- }
-
- public static String getHashAsHex(String text) {
- return Utils.HEX.encode(Sha256Hash.hash(Utils.formatMessageForSigning(text)));
- }
-
- public static String pubKeyToString(PublicKey publicKey) {
- final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
- return java.util.Base64.getEncoder().encodeToString(x509EncodedKeySpec.getEncoded());
- }
-
- // TODO just temp for arbitrator
- public static PublicKey decodeDSAPubKeyHex(String pubKeyHex) throws NoSuchAlgorithmException, InvalidKeySpecException {
- X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(Utils.HEX.decode(pubKeyHex));
- KeyFactory keyFactory = KeyFactory.getInstance("DSA");
- return keyFactory.generatePublic(pubKeySpec);
- }
-}
-
diff --git a/network/src/main/java/io/bitsquare/p2p/messaging/SealedAndSignedMessage.java b/common/src/main/java/io/bitsquare/common/crypto/DecryptedPayloadWithPubKey.java
similarity index 50%
rename from network/src/main/java/io/bitsquare/p2p/messaging/SealedAndSignedMessage.java
rename to common/src/main/java/io/bitsquare/common/crypto/DecryptedPayloadWithPubKey.java
index c0d3be665a..15b4e3df1d 100644
--- a/network/src/main/java/io/bitsquare/p2p/messaging/SealedAndSignedMessage.java
+++ b/common/src/main/java/io/bitsquare/common/crypto/DecryptedPayloadWithPubKey.java
@@ -15,54 +15,28 @@
* along with Bitsquare. If not, see .
*/
-package io.bitsquare.p2p.messaging;
+package io.bitsquare.common.crypto;
import io.bitsquare.app.Version;
-import io.bitsquare.common.util.Utilities;
-import javax.crypto.SealedObject;
+import java.io.Serializable;
import java.security.PublicKey;
-import java.util.Arrays;
/**
* Packs the encrypted symmetric secretKey and the encrypted and signed message into one object.
* SecretKey is encrypted with asymmetric pubKey of peer. Signed message is encrypted with secretKey.
* Using that hybrid encryption model we are not restricted by data size and performance as symmetric encryption is very fast.
*/
-public final class SealedAndSignedMessage implements MailMessage {
+public final class DecryptedPayloadWithPubKey implements Serializable {
// That object is sent over the wire, so we need to take care of version compatibility.
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
- public final SealedObject sealedSecretKey;
- public final SealedObject sealedMessage;
- public final PublicKey signaturePubKey;
+ public final Serializable payload;
+ public final PublicKey sigPublicKey;
- public SealedAndSignedMessage(SealedObject sealedSecretKey, SealedObject sealedMessage, PublicKey signaturePubKey) {
- this.sealedSecretKey = sealedSecretKey;
- this.sealedMessage = sealedMessage;
- this.signaturePubKey = signaturePubKey;
+ public DecryptedPayloadWithPubKey(Serializable payload, PublicKey sigPublicKey) {
+ this.payload = payload;
+ this.sigPublicKey = sigPublicKey;
}
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof SealedAndSignedMessage)) return false;
-
- SealedAndSignedMessage that = (SealedAndSignedMessage) o;
-
- return Arrays.equals(Utilities.objectToByteArray(this), Utilities.objectToByteArray(that));
- }
-
- @Override
- public int hashCode() {
- byte[] bytes = Utilities.objectToByteArray(this);
- return bytes != null ? Arrays.hashCode(bytes) : 0;
- }
-
- @Override
- public String toString() {
- return "SealedAndSignedMessage{" +
- "hashCode=" + hashCode() +
- '}';
- }
}
diff --git a/common/src/main/java/io/bitsquare/common/crypto/Encryption.java b/common/src/main/java/io/bitsquare/common/crypto/Encryption.java
new file mode 100644
index 0000000000..cee57d2fc3
--- /dev/null
+++ b/common/src/main/java/io/bitsquare/common/crypto/Encryption.java
@@ -0,0 +1,276 @@
+/*
+ * This file is part of Bitsquare.
+ *
+ * Bitsquare is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * Bitsquare is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Bitsquare. If not, see .
+ */
+
+package io.bitsquare.common.crypto;
+
+import io.bitsquare.common.util.Utilities;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.spongycastle.util.encoders.Hex;
+
+import javax.crypto.*;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.security.*;
+import java.util.Arrays;
+
+public class Encryption {
+ private static final Logger log = LoggerFactory.getLogger(Encryption.class);
+
+ public static final String ENCR_KEY_ALGO = "RSA";
+ public static final String SYM_KEY_ALGO = "AES";
+ public static final String SYM_CIPHER = "AES"; // java.security.NoSuchAlgorithmException: AES/ECB/PKCS5Padding KeyGenerator not available
+ public static final String ASYM_CIPHER = "RSA"; // TODO test with RSA/ECB/PKCS1Padding
+ public static final String HMAC = "HmacSHA256";
+
+ public static KeyPair generateEncryptionKeyPair() {
+ long ts = System.currentTimeMillis();
+ try {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ENCR_KEY_ALGO);
+ keyPairGenerator.initialize(2048);
+ KeyPair keyPair = keyPairGenerator.genKeyPair();
+ log.trace("Generate msgEncryptionKeyPair needed {} ms", System.currentTimeMillis() - ts);
+ return keyPair;
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ throw new RuntimeException("Could not create key.");
+ }
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Symmetric
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ public static byte[] encrypt(byte[] payload, SecretKey secretKey) throws CryptoException {
+ try {
+ Cipher cipher = Cipher.getInstance(SYM_CIPHER);
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+ return cipher.doFinal(payload);
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
+ | BadPaddingException | IllegalBlockSizeException e) {
+ e.printStackTrace();
+ throw new CryptoException(e);
+ }
+ }
+
+ public static byte[] decrypt(byte[] encryptedPayload, SecretKey secretKey) throws CryptoException {
+ try {
+ Cipher cipher = Cipher.getInstance(SYM_CIPHER);
+ cipher.init(Cipher.DECRYPT_MODE, secretKey);
+ return cipher.doFinal(encryptedPayload);
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
+ | BadPaddingException | IllegalBlockSizeException e) {
+ e.printStackTrace();
+ throw new CryptoException(e);
+ }
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Hmac
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ private static byte[] getPayloadWithHmac(byte[] payload, SecretKey secretKey) {
+ byte[] payloadWithHmac;
+ try {
+
+ ByteArrayOutputStream outputStream = null;
+ try {
+ byte[] hmac = getHmac(payload, secretKey);
+ outputStream = new ByteArrayOutputStream();
+ outputStream.write(payload);
+ outputStream.write(hmac);
+ outputStream.flush();
+ payloadWithHmac = outputStream.toByteArray().clone();
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new RuntimeException("Could not create hmac");
+ } finally {
+ if (outputStream != null) {
+ try {
+ outputStream.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+ e.printStackTrace();
+ throw new RuntimeException("Could not create hmac");
+ }
+ return payloadWithHmac;
+ }
+
+
+ private static boolean verifyHmac(byte[] message, byte[] hmac, SecretKey secretKey) throws CryptoException {
+ try {
+ byte[] hmacTest = getHmac(message, secretKey);
+ return Arrays.equals(hmacTest, hmac);
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+ e.printStackTrace();
+ throw new RuntimeException("Could not create cipher");
+ }
+ }
+
+ private static byte[] getHmac(byte[] payload, SecretKey secretKey) throws NoSuchAlgorithmException, InvalidKeyException {
+ Mac mac = Mac.getInstance(HMAC);
+ mac.init(secretKey);
+ return mac.doFinal(payload);
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Symmetric with Hmac
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ public static byte[] encryptPayloadWithHmac(Serializable object, SecretKey secretKey) throws CryptoException {
+ return encryptPayloadWithHmac(Utilities.serialize(object), secretKey);
+ }
+
+ public static byte[] encryptPayloadWithHmac(byte[] payload, SecretKey secretKey) throws CryptoException {
+ return encrypt(getPayloadWithHmac(payload, secretKey), secretKey);
+ }
+
+ public static byte[] decryptPayloadWithHmac(byte[] encryptedPayloadWithHmac, SecretKey secretKey) throws CryptoException {
+ byte[] payloadWithHmac = decrypt(encryptedPayloadWithHmac, secretKey);
+ String payloadWithHmacAsHex = Hex.toHexString(payloadWithHmac);
+ // first part is raw message
+ int length = payloadWithHmacAsHex.length();
+ int sep = length - 64;
+ String payloadAsHex = payloadWithHmacAsHex.substring(0, sep);
+ // last 64 bytes is hmac
+ String hmacAsHex = payloadWithHmacAsHex.substring(sep, length);
+ if (verifyHmac(Hex.decode(payloadAsHex), Hex.decode(hmacAsHex), secretKey)) {
+ return Hex.decode(payloadAsHex);
+ } else {
+ throw new CryptoException("Hmac does not match.");
+ }
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Asymmetric
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ public static byte[] encrypt(byte[] payload, PublicKey publicKey) throws CryptoException {
+ try {
+ Cipher cipher = Cipher.getInstance(ASYM_CIPHER);
+ cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+ return cipher.doFinal(payload);
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
+ | BadPaddingException | IllegalBlockSizeException e) {
+ e.printStackTrace();
+ throw new CryptoException("Couldn't encrypt payload");
+ }
+ }
+
+ public static byte[] decrypt(byte[] encryptedPayload, PrivateKey privateKey) throws CryptoException {
+ try {
+ Cipher cipher = Cipher.getInstance(ASYM_CIPHER);
+ cipher.init(Cipher.DECRYPT_MODE, privateKey);
+ return cipher.doFinal(encryptedPayload);
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
+ | BadPaddingException | IllegalBlockSizeException e) {
+ e.printStackTrace();
+ throw new CryptoException(e);
+ }
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Hybrid with signature of asymmetric key
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * @param payload The data to encrypt.
+ * @param sigPrivateKey The private key for signing.
+ * @param sigPublicKey The public key used for signing.
+ * @param encryptionPublicKey The public key used for encryption.
+ * @return A SealedAndSigned object.
+ * @throws CryptoException
+ */
+ public static SealedAndSigned encryptHybridWithSignature(Serializable payload, PrivateKey sigPrivateKey,
+ PublicKey sigPublicKey, PublicKey encryptionPublicKey)
+ throws CryptoException {
+ // Create a symmetric key
+ SecretKey secretKey = generateSecretKey();
+
+ // Encrypt secretKey with receivers publicKey
+ byte[] encryptedSecretKey = encrypt(secretKey.getEncoded(), encryptionPublicKey);
+
+ // Encrypt with sym key and add hmac
+ byte[] encryptedPayloadWithHmac = encryptPayloadWithHmac(payload, secretKey);
+
+ // sign hash of encryptedPayloadWithHmac
+ byte[] hash = Hash.getHash(encryptedPayloadWithHmac);
+ try {
+ byte[] signature = Sig.sign(sigPrivateKey, hash);
+
+ // Pack all together
+ return new SealedAndSigned(encryptedSecretKey, encryptedPayloadWithHmac, signature, sigPublicKey);
+ } catch (SignatureException | NoSuchAlgorithmException | InvalidKeyException e) {
+ e.printStackTrace();
+ throw new CryptoException(e);
+ }
+
+
+ }
+
+ /**
+ * @param sealedAndSigned The sealedAndSigned object.
+ * @param privateKey The private key for decryption
+ * @return A DecryptedPayloadWithPubKey object.
+ * @throws CryptoException
+ */
+ public static DecryptedPayloadWithPubKey decryptHybridWithSignature(SealedAndSigned sealedAndSigned, PrivateKey privateKey) throws CryptoException {
+ SecretKey secretKey = getSecretKeyFromBytes(decrypt(sealedAndSigned.encryptedSecretKey, privateKey));
+ try {
+ boolean isValid = Sig.verify(sealedAndSigned.sigPublicKey,
+ Hash.getHash(sealedAndSigned.encryptedPayloadWithHmac),
+ sealedAndSigned.signature);
+ if (!isValid)
+ throw new CryptoException("Signature verification failed.");
+
+ Serializable decryptedPayload = Utilities.deserialize(decryptPayloadWithHmac(sealedAndSigned.encryptedPayloadWithHmac, secretKey));
+ return new DecryptedPayloadWithPubKey(decryptedPayload, sealedAndSigned.sigPublicKey);
+ } catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
+ throw new CryptoException("Signature verification failed.");
+ }
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Private
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ private static SecretKey getSecretKeyFromBytes(byte[] encodedKey) {
+ return new SecretKeySpec(encodedKey, SYM_KEY_ALGO);
+ }
+
+ private static SecretKey generateSecretKey() {
+ try {
+ KeyGenerator keyPairGenerator = KeyGenerator.getInstance(SYM_CIPHER);
+ keyPairGenerator.init(256);
+ return keyPairGenerator.generateKey();
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("Couldn't generate key");
+ }
+ }
+}
+
diff --git a/common/src/main/java/io/bitsquare/common/crypto/Hash.java b/common/src/main/java/io/bitsquare/common/crypto/Hash.java
new file mode 100644
index 0000000000..bbeffb0700
--- /dev/null
+++ b/common/src/main/java/io/bitsquare/common/crypto/Hash.java
@@ -0,0 +1,83 @@
+/*
+ * This file is part of Bitsquare.
+ *
+ * Bitsquare is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * Bitsquare is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Bitsquare. If not, see .
+ */
+
+package io.bitsquare.common.crypto;
+
+import com.google.common.base.Charsets;
+import io.bitsquare.common.util.Utilities;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.spongycastle.util.encoders.Hex;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class Hash {
+ private static final Logger log = LoggerFactory.getLogger(Hash.class);
+
+ /**
+ * @param data Data as byte array
+ * @return Hash of data
+ */
+ public static byte[] getHash(byte[] data) {
+ MessageDigest digest;
+ try {
+ digest = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException e) {
+ log.error("Could not create MessageDigest for hash. " + e.getMessage());
+ throw new RuntimeException(e);
+ }
+ digest.update(data, 0, data.length);
+ return digest.digest();
+ }
+
+ /**
+ * @param data Any serializable object. Will be converted into a byte array using Java serialisation.
+ * @return Hash of data
+ */
+ public static byte[] getHash(Serializable data) {
+ return getHash(Utilities.serialize(data));
+ }
+
+ /**
+ * @param message UTF-8 encoded message
+ * @return Hash of data
+ */
+ public static byte[] getHash(String message) {
+ return getHash(message.getBytes(Charsets.UTF_8));
+ }
+
+ /**
+ * @param message UTF-8 encoded message
+ * @return Hex string of hash of data
+ */
+ public static String getHashAsHex(String message) {
+ return Hex.toHexString(message.getBytes(Charsets.UTF_8));
+ }
+
+ /**
+ * @param data data as Integer
+ * @return Hash of data
+ */
+ public static byte[] getHash(Integer data) {
+ return getHash(ByteBuffer.allocate(4).putInt(data).array());
+ }
+
+}
+
diff --git a/common/src/main/java/io/bitsquare/common/crypto/KeyRing.java b/common/src/main/java/io/bitsquare/common/crypto/KeyRing.java
index 6f2f244e18..5a2d35ef7f 100644
--- a/common/src/main/java/io/bitsquare/common/crypto/KeyRing.java
+++ b/common/src/main/java/io/bitsquare/common/crypto/KeyRing.java
@@ -22,77 +22,42 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
public class KeyRing {
private static final Logger log = LoggerFactory.getLogger(KeyRing.class);
- // Used for signing storage data
- private KeyPair storageSignatureKeyPair;
// Used for signing messages sent over the wire
- private KeyPair msgSignatureKeyPair;
+ private final KeyPair signatureKeyPair;
// Used for encrypting messages sent over the wire (hybrid encryption scheme is used, so it is used only to encrypt a symmetric session key)
- private KeyPair msgEncryptionKeyPair;
+ private final KeyPair encryptionKeyPair;
- private PubKeyRing pubKeyRing;
- private final KeyStorage keyStorage;
+ private final PubKeyRing pubKeyRing;
@Inject
- public KeyRing(KeyStorage keyStorage) throws CryptoException {
- this.keyStorage = keyStorage;
-
- init(keyStorage);
- }
-
- // consider extra thread for loading (takes about 264 ms at first startup, then load only takes nearly no time)
- private void init(KeyStorage keyStorage) throws CryptoException {
+ public KeyRing(KeyStorage keyStorage) {
if (keyStorage.allKeyFilesExist()) {
- storageSignatureKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.STORAGE_SIGNATURE);
- msgSignatureKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.MSG_SIGNATURE);
- msgEncryptionKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.MSG_ENCRYPTION);
+ signatureKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.MSG_SIGNATURE);
+ encryptionKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.MSG_ENCRYPTION);
} else {
// First time we create key pairs
- try {
- this.storageSignatureKeyPair = CryptoUtil.generateStorageSignatureKeyPair();
- this.msgSignatureKeyPair = CryptoUtil.generateMsgSignatureKeyPair();
- this.msgEncryptionKeyPair = CryptoUtil.generateMsgEncryptionKeyPair();
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- throw new CryptoException("Error at KeyRing constructor ", e);
- }
+ signatureKeyPair = Sig.generateKeyPair();
+ encryptionKeyPair = Encryption.generateEncryptionKeyPair();
keyStorage.saveKeyRing(this);
}
-
- pubKeyRing = new PubKeyRing(storageSignatureKeyPair.getPublic(), msgSignatureKeyPair.getPublic(), msgEncryptionKeyPair.getPublic());
- }
-
- // For unit testing
- KeyRing() throws NoSuchAlgorithmException {
- keyStorage = null;
- this.storageSignatureKeyPair = CryptoUtil.generateStorageSignatureKeyPair();
- this.msgSignatureKeyPair = CryptoUtil.generateMsgSignatureKeyPair();
- this.msgEncryptionKeyPair = CryptoUtil.generateMsgEncryptionKeyPair();
- pubKeyRing = new PubKeyRing(storageSignatureKeyPair.getPublic(), msgSignatureKeyPair.getPublic(), msgEncryptionKeyPair.getPublic());
- }
-
- KeyRing(KeyPair storageSignatureKeyPair, KeyPair msgSignatureKeyPair, KeyPair msgEncryptionKeyPair) {
- this.keyStorage = null;
- this.storageSignatureKeyPair = storageSignatureKeyPair;
- this.msgSignatureKeyPair = msgSignatureKeyPair;
- this.msgEncryptionKeyPair = msgEncryptionKeyPair;
- pubKeyRing = new PubKeyRing(storageSignatureKeyPair.getPublic(), msgSignatureKeyPair.getPublic(), msgEncryptionKeyPair.getPublic());
+ pubKeyRing = new PubKeyRing(signatureKeyPair.getPublic(), signatureKeyPair.getPublic(), encryptionKeyPair.getPublic());
}
+ //TODO
public KeyPair getStorageSignatureKeyPair() {
- return storageSignatureKeyPair;
+ return signatureKeyPair;
}
- public KeyPair getMsgSignatureKeyPair() {
- return msgSignatureKeyPair;
+ public KeyPair getSignatureKeyPair() {
+ return signatureKeyPair;
}
- public KeyPair getMsgEncryptionKeyPair() {
- return msgEncryptionKeyPair;
+ public KeyPair getEncryptionKeyPair() {
+ return encryptionKeyPair;
}
public PubKeyRing getPubKeyRing() {
diff --git a/common/src/main/java/io/bitsquare/common/crypto/KeyStorage.java b/common/src/main/java/io/bitsquare/common/crypto/KeyStorage.java
index 0c82548910..f9c10a5a65 100644
--- a/common/src/main/java/io/bitsquare/common/crypto/KeyStorage.java
+++ b/common/src/main/java/io/bitsquare/common/crypto/KeyStorage.java
@@ -18,7 +18,6 @@
package io.bitsquare.common.crypto;
import com.google.inject.Inject;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,14 +38,10 @@ public class KeyStorage {
public static final String DIR_KEY = "key.storage.dir";
- static {
- Security.addProvider(new BouncyCastleProvider());
- }
-
public enum Key {
- STORAGE_SIGNATURE("storageSignature", CryptoUtil.STORAGE_SIGN_KEY_ALGO),
- MSG_SIGNATURE("msgSignature", CryptoUtil.MSG_SIGN_KEY_ALGO),
- MSG_ENCRYPTION("msgEncryption", CryptoUtil.MSG_ENCR_KEY_ALGO);
+ STORAGE_SIGNATURE("storageSignature", Sig.KEY_ALGO),
+ MSG_SIGNATURE("msgSignature", Sig.KEY_ALGO),
+ MSG_ENCRYPTION("msgEncryption", Encryption.ENCR_KEY_ALGO);
private final String fileName;
private final String algorithm;
@@ -81,7 +76,7 @@ public class KeyStorage {
this.storageDir = storageDir;
}
- public boolean allKeyFilesExist() throws CryptoException {
+ public boolean allKeyFilesExist() {
return fileExists(KeyStorage.Key.STORAGE_SIGNATURE) && fileExists(KeyStorage.Key.MSG_SIGNATURE) && fileExists(KeyStorage.Key.MSG_ENCRYPTION);
}
@@ -89,7 +84,7 @@ public class KeyStorage {
return new File(storageDir + "/" + key.getFileName() + "Pub.key").exists();
}
- public KeyPair loadKeyPair(Key key) throws CryptoException {
+ public KeyPair loadKeyPair(Key key) {
// long now = System.currentTimeMillis();
try {
KeyFactory keyFactory = KeyFactory.getInstance(key.getAlgorithm());
@@ -106,7 +101,7 @@ public class KeyStorage {
} catch (InvalidKeySpecException | IOException e) {
e.printStackTrace();
log.error(e.getMessage());
- throw new CryptoException("Could not load key " + key.toString(), e);
+ throw new RuntimeException("Could not load key " + key.toString(), e);
}
File filePrivateKey = new File(storageDir + "/" + key.getFileName() + "Priv.key");
@@ -119,7 +114,7 @@ public class KeyStorage {
} catch (InvalidKeySpecException | IOException e) {
e.printStackTrace();
log.error(e.getMessage());
- throw new CryptoException("Could not load key " + key.toString(), e);
+ throw new RuntimeException("Could not load key " + key.toString(), e);
}
//log.info("load completed in {} msec", System.currentTimeMillis() - now);
return new KeyPair(publicKey, privateKey);
@@ -127,17 +122,17 @@ public class KeyStorage {
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
log.error(e.getMessage());
- throw new CryptoException("Could not load key " + key.toString(), e);
+ throw new RuntimeException("Could not load key " + key.toString(), e);
}
}
- public void saveKeyRing(KeyRing keyRing) throws CryptoException {
+ public void saveKeyRing(KeyRing keyRing) {
saveKeyPair(keyRing.getStorageSignatureKeyPair(), Key.STORAGE_SIGNATURE.getFileName());
- saveKeyPair(keyRing.getMsgSignatureKeyPair(), Key.MSG_SIGNATURE.getFileName());
- saveKeyPair(keyRing.getMsgEncryptionKeyPair(), Key.MSG_ENCRYPTION.getFileName());
+ saveKeyPair(keyRing.getSignatureKeyPair(), Key.MSG_SIGNATURE.getFileName());
+ saveKeyPair(keyRing.getEncryptionKeyPair(), Key.MSG_ENCRYPTION.getFileName());
}
- public void saveKeyPair(KeyPair keyPair, String name) throws CryptoException {
+ public void saveKeyPair(KeyPair keyPair, String name) {
if (!storageDir.exists())
storageDir.mkdir();
@@ -147,7 +142,7 @@ public class KeyStorage {
} catch (IOException e) {
e.printStackTrace();
log.error(e.getMessage());
- throw new CryptoException("Could not save key " + name, e);
+ throw new RuntimeException("Could not save key " + name, e);
}
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyPair.getPrivate().getEncoded());
@@ -156,7 +151,7 @@ public class KeyStorage {
} catch (IOException e) {
e.printStackTrace();
log.error(e.getMessage());
- throw new CryptoException("Could not save key " + name, e);
+ throw new RuntimeException("Could not save key " + name, e);
}
}
}
diff --git a/common/src/main/java/io/bitsquare/common/crypto/PubKeyRing.java b/common/src/main/java/io/bitsquare/common/crypto/PubKeyRing.java
index 05ecf93f7e..e785519e51 100644
--- a/common/src/main/java/io/bitsquare/common/crypto/PubKeyRing.java
+++ b/common/src/main/java/io/bitsquare/common/crypto/PubKeyRing.java
@@ -45,22 +45,22 @@ public class PubKeyRing implements Serializable {
transient private PublicKey storageSignaturePubKey;
transient private PublicKey msgSignaturePubKey;
- transient private PublicKey msgEncryptionPubKey;
+ transient private PublicKey encryptionPubKey;
- public PubKeyRing(PublicKey storageSignaturePubKey, PublicKey msgSignaturePubKey, PublicKey msgEncryptionPubKey) {
+ public PubKeyRing(PublicKey storageSignaturePubKey, PublicKey msgSignaturePubKey, PublicKey encryptionPubKey) {
this.storageSignaturePubKey = storageSignaturePubKey;
this.msgSignaturePubKey = msgSignaturePubKey;
- this.msgEncryptionPubKey = msgEncryptionPubKey;
+ this.encryptionPubKey = encryptionPubKey;
this.storageSignaturePubKeyBytes = new X509EncodedKeySpec(storageSignaturePubKey.getEncoded()).getEncoded();
this.msgSignaturePubKeyBytes = new X509EncodedKeySpec(msgSignaturePubKey.getEncoded()).getEncoded();
- this.msgEncryptionPubKeyBytes = new X509EncodedKeySpec(msgEncryptionPubKey.getEncoded()).getEncoded();
+ this.msgEncryptionPubKeyBytes = new X509EncodedKeySpec(encryptionPubKey.getEncoded()).getEncoded();
}
public PublicKey getStorageSignaturePubKey() {
if (storageSignaturePubKey == null) {
try {
- storageSignaturePubKey = KeyFactory.getInstance(CryptoUtil.STORAGE_SIGN_KEY_ALGO).generatePublic(new X509EncodedKeySpec(storageSignaturePubKeyBytes));
+ storageSignaturePubKey = KeyFactory.getInstance(Sig.KEY_ALGO).generatePublic(new X509EncodedKeySpec(storageSignaturePubKeyBytes));
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
e.printStackTrace();
log.error(e.getMessage());
@@ -73,7 +73,7 @@ public class PubKeyRing implements Serializable {
public PublicKey getMsgSignaturePubKey() {
if (msgSignaturePubKey == null) {
try {
- msgSignaturePubKey = KeyFactory.getInstance(CryptoUtil.MSG_SIGN_KEY_ALGO).generatePublic(new X509EncodedKeySpec(msgSignaturePubKeyBytes));
+ msgSignaturePubKey = KeyFactory.getInstance(Sig.KEY_ALGO).generatePublic(new X509EncodedKeySpec(msgSignaturePubKeyBytes));
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
e.printStackTrace();
log.error(e.getMessage());
@@ -82,16 +82,16 @@ public class PubKeyRing implements Serializable {
return msgSignaturePubKey;
}
- public PublicKey getMsgEncryptionPubKey() {
- if (msgEncryptionPubKey == null) {
+ public PublicKey getEncryptionPubKey() {
+ if (encryptionPubKey == null) {
try {
- msgEncryptionPubKey = KeyFactory.getInstance(CryptoUtil.MSG_ENCR_KEY_ALGO).generatePublic(new X509EncodedKeySpec(msgEncryptionPubKeyBytes));
+ encryptionPubKey = KeyFactory.getInstance(Encryption.ENCR_KEY_ALGO).generatePublic(new X509EncodedKeySpec(msgEncryptionPubKeyBytes));
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
e.printStackTrace();
log.error(e.getMessage());
}
}
- return msgEncryptionPubKey;
+ return encryptionPubKey;
}
@Override
@@ -118,9 +118,9 @@ public class PubKeyRing implements Serializable {
@Override
public String toString() {
return "PubKeyRing{" +
- "\nstorageSignaturePubKey=\n" + CryptoUtil.pubKeyToString(getStorageSignaturePubKey()) +
- "\n\nmsgSignaturePubKey=\n" + CryptoUtil.pubKeyToString(getMsgSignaturePubKey()) +
- "\n\nmsgEncryptionPubKey=\n" + CryptoUtil.pubKeyToString(getMsgEncryptionPubKey()) +
+ "\nstorageSignaturePubKey=\n" + Util.pubKeyToString(getStorageSignaturePubKey()) +
+ "\n\nmsgSignaturePubKey=\n" + Util.pubKeyToString(getMsgSignaturePubKey()) +
+ "\n\nmsgEncryptionPubKey=\n" + Util.pubKeyToString(getEncryptionPubKey()) +
'}';
}
diff --git a/common/src/main/java/io/bitsquare/common/crypto/SealedAndSigned.java b/common/src/main/java/io/bitsquare/common/crypto/SealedAndSigned.java
new file mode 100644
index 0000000000..458b23a52c
--- /dev/null
+++ b/common/src/main/java/io/bitsquare/common/crypto/SealedAndSigned.java
@@ -0,0 +1,70 @@
+/*
+ * This file is part of Bitsquare.
+ *
+ * Bitsquare is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * Bitsquare is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Bitsquare. If not, see .
+ */
+
+package io.bitsquare.common.crypto;
+
+import io.bitsquare.app.Version;
+
+import java.io.Serializable;
+import java.security.PublicKey;
+import java.util.Arrays;
+
+/**
+ * Packs the encrypted symmetric secretKey and the encrypted and signed message into one object.
+ * SecretKey is encrypted with asymmetric pubKey of peer. Signed message is encrypted with secretKey.
+ * Using that hybrid encryption model we are not restricted by data size and performance as symmetric encryption is very fast.
+ */
+public final class SealedAndSigned implements Serializable {
+ // That object is sent over the wire, so we need to take care of version compatibility.
+ private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
+
+ public final byte[] encryptedSecretKey;
+ public final byte[] encryptedPayloadWithHmac;
+ public final byte[] signature;
+ public final PublicKey sigPublicKey;
+
+ public SealedAndSigned(byte[] encryptedSecretKey, byte[] encryptedPayloadWithHmac, byte[] signature, PublicKey sigPublicKey) {
+ this.encryptedSecretKey = encryptedSecretKey;
+ this.encryptedPayloadWithHmac = encryptedPayloadWithHmac;
+ this.signature = signature;
+ this.sigPublicKey = sigPublicKey;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SealedAndSigned)) return false;
+
+ SealedAndSigned that = (SealedAndSigned) o;
+
+ if (!Arrays.equals(encryptedSecretKey, that.encryptedSecretKey)) return false;
+ if (!Arrays.equals(encryptedPayloadWithHmac, that.encryptedPayloadWithHmac)) return false;
+ if (!Arrays.equals(signature, that.signature)) return false;
+ return !(sigPublicKey != null ? !sigPublicKey.equals(that.sigPublicKey) : that.sigPublicKey != null);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = encryptedSecretKey != null ? Arrays.hashCode(encryptedSecretKey) : 0;
+ result = 31 * result + (encryptedPayloadWithHmac != null ? Arrays.hashCode(encryptedPayloadWithHmac) : 0);
+ result = 31 * result + (signature != null ? Arrays.hashCode(signature) : 0);
+ result = 31 * result + (sigPublicKey != null ? sigPublicKey.hashCode() : 0);
+ return result;
+ }
+
+}
diff --git a/common/src/main/java/io/bitsquare/common/crypto/Sig.java b/common/src/main/java/io/bitsquare/common/crypto/Sig.java
new file mode 100644
index 0000000000..3de75442fb
--- /dev/null
+++ b/common/src/main/java/io/bitsquare/common/crypto/Sig.java
@@ -0,0 +1,121 @@
+/*
+ * This file is part of Bitsquare.
+ *
+ * Bitsquare is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * Bitsquare is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Bitsquare. If not, see .
+ */
+
+package io.bitsquare.common.crypto;
+
+import com.google.common.base.Charsets;
+import org.bouncycastle.util.encoders.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.security.*;
+
+/**
+ * StorageSignatureKeyPair/STORAGE_SIGN_KEY_ALGO: That is used for signing the data to be stored to the P2P network (by flooding).
+ * The algo is selected because it originated from the TomP2P version which used DSA.
+ * Changing to EC keys might be considered.
+ *
+ * MsgSignatureKeyPair/MSG_SIGN_KEY_ALGO/MSG_SIGN_ALGO: That is used when sending a message to a peer which is encrypted and signed.
+ * Changing to EC keys might be considered.
+ */
+public class Sig {
+ private static final Logger log = LoggerFactory.getLogger(Sig.class);
+
+ public static final String KEY_ALGO = "DSA";
+ public static final String ALGO = "SHA1withDSA"; //TODO better SHA512withECDSA
+
+
+ /**
+ * @return keyPair
+ */
+ public static KeyPair generateKeyPair() {
+ long ts = System.currentTimeMillis();
+ try {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGO);
+ keyPairGenerator.initialize(1024);
+ KeyPair keyPair = keyPairGenerator.genKeyPair();
+ log.trace("Generate msgSignatureKeyPair needed {} ms", System.currentTimeMillis() - ts);
+ return keyPair;
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ throw new RuntimeException("Could not create key.");
+ }
+ }
+
+
+ /**
+ * @param privateKey
+ * @param data
+ * @return
+ * @throws SignatureException
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ */
+ public static byte[] sign(PrivateKey privateKey, byte[] data)
+ throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
+ Signature sig = Signature.getInstance(ALGO);
+ sig.initSign(privateKey);
+ sig.update(data);
+ return sig.sign();
+ }
+
+ /**
+ * @param privateKey
+ * @param message UTF-8 encoded message to sign
+ * @return Base64 encoded signature
+ * @throws SignatureException
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ */
+ public static String sign(PrivateKey privateKey, String message)
+ throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
+ byte[] sigAsBytes = sign(privateKey, message.getBytes(Charsets.UTF_8));
+ return Base64.toBase64String(sigAsBytes);
+ }
+
+ /**
+ * @param publicKey
+ * @param data
+ * @param signature
+ * @return
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ * @throws SignatureException
+ */
+ public static boolean verify(PublicKey publicKey, byte[] data, byte[] signature)
+ throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+ Signature sig = Signature.getInstance(ALGO);
+ sig.initVerify(publicKey);
+ sig.update(data);
+ return sig.verify(signature);
+ }
+
+ /**
+ * @param publicKey
+ * @param message UTF-8 encoded message
+ * @param signature Base64 encoded signature
+ * @return
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ * @throws SignatureException
+ */
+ public static boolean verify(PublicKey publicKey, String message, String signature)
+ throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+ return verify(publicKey, message.getBytes(Charsets.UTF_8), Base64.decode(signature));
+ }
+}
+
diff --git a/common/src/main/java/io/bitsquare/common/crypto/Util.java b/common/src/main/java/io/bitsquare/common/crypto/Util.java
new file mode 100644
index 0000000000..1c5f514241
--- /dev/null
+++ b/common/src/main/java/io/bitsquare/common/crypto/Util.java
@@ -0,0 +1,34 @@
+/*
+ * This file is part of Bitsquare.
+ *
+ * Bitsquare is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * Bitsquare is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Bitsquare. If not, see .
+ */
+
+package io.bitsquare.common.crypto;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.security.PublicKey;
+import java.security.spec.X509EncodedKeySpec;
+
+public class Util {
+ private static final Logger log = LoggerFactory.getLogger(Util.class);
+
+ public static String pubKeyToString(PublicKey publicKey) {
+ final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
+ return java.util.Base64.getEncoder().encodeToString(x509EncodedKeySpec.getEncoded());
+ }
+}
+
diff --git a/common/src/main/java/io/bitsquare/common/util/Tuple2.java b/common/src/main/java/io/bitsquare/common/util/Tuple2.java
index 8d2530f9e9..2e5fc4071e 100644
--- a/common/src/main/java/io/bitsquare/common/util/Tuple2.java
+++ b/common/src/main/java/io/bitsquare/common/util/Tuple2.java
@@ -17,7 +17,9 @@
package io.bitsquare.common.util;
-public class Tuple2 {
+import java.io.Serializable;
+
+public class Tuple2 implements Serializable {
final public A first;
final public B second;
diff --git a/common/src/main/java/io/bitsquare/common/util/Tuple3.java b/common/src/main/java/io/bitsquare/common/util/Tuple3.java
index 3229f98fd7..be08d6aa63 100644
--- a/common/src/main/java/io/bitsquare/common/util/Tuple3.java
+++ b/common/src/main/java/io/bitsquare/common/util/Tuple3.java
@@ -17,7 +17,9 @@
package io.bitsquare.common.util;
-public class Tuple3 {
+import java.io.Serializable;
+
+public class Tuple3 implements Serializable {
final public A first;
final public B second;
final public C third;
diff --git a/common/src/main/java/io/bitsquare/common/util/Utilities.java b/common/src/main/java/io/bitsquare/common/util/Utilities.java
index 676e576ba4..22bf0ebc9c 100644
--- a/common/src/main/java/io/bitsquare/common/util/Utilities.java
+++ b/common/src/main/java/io/bitsquare/common/util/Utilities.java
@@ -208,13 +208,15 @@ public class Utilities {
return result;
}*/
- public static T byteArrayToObject(byte[] data) {
+ public static T deserialize(byte[] data) {
ByteArrayInputStream bis = new ByteArrayInputStream(data);
ObjectInput in = null;
Object result = null;
try {
in = new ObjectInputStream(bis);
result = in.readObject();
+ if (!(result instanceof Serializable))
+ throw new RuntimeException("Object not of type Serializable");
} catch (Exception e) {
e.printStackTrace();
} finally {
@@ -234,14 +236,15 @@ public class Utilities {
return (T) result;
}
- public static byte[] objectToByteArray(Object object) {
+ public static byte[] serialize(Serializable object) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
byte[] result = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(object);
- result = bos.toByteArray();
+ out.flush();
+ result = bos.toByteArray().clone();
} catch (IOException e) {
e.printStackTrace();
} finally {
@@ -249,13 +252,11 @@ public class Utilities {
if (out != null) {
out.close();
}
- } catch (IOException ex) {
- // ignore close exception
+ } catch (IOException ignore) {
}
try {
bos.close();
- } catch (IOException ex) {
- // ignore close exception
+ } catch (IOException ignore) {
}
}
return result;
diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java
index 2fef2b1c61..5b8584dded 100644
--- a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java
+++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/PublishDepositTxRequest.java
@@ -25,6 +25,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.concurrent.Immutable;
+import java.util.ArrayList;
import java.util.List;
@Immutable
@@ -68,9 +69,9 @@ public class PublishDepositTxRequest extends TradeMessage {
this.openDisputeTimeAsBlockHeight = openDisputeTimeAsBlockHeight;
this.checkPaymentTimeAsBlockHeight = checkPaymentTimeAsBlockHeight;
- log.trace("offererPaymentAccount size " + Utilities.objectToByteArray(offererPaymentAccountContractData).length);
+ log.trace("offererPaymentAccount size " + Utilities.serialize(offererPaymentAccountContractData).length);
log.trace("offererTradeWalletPubKey size " + offererTradeWalletPubKey.length);
log.trace("preparedDepositTx size " + preparedDepositTx.length);
- log.trace("offererInputs size " + Utilities.objectToByteArray(offererInputs).length);
+ log.trace("offererInputs size " + Utilities.serialize(new ArrayList<>(offererInputs)).length);
}
}
diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateAndSignDepositTxAsBuyer.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateAndSignDepositTxAsBuyer.java
index c42e31d117..64424c61c2 100644
--- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateAndSignDepositTxAsBuyer.java
+++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/CreateAndSignDepositTxAsBuyer.java
@@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.buyer;
import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.data.PreparedDepositTxAndOffererInputs;
-import io.bitsquare.common.crypto.CryptoUtil;
+import io.bitsquare.common.crypto.Hash;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
@@ -49,7 +49,7 @@ public class CreateAndSignDepositTxAsBuyer extends TradeTask {
log.debug(trade.getContractAsJson());
log.debug("----------");
- byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
+ byte[] contractHash = Hash.getHash(trade.getContractAsJson());
trade.setContractHash(contractHash);
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(
true,
diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTxAsBuyer.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTxAsBuyer.java
index 12329e3647..4ea7c80d15 100644
--- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTxAsBuyer.java
+++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTxAsBuyer.java
@@ -18,7 +18,7 @@
package io.bitsquare.trade.protocol.trade.tasks.buyer;
import com.google.common.util.concurrent.FutureCallback;
-import io.bitsquare.common.crypto.CryptoUtil;
+import io.bitsquare.common.crypto.Hash;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
@@ -41,7 +41,7 @@ public class SignAndPublishDepositTxAsBuyer extends TradeTask {
try {
runInterceptHook();
- byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
+ byte[] contractHash = Hash.getHash(trade.getContractAsJson());
trade.setContractHash(contractHash);
processModel.getTradeWalletService().takerSignsAndPublishesDepositTx(
false,
diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/CreateAndSignContract.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/CreateAndSignContract.java
index a26fa33757..2eaf014234 100644
--- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/CreateAndSignContract.java
+++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/CreateAndSignContract.java
@@ -17,7 +17,7 @@
package io.bitsquare.trade.protocol.trade.tasks.offerer;
-import io.bitsquare.common.crypto.CryptoUtil;
+import io.bitsquare.common.crypto.Sig;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.common.util.Utilities;
import io.bitsquare.p2p.Address;
@@ -75,7 +75,7 @@ public class CreateAndSignContract extends TradeTask {
taker.getTradeWalletPubKey()
);
String contractAsJson = Utilities.objectToJson(contract);
- String signature = CryptoUtil.signMessage(processModel.getKeyRing().getMsgSignatureKeyPair().getPrivate(), contractAsJson);
+ String signature = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), contractAsJson);
trade.setContract(contract);
trade.setContractAsJson(contractAsJson);
diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/ProcessPayDepositRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/ProcessPayDepositRequest.java
index 41e2389fd9..6a243446be 100644
--- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/ProcessPayDepositRequest.java
+++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/ProcessPayDepositRequest.java
@@ -17,7 +17,7 @@
package io.bitsquare.trade.protocol.trade.tasks.offerer;
-import io.bitsquare.common.crypto.CryptoUtil;
+import io.bitsquare.common.crypto.Hash;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.payment.BlockChainAccountContractData;
@@ -66,7 +66,7 @@ public class ProcessPayDepositRequest extends TradeTask {
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
- String paymentId = CryptoUtil.getHashAsHex(trade.getId()).substring(0, 32);
+ String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, 32);
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
}
diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateAndSignDepositTxAsSeller.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateAndSignDepositTxAsSeller.java
index 957de8ea7e..dc8b059678 100644
--- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateAndSignDepositTxAsSeller.java
+++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/CreateAndSignDepositTxAsSeller.java
@@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.data.PreparedDepositTxAndOffererInputs;
-import io.bitsquare.common.crypto.CryptoUtil;
+import io.bitsquare.common.crypto.Hash;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
@@ -44,7 +44,7 @@ public class CreateAndSignDepositTxAsSeller extends TradeTask {
Coin sellerInputAmount = FeePolicy.SECURITY_DEPOSIT.add(FeePolicy.TX_FEE).add(trade.getTradeAmount());
Coin msOutputAmount = sellerInputAmount.add(FeePolicy.SECURITY_DEPOSIT);
- byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
+ byte[] contractHash = Hash.getHash(trade.getContractAsJson());
trade.setContractHash(contractHash);
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(
false,
diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SignAndPublishDepositTxAsSeller.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SignAndPublishDepositTxAsSeller.java
index 062279d1c9..018182abe3 100644
--- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SignAndPublishDepositTxAsSeller.java
+++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/seller/SignAndPublishDepositTxAsSeller.java
@@ -18,7 +18,7 @@
package io.bitsquare.trade.protocol.trade.tasks.seller;
import com.google.common.util.concurrent.FutureCallback;
-import io.bitsquare.common.crypto.CryptoUtil;
+import io.bitsquare.common.crypto.Hash;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
@@ -44,7 +44,7 @@ public class SignAndPublishDepositTxAsSeller extends TradeTask {
log.debug("----------");
log.debug(trade.getContractAsJson());
log.debug("----------");
- byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
+ byte[] contractHash = Hash.getHash(trade.getContractAsJson());
trade.setContractHash(contractHash);
processModel.getTradeWalletService().takerSignsAndPublishesDepositTx(
true,
diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java
index 214ee743f9..d0282fd6bb 100644
--- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java
+++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/ProcessPublishDepositTxRequest.java
@@ -17,7 +17,7 @@
package io.bitsquare.trade.protocol.trade.tasks.taker;
-import io.bitsquare.common.crypto.CryptoUtil;
+import io.bitsquare.common.crypto.Hash;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.payment.BlockChainAccountContractData;
@@ -54,7 +54,7 @@ public class ProcessPublishDepositTxRequest extends TradeTask {
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
- String paymentId = CryptoUtil.getHashAsHex(trade.getId()).substring(0, 32);
+ String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, 32);
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
}
diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/VerifyAndSignContract.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/VerifyAndSignContract.java
index 32396a0c06..4d114cd796 100644
--- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/VerifyAndSignContract.java
+++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/taker/VerifyAndSignContract.java
@@ -17,7 +17,7 @@
package io.bitsquare.trade.protocol.trade.tasks.taker;
-import io.bitsquare.common.crypto.CryptoUtil;
+import io.bitsquare.common.crypto.Sig;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.common.util.Utilities;
import io.bitsquare.p2p.Address;
@@ -74,13 +74,13 @@ public class VerifyAndSignContract extends TradeTask {
processModel.getTradeWalletPubKey()
);
String contractAsJson = Utilities.objectToJson(contract);
- String signature = CryptoUtil.signMessage(processModel.getKeyRing().getMsgSignatureKeyPair().getPrivate(), contractAsJson);
+ String signature = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), contractAsJson);
trade.setContract(contract);
trade.setContractAsJson(contractAsJson);
trade.setTakerContractSignature(signature);
try {
- CryptoUtil.verifyMessage(offerer.getPubKeyRing().getMsgSignaturePubKey(),
+ Sig.verify(offerer.getPubKeyRing().getMsgSignaturePubKey(),
contractAsJson,
offerer.getContractSignature());
} catch (Throwable t) {
diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java
index 96cfcff31b..5fe5f9eee3 100644
--- a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java
+++ b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java
@@ -54,6 +54,7 @@ import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.controlsfx.dialog.Dialogs;
import org.reactfx.EventStreams;
import org.reactfx.util.FxTimer;
@@ -62,6 +63,7 @@ import org.springframework.core.env.Environment;
import java.io.IOException;
import java.nio.file.Paths;
+import java.security.Security;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
@@ -113,6 +115,8 @@ public class BitsquareApp extends Application {
Thread.setDefaultUncaughtExceptionHandler(handler);
Thread.currentThread().setUncaughtExceptionHandler(handler);
+ Security.addProvider(new BouncyCastleProvider());
+
try {
// Use CrashFX for report crash logs
/*CrashFX.setup("Bitsquare/" + Version.VERSION,
diff --git a/network/src/main/java/io/bitsquare/crypto/EncryptionService.java b/network/src/main/java/io/bitsquare/crypto/EncryptionService.java
index cb254fb92d..46f861059a 100644
--- a/network/src/main/java/io/bitsquare/crypto/EncryptionService.java
+++ b/network/src/main/java/io/bitsquare/crypto/EncryptionService.java
@@ -17,27 +17,18 @@
package io.bitsquare.crypto;
-import io.bitsquare.common.crypto.CryptoException;
-import io.bitsquare.common.crypto.CryptoUtil;
-import io.bitsquare.common.crypto.KeyRing;
-import io.bitsquare.common.crypto.PubKeyRing;
-import io.bitsquare.common.util.Utilities;
+import io.bitsquare.common.crypto.*;
import io.bitsquare.p2p.Message;
import io.bitsquare.p2p.messaging.DecryptedMessageWithPubKey;
-import io.bitsquare.p2p.messaging.SealedAndSignedMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.Nullable;
-import javax.crypto.*;
import javax.inject.Inject;
-import java.io.IOException;
-import java.security.*;
+import java.security.KeyPair;
public class EncryptionService {
private static final Logger log = LoggerFactory.getLogger(EncryptionService.class);
- @Nullable
private final KeyRing keyRing;
@Inject
@@ -45,90 +36,22 @@ public class EncryptionService {
this.keyRing = keyRing;
}
-
- public SealedAndSignedMessage encryptAndSignMessage(PubKeyRing pubKeyRing, Message message) throws CryptoException {
+ public SealedAndSigned encryptAndSignMessage(PubKeyRing pubKeyRing, Message message) throws CryptoException {
log.trace("encryptAndSignMessage message = " + message);
- //long ts = System.currentTimeMillis();
-
- try {
- // Create symmetric key
- KeyGenerator keyGenerator = KeyGenerator.getInstance(CryptoUtil.SYM_ENCR_KEY_ALGO);
- // TODO consider 256 bit as key length
- keyGenerator.init(128);
- SecretKey secretKey = keyGenerator.generateKey();
-
- // Encrypt secretKey with peers pubKey using SealedObject
- Cipher cipherAsym = Cipher.getInstance(CryptoUtil.ASYM_CIPHER);
- cipherAsym.init(Cipher.ENCRYPT_MODE, pubKeyRing.getMsgEncryptionPubKey());
- SealedObject sealedSecretKey = new SealedObject(secretKey, cipherAsym);
-
- // Sign (hash of) message and pack it into SignedObject
- SignedObject signedMessage = new SignedObject(message, keyRing.getMsgSignatureKeyPair().getPrivate(), Signature.getInstance(CryptoUtil.MSG_SIGN_ALGO));
-
- // // Encrypt signedMessage with secretKey using SealedObject
- Cipher cipherSym = Cipher.getInstance(CryptoUtil.SYM_CIPHER);
- cipherSym.init(Cipher.ENCRYPT_MODE, secretKey);
- SealedObject sealedMessage = new SealedObject(signedMessage, cipherSym);
-
- SealedAndSignedMessage sealedAndSignedMessage = new SealedAndSignedMessage(sealedSecretKey,
- sealedMessage,
- keyRing.getMsgSignatureKeyPair().getPublic()
- );
- //log.trace("Encryption needed {} ms", System.currentTimeMillis() - ts);
- log.trace("sealedAndSignedMessage size " + Utilities.objectToByteArray(sealedAndSignedMessage).length);
- return sealedAndSignedMessage;
- } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException
- | IllegalBlockSizeException | IOException | SignatureException e) {
- throw new CryptoException(e);
- }
+ KeyPair signatureKeyPair = keyRing.getSignatureKeyPair();
+ return Encryption.encryptHybridWithSignature(message,
+ signatureKeyPair.getPrivate(),
+ signatureKeyPair.getPublic(),
+ pubKeyRing.getEncryptionPubKey());
}
- public DecryptedMessageWithPubKey decryptAndVerifyMessage(SealedAndSignedMessage sealedAndSignedMessage) throws CryptoException {
- // long ts = System.currentTimeMillis();
- try {
- if (keyRing == null)
- throw new CryptoException("keyRing is null");
-
- SealedObject sealedSecretKey = sealedAndSignedMessage.sealedSecretKey;
- SealedObject sealedMessage = sealedAndSignedMessage.sealedMessage;
- PublicKey signaturePubKey = sealedAndSignedMessage.signaturePubKey;
-
- // Decrypt secretKey with my privKey
- Cipher cipherAsym = Cipher.getInstance(CryptoUtil.ASYM_CIPHER);
- cipherAsym.init(Cipher.DECRYPT_MODE, keyRing.getMsgEncryptionKeyPair().getPrivate());
- Object secretKeyObject = sealedSecretKey.getObject(cipherAsym);
- if (secretKeyObject instanceof SecretKey) {
- SecretKey secretKey = (SecretKey) secretKeyObject;
-
- // Decrypt signedMessage with secretKey
- Cipher cipherSym = Cipher.getInstance(CryptoUtil.SYM_CIPHER);
- cipherSym.init(Cipher.DECRYPT_MODE, secretKey);
- Object signedMessageObject = sealedMessage.getObject(cipherSym);
- if (signedMessageObject instanceof SignedObject) {
- SignedObject signedMessage = (SignedObject) signedMessageObject;
-
- // Verify message with peers pubKey
- if (signedMessage.verify(signaturePubKey, Signature.getInstance(CryptoUtil.MSG_SIGN_ALGO))) {
- // Get message
- Object messageObject = signedMessage.getObject();
- if (messageObject instanceof Message) {
- //log.trace("Decryption needed {} ms", System.currentTimeMillis() - ts);
- return new DecryptedMessageWithPubKey((Message) messageObject, signaturePubKey);
- } else {
- throw new CryptoException("messageObject is not instance of Message");
- }
- } else {
- throw new CryptoException("Signature is not valid");
- }
- } else {
- throw new CryptoException("signedMessageObject is not instance of SignedObject");
- }
- } else {
- throw new CryptoException("secretKeyObject is not instance of SecretKey");
- }
- } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | BadPaddingException |
- ClassNotFoundException | IllegalBlockSizeException | IOException | SignatureException e) {
- throw new CryptoException(e);
+ public DecryptedMessageWithPubKey decryptAndVerifyMessage(SealedAndSigned sealedAndSigned) throws CryptoException {
+ DecryptedPayloadWithPubKey decryptedPayloadWithPubKey = Encryption.decryptHybridWithSignature(sealedAndSigned, keyRing.getEncryptionKeyPair().getPrivate());
+ if (decryptedPayloadWithPubKey.payload instanceof Message) {
+ //log.trace("Decryption needed {} ms", System.currentTimeMillis() - ts);
+ return new DecryptedMessageWithPubKey((Message) decryptedPayloadWithPubKey.payload, decryptedPayloadWithPubKey.sigPublicKey);
+ } else {
+ throw new CryptoException("messageObject is not instance of Message");
}
}
}
diff --git a/network/src/main/java/io/bitsquare/crypto/SealedAndSignedMessage.java b/network/src/main/java/io/bitsquare/crypto/SealedAndSignedMessage.java
new file mode 100644
index 0000000000..9a08a69b7b
--- /dev/null
+++ b/network/src/main/java/io/bitsquare/crypto/SealedAndSignedMessage.java
@@ -0,0 +1,23 @@
+package io.bitsquare.crypto;
+
+import io.bitsquare.common.crypto.SealedAndSigned;
+import io.bitsquare.p2p.Address;
+import io.bitsquare.p2p.messaging.MailboxMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SealedAndSignedMessage implements MailboxMessage {
+ private static final Logger log = LoggerFactory.getLogger(SealedAndSignedMessage.class);
+ public final SealedAndSigned sealedAndSigned;
+ public final Address peerAddress;
+
+ public SealedAndSignedMessage(SealedAndSigned sealedAndSigned, Address peerAddress) {
+ this.sealedAndSigned = sealedAndSigned;
+ this.peerAddress = peerAddress;
+ }
+
+ @Override
+ public Address getSenderAddress() {
+ return null;
+ }
+}
diff --git a/network/src/main/java/io/bitsquare/p2p/P2PService.java b/network/src/main/java/io/bitsquare/p2p/P2PService.java
index 097ed5fae0..3dad33535c 100644
--- a/network/src/main/java/io/bitsquare/p2p/P2PService.java
+++ b/network/src/main/java/io/bitsquare/p2p/P2PService.java
@@ -10,7 +10,9 @@ import io.bitsquare.common.UserThread;
import io.bitsquare.common.crypto.CryptoException;
import io.bitsquare.common.crypto.KeyRing;
import io.bitsquare.common.crypto.PubKeyRing;
+import io.bitsquare.common.crypto.SealedAndSigned;
import io.bitsquare.crypto.EncryptionService;
+import io.bitsquare.crypto.SealedAndSignedMessage;
import io.bitsquare.p2p.messaging.*;
import io.bitsquare.p2p.network.*;
import io.bitsquare.p2p.routing.Neighbor;
@@ -210,7 +212,8 @@ public class P2PService {
} else if (message instanceof SealedAndSignedMessage) {
if (encryptionService != null) {
try {
- DecryptedMessageWithPubKey decryptedMessageWithPubKey = encryptionService.decryptAndVerifyMessage((SealedAndSignedMessage) message);
+ SealedAndSignedMessage sealedAndSignedMessage = (SealedAndSignedMessage) message;
+ DecryptedMessageWithPubKey decryptedMessageWithPubKey = encryptionService.decryptAndVerifyMessage(sealedAndSignedMessage.sealedAndSigned);
UserThread.execute(() -> decryptedMailListeners.stream().forEach(e -> e.onMailMessage(decryptedMessageWithPubKey, connection.getPeerAddress())));
} catch (CryptoException e) {
log.info("Decryption of SealedAndSignedMessage failed. That is expected if the message is not intended for us.");
@@ -343,7 +346,7 @@ public class P2PService {
private void doSendEncryptedMailMessage(Address peerAddress, PubKeyRing pubKeyRing, MailMessage message, SendMailMessageListener sendMailMessageListener) {
if (encryptionService != null) {
try {
- SealedAndSignedMessage sealedAndSignedMessage = encryptionService.encryptAndSignMessage(pubKeyRing, message);
+ SealedAndSignedMessage sealedAndSignedMessage = new SealedAndSignedMessage(encryptionService.encryptAndSignMessage(pubKeyRing, message), peerAddress);
SettableFuture future = sendMessage(peerAddress, sealedAndSignedMessage);
Futures.addCallback(future, new FutureCallback() {
@Override
@@ -386,7 +389,7 @@ public class P2PService {
private void trySendEncryptedMailboxMessage(Address peerAddress, PubKeyRing peersPubKeyRing, MailboxMessage message, SendMailboxMessageListener sendMailboxMessageListener) {
if (encryptionService != null) {
try {
- SealedAndSignedMessage sealedAndSignedMessage = encryptionService.encryptAndSignMessage(peersPubKeyRing, message);
+ SealedAndSignedMessage sealedAndSignedMessage = new SealedAndSignedMessage(encryptionService.encryptAndSignMessage(peersPubKeyRing, message), peerAddress);
SettableFuture future = sendMessage(peerAddress, sealedAndSignedMessage);
Futures.addCallback(future, new FutureCallback() {
@Override
@@ -630,9 +633,9 @@ public class P2PService {
ExpirablePayload data = mailboxData.expirablePayload;
if (data instanceof ExpirableMailboxPayload) {
ExpirableMailboxPayload mailboxEntry = (ExpirableMailboxPayload) data;
- SealedAndSignedMessage sealedAndSignedMessage = mailboxEntry.sealedAndSignedMessage;
+ SealedAndSigned sealedAndSigned = mailboxEntry.sealedAndSignedMessage.sealedAndSigned;
try {
- DecryptedMessageWithPubKey decryptedMessageWithPubKey = encryptionService.decryptAndVerifyMessage(sealedAndSignedMessage);
+ DecryptedMessageWithPubKey decryptedMessageWithPubKey = encryptionService.decryptAndVerifyMessage(sealedAndSigned);
if (decryptedMessageWithPubKey.message instanceof MailboxMessage) {
MailboxMessage mailboxMessage = (MailboxMessage) decryptedMessageWithPubKey.message;
Address senderAddress = mailboxMessage.getSenderAddress();
@@ -640,8 +643,8 @@ public class P2PService {
log.trace("mailboxData.publicKey " + mailboxData.ownerStoragePubKey.hashCode());
log.trace("keyRing.getStorageSignatureKeyPair().getPublic() " + keyRing.getStorageSignatureKeyPair().getPublic().hashCode());
- log.trace("keyRing.getMsgSignatureKeyPair().getPublic() " + keyRing.getMsgSignatureKeyPair().getPublic().hashCode());
- log.trace("keyRing.getMsgEncryptionKeyPair().getPublic() " + keyRing.getMsgEncryptionKeyPair().getPublic().hashCode());
+ log.trace("keyRing.getMsgSignatureKeyPair().getPublic() " + keyRing.getSignatureKeyPair().getPublic().hashCode());
+ log.trace("keyRing.getMsgEncryptionKeyPair().getPublic() " + keyRing.getEncryptionKeyPair().getPublic().hashCode());
mailboxMap.put(decryptedMessageWithPubKey, mailboxData);
diff --git a/network/src/main/java/io/bitsquare/p2p/network/Connection.java b/network/src/main/java/io/bitsquare/p2p/network/Connection.java
index b153e628bd..96514c9de6 100644
--- a/network/src/main/java/io/bitsquare/p2p/network/Connection.java
+++ b/network/src/main/java/io/bitsquare/p2p/network/Connection.java
@@ -355,7 +355,6 @@ public class Connection {
reportIllegalRequest(IllegalRequest.MaxSizeExceeded);
}
} catch (IOException | ClassNotFoundException e) {
- log.error("Exception" + e);
inputHandlerStopped = true;
handleConnectionException(e);
}
diff --git a/network/src/main/java/io/bitsquare/p2p/storage/ProtectedExpirableDataStorage.java b/network/src/main/java/io/bitsquare/p2p/storage/ProtectedExpirableDataStorage.java
index 1f56c1e0fe..458a4b7d60 100644
--- a/network/src/main/java/io/bitsquare/p2p/storage/ProtectedExpirableDataStorage.java
+++ b/network/src/main/java/io/bitsquare/p2p/storage/ProtectedExpirableDataStorage.java
@@ -2,7 +2,8 @@ package io.bitsquare.p2p.storage;
import com.google.common.annotations.VisibleForTesting;
import io.bitsquare.common.UserThread;
-import io.bitsquare.common.crypto.CryptoUtil;
+import io.bitsquare.common.crypto.Hash;
+import io.bitsquare.common.crypto.Sig;
import io.bitsquare.p2p.Address;
import io.bitsquare.p2p.network.IllegalRequest;
import io.bitsquare.p2p.network.MessageListener;
@@ -192,8 +193,8 @@ public class ProtectedExpirableDataStorage {
else
sequenceNumber = 0;
- byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(payload, sequenceNumber));
- byte[] signature = CryptoUtil.signStorageData(ownerStoragePubKey.getPrivate(), hashOfDataAndSeqNr);
+ byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(payload, sequenceNumber));
+ byte[] signature = Sig.sign(ownerStoragePubKey.getPrivate(), hashOfDataAndSeqNr);
return new ProtectedData(payload, payload.getTTL(), ownerStoragePubKey.getPublic(), sequenceNumber, signature);
}
@@ -206,8 +207,8 @@ public class ProtectedExpirableDataStorage {
else
sequenceNumber = 0;
- byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(expirableMailboxPayload, sequenceNumber));
- byte[] signature = CryptoUtil.signStorageData(storageSignaturePubKey.getPrivate(), hashOfDataAndSeqNr);
+ byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(expirableMailboxPayload, sequenceNumber));
+ byte[] signature = Sig.sign(storageSignaturePubKey.getPrivate(), hashOfDataAndSeqNr);
return new ProtectedMailboxData(expirableMailboxPayload, expirableMailboxPayload.getTTL(), storageSignaturePubKey.getPublic(), sequenceNumber, signature, receiversPublicKey);
}
@@ -248,9 +249,9 @@ public class ProtectedExpirableDataStorage {
}
private boolean checkSignature(ProtectedData data) {
- byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, data.sequenceNumber));
+ byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, data.sequenceNumber));
try {
- boolean result = CryptoUtil.verifyStorageData(data.ownerStoragePubKey, hashOfDataAndSeqNr, data.signature);
+ boolean result = Sig.verify(data.ownerStoragePubKey, hashOfDataAndSeqNr, data.signature);
if (!result)
log.error("Signature verification failed at checkSignature. " +
"That should not happen. Consider it might be an attempt of fraud.");
@@ -317,6 +318,6 @@ public class ProtectedExpirableDataStorage {
}
private BigInteger getHashAsBigInteger(ExpirablePayload payload) {
- return new BigInteger(CryptoUtil.getHash(payload));
+ return new BigInteger(Hash.getHash(payload));
}
}
diff --git a/network/src/main/java/io/bitsquare/p2p/storage/data/ExpirableMailboxPayload.java b/network/src/main/java/io/bitsquare/p2p/storage/data/ExpirableMailboxPayload.java
index 4fc88f254c..193d7652ad 100644
--- a/network/src/main/java/io/bitsquare/p2p/storage/data/ExpirableMailboxPayload.java
+++ b/network/src/main/java/io/bitsquare/p2p/storage/data/ExpirableMailboxPayload.java
@@ -1,7 +1,7 @@
package io.bitsquare.p2p.storage.data;
import io.bitsquare.app.Version;
-import io.bitsquare.p2p.messaging.SealedAndSignedMessage;
+import io.bitsquare.crypto.SealedAndSignedMessage;
import java.security.PublicKey;
diff --git a/network/src/test/java/io/bitsquare/crypto/EncryptionServiceTests.java b/network/src/test/java/io/bitsquare/crypto/EncryptionServiceTests.java
index 0eba125c26..41bb5f4b25 100644
--- a/network/src/test/java/io/bitsquare/crypto/EncryptionServiceTests.java
+++ b/network/src/test/java/io/bitsquare/crypto/EncryptionServiceTests.java
@@ -26,7 +26,6 @@ import io.bitsquare.common.util.Utilities;
import io.bitsquare.p2p.Address;
import io.bitsquare.p2p.messaging.DecryptedMessageWithPubKey;
import io.bitsquare.p2p.messaging.MailboxMessage;
-import io.bitsquare.p2p.messaging.SealedAndSignedMessage;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -70,8 +69,8 @@ public class EncryptionServiceTests {
public void testDecryptAndVerifyMessage() throws CryptoException {
EncryptionService encryptionService = new EncryptionService(keyRing);
TestMessage data = new TestMessage("test");
- SealedAndSignedMessage encrypted = encryptionService.encryptAndSignMessage(pubKeyRing, data);
- DecryptedMessageWithPubKey decrypted = encryptionService.decryptAndVerifyMessage(encrypted);
+ SealedAndSignedMessage encrypted = new SealedAndSignedMessage(encryptionService.encryptAndSignMessage(pubKeyRing, data), null);
+ DecryptedMessageWithPubKey decrypted = encryptionService.decryptAndVerifyMessage(encrypted.sealedAndSigned);
assertEquals(data.data, ((TestMessage) decrypted.message).data);
}
diff --git a/network/src/test/java/io/bitsquare/p2p/P2PServiceTest.java b/network/src/test/java/io/bitsquare/p2p/P2PServiceTest.java
index 6982842a0c..2221c456cf 100644
--- a/network/src/test/java/io/bitsquare/p2p/P2PServiceTest.java
+++ b/network/src/test/java/io/bitsquare/p2p/P2PServiceTest.java
@@ -1,13 +1,10 @@
package io.bitsquare.p2p;
-import io.bitsquare.common.crypto.CryptoException;
-import io.bitsquare.common.crypto.CryptoUtil;
-import io.bitsquare.common.crypto.KeyRing;
-import io.bitsquare.common.crypto.KeyStorage;
+import io.bitsquare.common.crypto.*;
import io.bitsquare.crypto.EncryptionService;
+import io.bitsquare.crypto.SealedAndSignedMessage;
import io.bitsquare.p2p.messaging.DecryptedMessageWithPubKey;
import io.bitsquare.p2p.messaging.MailboxMessage;
-import io.bitsquare.p2p.messaging.SealedAndSignedMessage;
import io.bitsquare.p2p.messaging.SendMailboxMessageListener;
import io.bitsquare.p2p.mocks.MockMailboxMessage;
import io.bitsquare.p2p.network.LocalhostNetworkNode;
@@ -161,8 +158,8 @@ public class P2PServiceTest {
// try to manipulate seq nr. + pubKey + sig -> fails
int sequenceNumberManipulated = origProtectedData.sequenceNumber + 1;
- byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(origProtectedData.expirablePayload, sequenceNumberManipulated));
- byte[] signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
+ byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(origProtectedData.expirablePayload, sequenceNumberManipulated));
+ byte[] signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
Assert.assertFalse(p2PService3.removeData(protectedDataManipulated.expirablePayload));
Thread.sleep(sleepTime);
@@ -183,8 +180,8 @@ public class P2PServiceTest {
// first he tries to use the orig. pubKey in the data -> fails as pub keys not matching
MockData manipulatedData = new MockData("mockData1_manipulated", origData.publicKey);
sequenceNumberManipulated = 0;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
- signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
+ signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload));
Thread.sleep(sleepTime);
@@ -195,8 +192,8 @@ public class P2PServiceTest {
// then he tries to use his pubKey but orig data payload -> fails as pub keys nto matching
manipulatedData = new MockData("mockData1_manipulated", msgSignatureKeyPairAdversary.getPublic());
sequenceNumberManipulated = 0;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
- signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
+ signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload));
Thread.sleep(sleepTime);
@@ -208,8 +205,8 @@ public class P2PServiceTest {
// payload data has adversary's pubKey so he could hijack the owners data
manipulatedData = new MockData("mockData1_manipulated", msgSignatureKeyPairAdversary.getPublic());
sequenceNumberManipulated = 0;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
- signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
+ signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
protectedDataManipulated = new ProtectedData(manipulatedData, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
Assert.assertTrue(p2PService3.addData(protectedDataManipulated.expirablePayload));
Thread.sleep(sleepTime);
@@ -228,8 +225,8 @@ public class P2PServiceTest {
// finally he tries both previous attempts with same data - > same as before
manipulatedData = new MockData("mockData1", origData.publicKey);
sequenceNumberManipulated = 0;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
- signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
+ signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload));
Thread.sleep(sleepTime);
@@ -239,8 +236,8 @@ public class P2PServiceTest {
manipulatedData = new MockData("mockData1", msgSignatureKeyPairAdversary.getPublic());
sequenceNumberManipulated = 0;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
- signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
+ signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
protectedDataManipulated = new ProtectedData(manipulatedData, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
Assert.assertTrue(p2PService3.addData(protectedDataManipulated.expirablePayload));
Thread.sleep(sleepTime);
@@ -275,7 +272,8 @@ public class P2PServiceTest {
log.trace("message " + message);
if (message instanceof SealedAndSignedMessage) {
try {
- DecryptedMessageWithPubKey decryptedMessageWithPubKey = encryptionService2.decryptAndVerifyMessage((SealedAndSignedMessage) message);
+ SealedAndSignedMessage sealedAndSignedMessage = (SealedAndSignedMessage) message;
+ DecryptedMessageWithPubKey decryptedMessageWithPubKey = encryptionService2.decryptAndVerifyMessage(sealedAndSignedMessage.sealedAndSigned);
Assert.assertEquals(mockMessage, decryptedMessageWithPubKey.message);
Assert.assertEquals(p2PService2.getAddress(), ((MailboxMessage) decryptedMessageWithPubKey.message).getSenderAddress());
latch2.countDown();
diff --git a/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java b/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java
index 8ba0689ba9..60eb105a33 100644
--- a/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java
+++ b/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java
@@ -1,15 +1,12 @@
package io.bitsquare.p2p.storage;
import io.bitsquare.common.UserThread;
-import io.bitsquare.common.crypto.CryptoException;
-import io.bitsquare.common.crypto.CryptoUtil;
-import io.bitsquare.common.crypto.KeyRing;
-import io.bitsquare.common.crypto.KeyStorage;
+import io.bitsquare.common.crypto.*;
import io.bitsquare.common.util.Utilities;
import io.bitsquare.crypto.EncryptionService;
+import io.bitsquare.crypto.SealedAndSignedMessage;
import io.bitsquare.p2p.Address;
import io.bitsquare.p2p.TestUtils;
-import io.bitsquare.p2p.messaging.SealedAndSignedMessage;
import io.bitsquare.p2p.mocks.MockMessage;
import io.bitsquare.p2p.network.NetworkNode;
import io.bitsquare.p2p.routing.Routing;
@@ -89,8 +86,8 @@ public class ProtectedDataStorageTest {
Assert.assertEquals(1, dataStorage1.getMap().size());
int newSequenceNumber = data.sequenceNumber + 1;
- byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
- byte[] signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
+ byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
+ byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
ProtectedData dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
Assert.assertTrue(dataStorage1.remove(dataToRemove, null));
Assert.assertEquals(0, dataStorage1.getMap().size());
@@ -118,12 +115,12 @@ public class ProtectedDataStorageTest {
// add with date in future
data = dataStorage1.getDataWithSignedSeqNr(mockData, storageSignatureKeyPair1);
int newSequenceNumber = data.sequenceNumber + 1;
- byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
- byte[] signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
+ byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
+ byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
ProtectedData dataWithFutureDate = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
dataWithFutureDate.date = new Date(new Date().getTime() + 60 * 60 * sleepTime);
// force serialisation (date check is done in readObject)
- ProtectedData newData = Utilities.byteArrayToObject(Utilities.objectToByteArray(dataWithFutureDate));
+ ProtectedData newData = Utilities.deserialize(Utilities.serialize(dataWithFutureDate));
Assert.assertTrue(dataStorage1.add(newData, null));
Thread.sleep(5);
Assert.assertEquals(1, dataStorage1.getMap().size());
@@ -139,57 +136,57 @@ public class ProtectedDataStorageTest {
// remove with not updated seq nr -> failure
int newSequenceNumber = 0;
- byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
- byte[] signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
+ byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
+ byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
ProtectedData dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
Assert.assertFalse(dataStorage1.remove(dataToRemove, null));
// remove with too high updated seq nr -> ok
newSequenceNumber = 2;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
+ signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
Assert.assertTrue(dataStorage1.remove(dataToRemove, null));
// add with updated seq nr below previous -> failure
newSequenceNumber = 1;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
+ signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
ProtectedData dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
Assert.assertFalse(dataStorage1.add(dataToAdd, null));
// add with updated seq nr over previous -> ok
newSequenceNumber = 3;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
+ signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
Assert.assertTrue(dataStorage1.add(dataToAdd, null));
// add with same seq nr -> failure
newSequenceNumber = 3;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
+ signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
Assert.assertFalse(dataStorage1.add(dataToAdd, null));
// add with same data but higher seq nr. -> ok, ignore
newSequenceNumber = 4;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
+ signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
Assert.assertTrue(dataStorage1.add(dataToAdd, null));
// remove with with same seq nr as prev. ignored -> failed
newSequenceNumber = 4;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
+ signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
Assert.assertFalse(dataStorage1.remove(dataToRemove, null));
// remove with with higher seq nr -> ok
newSequenceNumber = 5;
- hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
+ hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
+ signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
Assert.assertTrue(dataStorage1.remove(dataToRemove, null));
}
@@ -198,7 +195,7 @@ public class ProtectedDataStorageTest {
public void testAddAndRemoveMailboxData() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException {
// sender
MockMessage mockMessage = new MockMessage("MockMessage");
- SealedAndSignedMessage sealedAndSignedMessage = encryptionService1.encryptAndSignMessage(keyRing1.getPubKeyRing(), mockMessage);
+ SealedAndSignedMessage sealedAndSignedMessage = new SealedAndSignedMessage(encryptionService1.encryptAndSignMessage(keyRing1.getPubKeyRing(), mockMessage), null);
ExpirableMailboxPayload expirableMailboxPayload = new ExpirableMailboxPayload(sealedAndSignedMessage,
keyRing1.getStorageSignatureKeyPair().getPublic(),
keyRing2.getStorageSignatureKeyPair().getPublic());
@@ -210,34 +207,34 @@ public class ProtectedDataStorageTest {
// receiver (storageSignatureKeyPair2)
int newSequenceNumber = data.sequenceNumber + 1;
- byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
+ byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
byte[] signature;
ProtectedMailboxData dataToRemove;
// wrong sig -> fail
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
+ signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
dataToRemove = new ProtectedMailboxData(expirableMailboxPayload, data.ttl, storageSignatureKeyPair2.getPublic(), newSequenceNumber, signature, storageSignatureKeyPair2.getPublic());
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
// wrong seq nr
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair2.getPrivate(), hashOfDataAndSeqNr);
+ signature = Sig.sign(storageSignatureKeyPair2.getPrivate(), hashOfDataAndSeqNr);
dataToRemove = new ProtectedMailboxData(expirableMailboxPayload, data.ttl, storageSignatureKeyPair2.getPublic(), data.sequenceNumber, signature, storageSignatureKeyPair2.getPublic());
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
// wrong signingKey
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair2.getPrivate(), hashOfDataAndSeqNr);
+ signature = Sig.sign(storageSignatureKeyPair2.getPrivate(), hashOfDataAndSeqNr);
dataToRemove = new ProtectedMailboxData(expirableMailboxPayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature, storageSignatureKeyPair2.getPublic());
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
// wrong peerPubKey
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair2.getPrivate(), hashOfDataAndSeqNr);
+ signature = Sig.sign(storageSignatureKeyPair2.getPrivate(), hashOfDataAndSeqNr);
dataToRemove = new ProtectedMailboxData(expirableMailboxPayload, data.ttl, storageSignatureKeyPair2.getPublic(), newSequenceNumber, signature, storageSignatureKeyPair1.getPublic());
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
// receiver can remove it (storageSignatureKeyPair2) -> all ok
Assert.assertEquals(1, dataStorage1.getMap().size());
- signature = CryptoUtil.signStorageData(storageSignatureKeyPair2.getPrivate(), hashOfDataAndSeqNr);
+ signature = Sig.sign(storageSignatureKeyPair2.getPrivate(), hashOfDataAndSeqNr);
dataToRemove = new ProtectedMailboxData(expirableMailboxPayload, data.ttl, storageSignatureKeyPair2.getPublic(), newSequenceNumber, signature, storageSignatureKeyPair2.getPublic());
Assert.assertTrue(dataStorage1.removeMailboxData(dataToRemove, null));