mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Add Hmac to encrypted object, refactor crypto code (WIP)
This commit is contained in:
parent
4604e9c0bd
commit
4883c90030
@ -1,6 +1,9 @@
|
|||||||
package io.bitsquare.p2p.seed;
|
package io.bitsquare.p2p.seed;
|
||||||
|
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.Security;
|
||||||
|
|
||||||
public class SeedNodeMain {
|
public class SeedNodeMain {
|
||||||
|
|
||||||
@ -8,6 +11,8 @@ public class SeedNodeMain {
|
|||||||
// eg. 4444 true localhost:7777 localhost:8888
|
// eg. 4444 true localhost:7777 localhost:8888
|
||||||
// To stop enter: q
|
// To stop enter: q
|
||||||
public static void main(String[] args) throws NoSuchAlgorithmException {
|
public static void main(String[] args) throws NoSuchAlgorithmException {
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
|
||||||
SeedNode seedNode = new SeedNode();
|
SeedNode seedNode = new SeedNode();
|
||||||
seedNode.processArgs(args);
|
seedNode.processArgs(args);
|
||||||
seedNode.createAndStartP2PService();
|
seedNode.createAndStartP2PService();
|
||||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,54 +15,28 @@
|
|||||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.bitsquare.p2p.messaging;
|
package io.bitsquare.common.crypto;
|
||||||
|
|
||||||
import io.bitsquare.app.Version;
|
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.security.PublicKey;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Packs the encrypted symmetric secretKey and the encrypted and signed message into one object.
|
* 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.
|
* 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.
|
* 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.
|
// 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;
|
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
public final SealedObject sealedSecretKey;
|
public final Serializable payload;
|
||||||
public final SealedObject sealedMessage;
|
public final PublicKey sigPublicKey;
|
||||||
public final PublicKey signaturePubKey;
|
|
||||||
|
|
||||||
public SealedAndSignedMessage(SealedObject sealedSecretKey, SealedObject sealedMessage, PublicKey signaturePubKey) {
|
public DecryptedPayloadWithPubKey(Serializable payload, PublicKey sigPublicKey) {
|
||||||
this.sealedSecretKey = sealedSecretKey;
|
this.payload = payload;
|
||||||
this.sealedMessage = sealedMessage;
|
this.sigPublicKey = sigPublicKey;
|
||||||
this.signaturePubKey = signaturePubKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@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() +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
}
|
276
common/src/main/java/io/bitsquare/common/crypto/Encryption.java
Normal file
276
common/src/main/java/io/bitsquare/common/crypto/Encryption.java
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
83
common/src/main/java/io/bitsquare/common/crypto/Hash.java
Normal file
83
common/src/main/java/io/bitsquare/common/crypto/Hash.java
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -22,77 +22,42 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
|
|
||||||
public class KeyRing {
|
public class KeyRing {
|
||||||
private static final Logger log = LoggerFactory.getLogger(KeyRing.class);
|
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
|
// 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)
|
// 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 PubKeyRing pubKeyRing;
|
||||||
private final KeyStorage keyStorage;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public KeyRing(KeyStorage keyStorage) throws CryptoException {
|
public KeyRing(KeyStorage keyStorage) {
|
||||||
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 {
|
|
||||||
if (keyStorage.allKeyFilesExist()) {
|
if (keyStorage.allKeyFilesExist()) {
|
||||||
storageSignatureKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.STORAGE_SIGNATURE);
|
signatureKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.MSG_SIGNATURE);
|
||||||
msgSignatureKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.MSG_SIGNATURE);
|
encryptionKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.MSG_ENCRYPTION);
|
||||||
msgEncryptionKeyPair = keyStorage.loadKeyPair(KeyStorage.Key.MSG_ENCRYPTION);
|
|
||||||
} else {
|
} else {
|
||||||
// First time we create key pairs
|
// First time we create key pairs
|
||||||
try {
|
signatureKeyPair = Sig.generateKeyPair();
|
||||||
this.storageSignatureKeyPair = CryptoUtil.generateStorageSignatureKeyPair();
|
encryptionKeyPair = Encryption.generateEncryptionKeyPair();
|
||||||
this.msgSignatureKeyPair = CryptoUtil.generateMsgSignatureKeyPair();
|
|
||||||
this.msgEncryptionKeyPair = CryptoUtil.generateMsgEncryptionKeyPair();
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new CryptoException("Error at KeyRing constructor ", e);
|
|
||||||
}
|
|
||||||
keyStorage.saveKeyRing(this);
|
keyStorage.saveKeyRing(this);
|
||||||
}
|
}
|
||||||
|
pubKeyRing = new PubKeyRing(signatureKeyPair.getPublic(), signatureKeyPair.getPublic(), encryptionKeyPair.getPublic());
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
public KeyPair getStorageSignatureKeyPair() {
|
public KeyPair getStorageSignatureKeyPair() {
|
||||||
return storageSignatureKeyPair;
|
return signatureKeyPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyPair getMsgSignatureKeyPair() {
|
public KeyPair getSignatureKeyPair() {
|
||||||
return msgSignatureKeyPair;
|
return signatureKeyPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyPair getMsgEncryptionKeyPair() {
|
public KeyPair getEncryptionKeyPair() {
|
||||||
return msgEncryptionKeyPair;
|
return encryptionKeyPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PubKeyRing getPubKeyRing() {
|
public PubKeyRing getPubKeyRing() {
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
package io.bitsquare.common.crypto;
|
package io.bitsquare.common.crypto;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -39,14 +38,10 @@ public class KeyStorage {
|
|||||||
|
|
||||||
public static final String DIR_KEY = "key.storage.dir";
|
public static final String DIR_KEY = "key.storage.dir";
|
||||||
|
|
||||||
static {
|
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Key {
|
public enum Key {
|
||||||
STORAGE_SIGNATURE("storageSignature", CryptoUtil.STORAGE_SIGN_KEY_ALGO),
|
STORAGE_SIGNATURE("storageSignature", Sig.KEY_ALGO),
|
||||||
MSG_SIGNATURE("msgSignature", CryptoUtil.MSG_SIGN_KEY_ALGO),
|
MSG_SIGNATURE("msgSignature", Sig.KEY_ALGO),
|
||||||
MSG_ENCRYPTION("msgEncryption", CryptoUtil.MSG_ENCR_KEY_ALGO);
|
MSG_ENCRYPTION("msgEncryption", Encryption.ENCR_KEY_ALGO);
|
||||||
|
|
||||||
private final String fileName;
|
private final String fileName;
|
||||||
private final String algorithm;
|
private final String algorithm;
|
||||||
@ -81,7 +76,7 @@ public class KeyStorage {
|
|||||||
this.storageDir = storageDir;
|
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);
|
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();
|
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();
|
// long now = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
KeyFactory keyFactory = KeyFactory.getInstance(key.getAlgorithm());
|
KeyFactory keyFactory = KeyFactory.getInstance(key.getAlgorithm());
|
||||||
@ -106,7 +101,7 @@ public class KeyStorage {
|
|||||||
} catch (InvalidKeySpecException | IOException e) {
|
} catch (InvalidKeySpecException | IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
log.error(e.getMessage());
|
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");
|
File filePrivateKey = new File(storageDir + "/" + key.getFileName() + "Priv.key");
|
||||||
@ -119,7 +114,7 @@ public class KeyStorage {
|
|||||||
} catch (InvalidKeySpecException | IOException e) {
|
} catch (InvalidKeySpecException | IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
log.error(e.getMessage());
|
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);
|
//log.info("load completed in {} msec", System.currentTimeMillis() - now);
|
||||||
return new KeyPair(publicKey, privateKey);
|
return new KeyPair(publicKey, privateKey);
|
||||||
@ -127,17 +122,17 @@ public class KeyStorage {
|
|||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
log.error(e.getMessage());
|
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.getStorageSignatureKeyPair(), Key.STORAGE_SIGNATURE.getFileName());
|
||||||
saveKeyPair(keyRing.getMsgSignatureKeyPair(), Key.MSG_SIGNATURE.getFileName());
|
saveKeyPair(keyRing.getSignatureKeyPair(), Key.MSG_SIGNATURE.getFileName());
|
||||||
saveKeyPair(keyRing.getMsgEncryptionKeyPair(), Key.MSG_ENCRYPTION.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())
|
if (!storageDir.exists())
|
||||||
storageDir.mkdir();
|
storageDir.mkdir();
|
||||||
|
|
||||||
@ -147,7 +142,7 @@ public class KeyStorage {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
log.error(e.getMessage());
|
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());
|
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyPair.getPrivate().getEncoded());
|
||||||
@ -156,7 +151,7 @@ public class KeyStorage {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
throw new CryptoException("Could not save key " + name, e);
|
throw new RuntimeException("Could not save key " + name, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,22 +45,22 @@ public class PubKeyRing implements Serializable {
|
|||||||
|
|
||||||
transient private PublicKey storageSignaturePubKey;
|
transient private PublicKey storageSignaturePubKey;
|
||||||
transient private PublicKey msgSignaturePubKey;
|
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.storageSignaturePubKey = storageSignaturePubKey;
|
||||||
this.msgSignaturePubKey = msgSignaturePubKey;
|
this.msgSignaturePubKey = msgSignaturePubKey;
|
||||||
this.msgEncryptionPubKey = msgEncryptionPubKey;
|
this.encryptionPubKey = encryptionPubKey;
|
||||||
|
|
||||||
this.storageSignaturePubKeyBytes = new X509EncodedKeySpec(storageSignaturePubKey.getEncoded()).getEncoded();
|
this.storageSignaturePubKeyBytes = new X509EncodedKeySpec(storageSignaturePubKey.getEncoded()).getEncoded();
|
||||||
this.msgSignaturePubKeyBytes = new X509EncodedKeySpec(msgSignaturePubKey.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() {
|
public PublicKey getStorageSignaturePubKey() {
|
||||||
if (storageSignaturePubKey == null) {
|
if (storageSignaturePubKey == null) {
|
||||||
try {
|
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) {
|
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
@ -73,7 +73,7 @@ public class PubKeyRing implements Serializable {
|
|||||||
public PublicKey getMsgSignaturePubKey() {
|
public PublicKey getMsgSignaturePubKey() {
|
||||||
if (msgSignaturePubKey == null) {
|
if (msgSignaturePubKey == null) {
|
||||||
try {
|
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) {
|
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
@ -82,16 +82,16 @@ public class PubKeyRing implements Serializable {
|
|||||||
return msgSignaturePubKey;
|
return msgSignaturePubKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PublicKey getMsgEncryptionPubKey() {
|
public PublicKey getEncryptionPubKey() {
|
||||||
if (msgEncryptionPubKey == null) {
|
if (encryptionPubKey == null) {
|
||||||
try {
|
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) {
|
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return msgEncryptionPubKey;
|
return encryptionPubKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -118,9 +118,9 @@ public class PubKeyRing implements Serializable {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PubKeyRing{" +
|
return "PubKeyRing{" +
|
||||||
"\nstorageSignaturePubKey=\n" + CryptoUtil.pubKeyToString(getStorageSignaturePubKey()) +
|
"\nstorageSignaturePubKey=\n" + Util.pubKeyToString(getStorageSignaturePubKey()) +
|
||||||
"\n\nmsgSignaturePubKey=\n" + CryptoUtil.pubKeyToString(getMsgSignaturePubKey()) +
|
"\n\nmsgSignaturePubKey=\n" + Util.pubKeyToString(getMsgSignaturePubKey()) +
|
||||||
"\n\nmsgEncryptionPubKey=\n" + CryptoUtil.pubKeyToString(getMsgEncryptionPubKey()) +
|
"\n\nmsgEncryptionPubKey=\n" + Util.pubKeyToString(getEncryptionPubKey()) +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
121
common/src/main/java/io/bitsquare/common/crypto/Sig.java
Normal file
121
common/src/main/java/io/bitsquare/common/crypto/Sig.java
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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.
|
||||||
|
* <p>
|
||||||
|
* 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
34
common/src/main/java/io/bitsquare/common/crypto/Util.java
Normal file
34
common/src/main/java/io/bitsquare/common/crypto/Util.java
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,7 +17,9 @@
|
|||||||
|
|
||||||
package io.bitsquare.common.util;
|
package io.bitsquare.common.util;
|
||||||
|
|
||||||
public class Tuple2<A, B> {
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class Tuple2<A, B> implements Serializable {
|
||||||
final public A first;
|
final public A first;
|
||||||
final public B second;
|
final public B second;
|
||||||
|
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
|
|
||||||
package io.bitsquare.common.util;
|
package io.bitsquare.common.util;
|
||||||
|
|
||||||
public class Tuple3<A, B, C> {
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class Tuple3<A, B, C> implements Serializable {
|
||||||
final public A first;
|
final public A first;
|
||||||
final public B second;
|
final public B second;
|
||||||
final public C third;
|
final public C third;
|
||||||
|
@ -208,13 +208,15 @@ public class Utilities {
|
|||||||
return result;
|
return result;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public static <T> T byteArrayToObject(byte[] data) {
|
public static <T extends Serializable> T deserialize(byte[] data) {
|
||||||
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
||||||
ObjectInput in = null;
|
ObjectInput in = null;
|
||||||
Object result = null;
|
Object result = null;
|
||||||
try {
|
try {
|
||||||
in = new ObjectInputStream(bis);
|
in = new ObjectInputStream(bis);
|
||||||
result = in.readObject();
|
result = in.readObject();
|
||||||
|
if (!(result instanceof Serializable))
|
||||||
|
throw new RuntimeException("Object not of type Serializable");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
@ -234,14 +236,15 @@ public class Utilities {
|
|||||||
return (T) result;
|
return (T) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] objectToByteArray(Object object) {
|
public static byte[] serialize(Serializable object) {
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
ObjectOutput out = null;
|
ObjectOutput out = null;
|
||||||
byte[] result = null;
|
byte[] result = null;
|
||||||
try {
|
try {
|
||||||
out = new ObjectOutputStream(bos);
|
out = new ObjectOutputStream(bos);
|
||||||
out.writeObject(object);
|
out.writeObject(object);
|
||||||
result = bos.toByteArray();
|
out.flush();
|
||||||
|
result = bos.toByteArray().clone();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
@ -249,13 +252,11 @@ public class Utilities {
|
|||||||
if (out != null) {
|
if (out != null) {
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ignore) {
|
||||||
// ignore close exception
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
bos.close();
|
bos.close();
|
||||||
} catch (IOException ex) {
|
} catch (IOException ignore) {
|
||||||
// ignore close exception
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -25,6 +25,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@ -68,9 +69,9 @@ public class PublishDepositTxRequest extends TradeMessage {
|
|||||||
this.openDisputeTimeAsBlockHeight = openDisputeTimeAsBlockHeight;
|
this.openDisputeTimeAsBlockHeight = openDisputeTimeAsBlockHeight;
|
||||||
this.checkPaymentTimeAsBlockHeight = checkPaymentTimeAsBlockHeight;
|
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("offererTradeWalletPubKey size " + offererTradeWalletPubKey.length);
|
||||||
log.trace("preparedDepositTx size " + preparedDepositTx.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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.buyer;
|
|||||||
|
|
||||||
import io.bitsquare.btc.FeePolicy;
|
import io.bitsquare.btc.FeePolicy;
|
||||||
import io.bitsquare.btc.data.PreparedDepositTxAndOffererInputs;
|
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.common.taskrunner.TaskRunner;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||||
@ -49,7 +49,7 @@ public class CreateAndSignDepositTxAsBuyer extends TradeTask {
|
|||||||
log.debug(trade.getContractAsJson());
|
log.debug(trade.getContractAsJson());
|
||||||
log.debug("----------");
|
log.debug("----------");
|
||||||
|
|
||||||
byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
|
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
|
||||||
trade.setContractHash(contractHash);
|
trade.setContractHash(contractHash);
|
||||||
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(
|
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(
|
||||||
true,
|
true,
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
package io.bitsquare.trade.protocol.trade.tasks.buyer;
|
package io.bitsquare.trade.protocol.trade.tasks.buyer;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
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.common.taskrunner.TaskRunner;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||||
@ -41,7 +41,7 @@ public class SignAndPublishDepositTxAsBuyer extends TradeTask {
|
|||||||
try {
|
try {
|
||||||
runInterceptHook();
|
runInterceptHook();
|
||||||
|
|
||||||
byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
|
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
|
||||||
trade.setContractHash(contractHash);
|
trade.setContractHash(contractHash);
|
||||||
processModel.getTradeWalletService().takerSignsAndPublishesDepositTx(
|
processModel.getTradeWalletService().takerSignsAndPublishesDepositTx(
|
||||||
false,
|
false,
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.tasks.offerer;
|
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.taskrunner.TaskRunner;
|
||||||
import io.bitsquare.common.util.Utilities;
|
import io.bitsquare.common.util.Utilities;
|
||||||
import io.bitsquare.p2p.Address;
|
import io.bitsquare.p2p.Address;
|
||||||
@ -75,7 +75,7 @@ public class CreateAndSignContract extends TradeTask {
|
|||||||
taker.getTradeWalletPubKey()
|
taker.getTradeWalletPubKey()
|
||||||
);
|
);
|
||||||
String contractAsJson = Utilities.objectToJson(contract);
|
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.setContract(contract);
|
||||||
trade.setContractAsJson(contractAsJson);
|
trade.setContractAsJson(contractAsJson);
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.tasks.offerer;
|
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.common.taskrunner.TaskRunner;
|
||||||
import io.bitsquare.locale.CurrencyUtil;
|
import io.bitsquare.locale.CurrencyUtil;
|
||||||
import io.bitsquare.payment.BlockChainAccountContractData;
|
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
|
// 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 &&
|
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
|
||||||
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
|
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);
|
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
|
|||||||
|
|
||||||
import io.bitsquare.btc.FeePolicy;
|
import io.bitsquare.btc.FeePolicy;
|
||||||
import io.bitsquare.btc.data.PreparedDepositTxAndOffererInputs;
|
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.common.taskrunner.TaskRunner;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
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 sellerInputAmount = FeePolicy.SECURITY_DEPOSIT.add(FeePolicy.TX_FEE).add(trade.getTradeAmount());
|
||||||
Coin msOutputAmount = sellerInputAmount.add(FeePolicy.SECURITY_DEPOSIT);
|
Coin msOutputAmount = sellerInputAmount.add(FeePolicy.SECURITY_DEPOSIT);
|
||||||
|
|
||||||
byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
|
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
|
||||||
trade.setContractHash(contractHash);
|
trade.setContractHash(contractHash);
|
||||||
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(
|
PreparedDepositTxAndOffererInputs result = processModel.getTradeWalletService().offererCreatesAndSignsDepositTx(
|
||||||
false,
|
false,
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
package io.bitsquare.trade.protocol.trade.tasks.seller;
|
package io.bitsquare.trade.protocol.trade.tasks.seller;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
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.common.taskrunner.TaskRunner;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
|
||||||
@ -44,7 +44,7 @@ public class SignAndPublishDepositTxAsSeller extends TradeTask {
|
|||||||
log.debug("----------");
|
log.debug("----------");
|
||||||
log.debug(trade.getContractAsJson());
|
log.debug(trade.getContractAsJson());
|
||||||
log.debug("----------");
|
log.debug("----------");
|
||||||
byte[] contractHash = CryptoUtil.getHash(trade.getContractAsJson());
|
byte[] contractHash = Hash.getHash(trade.getContractAsJson());
|
||||||
trade.setContractHash(contractHash);
|
trade.setContractHash(contractHash);
|
||||||
processModel.getTradeWalletService().takerSignsAndPublishesDepositTx(
|
processModel.getTradeWalletService().takerSignsAndPublishesDepositTx(
|
||||||
true,
|
true,
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.tasks.taker;
|
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.common.taskrunner.TaskRunner;
|
||||||
import io.bitsquare.locale.CurrencyUtil;
|
import io.bitsquare.locale.CurrencyUtil;
|
||||||
import io.bitsquare.payment.BlockChainAccountContractData;
|
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
|
// 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 &&
|
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
|
||||||
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
|
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);
|
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.tasks.taker;
|
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.taskrunner.TaskRunner;
|
||||||
import io.bitsquare.common.util.Utilities;
|
import io.bitsquare.common.util.Utilities;
|
||||||
import io.bitsquare.p2p.Address;
|
import io.bitsquare.p2p.Address;
|
||||||
@ -74,13 +74,13 @@ public class VerifyAndSignContract extends TradeTask {
|
|||||||
processModel.getTradeWalletPubKey()
|
processModel.getTradeWalletPubKey()
|
||||||
);
|
);
|
||||||
String contractAsJson = Utilities.objectToJson(contract);
|
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.setContract(contract);
|
||||||
trade.setContractAsJson(contractAsJson);
|
trade.setContractAsJson(contractAsJson);
|
||||||
trade.setTakerContractSignature(signature);
|
trade.setTakerContractSignature(signature);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CryptoUtil.verifyMessage(offerer.getPubKeyRing().getMsgSignaturePubKey(),
|
Sig.verify(offerer.getPubKeyRing().getMsgSignaturePubKey(),
|
||||||
contractAsJson,
|
contractAsJson,
|
||||||
offerer.getContractSignature());
|
offerer.getContractSignature());
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
@ -54,6 +54,7 @@ import javafx.scene.layout.StackPane;
|
|||||||
import javafx.stage.Modality;
|
import javafx.stage.Modality;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import javafx.stage.StageStyle;
|
import javafx.stage.StageStyle;
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.controlsfx.dialog.Dialogs;
|
import org.controlsfx.dialog.Dialogs;
|
||||||
import org.reactfx.EventStreams;
|
import org.reactfx.EventStreams;
|
||||||
import org.reactfx.util.FxTimer;
|
import org.reactfx.util.FxTimer;
|
||||||
@ -62,6 +63,7 @@ import org.springframework.core.env.Environment;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.security.Security;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -113,6 +115,8 @@ public class BitsquareApp extends Application {
|
|||||||
Thread.setDefaultUncaughtExceptionHandler(handler);
|
Thread.setDefaultUncaughtExceptionHandler(handler);
|
||||||
Thread.currentThread().setUncaughtExceptionHandler(handler);
|
Thread.currentThread().setUncaughtExceptionHandler(handler);
|
||||||
|
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Use CrashFX for report crash logs
|
// Use CrashFX for report crash logs
|
||||||
/*CrashFX.setup("Bitsquare/" + Version.VERSION,
|
/*CrashFX.setup("Bitsquare/" + Version.VERSION,
|
||||||
|
@ -17,27 +17,18 @@
|
|||||||
|
|
||||||
package io.bitsquare.crypto;
|
package io.bitsquare.crypto;
|
||||||
|
|
||||||
import io.bitsquare.common.crypto.CryptoException;
|
import io.bitsquare.common.crypto.*;
|
||||||
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.p2p.Message;
|
import io.bitsquare.p2p.Message;
|
||||||
import io.bitsquare.p2p.messaging.DecryptedMessageWithPubKey;
|
import io.bitsquare.p2p.messaging.DecryptedMessageWithPubKey;
|
||||||
import io.bitsquare.p2p.messaging.SealedAndSignedMessage;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.crypto.*;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.io.IOException;
|
import java.security.KeyPair;
|
||||||
import java.security.*;
|
|
||||||
|
|
||||||
public class EncryptionService {
|
public class EncryptionService {
|
||||||
private static final Logger log = LoggerFactory.getLogger(EncryptionService.class);
|
private static final Logger log = LoggerFactory.getLogger(EncryptionService.class);
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private final KeyRing keyRing;
|
private final KeyRing keyRing;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@ -45,90 +36,22 @@ public class EncryptionService {
|
|||||||
this.keyRing = keyRing;
|
this.keyRing = keyRing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SealedAndSigned encryptAndSignMessage(PubKeyRing pubKeyRing, Message message) throws CryptoException {
|
||||||
public SealedAndSignedMessage encryptAndSignMessage(PubKeyRing pubKeyRing, Message message) throws CryptoException {
|
|
||||||
log.trace("encryptAndSignMessage message = " + message);
|
log.trace("encryptAndSignMessage message = " + message);
|
||||||
//long ts = System.currentTimeMillis();
|
KeyPair signatureKeyPair = keyRing.getSignatureKeyPair();
|
||||||
|
return Encryption.encryptHybridWithSignature(message,
|
||||||
try {
|
signatureKeyPair.getPrivate(),
|
||||||
// Create symmetric key
|
signatureKeyPair.getPublic(),
|
||||||
KeyGenerator keyGenerator = KeyGenerator.getInstance(CryptoUtil.SYM_ENCR_KEY_ALGO);
|
pubKeyRing.getEncryptionPubKey());
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DecryptedMessageWithPubKey decryptAndVerifyMessage(SealedAndSignedMessage sealedAndSignedMessage) throws CryptoException {
|
public DecryptedMessageWithPubKey decryptAndVerifyMessage(SealedAndSigned sealedAndSigned) throws CryptoException {
|
||||||
// long ts = System.currentTimeMillis();
|
DecryptedPayloadWithPubKey decryptedPayloadWithPubKey = Encryption.decryptHybridWithSignature(sealedAndSigned, keyRing.getEncryptionKeyPair().getPrivate());
|
||||||
try {
|
if (decryptedPayloadWithPubKey.payload instanceof Message) {
|
||||||
if (keyRing == null)
|
//log.trace("Decryption needed {} ms", System.currentTimeMillis() - ts);
|
||||||
throw new CryptoException("keyRing is null");
|
return new DecryptedMessageWithPubKey((Message) decryptedPayloadWithPubKey.payload, decryptedPayloadWithPubKey.sigPublicKey);
|
||||||
|
} else {
|
||||||
SealedObject sealedSecretKey = sealedAndSignedMessage.sealedSecretKey;
|
throw new CryptoException("messageObject is not instance of Message");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,9 @@ import io.bitsquare.common.UserThread;
|
|||||||
import io.bitsquare.common.crypto.CryptoException;
|
import io.bitsquare.common.crypto.CryptoException;
|
||||||
import io.bitsquare.common.crypto.KeyRing;
|
import io.bitsquare.common.crypto.KeyRing;
|
||||||
import io.bitsquare.common.crypto.PubKeyRing;
|
import io.bitsquare.common.crypto.PubKeyRing;
|
||||||
|
import io.bitsquare.common.crypto.SealedAndSigned;
|
||||||
import io.bitsquare.crypto.EncryptionService;
|
import io.bitsquare.crypto.EncryptionService;
|
||||||
|
import io.bitsquare.crypto.SealedAndSignedMessage;
|
||||||
import io.bitsquare.p2p.messaging.*;
|
import io.bitsquare.p2p.messaging.*;
|
||||||
import io.bitsquare.p2p.network.*;
|
import io.bitsquare.p2p.network.*;
|
||||||
import io.bitsquare.p2p.routing.Neighbor;
|
import io.bitsquare.p2p.routing.Neighbor;
|
||||||
@ -210,7 +212,8 @@ public class P2PService {
|
|||||||
} else if (message instanceof SealedAndSignedMessage) {
|
} else if (message instanceof SealedAndSignedMessage) {
|
||||||
if (encryptionService != null) {
|
if (encryptionService != null) {
|
||||||
try {
|
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())));
|
UserThread.execute(() -> decryptedMailListeners.stream().forEach(e -> e.onMailMessage(decryptedMessageWithPubKey, connection.getPeerAddress())));
|
||||||
} catch (CryptoException e) {
|
} catch (CryptoException e) {
|
||||||
log.info("Decryption of SealedAndSignedMessage failed. That is expected if the message is not intended for us.");
|
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) {
|
private void doSendEncryptedMailMessage(Address peerAddress, PubKeyRing pubKeyRing, MailMessage message, SendMailMessageListener sendMailMessageListener) {
|
||||||
if (encryptionService != null) {
|
if (encryptionService != null) {
|
||||||
try {
|
try {
|
||||||
SealedAndSignedMessage sealedAndSignedMessage = encryptionService.encryptAndSignMessage(pubKeyRing, message);
|
SealedAndSignedMessage sealedAndSignedMessage = new SealedAndSignedMessage(encryptionService.encryptAndSignMessage(pubKeyRing, message), peerAddress);
|
||||||
SettableFuture<Connection> future = sendMessage(peerAddress, sealedAndSignedMessage);
|
SettableFuture<Connection> future = sendMessage(peerAddress, sealedAndSignedMessage);
|
||||||
Futures.addCallback(future, new FutureCallback<Connection>() {
|
Futures.addCallback(future, new FutureCallback<Connection>() {
|
||||||
@Override
|
@Override
|
||||||
@ -386,7 +389,7 @@ public class P2PService {
|
|||||||
private void trySendEncryptedMailboxMessage(Address peerAddress, PubKeyRing peersPubKeyRing, MailboxMessage message, SendMailboxMessageListener sendMailboxMessageListener) {
|
private void trySendEncryptedMailboxMessage(Address peerAddress, PubKeyRing peersPubKeyRing, MailboxMessage message, SendMailboxMessageListener sendMailboxMessageListener) {
|
||||||
if (encryptionService != null) {
|
if (encryptionService != null) {
|
||||||
try {
|
try {
|
||||||
SealedAndSignedMessage sealedAndSignedMessage = encryptionService.encryptAndSignMessage(peersPubKeyRing, message);
|
SealedAndSignedMessage sealedAndSignedMessage = new SealedAndSignedMessage(encryptionService.encryptAndSignMessage(peersPubKeyRing, message), peerAddress);
|
||||||
SettableFuture<Connection> future = sendMessage(peerAddress, sealedAndSignedMessage);
|
SettableFuture<Connection> future = sendMessage(peerAddress, sealedAndSignedMessage);
|
||||||
Futures.addCallback(future, new FutureCallback<Connection>() {
|
Futures.addCallback(future, new FutureCallback<Connection>() {
|
||||||
@Override
|
@Override
|
||||||
@ -630,9 +633,9 @@ public class P2PService {
|
|||||||
ExpirablePayload data = mailboxData.expirablePayload;
|
ExpirablePayload data = mailboxData.expirablePayload;
|
||||||
if (data instanceof ExpirableMailboxPayload) {
|
if (data instanceof ExpirableMailboxPayload) {
|
||||||
ExpirableMailboxPayload mailboxEntry = (ExpirableMailboxPayload) data;
|
ExpirableMailboxPayload mailboxEntry = (ExpirableMailboxPayload) data;
|
||||||
SealedAndSignedMessage sealedAndSignedMessage = mailboxEntry.sealedAndSignedMessage;
|
SealedAndSigned sealedAndSigned = mailboxEntry.sealedAndSignedMessage.sealedAndSigned;
|
||||||
try {
|
try {
|
||||||
DecryptedMessageWithPubKey decryptedMessageWithPubKey = encryptionService.decryptAndVerifyMessage(sealedAndSignedMessage);
|
DecryptedMessageWithPubKey decryptedMessageWithPubKey = encryptionService.decryptAndVerifyMessage(sealedAndSigned);
|
||||||
if (decryptedMessageWithPubKey.message instanceof MailboxMessage) {
|
if (decryptedMessageWithPubKey.message instanceof MailboxMessage) {
|
||||||
MailboxMessage mailboxMessage = (MailboxMessage) decryptedMessageWithPubKey.message;
|
MailboxMessage mailboxMessage = (MailboxMessage) decryptedMessageWithPubKey.message;
|
||||||
Address senderAddress = mailboxMessage.getSenderAddress();
|
Address senderAddress = mailboxMessage.getSenderAddress();
|
||||||
@ -640,8 +643,8 @@ public class P2PService {
|
|||||||
|
|
||||||
log.trace("mailboxData.publicKey " + mailboxData.ownerStoragePubKey.hashCode());
|
log.trace("mailboxData.publicKey " + mailboxData.ownerStoragePubKey.hashCode());
|
||||||
log.trace("keyRing.getStorageSignatureKeyPair().getPublic() " + keyRing.getStorageSignatureKeyPair().getPublic().hashCode());
|
log.trace("keyRing.getStorageSignatureKeyPair().getPublic() " + keyRing.getStorageSignatureKeyPair().getPublic().hashCode());
|
||||||
log.trace("keyRing.getMsgSignatureKeyPair().getPublic() " + keyRing.getMsgSignatureKeyPair().getPublic().hashCode());
|
log.trace("keyRing.getMsgSignatureKeyPair().getPublic() " + keyRing.getSignatureKeyPair().getPublic().hashCode());
|
||||||
log.trace("keyRing.getMsgEncryptionKeyPair().getPublic() " + keyRing.getMsgEncryptionKeyPair().getPublic().hashCode());
|
log.trace("keyRing.getMsgEncryptionKeyPair().getPublic() " + keyRing.getEncryptionKeyPair().getPublic().hashCode());
|
||||||
|
|
||||||
|
|
||||||
mailboxMap.put(decryptedMessageWithPubKey, mailboxData);
|
mailboxMap.put(decryptedMessageWithPubKey, mailboxData);
|
||||||
|
@ -355,7 +355,6 @@ public class Connection {
|
|||||||
reportIllegalRequest(IllegalRequest.MaxSizeExceeded);
|
reportIllegalRequest(IllegalRequest.MaxSizeExceeded);
|
||||||
}
|
}
|
||||||
} catch (IOException | ClassNotFoundException e) {
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
log.error("Exception" + e);
|
|
||||||
inputHandlerStopped = true;
|
inputHandlerStopped = true;
|
||||||
handleConnectionException(e);
|
handleConnectionException(e);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@ package io.bitsquare.p2p.storage;
|
|||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import io.bitsquare.common.UserThread;
|
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.Address;
|
||||||
import io.bitsquare.p2p.network.IllegalRequest;
|
import io.bitsquare.p2p.network.IllegalRequest;
|
||||||
import io.bitsquare.p2p.network.MessageListener;
|
import io.bitsquare.p2p.network.MessageListener;
|
||||||
@ -192,8 +193,8 @@ public class ProtectedExpirableDataStorage {
|
|||||||
else
|
else
|
||||||
sequenceNumber = 0;
|
sequenceNumber = 0;
|
||||||
|
|
||||||
byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(payload, sequenceNumber));
|
byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(payload, sequenceNumber));
|
||||||
byte[] signature = CryptoUtil.signStorageData(ownerStoragePubKey.getPrivate(), hashOfDataAndSeqNr);
|
byte[] signature = Sig.sign(ownerStoragePubKey.getPrivate(), hashOfDataAndSeqNr);
|
||||||
return new ProtectedData(payload, payload.getTTL(), ownerStoragePubKey.getPublic(), sequenceNumber, signature);
|
return new ProtectedData(payload, payload.getTTL(), ownerStoragePubKey.getPublic(), sequenceNumber, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,8 +207,8 @@ public class ProtectedExpirableDataStorage {
|
|||||||
else
|
else
|
||||||
sequenceNumber = 0;
|
sequenceNumber = 0;
|
||||||
|
|
||||||
byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(expirableMailboxPayload, sequenceNumber));
|
byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(expirableMailboxPayload, sequenceNumber));
|
||||||
byte[] signature = CryptoUtil.signStorageData(storageSignaturePubKey.getPrivate(), hashOfDataAndSeqNr);
|
byte[] signature = Sig.sign(storageSignaturePubKey.getPrivate(), hashOfDataAndSeqNr);
|
||||||
return new ProtectedMailboxData(expirableMailboxPayload, expirableMailboxPayload.getTTL(), storageSignaturePubKey.getPublic(), sequenceNumber, signature, receiversPublicKey);
|
return new ProtectedMailboxData(expirableMailboxPayload, expirableMailboxPayload.getTTL(), storageSignaturePubKey.getPublic(), sequenceNumber, signature, receiversPublicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,9 +249,9 @@ public class ProtectedExpirableDataStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkSignature(ProtectedData data) {
|
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 {
|
try {
|
||||||
boolean result = CryptoUtil.verifyStorageData(data.ownerStoragePubKey, hashOfDataAndSeqNr, data.signature);
|
boolean result = Sig.verify(data.ownerStoragePubKey, hashOfDataAndSeqNr, data.signature);
|
||||||
if (!result)
|
if (!result)
|
||||||
log.error("Signature verification failed at checkSignature. " +
|
log.error("Signature verification failed at checkSignature. " +
|
||||||
"That should not happen. Consider it might be an attempt of fraud.");
|
"That should not happen. Consider it might be an attempt of fraud.");
|
||||||
@ -317,6 +318,6 @@ public class ProtectedExpirableDataStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private BigInteger getHashAsBigInteger(ExpirablePayload payload) {
|
private BigInteger getHashAsBigInteger(ExpirablePayload payload) {
|
||||||
return new BigInteger(CryptoUtil.getHash(payload));
|
return new BigInteger(Hash.getHash(payload));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package io.bitsquare.p2p.storage.data;
|
package io.bitsquare.p2p.storage.data;
|
||||||
|
|
||||||
import io.bitsquare.app.Version;
|
import io.bitsquare.app.Version;
|
||||||
import io.bitsquare.p2p.messaging.SealedAndSignedMessage;
|
import io.bitsquare.crypto.SealedAndSignedMessage;
|
||||||
|
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ import io.bitsquare.common.util.Utilities;
|
|||||||
import io.bitsquare.p2p.Address;
|
import io.bitsquare.p2p.Address;
|
||||||
import io.bitsquare.p2p.messaging.DecryptedMessageWithPubKey;
|
import io.bitsquare.p2p.messaging.DecryptedMessageWithPubKey;
|
||||||
import io.bitsquare.p2p.messaging.MailboxMessage;
|
import io.bitsquare.p2p.messaging.MailboxMessage;
|
||||||
import io.bitsquare.p2p.messaging.SealedAndSignedMessage;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
@ -70,8 +69,8 @@ public class EncryptionServiceTests {
|
|||||||
public void testDecryptAndVerifyMessage() throws CryptoException {
|
public void testDecryptAndVerifyMessage() throws CryptoException {
|
||||||
EncryptionService encryptionService = new EncryptionService(keyRing);
|
EncryptionService encryptionService = new EncryptionService(keyRing);
|
||||||
TestMessage data = new TestMessage("test");
|
TestMessage data = new TestMessage("test");
|
||||||
SealedAndSignedMessage encrypted = encryptionService.encryptAndSignMessage(pubKeyRing, data);
|
SealedAndSignedMessage encrypted = new SealedAndSignedMessage(encryptionService.encryptAndSignMessage(pubKeyRing, data), null);
|
||||||
DecryptedMessageWithPubKey decrypted = encryptionService.decryptAndVerifyMessage(encrypted);
|
DecryptedMessageWithPubKey decrypted = encryptionService.decryptAndVerifyMessage(encrypted.sealedAndSigned);
|
||||||
assertEquals(data.data, ((TestMessage) decrypted.message).data);
|
assertEquals(data.data, ((TestMessage) decrypted.message).data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
package io.bitsquare.p2p;
|
package io.bitsquare.p2p;
|
||||||
|
|
||||||
import io.bitsquare.common.crypto.CryptoException;
|
import io.bitsquare.common.crypto.*;
|
||||||
import io.bitsquare.common.crypto.CryptoUtil;
|
|
||||||
import io.bitsquare.common.crypto.KeyRing;
|
|
||||||
import io.bitsquare.common.crypto.KeyStorage;
|
|
||||||
import io.bitsquare.crypto.EncryptionService;
|
import io.bitsquare.crypto.EncryptionService;
|
||||||
|
import io.bitsquare.crypto.SealedAndSignedMessage;
|
||||||
import io.bitsquare.p2p.messaging.DecryptedMessageWithPubKey;
|
import io.bitsquare.p2p.messaging.DecryptedMessageWithPubKey;
|
||||||
import io.bitsquare.p2p.messaging.MailboxMessage;
|
import io.bitsquare.p2p.messaging.MailboxMessage;
|
||||||
import io.bitsquare.p2p.messaging.SealedAndSignedMessage;
|
|
||||||
import io.bitsquare.p2p.messaging.SendMailboxMessageListener;
|
import io.bitsquare.p2p.messaging.SendMailboxMessageListener;
|
||||||
import io.bitsquare.p2p.mocks.MockMailboxMessage;
|
import io.bitsquare.p2p.mocks.MockMailboxMessage;
|
||||||
import io.bitsquare.p2p.network.LocalhostNetworkNode;
|
import io.bitsquare.p2p.network.LocalhostNetworkNode;
|
||||||
@ -161,8 +158,8 @@ public class P2PServiceTest {
|
|||||||
|
|
||||||
// try to manipulate seq nr. + pubKey + sig -> fails
|
// try to manipulate seq nr. + pubKey + sig -> fails
|
||||||
int sequenceNumberManipulated = origProtectedData.sequenceNumber + 1;
|
int sequenceNumberManipulated = origProtectedData.sequenceNumber + 1;
|
||||||
byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(origProtectedData.expirablePayload, sequenceNumberManipulated));
|
byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(origProtectedData.expirablePayload, sequenceNumberManipulated));
|
||||||
byte[] signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
byte[] signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
||||||
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
||||||
Assert.assertFalse(p2PService3.removeData(protectedDataManipulated.expirablePayload));
|
Assert.assertFalse(p2PService3.removeData(protectedDataManipulated.expirablePayload));
|
||||||
Thread.sleep(sleepTime);
|
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
|
// 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);
|
MockData manipulatedData = new MockData("mockData1_manipulated", origData.publicKey);
|
||||||
sequenceNumberManipulated = 0;
|
sequenceNumberManipulated = 0;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
|
||||||
signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
||||||
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
||||||
Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload));
|
Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload));
|
||||||
Thread.sleep(sleepTime);
|
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
|
// then he tries to use his pubKey but orig data payload -> fails as pub keys nto matching
|
||||||
manipulatedData = new MockData("mockData1_manipulated", msgSignatureKeyPairAdversary.getPublic());
|
manipulatedData = new MockData("mockData1_manipulated", msgSignatureKeyPairAdversary.getPublic());
|
||||||
sequenceNumberManipulated = 0;
|
sequenceNumberManipulated = 0;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
|
||||||
signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
||||||
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
||||||
Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload));
|
Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload));
|
||||||
Thread.sleep(sleepTime);
|
Thread.sleep(sleepTime);
|
||||||
@ -208,8 +205,8 @@ public class P2PServiceTest {
|
|||||||
// payload data has adversary's pubKey so he could hijack the owners data
|
// payload data has adversary's pubKey so he could hijack the owners data
|
||||||
manipulatedData = new MockData("mockData1_manipulated", msgSignatureKeyPairAdversary.getPublic());
|
manipulatedData = new MockData("mockData1_manipulated", msgSignatureKeyPairAdversary.getPublic());
|
||||||
sequenceNumberManipulated = 0;
|
sequenceNumberManipulated = 0;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
|
||||||
signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
||||||
protectedDataManipulated = new ProtectedData(manipulatedData, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
protectedDataManipulated = new ProtectedData(manipulatedData, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
||||||
Assert.assertTrue(p2PService3.addData(protectedDataManipulated.expirablePayload));
|
Assert.assertTrue(p2PService3.addData(protectedDataManipulated.expirablePayload));
|
||||||
Thread.sleep(sleepTime);
|
Thread.sleep(sleepTime);
|
||||||
@ -228,8 +225,8 @@ public class P2PServiceTest {
|
|||||||
// finally he tries both previous attempts with same data - > same as before
|
// finally he tries both previous attempts with same data - > same as before
|
||||||
manipulatedData = new MockData("mockData1", origData.publicKey);
|
manipulatedData = new MockData("mockData1", origData.publicKey);
|
||||||
sequenceNumberManipulated = 0;
|
sequenceNumberManipulated = 0;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
|
||||||
signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
||||||
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
||||||
Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload));
|
Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload));
|
||||||
Thread.sleep(sleepTime);
|
Thread.sleep(sleepTime);
|
||||||
@ -239,8 +236,8 @@ public class P2PServiceTest {
|
|||||||
|
|
||||||
manipulatedData = new MockData("mockData1", msgSignatureKeyPairAdversary.getPublic());
|
manipulatedData = new MockData("mockData1", msgSignatureKeyPairAdversary.getPublic());
|
||||||
sequenceNumberManipulated = 0;
|
sequenceNumberManipulated = 0;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated));
|
||||||
signature = CryptoUtil.signStorageData(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr);
|
||||||
protectedDataManipulated = new ProtectedData(manipulatedData, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
protectedDataManipulated = new ProtectedData(manipulatedData, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature);
|
||||||
Assert.assertTrue(p2PService3.addData(protectedDataManipulated.expirablePayload));
|
Assert.assertTrue(p2PService3.addData(protectedDataManipulated.expirablePayload));
|
||||||
Thread.sleep(sleepTime);
|
Thread.sleep(sleepTime);
|
||||||
@ -275,7 +272,8 @@ public class P2PServiceTest {
|
|||||||
log.trace("message " + message);
|
log.trace("message " + message);
|
||||||
if (message instanceof SealedAndSignedMessage) {
|
if (message instanceof SealedAndSignedMessage) {
|
||||||
try {
|
try {
|
||||||
DecryptedMessageWithPubKey decryptedMessageWithPubKey = encryptionService2.decryptAndVerifyMessage((SealedAndSignedMessage) message);
|
SealedAndSignedMessage sealedAndSignedMessage = (SealedAndSignedMessage) message;
|
||||||
|
DecryptedMessageWithPubKey decryptedMessageWithPubKey = encryptionService2.decryptAndVerifyMessage(sealedAndSignedMessage.sealedAndSigned);
|
||||||
Assert.assertEquals(mockMessage, decryptedMessageWithPubKey.message);
|
Assert.assertEquals(mockMessage, decryptedMessageWithPubKey.message);
|
||||||
Assert.assertEquals(p2PService2.getAddress(), ((MailboxMessage) decryptedMessageWithPubKey.message).getSenderAddress());
|
Assert.assertEquals(p2PService2.getAddress(), ((MailboxMessage) decryptedMessageWithPubKey.message).getSenderAddress());
|
||||||
latch2.countDown();
|
latch2.countDown();
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
package io.bitsquare.p2p.storage;
|
package io.bitsquare.p2p.storage;
|
||||||
|
|
||||||
import io.bitsquare.common.UserThread;
|
import io.bitsquare.common.UserThread;
|
||||||
import io.bitsquare.common.crypto.CryptoException;
|
import io.bitsquare.common.crypto.*;
|
||||||
import io.bitsquare.common.crypto.CryptoUtil;
|
|
||||||
import io.bitsquare.common.crypto.KeyRing;
|
|
||||||
import io.bitsquare.common.crypto.KeyStorage;
|
|
||||||
import io.bitsquare.common.util.Utilities;
|
import io.bitsquare.common.util.Utilities;
|
||||||
import io.bitsquare.crypto.EncryptionService;
|
import io.bitsquare.crypto.EncryptionService;
|
||||||
|
import io.bitsquare.crypto.SealedAndSignedMessage;
|
||||||
import io.bitsquare.p2p.Address;
|
import io.bitsquare.p2p.Address;
|
||||||
import io.bitsquare.p2p.TestUtils;
|
import io.bitsquare.p2p.TestUtils;
|
||||||
import io.bitsquare.p2p.messaging.SealedAndSignedMessage;
|
|
||||||
import io.bitsquare.p2p.mocks.MockMessage;
|
import io.bitsquare.p2p.mocks.MockMessage;
|
||||||
import io.bitsquare.p2p.network.NetworkNode;
|
import io.bitsquare.p2p.network.NetworkNode;
|
||||||
import io.bitsquare.p2p.routing.Routing;
|
import io.bitsquare.p2p.routing.Routing;
|
||||||
@ -89,8 +86,8 @@ public class ProtectedDataStorageTest {
|
|||||||
Assert.assertEquals(1, dataStorage1.getMap().size());
|
Assert.assertEquals(1, dataStorage1.getMap().size());
|
||||||
|
|
||||||
int newSequenceNumber = data.sequenceNumber + 1;
|
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 = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
ProtectedData dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
ProtectedData dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
Assert.assertTrue(dataStorage1.remove(dataToRemove, null));
|
Assert.assertTrue(dataStorage1.remove(dataToRemove, null));
|
||||||
Assert.assertEquals(0, dataStorage1.getMap().size());
|
Assert.assertEquals(0, dataStorage1.getMap().size());
|
||||||
@ -118,12 +115,12 @@ public class ProtectedDataStorageTest {
|
|||||||
// add with date in future
|
// add with date in future
|
||||||
data = dataStorage1.getDataWithSignedSeqNr(mockData, storageSignatureKeyPair1);
|
data = dataStorage1.getDataWithSignedSeqNr(mockData, storageSignatureKeyPair1);
|
||||||
int newSequenceNumber = data.sequenceNumber + 1;
|
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 = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
ProtectedData dataWithFutureDate = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
ProtectedData dataWithFutureDate = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
dataWithFutureDate.date = new Date(new Date().getTime() + 60 * 60 * sleepTime);
|
dataWithFutureDate.date = new Date(new Date().getTime() + 60 * 60 * sleepTime);
|
||||||
// force serialisation (date check is done in readObject)
|
// 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));
|
Assert.assertTrue(dataStorage1.add(newData, null));
|
||||||
Thread.sleep(5);
|
Thread.sleep(5);
|
||||||
Assert.assertEquals(1, dataStorage1.getMap().size());
|
Assert.assertEquals(1, dataStorage1.getMap().size());
|
||||||
@ -139,57 +136,57 @@ public class ProtectedDataStorageTest {
|
|||||||
|
|
||||||
// remove with not updated seq nr -> failure
|
// remove with not updated seq nr -> failure
|
||||||
int newSequenceNumber = 0;
|
int newSequenceNumber = 0;
|
||||||
byte[] hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
||||||
byte[] signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
ProtectedData dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
ProtectedData dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
Assert.assertFalse(dataStorage1.remove(dataToRemove, null));
|
Assert.assertFalse(dataStorage1.remove(dataToRemove, null));
|
||||||
|
|
||||||
// remove with too high updated seq nr -> ok
|
// remove with too high updated seq nr -> ok
|
||||||
newSequenceNumber = 2;
|
newSequenceNumber = 2;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
||||||
signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
Assert.assertTrue(dataStorage1.remove(dataToRemove, null));
|
Assert.assertTrue(dataStorage1.remove(dataToRemove, null));
|
||||||
|
|
||||||
// add with updated seq nr below previous -> failure
|
// add with updated seq nr below previous -> failure
|
||||||
newSequenceNumber = 1;
|
newSequenceNumber = 1;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
||||||
signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
ProtectedData dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
ProtectedData dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
Assert.assertFalse(dataStorage1.add(dataToAdd, null));
|
Assert.assertFalse(dataStorage1.add(dataToAdd, null));
|
||||||
|
|
||||||
// add with updated seq nr over previous -> ok
|
// add with updated seq nr over previous -> ok
|
||||||
newSequenceNumber = 3;
|
newSequenceNumber = 3;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
||||||
signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
Assert.assertTrue(dataStorage1.add(dataToAdd, null));
|
Assert.assertTrue(dataStorage1.add(dataToAdd, null));
|
||||||
|
|
||||||
// add with same seq nr -> failure
|
// add with same seq nr -> failure
|
||||||
newSequenceNumber = 3;
|
newSequenceNumber = 3;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
||||||
signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
Assert.assertFalse(dataStorage1.add(dataToAdd, null));
|
Assert.assertFalse(dataStorage1.add(dataToAdd, null));
|
||||||
|
|
||||||
// add with same data but higher seq nr. -> ok, ignore
|
// add with same data but higher seq nr. -> ok, ignore
|
||||||
newSequenceNumber = 4;
|
newSequenceNumber = 4;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
||||||
signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
Assert.assertTrue(dataStorage1.add(dataToAdd, null));
|
Assert.assertTrue(dataStorage1.add(dataToAdd, null));
|
||||||
|
|
||||||
// remove with with same seq nr as prev. ignored -> failed
|
// remove with with same seq nr as prev. ignored -> failed
|
||||||
newSequenceNumber = 4;
|
newSequenceNumber = 4;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
||||||
signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
Assert.assertFalse(dataStorage1.remove(dataToRemove, null));
|
Assert.assertFalse(dataStorage1.remove(dataToRemove, null));
|
||||||
|
|
||||||
// remove with with higher seq nr -> ok
|
// remove with with higher seq nr -> ok
|
||||||
newSequenceNumber = 5;
|
newSequenceNumber = 5;
|
||||||
hashOfDataAndSeqNr = CryptoUtil.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber));
|
||||||
signature = CryptoUtil.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr);
|
||||||
dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature);
|
||||||
Assert.assertTrue(dataStorage1.remove(dataToRemove, null));
|
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 {
|
public void testAddAndRemoveMailboxData() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException {
|
||||||
// sender
|
// sender
|
||||||
MockMessage mockMessage = new MockMessage("MockMessage");
|
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,
|
ExpirableMailboxPayload expirableMailboxPayload = new ExpirableMailboxPayload(sealedAndSignedMessage,
|
||||||
keyRing1.getStorageSignatureKeyPair().getPublic(),
|
keyRing1.getStorageSignatureKeyPair().getPublic(),
|
||||||
keyRing2.getStorageSignatureKeyPair().getPublic());
|
keyRing2.getStorageSignatureKeyPair().getPublic());
|
||||||
@ -210,34 +207,34 @@ public class ProtectedDataStorageTest {
|
|||||||
|
|
||||||
// receiver (storageSignatureKeyPair2)
|
// receiver (storageSignatureKeyPair2)
|
||||||
int newSequenceNumber = data.sequenceNumber + 1;
|
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;
|
byte[] signature;
|
||||||
ProtectedMailboxData dataToRemove;
|
ProtectedMailboxData dataToRemove;
|
||||||
|
|
||||||
// wrong sig -> fail
|
// 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());
|
dataToRemove = new ProtectedMailboxData(expirableMailboxPayload, data.ttl, storageSignatureKeyPair2.getPublic(), newSequenceNumber, signature, storageSignatureKeyPair2.getPublic());
|
||||||
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
|
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
|
||||||
|
|
||||||
// wrong seq nr
|
// 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());
|
dataToRemove = new ProtectedMailboxData(expirableMailboxPayload, data.ttl, storageSignatureKeyPair2.getPublic(), data.sequenceNumber, signature, storageSignatureKeyPair2.getPublic());
|
||||||
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
|
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
|
||||||
|
|
||||||
// wrong signingKey
|
// 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());
|
dataToRemove = new ProtectedMailboxData(expirableMailboxPayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature, storageSignatureKeyPair2.getPublic());
|
||||||
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
|
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
|
||||||
|
|
||||||
// wrong peerPubKey
|
// 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());
|
dataToRemove = new ProtectedMailboxData(expirableMailboxPayload, data.ttl, storageSignatureKeyPair2.getPublic(), newSequenceNumber, signature, storageSignatureKeyPair1.getPublic());
|
||||||
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
|
Assert.assertFalse(dataStorage1.removeMailboxData(dataToRemove, null));
|
||||||
|
|
||||||
// receiver can remove it (storageSignatureKeyPair2) -> all ok
|
// receiver can remove it (storageSignatureKeyPair2) -> all ok
|
||||||
Assert.assertEquals(1, dataStorage1.getMap().size());
|
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());
|
dataToRemove = new ProtectedMailboxData(expirableMailboxPayload, data.ttl, storageSignatureKeyPair2.getPublic(), newSequenceNumber, signature, storageSignatureKeyPair2.getPublic());
|
||||||
Assert.assertTrue(dataStorage1.removeMailboxData(dataToRemove, null));
|
Assert.assertTrue(dataStorage1.removeMailboxData(dataToRemove, null));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user