Add sym encryption

This commit is contained in:
Manfred Karrer 2015-03-20 19:06:57 +01:00
parent b531c3a0c2
commit 506ac37293
29 changed files with 189 additions and 84 deletions

View file

@ -31,7 +31,7 @@ public class Arbitrator implements Serializable {
private String id; private String id;
private String pubKeyAsHex; private String pubKeyAsHex;
private byte[] pubKey; private byte[] pubKey;
private String messagePubKeyAsHex; private String p2pSigPubKeyAsHex;
private String name; private String name;
private ID_TYPE idType; private ID_TYPE idType;
private List<Locale> languages; private List<Locale> languages;
@ -48,7 +48,7 @@ public class Arbitrator implements Serializable {
} }
public Arbitrator(byte[] pubKey, public Arbitrator(byte[] pubKey,
String messagePubKeyAsHex, String p2pSigPubKeyAsHex,
String name, String name,
ID_TYPE idType, ID_TYPE idType,
List<Locale> languages, List<Locale> languages,
@ -59,7 +59,7 @@ public class Arbitrator implements Serializable {
String webUrl, String webUrl,
String description) { String description) {
this.pubKey = pubKey; this.pubKey = pubKey;
this.messagePubKeyAsHex = messagePubKeyAsHex; this.p2pSigPubKeyAsHex = p2pSigPubKeyAsHex;
this.name = name; this.name = name;
this.idType = idType; this.idType = idType;
this.languages = languages; this.languages = languages;
@ -76,7 +76,7 @@ public class Arbitrator implements Serializable {
public void applyPersistedArbitrator(Arbitrator persistedArbitrator) { public void applyPersistedArbitrator(Arbitrator persistedArbitrator) {
this.pubKeyAsHex = persistedArbitrator.getPubKeyAsHex(); this.pubKeyAsHex = persistedArbitrator.getPubKeyAsHex();
this.messagePubKeyAsHex = persistedArbitrator.getPubKeyAsHex(); this.p2pSigPubKeyAsHex = persistedArbitrator.getPubKeyAsHex();
this.name = persistedArbitrator.getName(); this.name = persistedArbitrator.getName();
this.idType = persistedArbitrator.getIdType(); this.idType = persistedArbitrator.getIdType();
this.languages = persistedArbitrator.getLanguages(); this.languages = persistedArbitrator.getLanguages();
@ -126,8 +126,8 @@ public class Arbitrator implements Serializable {
return pubKey; return pubKey;
} }
public String getMessagePubKeyAsHex() { public String getP2pSigPubKeyAsHex() {
return messagePubKeyAsHex; return p2pSigPubKeyAsHex;
} }

View file

@ -21,5 +21,5 @@ package io.bitsquare.common.handlers;
* For reporting a description message and throwable * For reporting a description message and throwable
*/ */
public interface FaultHandler { public interface FaultHandler {
void handleFault(String message, Throwable throwable); void handleFault(String errorMessage, Throwable throwable);
} }

View file

@ -19,6 +19,9 @@ package io.bitsquare.crypto;
import io.bitsquare.util.Utilities; import io.bitsquare.util.Utilities;
import java.io.Serializable;
import java.security.Key;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.KeyPairGenerator; import java.security.KeyPairGenerator;
import java.security.PrivateKey; import java.security.PrivateKey;
@ -30,8 +33,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class EncryptionService { public class EncryptionService<T> {
private static final Logger log = LoggerFactory.getLogger(EncryptionService.class); private static final Logger log = LoggerFactory.getLogger(EncryptionService.class);
@Inject @Inject
@ -51,38 +57,73 @@ public class EncryptionService {
return keyPair; return keyPair;
} }
public byte[] encryptObject(PublicKey publicKey, Object object) { public Tuple encryptObject(PublicKey publicKey, Object object) {
return encrypt(publicKey, Utilities.objectToBytArray(object)); return encrypt(publicKey, Utilities.objectToBytArray(object));
} }
public Object decryptObject(PrivateKey privateKey, byte[] cipherMessage) { public T decryptToObject(PrivateKey privateKey, Tuple tuple) {
return Utilities.byteArrayToObject(decrypt(privateKey, cipherMessage)); return (T) Utilities.byteArrayToObject(decrypt(privateKey, tuple));
} }
public byte[] encrypt(PublicKey publicKey, byte[] data) { public Tuple encrypt(PublicKey publicKey, byte[] payload) {
byte[] cipherData = null; byte[] encryptedPayload = null;
byte[] encryptedKey = null;
try { try {
Cipher cipher = Cipher.getInstance("RSA"); // Create symmetric key and
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256);
SecretKey secretKey = keyGenerator.generateKey();
// Encrypt secretKey with asymmetric key
Cipher cipher = Cipher.getInstance("RSA/NONE/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey); cipher.init(Cipher.ENCRYPT_MODE, publicKey);
cipherData = cipher.doFinal(data); encryptedKey = cipher.doFinal(secretKey.getEncoded());
// Encrypt payload with symmetric key
SecretKeySpec keySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
encryptedPayload = cipher.doFinal(payload);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
log.error("Exception at encrypt " + e.getMessage()); log.error("Exception at encrypt " + e.getMessage());
} }
return cipherData; return new Tuple(encryptedKey, encryptedPayload);
} }
public byte[] decrypt(PrivateKey privateKey, byte[] cipherText) { public byte[] decrypt(PrivateKey privateKey, Tuple tuple) {
byte[] data = null; byte[] encryptedPayload = tuple.encryptedPayload;
byte[] encryptedKey = tuple.encryptedKey;
byte[] payload = null;
try { try {
Cipher cipher = Cipher.getInstance("RSA"); // Decrypt secretKey key with asymmetric key
Cipher cipher = Cipher.getInstance("RSA/NONE/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey); cipher.init(Cipher.DECRYPT_MODE, privateKey);
data = cipher.doFinal(cipherText); byte[] secretKey = cipher.doFinal(encryptedKey);
// Decrypt payload with symmetric key
Key key = new SecretKeySpec(secretKey, "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
payload = cipher.doFinal(encryptedPayload);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
log.error("Exception at decrypt " + e.getMessage()); log.error("Exception at decrypt " + e.getMessage());
} }
return data; return payload;
} }
public class Tuple implements Serializable {
private static final long serialVersionUID = -8709538217388076762L;
public final byte[] encryptedKey;
public final byte[] encryptedPayload;
public Tuple(byte[] encryptedKey, byte[] encryptedPayload) {
this.encryptedKey = encryptedKey;
this.encryptedPayload = encryptedPayload;
} }
}
}

View file

@ -29,10 +29,10 @@ import io.bitsquare.fiat.FiatAccountType;
import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.CountryUtil; import io.bitsquare.locale.CountryUtil;
import io.bitsquare.locale.LanguageUtil; import io.bitsquare.locale.LanguageUtil;
import io.bitsquare.p2p.BaseP2PService;
import io.bitsquare.p2p.BootstrapState; import io.bitsquare.p2p.BootstrapState;
import io.bitsquare.p2p.ClientNode; import io.bitsquare.p2p.ClientNode;
import io.bitsquare.p2p.MessageService; import io.bitsquare.p2p.MessageService;
import io.bitsquare.p2p.BaseP2PService;
import io.bitsquare.persistence.Persistence; import io.bitsquare.persistence.Persistence;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeManager; import io.bitsquare.trade.TradeManager;
@ -356,7 +356,7 @@ class MainViewModel implements ViewModel {
private void addMockArbitrator() { private void addMockArbitrator() {
if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getP2pSigKeyPair() != null) { if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getP2pSigKeyPair() != null) {
byte[] pubKey = new ECKey().getPubKey(); byte[] pubKey = new ECKey().getPubKey();
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePubKey()); String p2pSigPubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getP2PSigPubKey());
List<Locale> languages = new ArrayList<>(); List<Locale> languages = new ArrayList<>();
languages.add(LanguageUtil.getDefaultLanguageLocale()); languages.add(LanguageUtil.getDefaultLanguageLocale());
List<Arbitrator.METHOD> arbitrationMethods = new ArrayList<>(); List<Arbitrator.METHOD> arbitrationMethods = new ArrayList<>();
@ -366,7 +366,7 @@ class MainViewModel implements ViewModel {
idVerifications.add(Arbitrator.ID_VERIFICATION.GOV_ID); idVerifications.add(Arbitrator.ID_VERIFICATION.GOV_ID);
Arbitrator arbitrator = new Arbitrator(pubKey, Arbitrator arbitrator = new Arbitrator(pubKey,
messagePubKeyAsHex, p2pSigPubKeyAsHex,
"Manfred Karrer", "Manfred Karrer",
Arbitrator.ID_TYPE.REAL_LIFE_ID, Arbitrator.ID_TYPE.REAL_LIFE_ID,
languages, languages,

View file

@ -370,14 +370,14 @@ public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void
private Arbitrator getEditedArbitrator() { private Arbitrator getEditedArbitrator() {
byte[] pubKey = walletService.getArbitratorDepositAddressEntry().getPubKey(); byte[] pubKey = walletService.getArbitratorDepositAddressEntry().getPubKey();
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePubKey()); String p2pSigPubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getP2PSigPubKey());
String name = nameTextField.getText(); String name = nameTextField.getText();
Coin fee = formatter.parseToCoin(arbitrationFeeTextField.getText()); Coin fee = formatter.parseToCoin(arbitrationFeeTextField.getText());
String webUrl = webPageTextField.getText(); String webUrl = webPageTextField.getText();
String description = descriptionTextArea.getText(); String description = descriptionTextArea.getText();
return new Arbitrator(pubKey, return new Arbitrator(pubKey,
messagePubKeyAsHex, p2pSigPubKeyAsHex,
name, name,
idType, idType,
languageList, languageList,

View file

@ -124,7 +124,7 @@ class IrcAccountDataModel implements Activatable, DataModel {
private void addMockArbitrator() { private void addMockArbitrator() {
if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getP2pSigKeyPair() != null) { if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getP2pSigKeyPair() != null) {
byte[] pubKey = new ECKey().getPubKey(); byte[] pubKey = new ECKey().getPubKey();
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePubKey()); String p2pSigPubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getP2PSigPubKey());
List<Locale> languages = new ArrayList<>(); List<Locale> languages = new ArrayList<>();
languages.add(LanguageUtil.getDefaultLanguageLocale()); languages.add(LanguageUtil.getDefaultLanguageLocale());
List<Arbitrator.METHOD> arbitrationMethods = new ArrayList<>(); List<Arbitrator.METHOD> arbitrationMethods = new ArrayList<>();
@ -134,7 +134,7 @@ class IrcAccountDataModel implements Activatable, DataModel {
idVerifications.add(Arbitrator.ID_VERIFICATION.GOV_ID); idVerifications.add(Arbitrator.ID_VERIFICATION.GOV_ID);
Arbitrator arbitrator = new Arbitrator(pubKey, Arbitrator arbitrator = new Arbitrator(pubKey,
messagePubKeyAsHex, p2pSigPubKeyAsHex,
"Manfred Karrer", "Manfred Karrer",
Arbitrator.ID_TYPE.REAL_LIFE_ID, Arbitrator.ID_TYPE.REAL_LIFE_ID,
languages, languages,

View file

@ -154,7 +154,7 @@ class RestrictionsDataModel implements Activatable, DataModel {
private void addMockArbitrator() { private void addMockArbitrator() {
if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getP2pSigKeyPair() != null) { if (accountSettings.getAcceptedArbitrators().isEmpty() && user.getP2pSigKeyPair() != null) {
byte[] pubKey = new ECKey().getPubKey(); byte[] pubKey = new ECKey().getPubKey();
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getMessagePubKey()); String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(user.getP2PSigPubKey());
List<Locale> languages = new ArrayList<>(); List<Locale> languages = new ArrayList<>();
languages.add(LanguageUtil.getDefaultLanguageLocale()); languages.add(LanguageUtil.getDefaultLanguageLocale());
List<Arbitrator.METHOD> arbitrationMethods = new ArrayList<>(); List<Arbitrator.METHOD> arbitrationMethods = new ArrayList<>();

View file

@ -74,7 +74,7 @@ class ClosedTradesDataModel implements Activatable, DataModel {
} }
public Direction getDirection(Offer offer) { public Direction getDirection(Offer offer) {
return offer.getMessagePublicKey().equals(user.getMessagePubKey()) ? return offer.getMessagePublicKey().equals(user.getP2PSigPubKey()) ?
offer.getDirection() : offer.getMirroredDirection(); offer.getDirection() : offer.getMirroredDirection();
} }

View file

@ -86,7 +86,7 @@ class OffersDataModel implements Activatable, DataModel {
} }
public Direction getDirection(Offer offer) { public Direction getDirection(Offer offer) {
return offer.getMessagePublicKey().equals(user.getMessagePubKey()) ? return offer.getMessagePublicKey().equals(user.getP2PSigPubKey()) ?
offer.getDirection() : offer.getMirroredDirection(); offer.getDirection() : offer.getMirroredDirection();
} }
} }

View file

@ -146,7 +146,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
selectedItem = item; selectedItem = item;
if (selectedItem != null) { if (selectedItem != null) {
isOfferer = getTrade().getOffer().getMessagePublicKey().equals(user.getMessagePubKey()); isOfferer = getTrade().getOffer().getMessagePublicKey().equals(user.getP2PSigPubKey());
Trade trade = getTrade(); Trade trade = getTrade();
trade.stateProperty().addListener(tradeStateChangeListener); trade.stateProperty().addListener(tradeStateChangeListener);
@ -269,7 +269,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
} }
public Direction getDirection(Offer offer) { public Direction getDirection(Offer offer) {
return offer.getMessagePublicKey().equals(user.getMessagePubKey()) ? return offer.getMessagePublicKey().equals(user.getP2PSigPubKey()) ?
offer.getDirection() : offer.getMirroredDirection(); offer.getDirection() : offer.getMirroredDirection();
} }

View file

@ -213,7 +213,7 @@ class OfferBookDataModel implements Activatable, DataModel {
} }
boolean isMyOffer(Offer offer) { boolean isMyOffer(Offer offer) {
return offer.getMessagePublicKey() != null && offer.getMessagePublicKey().equals(user.getMessagePubKey()); return offer.getMessagePublicKey() != null && offer.getMessagePublicKey().equals(user.getP2PSigPubKey());
} }
Coin getAmountAsCoin() { Coin getAmountAsCoin() {

View file

@ -0,0 +1,43 @@
/*
* 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.p2p;
import io.bitsquare.crypto.EncryptionService;
import java.io.Serializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
Stores a message in encrypted form, so it never leaves the client in plain text.
*/
public class EncryptedMailboxMessage implements MailboxMessage, Serializable {
private static final long serialVersionUID = -3111178895546299769L;
private static final Logger log = LoggerFactory.getLogger(EncryptedMailboxMessage.class);
private EncryptionService.Tuple tuple;
public EncryptedMailboxMessage(EncryptionService.Tuple tuple) {
this.tuple = tuple;
}
public EncryptionService.Tuple getTuple() {
return tuple;
}
}

View file

@ -19,23 +19,5 @@ package io.bitsquare.p2p;
import java.io.Serializable; import java.io.Serializable;
import org.slf4j.Logger; public interface MailboxMessage extends Message, Serializable {
import org.slf4j.LoggerFactory;
/*
Stores a message in encrypted form, so it never leaves the client in plain text.
*/
public class MailboxMessage implements Message, Serializable {
private static final long serialVersionUID = -3111178895546299769L;
private static final Logger log = LoggerFactory.getLogger(MailboxMessage.class);
private byte[] cipherMessage;
public MailboxMessage(byte[] cipherMessage) {
this.cipherMessage = cipherMessage;
}
public byte[] getCipherMessage() {
return cipherMessage;
}
} }

View file

@ -24,9 +24,9 @@ import io.bitsquare.p2p.tomp2p.TomP2PMailboxService;
import java.security.PublicKey; import java.security.PublicKey;
public interface MailboxService { public interface MailboxService {
void addMessage(PublicKey publicKey, MailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler); void addMessage(PublicKey publicKey, EncryptedMailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler);
void removeMessage(PublicKey publicKey, MailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler); void removeMessage(PublicKey publicKey, EncryptedMailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler);
void getMessages(PublicKey publicKey, TomP2PMailboxService.MailboxMessagesResultHandler resultHandler); void getMessages(PublicKey publicKey, TomP2PMailboxService.MailboxMessagesResultHandler resultHandler);
} }

View file

@ -20,7 +20,7 @@ package io.bitsquare.p2p.tomp2p;
import io.bitsquare.common.handlers.FaultHandler; import io.bitsquare.common.handlers.FaultHandler;
import io.bitsquare.common.handlers.ResultHandler; import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.offer.OfferBookService; import io.bitsquare.offer.OfferBookService;
import io.bitsquare.p2p.MailboxMessage; import io.bitsquare.p2p.EncryptedMailboxMessage;
import io.bitsquare.p2p.MailboxService; import io.bitsquare.p2p.MailboxService;
import io.bitsquare.user.User; import io.bitsquare.user.User;
@ -69,7 +69,7 @@ public class TomP2PMailboxService extends TomP2PDHTService implements MailboxSer
} }
@Override @Override
public void addMessage(PublicKey publicKey, MailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler) { public void addMessage(PublicKey publicKey, EncryptedMailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler) {
try { try {
final Data data = new Data(message); final Data data = new Data(message);
data.ttlSeconds(TTL); data.ttlSeconds(TTL);
@ -101,7 +101,7 @@ public class TomP2PMailboxService extends TomP2PDHTService implements MailboxSer
} }
@Override @Override
public void removeMessage(PublicKey publicKey, MailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler) { public void removeMessage(PublicKey publicKey, EncryptedMailboxMessage message, ResultHandler resultHandler, FaultHandler faultHandler) {
try { try {
final Data data = new Data(message); final Data data = new Data(message);
log.trace("Remove message from DHT requested. Removed data: [locationKey: " + getLocationKey(publicKey) + log.trace("Remove message from DHT requested. Removed data: [locationKey: " + getLocationKey(publicKey) +
@ -141,13 +141,13 @@ public class TomP2PMailboxService extends TomP2PDHTService implements MailboxSer
public void operationComplete(BaseFuture future) throws Exception { public void operationComplete(BaseFuture future) throws Exception {
if (future.isSuccess()) { if (future.isSuccess()) {
final Map<Number640, Data> dataMap = futureGet.dataMap(); final Map<Number640, Data> dataMap = futureGet.dataMap();
List<MailboxMessage> messages = new ArrayList<>(); List<EncryptedMailboxMessage> messages = new ArrayList<>();
if (dataMap != null) { if (dataMap != null) {
for (Data messageData : dataMap.values()) { for (Data messageData : dataMap.values()) {
try { try {
Object messageDataObject = messageData.object(); Object messageDataObject = messageData.object();
if (messageDataObject instanceof MailboxMessage) { if (messageDataObject instanceof EncryptedMailboxMessage) {
messages.add((MailboxMessage) messageDataObject); messages.add((EncryptedMailboxMessage) messageDataObject);
} }
} catch (ClassNotFoundException | IOException e) { } catch (ClassNotFoundException | IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -183,6 +183,6 @@ public class TomP2PMailboxService extends TomP2PDHTService implements MailboxSer
} }
public interface MailboxMessagesResultHandler { public interface MailboxMessagesResultHandler {
void handleResult(List<MailboxMessage> messages); void handleResult(List<EncryptedMailboxMessage> messages);
} }
} }

View file

@ -17,11 +17,16 @@
package io.bitsquare.p2p.tomp2p; package io.bitsquare.p2p.tomp2p;
import io.bitsquare.crypto.EncryptionService;
import io.bitsquare.p2p.EncryptedMailboxMessage;
import io.bitsquare.p2p.MailboxMessage;
import io.bitsquare.p2p.MailboxService;
import io.bitsquare.p2p.Message; import io.bitsquare.p2p.Message;
import io.bitsquare.p2p.MessageHandler; import io.bitsquare.p2p.MessageHandler;
import io.bitsquare.p2p.MessageService; import io.bitsquare.p2p.MessageService;
import io.bitsquare.p2p.Peer; import io.bitsquare.p2p.Peer;
import io.bitsquare.p2p.listener.SendMessageListener; import io.bitsquare.p2p.listener.SendMessageListener;
import io.bitsquare.user.User;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
@ -38,6 +43,9 @@ public class TomP2PMessageService extends TomP2PService implements MessageServic
private static final Logger log = LoggerFactory.getLogger(TomP2PMessageService.class); private static final Logger log = LoggerFactory.getLogger(TomP2PMessageService.class);
private final CopyOnWriteArrayList<MessageHandler> messageHandlers = new CopyOnWriteArrayList<>(); private final CopyOnWriteArrayList<MessageHandler> messageHandlers = new CopyOnWriteArrayList<>();
private MailboxService mailboxService;
private User user;
private EncryptionService<MailboxMessage> encryptionService;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -45,8 +53,11 @@ public class TomP2PMessageService extends TomP2PService implements MessageServic
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Inject @Inject
public TomP2PMessageService(TomP2PNode tomP2PNode) { public TomP2PMessageService(TomP2PNode tomP2PNode, MailboxService mailboxService, User user, EncryptionService encryptionService) {
super(tomP2PNode); super(tomP2PNode);
this.mailboxService = mailboxService;
this.user = user;
this.encryptionService = encryptionService;
} }
@ -74,20 +85,46 @@ public class TomP2PMessageService extends TomP2PService implements MessageServic
log.debug("sendMessage completed"); log.debug("sendMessage completed");
executor.execute(listener::handleResult); executor.execute(listener::handleResult);
} }
else {
if (message instanceof MailboxMessage) {
sendMailboxMessage((MailboxMessage) message, listener);
}
else { else {
log.error("sendMessage failed with reason " + futureDirect.failedReason()); log.error("sendMessage failed with reason " + futureDirect.failedReason());
executor.execute(listener::handleFault); executor.execute(listener::handleFault);
} }
} }
}
@Override @Override
public void exceptionCaught(Throwable t) throws Exception { public void exceptionCaught(Throwable t) throws Exception {
log.error("Exception at sendMessage " + t.toString()); if (message instanceof MailboxMessage) {
sendMailboxMessage((MailboxMessage) message, listener);
}
else {
log.error("sendMessage failed with exception " + t.getMessage());
executor.execute(listener::handleFault); executor.execute(listener::handleFault);
} }
}
}); });
} }
private void sendMailboxMessage(MailboxMessage message, SendMessageListener listener) {
EncryptionService.Tuple tuple = encryptionService.encryptObject(user.getP2pEncryptKeyPair().getPublic(), message);
EncryptedMailboxMessage encrypted = new EncryptedMailboxMessage(tuple);
mailboxService.addMessage(user.getP2PSigPubKey(), encrypted,
() -> {
log.debug("Message successfully added to peers mailbox.");
executor.execute(listener::handleResult);
},
(errorMessage, throwable) -> {
log.error("Message failed to add to peers mailbox.");
executor.execute(listener::handleFault);
}
);
}
@Override @Override
public void addMessageHandler(MessageHandler listener) { public void addMessageHandler(MessageHandler listener) {
if (!messageHandlers.add(listener)) if (!messageHandlers.add(listener))

View file

@ -164,7 +164,7 @@ public class TradeManager {
} }
public boolean isMyOffer(Offer offer) { public boolean isMyOffer(Offer offer) {
return offer.getMessagePublicKey().equals(user.getMessagePubKey()); return offer.getMessagePublicKey().equals(user.getP2PSigPubKey());
} }
@ -206,7 +206,7 @@ public class TradeManager {
FiatAccount currentFiatAccount = user.getCurrentBankAccount().get(); FiatAccount currentFiatAccount = user.getCurrentBankAccount().get();
Offer offer = new Offer(id, Offer offer = new Offer(id,
user.getMessagePubKey(), user.getP2PSigPubKey(),
direction, direction,
price.getValue(), price.getValue(),
amount, amount,

View file

@ -17,11 +17,13 @@
package io.bitsquare.trade.protocol.trade.messages; package io.bitsquare.trade.protocol.trade.messages;
import io.bitsquare.p2p.MailboxMessage;
import org.bitcoinj.core.Coin; import org.bitcoinj.core.Coin;
import java.io.Serializable; import java.io.Serializable;
public class BankTransferStartedMessage extends TradeMessage implements Serializable { public class BankTransferStartedMessage extends TradeMessage implements MailboxMessage, Serializable {
private static final long serialVersionUID = -3479634129543632523L; private static final long serialVersionUID = -3479634129543632523L;
public final byte[] offererSignature; public final byte[] offererSignature;

View file

@ -37,7 +37,7 @@ public class BuyerAsOffererModel extends SharedTradeModel implements Serializabl
private static final Logger log = LoggerFactory.getLogger(BuyerAsOffererModel.class); private static final Logger log = LoggerFactory.getLogger(BuyerAsOffererModel.class);
transient public final Trade trade; transient public final Trade trade;
public final MailboxService mailboxService; transient public final MailboxService mailboxService;
public final TakerModel taker; public final TakerModel taker;
public final OffererModel offerer; public final OffererModel offerer;
@ -82,7 +82,7 @@ public class BuyerAsOffererModel extends SharedTradeModel implements Serializabl
offerer.addressEntry = walletService.getAddressEntry(id); offerer.addressEntry = walletService.getAddressEntry(id);
offerer.fiatAccount = user.getBankAccount(offer.getBankAccountId()); offerer.fiatAccount = user.getBankAccount(offer.getBankAccountId());
offerer.accountId = user.getAccountId(); offerer.accountId = user.getAccountId();
offerer.messagePubKey = user.getMessagePubKey(); offerer.p2pSigPubKey = user.getP2PSigPubKey();
offerer.pubKey = offerer.addressEntry.getPubKey(); offerer.pubKey = offerer.addressEntry.getPubKey();
log.debug("BuyerAsOffererModel addressEntry " + offerer.addressEntry); log.debug("BuyerAsOffererModel addressEntry " + offerer.addressEntry);
} }

View file

@ -37,7 +37,7 @@ public class OffererModel implements Serializable {
// Declared transient as they will be provided in any case at construction time // Declared transient as they will be provided in any case at construction time
transient public FiatAccount fiatAccount; transient public FiatAccount fiatAccount;
transient public String accountId; transient public String accountId;
transient public PublicKey messagePubKey; transient public PublicKey p2pSigPubKey;
transient public byte[] registrationPubKey; transient public byte[] registrationPubKey;
transient public DeterministicKey registrationKeyPair; transient public DeterministicKey registrationKeyPair;
transient public AddressEntry addressEntry; transient public AddressEntry addressEntry;

View file

@ -37,7 +37,7 @@ public class TakerModel implements Serializable {
public Peer peer; public Peer peer;
public String accountId; public String accountId;
public FiatAccount fiatAccount; public FiatAccount fiatAccount;
public PublicKey messagePublicKey; public PublicKey p2pSigPublicKey;
public String contractAsJson;//TODO only write access now, missing impl. public String contractAsJson;//TODO only write access now, missing impl.
public String contractSignature; public String contractSignature;
public Coin payoutAmount; public Coin payoutAmount;

View file

@ -43,7 +43,7 @@ public class ProcessRequestOffererPublishDepositTxMessage extends Task<BuyerAsOf
model.taker.fiatAccount = checkNotNull(message.takerFiatAccount); model.taker.fiatAccount = checkNotNull(message.takerFiatAccount);
model.taker.accountId = nonEmptyStringOf(message.takerAccountId); model.taker.accountId = nonEmptyStringOf(message.takerAccountId);
model.taker.messagePublicKey = checkNotNull(message.takerMessagePublicKey); model.taker.p2pSigPublicKey = checkNotNull(message.takerMessagePublicKey);
model.taker.contractAsJson = nonEmptyStringOf(message.takerContractAsJson); model.taker.contractAsJson = nonEmptyStringOf(message.takerContractAsJson);
model.taker.contractSignature = nonEmptyStringOf(message.takerContractSignature); model.taker.contractSignature = nonEmptyStringOf(message.takerContractSignature);
model.taker.payoutAddressString = nonEmptyStringOf(message.takerPayoutAddressString); model.taker.payoutAddressString = nonEmptyStringOf(message.takerPayoutAddressString);

View file

@ -46,8 +46,8 @@ public class VerifyAndSignContract extends Task<BuyerAsOffererModel> {
model.taker.accountId, model.taker.accountId,
model.offerer.fiatAccount, model.offerer.fiatAccount,
model.taker.fiatAccount, model.taker.fiatAccount,
model.offerer.messagePubKey, model.offerer.p2pSigPubKey,
model.taker.messagePublicKey); model.taker.p2pSigPublicKey);
String contractAsJson = Utilities.objectToJson(contract); String contractAsJson = Utilities.objectToJson(contract);
String signature = model.signatureService.signMessage(model.offerer.registrationKeyPair, contractAsJson); String signature = model.signatureService.signMessage(model.offerer.registrationKeyPair, contractAsJson);

View file

@ -86,7 +86,7 @@ public class SellerAsTakerModel extends SharedTradeModel implements Serializable
taker.addressEntry = walletService.getAddressEntry(id); taker.addressEntry = walletService.getAddressEntry(id);
taker.fiatAccount = user.getBankAccount(offer.getBankAccountId()); taker.fiatAccount = user.getBankAccount(offer.getBankAccountId());
taker.accountId = user.getAccountId(); taker.accountId = user.getAccountId();
taker.messagePubKey = user.getMessagePubKey(); taker.p2pSigPubKey = user.getP2PSigPubKey();
taker.pubKey = taker.addressEntry.getPubKey(); taker.pubKey = taker.addressEntry.getPubKey();
} }

View file

@ -38,7 +38,7 @@ public class TakerModel implements Serializable {
// Declared transient as they will be provided in any case at construction time // Declared transient as they will be provided in any case at construction time
transient public FiatAccount fiatAccount; transient public FiatAccount fiatAccount;
transient public String accountId; transient public String accountId;
transient public PublicKey messagePubKey; transient public PublicKey p2pSigPubKey;
transient public byte[] registrationPubKey; // TODO not read yet, missing impl. transient public byte[] registrationPubKey; // TODO not read yet, missing impl.
transient public DeterministicKey registrationKeyPair; transient public DeterministicKey registrationKeyPair;
transient public AddressEntry addressEntry; transient public AddressEntry addressEntry;

View file

@ -46,7 +46,7 @@ public class CreateAndSignContract extends Task<SellerAsTakerModel> {
model.offerer.fiatAccount, model.offerer.fiatAccount,
model.taker.fiatAccount, model.taker.fiatAccount,
model.offer.getMessagePublicKey(), model.offer.getMessagePublicKey(),
model.taker.messagePubKey); model.taker.p2pSigPubKey);
String contractAsJson = Utilities.objectToJson(contract); String contractAsJson = Utilities.objectToJson(contract);
String signature = model.signatureService.signMessage(model.taker.registrationKeyPair, contractAsJson); String signature = model.signatureService.signMessage(model.taker.registrationKeyPair, contractAsJson);

View file

@ -39,7 +39,7 @@ public class SendSignedTakerDepositTx extends Task<SellerAsTakerModel> {
model.id, model.id,
model.taker.fiatAccount, model.taker.fiatAccount,
model.taker.accountId, model.taker.accountId,
model.taker.messagePubKey, model.taker.p2pSigPubKey,
model.trade.getContractAsJson(), model.trade.getContractAsJson(),
model.trade.getTakerContractSignature(), model.trade.getTakerContractSignature(),
model.taker.addressEntry.getAddressString(), model.taker.addressEntry.getAddressString(),

View file

@ -175,7 +175,7 @@ public class User implements Serializable {
return p2pSigKeyPair; return p2pSigKeyPair;
} }
public PublicKey getMessagePubKey() { public PublicKey getP2PSigPubKey() {
return p2pSigKeyPair.getPublic(); return p2pSigKeyPair.getPublic();
} }

View file

@ -96,7 +96,7 @@ public class PlaceOfferProtocolTest {
user.applyPersistedUser(null); user.applyPersistedUser(null);
bootstrappedPeerBuilder = new BootstrappedPeerBuilder(Node.DEFAULT_PORT, false, bootstrapNode, "<unspecified>"); bootstrappedPeerBuilder = new BootstrappedPeerBuilder(Node.DEFAULT_PORT, false, bootstrapNode, "<unspecified>");
tomP2PNode = new TomP2PNode(bootstrappedPeerBuilder); tomP2PNode = new TomP2PNode(bootstrappedPeerBuilder);
messageService = new TomP2PMessageService(tomP2PNode); messageService = new TomP2PMessageService(tomP2PNode, null, null, null);
Observable<BootstrapState> messageObservable = tomP2PNode.bootstrap(user.getP2pSigKeyPair()); Observable<BootstrapState> messageObservable = tomP2PNode.bootstrap(user.getP2pSigKeyPair());
messageObservable.publish(); messageObservable.publish();