mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-12-22 19:49:32 +00:00
use byte[] for signatures instead of strings
This commit is contained in:
parent
ead70751dc
commit
4650003838
23 changed files with 265 additions and 255 deletions
|
@ -20,12 +20,15 @@ package haveno.core.offer;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonSerializationContext;
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
|
||||||
import haveno.common.crypto.Hash;
|
import haveno.common.crypto.Hash;
|
||||||
import haveno.common.crypto.PubKeyRing;
|
import haveno.common.crypto.PubKeyRing;
|
||||||
import haveno.common.proto.ProtoUtil;
|
import haveno.common.proto.ProtoUtil;
|
||||||
import haveno.common.util.CollectionUtils;
|
import haveno.common.util.CollectionUtils;
|
||||||
import haveno.common.util.Hex;
|
import haveno.common.util.Hex;
|
||||||
import haveno.common.util.JsonExclude;
|
import haveno.common.util.JsonExclude;
|
||||||
|
import haveno.common.util.Utilities;
|
||||||
import haveno.network.p2p.NodeAddress;
|
import haveno.network.p2p.NodeAddress;
|
||||||
import haveno.network.p2p.storage.payload.ExpirablePayload;
|
import haveno.network.p2p.storage.payload.ExpirablePayload;
|
||||||
import haveno.network.p2p.storage.payload.ProtectedStoragePayload;
|
import haveno.network.p2p.storage.payload.ProtectedStoragePayload;
|
||||||
|
@ -81,7 +84,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||||
protected NodeAddress arbitratorSigner;
|
protected NodeAddress arbitratorSigner;
|
||||||
@Setter
|
@Setter
|
||||||
@Nullable
|
@Nullable
|
||||||
protected String arbitratorSignature;
|
protected byte[] arbitratorSignature;
|
||||||
@Setter
|
@Setter
|
||||||
@Nullable
|
@Nullable
|
||||||
protected List<String> reserveTxKeyImages;
|
protected List<String> reserveTxKeyImages;
|
||||||
|
@ -191,7 +194,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||||
@Nullable Map<String, String> extraDataMap,
|
@Nullable Map<String, String> extraDataMap,
|
||||||
int protocolVersion,
|
int protocolVersion,
|
||||||
@Nullable NodeAddress arbitratorSigner,
|
@Nullable NodeAddress arbitratorSigner,
|
||||||
@Nullable String arbitratorSignature,
|
@Nullable byte[] arbitratorSignature,
|
||||||
@Nullable List<String> reserveTxKeyImages) {
|
@Nullable List<String> reserveTxKeyImages) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.date = date;
|
this.date = date;
|
||||||
|
@ -302,7 +305,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||||
Optional.ofNullable(acceptedCountryCodes).ifPresent(builder::addAllAcceptedCountryCodes);
|
Optional.ofNullable(acceptedCountryCodes).ifPresent(builder::addAllAcceptedCountryCodes);
|
||||||
Optional.ofNullable(hashOfChallenge).ifPresent(builder::setHashOfChallenge);
|
Optional.ofNullable(hashOfChallenge).ifPresent(builder::setHashOfChallenge);
|
||||||
Optional.ofNullable(extraDataMap).ifPresent(builder::putAllExtraData);
|
Optional.ofNullable(extraDataMap).ifPresent(builder::putAllExtraData);
|
||||||
Optional.ofNullable(arbitratorSignature).ifPresent(builder::setArbitratorSignature);
|
Optional.ofNullable(arbitratorSignature).ifPresent(e -> builder.setArbitratorSignature(ByteString.copyFrom(e)));
|
||||||
Optional.ofNullable(reserveTxKeyImages).ifPresent(builder::addAllReserveTxKeyImages);
|
Optional.ofNullable(reserveTxKeyImages).ifPresent(builder::addAllReserveTxKeyImages);
|
||||||
|
|
||||||
return protobuf.StoragePayload.newBuilder().setOfferPayload(builder).build();
|
return protobuf.StoragePayload.newBuilder().setOfferPayload(builder).build();
|
||||||
|
@ -352,7 +355,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||||
extraDataMapMap,
|
extraDataMapMap,
|
||||||
proto.getProtocolVersion(),
|
proto.getProtocolVersion(),
|
||||||
proto.hasArbitratorSigner() ? NodeAddress.fromProto(proto.getArbitratorSigner()) : null,
|
proto.hasArbitratorSigner() ? NodeAddress.fromProto(proto.getArbitratorSigner()) : null,
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getArbitratorSignature()),
|
ProtoUtil.byteArrayOrNullFromProto(proto.getArbitratorSignature()),
|
||||||
proto.getReserveTxKeyImagesList() == null ? null : new ArrayList<String>(proto.getReserveTxKeyImagesList()));
|
proto.getReserveTxKeyImagesList() == null ? null : new ArrayList<String>(proto.getReserveTxKeyImagesList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,8 +378,6 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||||
",\r\n pubKeyRing=" + pubKeyRing +
|
",\r\n pubKeyRing=" + pubKeyRing +
|
||||||
",\r\n hash=" + (hash != null ? Hex.encode(hash) : "null") +
|
",\r\n hash=" + (hash != null ? Hex.encode(hash) : "null") +
|
||||||
",\r\n extraDataMap=" + extraDataMap +
|
",\r\n extraDataMap=" + extraDataMap +
|
||||||
",\r\n arbitratorSigner=" + arbitratorSigner +
|
|
||||||
",\r\n arbitratorSignature=" + arbitratorSignature +
|
|
||||||
",\r\n reserveTxKeyImages=" + reserveTxKeyImages +
|
",\r\n reserveTxKeyImages=" + reserveTxKeyImages +
|
||||||
",\r\n marketPriceMargin=" + marketPriceMarginPct +
|
",\r\n marketPriceMargin=" + marketPriceMarginPct +
|
||||||
",\r\n useMarketBasedPrice=" + useMarketBasedPrice +
|
",\r\n useMarketBasedPrice=" + useMarketBasedPrice +
|
||||||
|
@ -398,7 +399,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||||
",\r\n isPrivateOffer=" + isPrivateOffer +
|
",\r\n isPrivateOffer=" + isPrivateOffer +
|
||||||
",\r\n hashOfChallenge='" + hashOfChallenge + '\'' +
|
",\r\n hashOfChallenge='" + hashOfChallenge + '\'' +
|
||||||
",\n arbitratorSigner=" + arbitratorSigner +
|
",\n arbitratorSigner=" + arbitratorSigner +
|
||||||
",\n arbitratorSignature=" + arbitratorSignature +
|
",\n arbitratorSignature=" + Utilities.bytesAsHexString(arbitratorSignature) +
|
||||||
"\r\n} ";
|
"\r\n} ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ import haveno.common.app.Capability;
|
||||||
import haveno.common.app.Version;
|
import haveno.common.app.Version;
|
||||||
import haveno.common.crypto.KeyRing;
|
import haveno.common.crypto.KeyRing;
|
||||||
import haveno.common.crypto.PubKeyRing;
|
import haveno.common.crypto.PubKeyRing;
|
||||||
import haveno.common.crypto.Sig;
|
|
||||||
import haveno.common.handlers.ErrorMessageHandler;
|
import haveno.common.handlers.ErrorMessageHandler;
|
||||||
import haveno.common.handlers.ResultHandler;
|
import haveno.common.handlers.ResultHandler;
|
||||||
import haveno.common.persistence.PersistenceManager;
|
import haveno.common.persistence.PersistenceManager;
|
||||||
|
@ -1000,7 +999,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
|
|
||||||
// arbitrator signs offer to certify they have valid reserve tx
|
// arbitrator signs offer to certify they have valid reserve tx
|
||||||
String offerPayloadAsJson = JsonUtil.objectToJson(request.getOfferPayload());
|
String offerPayloadAsJson = JsonUtil.objectToJson(request.getOfferPayload());
|
||||||
String signature = Sig.sign(keyRing.getSignatureKeyPair().getPrivate(), offerPayloadAsJson);
|
byte[] signature = HavenoUtils.sign(keyRing, offerPayloadAsJson);
|
||||||
OfferPayload signedOfferPayload = request.getOfferPayload();
|
OfferPayload signedOfferPayload = request.getOfferPayload();
|
||||||
signedOfferPayload.setArbitratorSignature(signature);
|
signedOfferPayload.setArbitratorSignature(signature);
|
||||||
|
|
||||||
|
@ -1119,7 +1118,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
try {
|
try {
|
||||||
Optional<OpenOffer> openOfferOptional = getOpenOfferById(request.offerId);
|
Optional<OpenOffer> openOfferOptional = getOpenOfferById(request.offerId);
|
||||||
AvailabilityResult availabilityResult;
|
AvailabilityResult availabilityResult;
|
||||||
String makerSignature = null;
|
byte[] makerSignature = null;
|
||||||
if (openOfferOptional.isPresent()) {
|
if (openOfferOptional.isPresent()) {
|
||||||
OpenOffer openOffer = openOfferOptional.get();
|
OpenOffer openOffer = openOfferOptional.get();
|
||||||
if (!apiUserDeniedByOffer(request)) {
|
if (!apiUserDeniedByOffer(request)) {
|
||||||
|
@ -1130,7 +1129,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
|
|
||||||
// maker signs taker's request
|
// maker signs taker's request
|
||||||
String tradeRequestAsJson = JsonUtil.objectToJson(request.getTradeRequest());
|
String tradeRequestAsJson = JsonUtil.objectToJson(request.getTradeRequest());
|
||||||
makerSignature = Sig.sign(keyRing.getSignatureKeyPair().getPrivate(), tradeRequestAsJson);
|
makerSignature = HavenoUtils.sign(keyRing, tradeRequestAsJson);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check also tradePrice to avoid failures after taker fee is paid caused by a too big difference
|
// Check also tradePrice to avoid failures after taker fee is paid caused by a too big difference
|
||||||
|
|
|
@ -17,10 +17,14 @@
|
||||||
|
|
||||||
package haveno.core.offer;
|
package haveno.core.offer;
|
||||||
|
|
||||||
|
import haveno.common.proto.ProtoUtil;
|
||||||
import haveno.common.proto.persistable.PersistablePayload;
|
import haveno.common.proto.persistable.PersistablePayload;
|
||||||
import haveno.core.util.JsonUtil;
|
import haveno.core.util.JsonUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -48,7 +52,7 @@ public final class SignedOffer implements PersistablePayload {
|
||||||
@Getter
|
@Getter
|
||||||
private final long reserveTxMinerFee;
|
private final long reserveTxMinerFee;
|
||||||
@Getter
|
@Getter
|
||||||
private final String arbitratorSignature;
|
private final byte[] arbitratorSignature;
|
||||||
|
|
||||||
public SignedOffer(long timeStamp,
|
public SignedOffer(long timeStamp,
|
||||||
int traderId,
|
int traderId,
|
||||||
|
@ -59,7 +63,7 @@ public final class SignedOffer implements PersistablePayload {
|
||||||
String reserveTxHex,
|
String reserveTxHex,
|
||||||
List<String> reserveTxKeyImages,
|
List<String> reserveTxKeyImages,
|
||||||
long reserveTxMinerFee,
|
long reserveTxMinerFee,
|
||||||
String arbitratorSignature) {
|
byte[] arbitratorSignature) {
|
||||||
this.timeStamp = timeStamp;
|
this.timeStamp = timeStamp;
|
||||||
this.traderId = traderId;
|
this.traderId = traderId;
|
||||||
this.offerId = offerId;
|
this.offerId = offerId;
|
||||||
|
@ -88,7 +92,7 @@ public final class SignedOffer implements PersistablePayload {
|
||||||
.setReserveTxHex(reserveTxHex)
|
.setReserveTxHex(reserveTxHex)
|
||||||
.addAllReserveTxKeyImages(reserveTxKeyImages)
|
.addAllReserveTxKeyImages(reserveTxKeyImages)
|
||||||
.setReserveTxMinerFee(reserveTxMinerFee)
|
.setReserveTxMinerFee(reserveTxMinerFee)
|
||||||
.setArbitratorSignature(arbitratorSignature);
|
.setArbitratorSignature(ByteString.copyFrom(arbitratorSignature));
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +106,7 @@ public final class SignedOffer implements PersistablePayload {
|
||||||
proto.getReserveTxHex(),
|
proto.getReserveTxHex(),
|
||||||
proto.getReserveTxKeyImagesList(),
|
proto.getReserveTxKeyImagesList(),
|
||||||
proto.getReserveTxMinerFee(),
|
proto.getReserveTxMinerFee(),
|
||||||
proto.getArbitratorSignature());
|
ProtoUtil.byteArrayOrNullFromProto(proto.getArbitratorSignature()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class OfferAvailabilityModel implements Model {
|
||||||
@Nullable
|
@Nullable
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
private String makerSignature;
|
private byte[] makerSignature;
|
||||||
|
|
||||||
// Added in v1.5.5
|
// Added in v1.5.5
|
||||||
@Getter
|
@Getter
|
||||||
|
|
|
@ -17,9 +17,7 @@
|
||||||
|
|
||||||
package haveno.core.offer.availability.tasks;
|
package haveno.core.offer.availability.tasks;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import haveno.common.app.Version;
|
import haveno.common.app.Version;
|
||||||
import haveno.common.crypto.Sig;
|
|
||||||
import haveno.common.taskrunner.Task;
|
import haveno.common.taskrunner.Task;
|
||||||
import haveno.common.taskrunner.TaskRunner;
|
import haveno.common.taskrunner.TaskRunner;
|
||||||
import haveno.core.monetary.Price;
|
import haveno.core.monetary.Price;
|
||||||
|
@ -59,7 +57,7 @@ public class SendOfferAvailabilityRequest extends Task<OfferAvailabilityModel> {
|
||||||
String payoutAddress = walletService.getOrCreateAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString(); // reserve new payout address
|
String payoutAddress = walletService.getOrCreateAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString(); // reserve new payout address
|
||||||
|
|
||||||
// taker signs offer using offer id as nonce to avoid challenge protocol
|
// taker signs offer using offer id as nonce to avoid challenge protocol
|
||||||
byte[] sig = Sig.sign(model.getP2PService().getKeyRing().getSignatureKeyPair().getPrivate(), offer.getId().getBytes(Charsets.UTF_8));
|
byte[] sig = HavenoUtils.sign(model.getP2PService().getKeyRing(), offer.getId());
|
||||||
|
|
||||||
// get price
|
// get price
|
||||||
Price price = offer.getPrice();
|
Price price = offer.getPrice();
|
||||||
|
|
|
@ -31,6 +31,8 @@ import lombok.Value;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
|
||||||
// We add here the SupportedCapabilitiesMessage interface as that message always predates a direct connection
|
// We add here the SupportedCapabilitiesMessage interface as that message always predates a direct connection
|
||||||
// to the trading peer
|
// to the trading peer
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ -41,11 +43,11 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
|
||||||
private final Capabilities supportedCapabilities;
|
private final Capabilities supportedCapabilities;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String makerSignature;
|
private byte[] makerSignature;
|
||||||
|
|
||||||
public OfferAvailabilityResponse(String offerId,
|
public OfferAvailabilityResponse(String offerId,
|
||||||
AvailabilityResult availabilityResult,
|
AvailabilityResult availabilityResult,
|
||||||
String makerSignature) {
|
@Nullable byte[] makerSignature) {
|
||||||
this(offerId,
|
this(offerId,
|
||||||
availabilityResult,
|
availabilityResult,
|
||||||
Capabilities.app,
|
Capabilities.app,
|
||||||
|
@ -64,7 +66,7 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
|
||||||
@Nullable Capabilities supportedCapabilities,
|
@Nullable Capabilities supportedCapabilities,
|
||||||
String messageVersion,
|
String messageVersion,
|
||||||
@Nullable String uid,
|
@Nullable String uid,
|
||||||
String makerSignature) {
|
byte[] makerSignature) {
|
||||||
super(messageVersion, offerId, uid);
|
super(messageVersion, offerId, uid);
|
||||||
this.availabilityResult = availabilityResult;
|
this.availabilityResult = availabilityResult;
|
||||||
this.supportedCapabilities = supportedCapabilities;
|
this.supportedCapabilities = supportedCapabilities;
|
||||||
|
@ -79,7 +81,7 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
|
||||||
|
|
||||||
Optional.ofNullable(supportedCapabilities).ifPresent(e -> builder.addAllSupportedCapabilities(Capabilities.toIntList(supportedCapabilities)));
|
Optional.ofNullable(supportedCapabilities).ifPresent(e -> builder.addAllSupportedCapabilities(Capabilities.toIntList(supportedCapabilities)));
|
||||||
Optional.ofNullable(uid).ifPresent(e -> builder.setUid(uid));
|
Optional.ofNullable(uid).ifPresent(e -> builder.setUid(uid));
|
||||||
Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(makerSignature));
|
Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(ByteString.copyFrom(e)));
|
||||||
|
|
||||||
return getNetworkEnvelopeBuilder()
|
return getNetworkEnvelopeBuilder()
|
||||||
.setOfferAvailabilityResponse(builder)
|
.setOfferAvailabilityResponse(builder)
|
||||||
|
@ -92,6 +94,6 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
|
||||||
Capabilities.fromIntList(proto.getSupportedCapabilitiesList()),
|
Capabilities.fromIntList(proto.getSupportedCapabilitiesList()),
|
||||||
messageVersion,
|
messageVersion,
|
||||||
proto.getUid().isEmpty() ? null : proto.getUid(),
|
proto.getUid().isEmpty() ? null : proto.getUid(),
|
||||||
proto.getMakerSignature().isEmpty() ? null : proto.getMakerSignature());
|
ProtoUtil.byteArrayOrNullFromProto(proto.getMakerSignature()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,9 +104,9 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
|
||||||
private final String payoutTxId;
|
private final String payoutTxId;
|
||||||
private String contractAsJson;
|
private String contractAsJson;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String makerContractSignature;
|
private final byte[] makerContractSignature;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String takerContractSignature;
|
private final byte[] takerContractSignature;
|
||||||
private final PubKeyRing agentPubKeyRing; // dispute agent
|
private final PubKeyRing agentPubKeyRing; // dispute agent
|
||||||
private final boolean isSupportTicket;
|
private final boolean isSupportTicket;
|
||||||
private final ObservableList<ChatMessage> chatMessages = FXCollections.observableArrayList();
|
private final ObservableList<ChatMessage> chatMessages = FXCollections.observableArrayList();
|
||||||
|
@ -179,8 +179,8 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
|
||||||
@Nullable String depositTxId,
|
@Nullable String depositTxId,
|
||||||
@Nullable String payoutTxId,
|
@Nullable String payoutTxId,
|
||||||
String contractAsJson,
|
String contractAsJson,
|
||||||
@Nullable String makerContractSignature,
|
@Nullable byte[] makerContractSignature,
|
||||||
@Nullable String takerContractSignature,
|
@Nullable byte[] takerContractSignature,
|
||||||
@Nullable PaymentAccountPayload makerPaymentAccountPayload,
|
@Nullable PaymentAccountPayload makerPaymentAccountPayload,
|
||||||
@Nullable PaymentAccountPayload takerPaymentAccountPayload,
|
@Nullable PaymentAccountPayload takerPaymentAccountPayload,
|
||||||
PubKeyRing agentPubKeyRing,
|
PubKeyRing agentPubKeyRing,
|
||||||
|
@ -251,8 +251,8 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
|
||||||
Optional.ofNullable(depositTxId).ifPresent(builder::setDepositTxId);
|
Optional.ofNullable(depositTxId).ifPresent(builder::setDepositTxId);
|
||||||
Optional.ofNullable(payoutTxId).ifPresent(builder::setPayoutTxId);
|
Optional.ofNullable(payoutTxId).ifPresent(builder::setPayoutTxId);
|
||||||
Optional.ofNullable(disputePayoutTxId).ifPresent(builder::setDisputePayoutTxId);
|
Optional.ofNullable(disputePayoutTxId).ifPresent(builder::setDisputePayoutTxId);
|
||||||
Optional.ofNullable(makerContractSignature).ifPresent(builder::setMakerContractSignature);
|
Optional.ofNullable(makerContractSignature).ifPresent(e -> builder.setMakerContractSignature(ByteString.copyFrom(e)));
|
||||||
Optional.ofNullable(takerContractSignature).ifPresent(builder::setTakerContractSignature);
|
Optional.ofNullable(takerContractSignature).ifPresent(e -> builder.setTakerContractSignature(ByteString.copyFrom(e)));
|
||||||
Optional.ofNullable(makerPaymentAccountPayload).ifPresent(e -> builder.setMakerPaymentAccountPayload((protobuf.PaymentAccountPayload) makerPaymentAccountPayload.toProtoMessage()));
|
Optional.ofNullable(makerPaymentAccountPayload).ifPresent(e -> builder.setMakerPaymentAccountPayload((protobuf.PaymentAccountPayload) makerPaymentAccountPayload.toProtoMessage()));
|
||||||
Optional.ofNullable(takerPaymentAccountPayload).ifPresent(e -> builder.setTakerPaymentAccountPayload((protobuf.PaymentAccountPayload) takerPaymentAccountPayload.toProtoMessage()));
|
Optional.ofNullable(takerPaymentAccountPayload).ifPresent(e -> builder.setTakerPaymentAccountPayload((protobuf.PaymentAccountPayload) takerPaymentAccountPayload.toProtoMessage()));
|
||||||
Optional.ofNullable(disputeResultProperty.get()).ifPresent(result -> builder.setDisputeResult(disputeResultProperty.get().toProtoMessage()));
|
Optional.ofNullable(disputeResultProperty.get()).ifPresent(result -> builder.setDisputeResult(disputeResultProperty.get().toProtoMessage()));
|
||||||
|
@ -281,8 +281,8 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getDepositTxId()),
|
ProtoUtil.stringOrNullFromProto(proto.getDepositTxId()),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getPayoutTxId()),
|
ProtoUtil.stringOrNullFromProto(proto.getPayoutTxId()),
|
||||||
proto.getContractAsJson(),
|
proto.getContractAsJson(),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getMakerContractSignature()),
|
ProtoUtil.byteArrayOrNullFromProto(proto.getMakerContractSignature()),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getTakerContractSignature()),
|
ProtoUtil.byteArrayOrNullFromProto(proto.getTakerContractSignature()),
|
||||||
proto.hasMakerPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getMakerPaymentAccountPayload()) : null,
|
proto.hasMakerPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getMakerPaymentAccountPayload()) : null,
|
||||||
proto.hasTakerPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getTakerPaymentAccountPayload()) : null,
|
proto.hasTakerPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getTakerPaymentAccountPayload()) : null,
|
||||||
PubKeyRing.fromProto(proto.getAgentPubKeyRing()),
|
PubKeyRing.fromProto(proto.getAgentPubKeyRing()),
|
||||||
|
@ -524,8 +524,8 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
|
||||||
",\n depositTxId='" + depositTxId + '\'' +
|
",\n depositTxId='" + depositTxId + '\'' +
|
||||||
",\n payoutTxId='" + payoutTxId + '\'' +
|
",\n payoutTxId='" + payoutTxId + '\'' +
|
||||||
",\n contractAsJson='" + contractAsJson + '\'' +
|
",\n contractAsJson='" + contractAsJson + '\'' +
|
||||||
",\n makerContractSignature='" + makerContractSignature + '\'' +
|
",\n makerContractSignature='" + Utilities.bytesAsHexString(makerContractSignature) + '\'' +
|
||||||
",\n takerContractSignature='" + takerContractSignature + '\'' +
|
",\n takerContractSignature='" + Utilities.bytesAsHexString(takerContractSignature) + '\'' +
|
||||||
",\n agentPubKeyRing=" + agentPubKeyRing +
|
",\n agentPubKeyRing=" + agentPubKeyRing +
|
||||||
",\n isSupportTicket=" + isSupportTicket +
|
",\n isSupportTicket=" + isSupportTicket +
|
||||||
",\n chatMessages=" + chatMessages +
|
",\n chatMessages=" + chatMessages +
|
||||||
|
|
|
@ -17,16 +17,14 @@
|
||||||
|
|
||||||
package haveno.core.support.dispute;
|
package haveno.core.support.dispute;
|
||||||
|
|
||||||
import haveno.common.crypto.CryptoException;
|
|
||||||
import haveno.common.crypto.Hash;
|
import haveno.common.crypto.Hash;
|
||||||
import haveno.common.crypto.Sig;
|
|
||||||
import haveno.common.util.Utilities;
|
import haveno.common.util.Utilities;
|
||||||
import haveno.core.locale.Res;
|
import haveno.core.locale.Res;
|
||||||
import haveno.core.support.dispute.agent.DisputeAgent;
|
import haveno.core.support.dispute.agent.DisputeAgent;
|
||||||
import haveno.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
|
import haveno.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
|
||||||
|
import haveno.core.trade.HavenoUtils;
|
||||||
import haveno.network.p2p.NodeAddress;
|
import haveno.network.p2p.NodeAddress;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.PublicKey;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@ -46,10 +44,10 @@ public class DisputeSummaryVerification {
|
||||||
KeyPair signatureKeyPair = disputeManager.getSignatureKeyPair();
|
KeyPair signatureKeyPair = disputeManager.getSignatureKeyPair();
|
||||||
String sigAsHex;
|
String sigAsHex;
|
||||||
try {
|
try {
|
||||||
byte[] signature = Sig.sign(signatureKeyPair.getPrivate(), hash);
|
byte[] signature = HavenoUtils.sign(signatureKeyPair.getPrivate(), hash);
|
||||||
sigAsHex = Utilities.encodeToHex(signature);
|
sigAsHex = Utilities.encodeToHex(signature);
|
||||||
disputeResult.setArbitratorSignature(signature);
|
disputeResult.setArbitratorSignature(signature);
|
||||||
} catch (CryptoException e) {
|
} catch (Exception e) {
|
||||||
sigAsHex = "Signing failed";
|
sigAsHex = "Signing failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,19 +67,13 @@ public class DisputeSummaryVerification {
|
||||||
NodeAddress nodeAddress = new NodeAddress(fullAddress);
|
NodeAddress nodeAddress = new NodeAddress(fullAddress);
|
||||||
DisputeAgent disputeAgent = arbitratorMediator.getDisputeAgentByNodeAddress(nodeAddress).orElse(null);
|
DisputeAgent disputeAgent = arbitratorMediator.getDisputeAgentByNodeAddress(nodeAddress).orElse(null);
|
||||||
checkNotNull(disputeAgent, "Dispute agent is null");
|
checkNotNull(disputeAgent, "Dispute agent is null");
|
||||||
PublicKey pubKey = disputeAgent.getPubKeyRing().getSignaturePubKey();
|
|
||||||
|
|
||||||
String sigString = parts[1].split(SEPARATOR2)[0];
|
String sigString = parts[1].split(SEPARATOR2)[0];
|
||||||
byte[] sig = Utilities.decodeFromHex(sigString);
|
byte[] sig = Utilities.decodeFromHex(sigString);
|
||||||
byte[] hash = Hash.getSha256Hash(textToSign);
|
byte[] hash = Hash.getSha256Hash(textToSign);
|
||||||
try {
|
try {
|
||||||
boolean result = Sig.verify(pubKey, hash, sig);
|
HavenoUtils.verifySignature(disputeAgent.getPubKeyRing(), hash, sig);
|
||||||
if (result) {
|
} catch (Exception e) {
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(Res.get("support.sigCheck.popup.failed"));
|
|
||||||
}
|
|
||||||
} catch (CryptoException e) {
|
|
||||||
throw new IllegalArgumentException(Res.get("support.sigCheck.popup.failed"));
|
throw new IllegalArgumentException(Res.get("support.sigCheck.popup.failed"));
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
|
@ -18,12 +18,11 @@
|
||||||
package haveno.core.support.dispute;
|
package haveno.core.support.dispute;
|
||||||
|
|
||||||
import haveno.common.config.Config;
|
import haveno.common.config.Config;
|
||||||
import haveno.common.crypto.CryptoException;
|
|
||||||
import haveno.common.crypto.Hash;
|
import haveno.common.crypto.Hash;
|
||||||
import haveno.common.crypto.Sig;
|
|
||||||
import haveno.common.util.Tuple3;
|
import haveno.common.util.Tuple3;
|
||||||
import haveno.core.support.SupportType;
|
import haveno.core.support.SupportType;
|
||||||
import haveno.core.trade.Contract;
|
import haveno.core.trade.Contract;
|
||||||
|
import haveno.core.trade.HavenoUtils;
|
||||||
import haveno.core.trade.Trade;
|
import haveno.core.trade.Trade;
|
||||||
import haveno.core.util.JsonUtil;
|
import haveno.core.util.JsonUtil;
|
||||||
import haveno.core.util.validation.RegexValidatorFactory;
|
import haveno.core.util.validation.RegexValidatorFactory;
|
||||||
|
@ -64,23 +63,11 @@ public class DisputeValidation {
|
||||||
checkArgument(Arrays.equals(Objects.requireNonNull(dispute.getContractHash()), Hash.getSha256Hash(checkNotNull(dispute.getContractAsJson()))),
|
checkArgument(Arrays.equals(Objects.requireNonNull(dispute.getContractHash()), Hash.getSha256Hash(checkNotNull(dispute.getContractAsJson()))),
|
||||||
"Invalid contractHash");
|
"Invalid contractHash");
|
||||||
|
|
||||||
try {
|
|
||||||
// Only the dispute opener has set the signature
|
// Only the dispute opener has set the signature
|
||||||
String makerContractSignature = dispute.getMakerContractSignature();
|
byte[] makerContractSignature = dispute.getMakerContractSignature();
|
||||||
if (makerContractSignature != null) {
|
if (makerContractSignature != null) HavenoUtils.verifySignature(contract.getMakerPubKeyRing(), dispute.getContractAsJson(), makerContractSignature);
|
||||||
Sig.verify(contract.getMakerPubKeyRing().getSignaturePubKey(),
|
byte[] takerContractSignature = dispute.getTakerContractSignature();
|
||||||
dispute.getContractAsJson(),
|
if (takerContractSignature != null) HavenoUtils.verifySignature(contract.getTakerPubKeyRing(), dispute.getContractAsJson(), takerContractSignature);
|
||||||
makerContractSignature);
|
|
||||||
}
|
|
||||||
String takerContractSignature = dispute.getTakerContractSignature();
|
|
||||||
if (takerContractSignature != null) {
|
|
||||||
Sig.verify(contract.getTakerPubKeyRing().getSignaturePubKey(),
|
|
||||||
dispute.getContractAsJson(),
|
|
||||||
takerContractSignature);
|
|
||||||
}
|
|
||||||
} catch (CryptoException e) {
|
|
||||||
throw new ValidationException(dispute, e.getMessage());
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new ValidationException(dispute, t.getMessage());
|
throw new ValidationException(dispute, t.getMessage());
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import com.google.common.base.CaseFormat;
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import haveno.common.config.Config;
|
import haveno.common.config.Config;
|
||||||
import haveno.common.crypto.Hash;
|
import haveno.common.crypto.Hash;
|
||||||
|
import haveno.common.crypto.KeyRing;
|
||||||
import haveno.common.crypto.PubKeyRing;
|
import haveno.common.crypto.PubKeyRing;
|
||||||
import haveno.common.crypto.Sig;
|
import haveno.common.crypto.Sig;
|
||||||
import haveno.common.util.Utilities;
|
import haveno.common.util.Utilities;
|
||||||
|
@ -39,7 +40,7 @@ import java.text.DecimalFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
@ -236,6 +237,170 @@ public class HavenoUtils {
|
||||||
return feePerXmrAsDecimal.multiply(amountMultiplier).toBigInteger();
|
return feePerXmrAsDecimal.multiply(amountMultiplier).toBigInteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------ SIGNING AND VERIFYING -------------------------
|
||||||
|
|
||||||
|
public static byte[] sign(KeyRing keyRing, String message) {
|
||||||
|
return sign(keyRing.getSignatureKeyPair().getPrivate(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] sign(PrivateKey privateKey, String message) {
|
||||||
|
return sign(privateKey, message.getBytes(Charsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] sign(PrivateKey privateKey, byte[] bytes) {
|
||||||
|
try {
|
||||||
|
return Sig.sign(privateKey, bytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void verifySignature(PubKeyRing pubKeyRing, String message, byte[] signature) {
|
||||||
|
verifySignature(pubKeyRing, message.getBytes(Charsets.UTF_8), signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void verifySignature(PubKeyRing pubKeyRing, byte[] bytes, byte[] signature) {
|
||||||
|
try {
|
||||||
|
Sig.verify(pubKeyRing.getSignaturePubKey(), bytes, signature);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSignatureValid(PubKeyRing pubKeyRing, String message, byte[] signature) {
|
||||||
|
return isSignatureValid(pubKeyRing, message.getBytes(Charsets.UTF_8), signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSignatureValid(PubKeyRing pubKeyRing, byte[] bytes, byte[] signature) {
|
||||||
|
try {
|
||||||
|
verifySignature(pubKeyRing, bytes, signature);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the arbitrator signature is valid for an offer.
|
||||||
|
*
|
||||||
|
* @param offer is a signed offer with payload
|
||||||
|
* @param arbitrator is the original signing arbitrator
|
||||||
|
* @return true if the arbitrator's signature is valid for the offer
|
||||||
|
*/
|
||||||
|
public static boolean isArbitratorSignatureValid(Offer offer, Arbitrator arbitrator) {
|
||||||
|
|
||||||
|
// copy offer payload
|
||||||
|
OfferPayload offerPayloadCopy = OfferPayload.fromProto(offer.toProtoMessage().getOfferPayload());
|
||||||
|
|
||||||
|
// remove arbitrator signature from signed payload
|
||||||
|
byte[] signature = offerPayloadCopy.getArbitratorSignature();
|
||||||
|
offerPayloadCopy.setArbitratorSignature(null);
|
||||||
|
|
||||||
|
// get unsigned offer payload as json string
|
||||||
|
String unsignedOfferAsJson = JsonUtil.objectToJson(offerPayloadCopy);
|
||||||
|
|
||||||
|
// verify signature
|
||||||
|
return isSignatureValid(arbitrator.getPubKeyRing(), unsignedOfferAsJson, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the maker signature for a trade request is valid.
|
||||||
|
*
|
||||||
|
* @param request is the trade request to check
|
||||||
|
* @return true if the maker's signature is valid for the trade request
|
||||||
|
*/
|
||||||
|
public static boolean isMakerSignatureValid(InitTradeRequest request, byte[] signature, PubKeyRing makerPubKeyRing) {
|
||||||
|
|
||||||
|
// re-create trade request with signed fields
|
||||||
|
InitTradeRequest signedRequest = new InitTradeRequest(
|
||||||
|
request.getTradeId(),
|
||||||
|
request.getSenderNodeAddress(),
|
||||||
|
request.getPubKeyRing(),
|
||||||
|
request.getTradeAmount(),
|
||||||
|
request.getTradePrice(),
|
||||||
|
request.getTradeFee(),
|
||||||
|
request.getAccountId(),
|
||||||
|
request.getPaymentAccountId(),
|
||||||
|
request.getPaymentMethodId(),
|
||||||
|
request.getUid(),
|
||||||
|
request.getMessageVersion(),
|
||||||
|
request.getAccountAgeWitnessSignatureOfOfferId(),
|
||||||
|
request.getCurrentDate(),
|
||||||
|
request.getMakerNodeAddress(),
|
||||||
|
request.getTakerNodeAddress(),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
request.getPayoutAddress(),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
// get trade request as string
|
||||||
|
String tradeRequestAsJson = JsonUtil.objectToJson(signedRequest);
|
||||||
|
|
||||||
|
// verify maker signature
|
||||||
|
return isSignatureValid(makerPubKeyRing, tradeRequestAsJson, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the buyer signature for a PaymentSentMessage.
|
||||||
|
*
|
||||||
|
* @param trade - the trade to verify
|
||||||
|
* @param message - signed payment sent message to verify
|
||||||
|
* @return true if the buyer's signature is valid for the message
|
||||||
|
*/
|
||||||
|
public static void verifyPaymentSentMessage(Trade trade, PaymentSentMessage message) {
|
||||||
|
|
||||||
|
// remove signature from message
|
||||||
|
byte[] signature = message.getBuyerSignature();
|
||||||
|
message.setBuyerSignature(null);
|
||||||
|
|
||||||
|
// get unsigned message as json string
|
||||||
|
String unsignedMessageAsJson = JsonUtil.objectToJson(message);
|
||||||
|
|
||||||
|
// replace signature
|
||||||
|
message.setBuyerSignature(signature);
|
||||||
|
|
||||||
|
// verify signature
|
||||||
|
if (!isSignatureValid(trade.getBuyer().getPubKeyRing(), unsignedMessageAsJson, signature)) {
|
||||||
|
throw new IllegalArgumentException("The buyer signature is invalid for the " + message.getClass().getSimpleName() + " for " + trade.getClass().getSimpleName() + " " + trade.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify trade id
|
||||||
|
if (!trade.getId().equals(message.getTradeId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getTradeId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the seller signature for a PaymentReceivedMessage.
|
||||||
|
*
|
||||||
|
* @param trade - the trade to verify
|
||||||
|
* @param message - signed payment received message to verify
|
||||||
|
* @return true if the seller's signature is valid for the message
|
||||||
|
*/
|
||||||
|
public static void verifyPaymentReceivedMessage(Trade trade, PaymentReceivedMessage message) {
|
||||||
|
|
||||||
|
// remove signature from message
|
||||||
|
byte[] signature = message.getSellerSignature();
|
||||||
|
message.setSellerSignature(null);
|
||||||
|
|
||||||
|
// get unsigned message as json string
|
||||||
|
String unsignedMessageAsJson = JsonUtil.objectToJson(message);
|
||||||
|
|
||||||
|
// replace signature
|
||||||
|
message.setSellerSignature(signature);
|
||||||
|
|
||||||
|
// verify signature
|
||||||
|
if (!isSignatureValid(trade.getSeller().getPubKeyRing(), unsignedMessageAsJson, signature)) {
|
||||||
|
throw new IllegalArgumentException("The seller signature is invalid for the " + message.getClass().getSimpleName() + " for " + trade.getClass().getSimpleName() + " " + trade.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify trade id
|
||||||
|
if (!trade.getId().equals(message.getTradeId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getTradeId());
|
||||||
|
|
||||||
|
// verify buyer signature of payment sent message
|
||||||
|
verifyPaymentSentMessage(trade, message.getPaymentSentMessage());
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------- OTHER UTILS ------------------------------
|
// ----------------------------- OTHER UTILS ------------------------------
|
||||||
|
|
||||||
|
@ -282,144 +447,6 @@ public class HavenoUtils {
|
||||||
return Utilities.bytesAsHexString(Hash.getSha256Ripemd160hash(uniqueId.getBytes(Charsets.UTF_8)));
|
return Utilities.bytesAsHexString(Hash.getSha256Ripemd160hash(uniqueId.getBytes(Charsets.UTF_8)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the arbitrator signature is valid for an offer.
|
|
||||||
*
|
|
||||||
* @param offer is a signed offer with payload
|
|
||||||
* @param arbitrator is the original signing arbitrator
|
|
||||||
* @return true if the arbitrator's signature is valid for the offer
|
|
||||||
*/
|
|
||||||
public static boolean isArbitratorSignatureValid(Offer offer, Arbitrator arbitrator) {
|
|
||||||
|
|
||||||
// copy offer payload
|
|
||||||
OfferPayload offerPayloadCopy = OfferPayload.fromProto(offer.toProtoMessage().getOfferPayload());
|
|
||||||
|
|
||||||
// remove arbitrator signature from signed payload
|
|
||||||
String signature = offerPayloadCopy.getArbitratorSignature();
|
|
||||||
offerPayloadCopy.setArbitratorSignature(null);
|
|
||||||
|
|
||||||
// get unsigned offer payload as json string
|
|
||||||
String unsignedOfferAsJson = JsonUtil.objectToJson(offerPayloadCopy);
|
|
||||||
|
|
||||||
// verify arbitrator signature
|
|
||||||
try {
|
|
||||||
return Sig.verify(arbitrator.getPubKeyRing().getSignaturePubKey(), unsignedOfferAsJson, signature);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the maker signature for a trade request is valid.
|
|
||||||
*
|
|
||||||
* @param request is the trade request to check
|
|
||||||
* @return true if the maker's signature is valid for the trade request
|
|
||||||
*/
|
|
||||||
public static boolean isMakerSignatureValid(InitTradeRequest request, String signature, PubKeyRing makerPubKeyRing) {
|
|
||||||
|
|
||||||
// re-create trade request with signed fields
|
|
||||||
InitTradeRequest signedRequest = new InitTradeRequest(
|
|
||||||
request.getTradeId(),
|
|
||||||
request.getSenderNodeAddress(),
|
|
||||||
request.getPubKeyRing(),
|
|
||||||
request.getTradeAmount(),
|
|
||||||
request.getTradePrice(),
|
|
||||||
request.getTradeFee(),
|
|
||||||
request.getAccountId(),
|
|
||||||
request.getPaymentAccountId(),
|
|
||||||
request.getPaymentMethodId(),
|
|
||||||
request.getUid(),
|
|
||||||
request.getMessageVersion(),
|
|
||||||
request.getAccountAgeWitnessSignatureOfOfferId(),
|
|
||||||
request.getCurrentDate(),
|
|
||||||
request.getMakerNodeAddress(),
|
|
||||||
request.getTakerNodeAddress(),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
request.getPayoutAddress(),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
// get trade request as string
|
|
||||||
String tradeRequestAsJson = JsonUtil.objectToJson(signedRequest);
|
|
||||||
|
|
||||||
// verify maker signature
|
|
||||||
try {
|
|
||||||
return Sig.verify(makerPubKeyRing.getSignaturePubKey(),
|
|
||||||
tradeRequestAsJson,
|
|
||||||
signature);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify the buyer signature for a PaymentSentMessage.
|
|
||||||
*
|
|
||||||
* @param trade - the trade to verify
|
|
||||||
* @param message - signed payment sent message to verify
|
|
||||||
* @return true if the buyer's signature is valid for the message
|
|
||||||
*/
|
|
||||||
public static void verifyPaymentSentMessage(Trade trade, PaymentSentMessage message) {
|
|
||||||
|
|
||||||
// remove signature from message
|
|
||||||
byte[] signature = message.getBuyerSignature();
|
|
||||||
message.setBuyerSignature(null);
|
|
||||||
|
|
||||||
// get unsigned message as json string
|
|
||||||
String unsignedMessageAsJson = JsonUtil.objectToJson(message);
|
|
||||||
|
|
||||||
// replace signature
|
|
||||||
message.setBuyerSignature(signature);
|
|
||||||
|
|
||||||
// verify signature
|
|
||||||
String errMessage = "The buyer signature is invalid for the " + message.getClass().getSimpleName() + " for " + trade.getClass().getSimpleName() + " " + trade.getId();
|
|
||||||
try {
|
|
||||||
if (!Sig.verify(trade.getBuyer().getPubKeyRing().getSignaturePubKey(), unsignedMessageAsJson.getBytes(Charsets.UTF_8), signature)) throw new IllegalArgumentException(errMessage);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IllegalArgumentException(errMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify trade id
|
|
||||||
if (!trade.getId().equals(message.getTradeId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getTradeId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify the seller signature for a PaymentReceivedMessage.
|
|
||||||
*
|
|
||||||
* @param trade - the trade to verify
|
|
||||||
* @param message - signed payment received message to verify
|
|
||||||
* @return true if the seller's signature is valid for the message
|
|
||||||
*/
|
|
||||||
public static void verifyPaymentReceivedMessage(Trade trade, PaymentReceivedMessage message) {
|
|
||||||
|
|
||||||
// remove signature from message
|
|
||||||
byte[] signature = message.getSellerSignature();
|
|
||||||
message.setSellerSignature(null);
|
|
||||||
|
|
||||||
// get unsigned message as json string
|
|
||||||
String unsignedMessageAsJson = JsonUtil.objectToJson(message);
|
|
||||||
|
|
||||||
// replace signature
|
|
||||||
message.setSellerSignature(signature);
|
|
||||||
|
|
||||||
// verify signature
|
|
||||||
String errMessage = "The seller signature is invalid for the " + message.getClass().getSimpleName() + " for " + trade.getClass().getSimpleName() + " " + trade.getId();
|
|
||||||
try {
|
|
||||||
if (!Sig.verify(trade.getSeller().getPubKeyRing().getSignaturePubKey(), unsignedMessageAsJson.getBytes(Charsets.UTF_8), signature)) throw new IllegalArgumentException(errMessage);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IllegalArgumentException(errMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify trade id
|
|
||||||
if (!trade.getId().equals(message.getTradeId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getTradeId());
|
|
||||||
|
|
||||||
// verify buyer signature of payment sent message
|
|
||||||
verifyPaymentSentMessage(trade, message.getPaymentSentMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void awaitLatch(CountDownLatch latch) {
|
public static void awaitLatch(CountDownLatch latch) {
|
||||||
try {
|
try {
|
||||||
latch.await();
|
latch.await();
|
||||||
|
|
|
@ -19,6 +19,7 @@ package haveno.core.trade.messages;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import haveno.common.proto.ProtoUtil;
|
import haveno.common.proto.ProtoUtil;
|
||||||
|
import haveno.common.util.Utilities;
|
||||||
import haveno.core.proto.CoreProtoResolver;
|
import haveno.core.proto.CoreProtoResolver;
|
||||||
import haveno.network.p2p.DirectMessage;
|
import haveno.network.p2p.DirectMessage;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
@ -30,7 +31,7 @@ import lombok.Value;
|
||||||
@Value
|
@Value
|
||||||
public final class DepositRequest extends TradeMessage implements DirectMessage {
|
public final class DepositRequest extends TradeMessage implements DirectMessage {
|
||||||
private final long currentDate;
|
private final long currentDate;
|
||||||
private final String contractSignature;
|
private final byte[] contractSignature;
|
||||||
private final String depositTxHex;
|
private final String depositTxHex;
|
||||||
private final String depositTxKey;
|
private final String depositTxKey;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -40,7 +41,7 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
|
||||||
String uid,
|
String uid,
|
||||||
String messageVersion,
|
String messageVersion,
|
||||||
long currentDate,
|
long currentDate,
|
||||||
String contractSignature,
|
byte[] contractSignature,
|
||||||
String depositTxHex,
|
String depositTxHex,
|
||||||
String depositTxKey,
|
String depositTxKey,
|
||||||
@Nullable byte[] paymentAccountKey) {
|
@Nullable byte[] paymentAccountKey) {
|
||||||
|
@ -62,11 +63,11 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
|
||||||
protobuf.DepositRequest.Builder builder = protobuf.DepositRequest.newBuilder()
|
protobuf.DepositRequest.Builder builder = protobuf.DepositRequest.newBuilder()
|
||||||
.setTradeId(tradeId)
|
.setTradeId(tradeId)
|
||||||
.setUid(uid)
|
.setUid(uid)
|
||||||
.setContractSignature(contractSignature)
|
|
||||||
.setDepositTxHex(depositTxHex)
|
.setDepositTxHex(depositTxHex)
|
||||||
.setDepositTxKey(depositTxKey);
|
.setDepositTxKey(depositTxKey);
|
||||||
builder.setCurrentDate(currentDate);
|
builder.setCurrentDate(currentDate);
|
||||||
Optional.ofNullable(paymentAccountKey).ifPresent(e -> builder.setPaymentAccountKey(ByteString.copyFrom(e)));
|
Optional.ofNullable(paymentAccountKey).ifPresent(e -> builder.setPaymentAccountKey(ByteString.copyFrom(e)));
|
||||||
|
Optional.ofNullable(contractSignature).ifPresent(e -> builder.setContractSignature(ByteString.copyFrom(e)));
|
||||||
|
|
||||||
return getNetworkEnvelopeBuilder().setDepositRequest(builder).build();
|
return getNetworkEnvelopeBuilder().setDepositRequest(builder).build();
|
||||||
}
|
}
|
||||||
|
@ -78,7 +79,7 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
|
||||||
proto.getUid(),
|
proto.getUid(),
|
||||||
messageVersion,
|
messageVersion,
|
||||||
proto.getCurrentDate(),
|
proto.getCurrentDate(),
|
||||||
proto.getContractSignature(),
|
ProtoUtil.byteArrayOrNullFromProto(proto.getContractSignature()),
|
||||||
proto.getDepositTxHex(),
|
proto.getDepositTxHex(),
|
||||||
proto.getDepositTxKey(),
|
proto.getDepositTxKey(),
|
||||||
ProtoUtil.byteArrayOrNullFromProto(proto.getPaymentAccountKey()));
|
ProtoUtil.byteArrayOrNullFromProto(proto.getPaymentAccountKey()));
|
||||||
|
@ -88,7 +89,7 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "DepositRequest {" +
|
return "DepositRequest {" +
|
||||||
",\n currentDate=" + currentDate +
|
",\n currentDate=" + currentDate +
|
||||||
",\n contractSignature=" + contractSignature +
|
",\n contractSignature=" + Utilities.bytesAsHexString(contractSignature) +
|
||||||
",\n depositTxHex='" + depositTxHex +
|
",\n depositTxHex='" + depositTxHex +
|
||||||
",\n depositTxKey='" + depositTxKey +
|
",\n depositTxKey='" + depositTxKey +
|
||||||
",\n paymentAccountKey='" + paymentAccountKey +
|
",\n paymentAccountKey='" + paymentAccountKey +
|
||||||
|
|
|
@ -62,7 +62,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String payoutAddress;
|
private final String payoutAddress;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String makerSignature;
|
private final byte[] makerSignature;
|
||||||
|
|
||||||
public InitTradeRequest(String tradeId,
|
public InitTradeRequest(String tradeId,
|
||||||
NodeAddress senderNodeAddress,
|
NodeAddress senderNodeAddress,
|
||||||
|
@ -84,7 +84,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
|
||||||
@Nullable String reserveTxHex,
|
@Nullable String reserveTxHex,
|
||||||
@Nullable String reserveTxKey,
|
@Nullable String reserveTxKey,
|
||||||
@Nullable String payoutAddress,
|
@Nullable String payoutAddress,
|
||||||
@Nullable String makerSignature) {
|
@Nullable byte[] makerSignature) {
|
||||||
super(messageVersion, tradeId, uid);
|
super(messageVersion, tradeId, uid);
|
||||||
this.senderNodeAddress = senderNodeAddress;
|
this.senderNodeAddress = senderNodeAddress;
|
||||||
this.pubKeyRing = pubKeyRing;
|
this.pubKeyRing = pubKeyRing;
|
||||||
|
@ -133,7 +133,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
|
||||||
Optional.ofNullable(reserveTxKey).ifPresent(e -> builder.setReserveTxKey(reserveTxKey));
|
Optional.ofNullable(reserveTxKey).ifPresent(e -> builder.setReserveTxKey(reserveTxKey));
|
||||||
Optional.ofNullable(payoutAddress).ifPresent(e -> builder.setPayoutAddress(payoutAddress));
|
Optional.ofNullable(payoutAddress).ifPresent(e -> builder.setPayoutAddress(payoutAddress));
|
||||||
Optional.ofNullable(accountAgeWitnessSignatureOfOfferId).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfOfferId(ByteString.copyFrom(e)));
|
Optional.ofNullable(accountAgeWitnessSignatureOfOfferId).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfOfferId(ByteString.copyFrom(e)));
|
||||||
Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(makerSignature));
|
Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(ByteString.copyFrom(e)));
|
||||||
builder.setCurrentDate(currentDate);
|
builder.setCurrentDate(currentDate);
|
||||||
|
|
||||||
return getNetworkEnvelopeBuilder().setInitTradeRequest(builder).build();
|
return getNetworkEnvelopeBuilder().setInitTradeRequest(builder).build();
|
||||||
|
@ -162,7 +162,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getReserveTxHex()),
|
ProtoUtil.stringOrNullFromProto(proto.getReserveTxHex()),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getReserveTxKey()),
|
ProtoUtil.stringOrNullFromProto(proto.getReserveTxKey()),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getPayoutAddress()),
|
ProtoUtil.stringOrNullFromProto(proto.getPayoutAddress()),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getMakerSignature()));
|
ProtoUtil.byteArrayOrNullFromProto(proto.getMakerSignature()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -183,7 +183,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
|
||||||
",\n reserveTxHex=" + reserveTxHex +
|
",\n reserveTxHex=" + reserveTxHex +
|
||||||
",\n reserveTxKey=" + reserveTxKey +
|
",\n reserveTxKey=" + reserveTxKey +
|
||||||
",\n payoutAddress=" + payoutAddress +
|
",\n payoutAddress=" + payoutAddress +
|
||||||
",\n makerSignature=" + makerSignature +
|
",\n makerSignature=" + Utilities.byteArrayToInteger(makerSignature) +
|
||||||
"\n} " + super.toString();
|
"\n} " + super.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,10 @@
|
||||||
package haveno.core.trade.messages;
|
package haveno.core.trade.messages;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import haveno.common.crypto.PubKeyRing;
|
|
||||||
import haveno.common.proto.ProtoUtil;
|
import haveno.common.proto.ProtoUtil;
|
||||||
|
import haveno.common.util.Utilities;
|
||||||
import haveno.core.proto.CoreProtoResolver;
|
import haveno.core.proto.CoreProtoResolver;
|
||||||
import haveno.network.p2p.DirectMessage;
|
import haveno.network.p2p.DirectMessage;
|
||||||
import haveno.network.p2p.NodeAddress;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
@ -33,7 +32,7 @@ import lombok.Value;
|
||||||
public final class SignContractResponse extends TradeMessage implements DirectMessage {
|
public final class SignContractResponse extends TradeMessage implements DirectMessage {
|
||||||
private final long currentDate;
|
private final long currentDate;
|
||||||
private final String contractAsJson;
|
private final String contractAsJson;
|
||||||
private final String contractSignature;
|
private final byte[] contractSignature;
|
||||||
private final byte[] encryptedPaymentAccountPayload;
|
private final byte[] encryptedPaymentAccountPayload;
|
||||||
|
|
||||||
public SignContractResponse(String tradeId,
|
public SignContractResponse(String tradeId,
|
||||||
|
@ -41,7 +40,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
|
||||||
String messageVersion,
|
String messageVersion,
|
||||||
long currentDate,
|
long currentDate,
|
||||||
String contractAsJson,
|
String contractAsJson,
|
||||||
String contractSignature,
|
byte[] contractSignature,
|
||||||
@Nullable byte[] encryptedPaymentAccountPayload) {
|
@Nullable byte[] encryptedPaymentAccountPayload) {
|
||||||
super(messageVersion, tradeId, uid);
|
super(messageVersion, tradeId, uid);
|
||||||
this.currentDate = currentDate;
|
this.currentDate = currentDate;
|
||||||
|
@ -62,7 +61,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
|
||||||
.setUid(uid);
|
.setUid(uid);
|
||||||
|
|
||||||
Optional.ofNullable(contractAsJson).ifPresent(e -> builder.setContractAsJson(contractAsJson));
|
Optional.ofNullable(contractAsJson).ifPresent(e -> builder.setContractAsJson(contractAsJson));
|
||||||
Optional.ofNullable(contractSignature).ifPresent(e -> builder.setContractSignature(contractSignature));
|
Optional.ofNullable(contractSignature).ifPresent(e -> builder.setContractSignature(ByteString.copyFrom(e)));
|
||||||
Optional.ofNullable(encryptedPaymentAccountPayload).ifPresent(e -> builder.setEncryptedPaymentAccountPayload(ByteString.copyFrom(e)));
|
Optional.ofNullable(encryptedPaymentAccountPayload).ifPresent(e -> builder.setEncryptedPaymentAccountPayload(ByteString.copyFrom(e)));
|
||||||
|
|
||||||
builder.setCurrentDate(currentDate);
|
builder.setCurrentDate(currentDate);
|
||||||
|
@ -78,7 +77,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
|
||||||
messageVersion,
|
messageVersion,
|
||||||
proto.getCurrentDate(),
|
proto.getCurrentDate(),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getContractAsJson()),
|
ProtoUtil.stringOrNullFromProto(proto.getContractAsJson()),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getContractSignature()),
|
ProtoUtil.byteArrayOrNullFromProto(proto.getContractSignature()),
|
||||||
proto.getEncryptedPaymentAccountPayload().toByteArray());
|
proto.getEncryptedPaymentAccountPayload().toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +86,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
|
||||||
return "SignContractResponse {" +
|
return "SignContractResponse {" +
|
||||||
",\n currentDate=" + currentDate +
|
",\n currentDate=" + currentDate +
|
||||||
",\n contractAsJson='" + contractAsJson +
|
",\n contractAsJson='" + contractAsJson +
|
||||||
",\n contractSignature='" + contractSignature +
|
",\n contractSignature='" + Utilities.bytesAsHexString(contractSignature) +
|
||||||
"\n} " + super.toString();
|
"\n} " + super.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ public class ProcessModel implements Model, PersistablePayload {
|
||||||
transient private TradeMessage tradeMessage;
|
transient private TradeMessage tradeMessage;
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private String makerSignature;
|
private byte[] makerSignature;
|
||||||
@Nullable
|
@Nullable
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
@ -220,7 +220,8 @@ public class ProcessModel implements Model, PersistablePayload {
|
||||||
Optional.ofNullable(takeOfferFeeTxId).ifPresent(builder::setTakeOfferFeeTxId);
|
Optional.ofNullable(takeOfferFeeTxId).ifPresent(builder::setTakeOfferFeeTxId);
|
||||||
Optional.ofNullable(payoutTxSignature).ifPresent(e -> builder.setPayoutTxSignature(ByteString.copyFrom(payoutTxSignature)));
|
Optional.ofNullable(payoutTxSignature).ifPresent(e -> builder.setPayoutTxSignature(ByteString.copyFrom(payoutTxSignature)));
|
||||||
Optional.ofNullable(tempTradePeerNodeAddress).ifPresent(e -> builder.setTempTradePeerNodeAddress(tempTradePeerNodeAddress.toProtoMessage()));
|
Optional.ofNullable(tempTradePeerNodeAddress).ifPresent(e -> builder.setTempTradePeerNodeAddress(tempTradePeerNodeAddress.toProtoMessage()));
|
||||||
Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(makerSignature));
|
Optional.ofNullable(mediatedPayoutTxSignature).ifPresent(e -> builder.setMediatedPayoutTxSignature(ByteString.copyFrom(e)));
|
||||||
|
Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(ByteString.copyFrom(e)));
|
||||||
Optional.ofNullable(multisigAddress).ifPresent(e -> builder.setMultisigAddress(multisigAddress));
|
Optional.ofNullable(multisigAddress).ifPresent(e -> builder.setMultisigAddress(multisigAddress));
|
||||||
Optional.ofNullable(paymentSentMessage).ifPresent(e -> builder.setPaymentSentMessage(paymentSentMessage.toProtoNetworkEnvelope().getPaymentSentMessage()));
|
Optional.ofNullable(paymentSentMessage).ifPresent(e -> builder.setPaymentSentMessage(paymentSentMessage.toProtoNetworkEnvelope().getPaymentSentMessage()));
|
||||||
Optional.ofNullable(paymentReceivedMessage).ifPresent(e -> builder.setPaymentReceivedMessage(paymentReceivedMessage.toProtoNetworkEnvelope().getPaymentReceivedMessage()));
|
Optional.ofNullable(paymentReceivedMessage).ifPresent(e -> builder.setPaymentReceivedMessage(paymentReceivedMessage.toProtoNetworkEnvelope().getPaymentReceivedMessage()));
|
||||||
|
@ -245,7 +246,7 @@ public class ProcessModel implements Model, PersistablePayload {
|
||||||
processModel.setPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getPayoutTxSignature()));
|
processModel.setPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getPayoutTxSignature()));
|
||||||
processModel.setTempTradePeerNodeAddress(proto.hasTempTradePeerNodeAddress() ? NodeAddress.fromProto(proto.getTempTradePeerNodeAddress()) : null);
|
processModel.setTempTradePeerNodeAddress(proto.hasTempTradePeerNodeAddress() ? NodeAddress.fromProto(proto.getTempTradePeerNodeAddress()) : null);
|
||||||
processModel.setMediatedPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getMediatedPayoutTxSignature()));
|
processModel.setMediatedPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getMediatedPayoutTxSignature()));
|
||||||
processModel.setMakerSignature(proto.getMakerSignature());
|
processModel.setMakerSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getMakerSignature()));
|
||||||
processModel.setMultisigAddress(ProtoUtil.stringOrNullFromProto(proto.getMultisigAddress()));
|
processModel.setMultisigAddress(ProtoUtil.stringOrNullFromProto(proto.getMultisigAddress()));
|
||||||
|
|
||||||
String paymentSentMessageStateString = ProtoUtil.stringOrNullFromProto(proto.getPaymentSentMessageState());
|
String paymentSentMessageStateString = ProtoUtil.stringOrNullFromProto(proto.getPaymentSentMessageState());
|
||||||
|
|
|
@ -79,7 +79,7 @@ public final class TradePeer implements PersistablePayload {
|
||||||
@Nullable
|
@Nullable
|
||||||
private String contractAsJson;
|
private String contractAsJson;
|
||||||
@Nullable
|
@Nullable
|
||||||
private String contractSignature;
|
private byte[] contractSignature;
|
||||||
|
|
||||||
// added in v 0.6
|
// added in v 0.6
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -146,7 +146,7 @@ public final class TradePeer implements PersistablePayload {
|
||||||
Optional.ofNullable(paymentAccountPayload).ifPresent(e -> builder.setPaymentAccountPayload((protobuf.PaymentAccountPayload) e.toProtoMessage()));
|
Optional.ofNullable(paymentAccountPayload).ifPresent(e -> builder.setPaymentAccountPayload((protobuf.PaymentAccountPayload) e.toProtoMessage()));
|
||||||
Optional.ofNullable(payoutAddressString).ifPresent(builder::setPayoutAddressString);
|
Optional.ofNullable(payoutAddressString).ifPresent(builder::setPayoutAddressString);
|
||||||
Optional.ofNullable(contractAsJson).ifPresent(builder::setContractAsJson);
|
Optional.ofNullable(contractAsJson).ifPresent(builder::setContractAsJson);
|
||||||
Optional.ofNullable(contractSignature).ifPresent(builder::setContractSignature);
|
Optional.ofNullable(contractSignature).ifPresent(e -> builder.setContractSignature(ByteString.copyFrom(e)));
|
||||||
Optional.ofNullable(pubKeyRing).ifPresent(e -> builder.setPubKeyRing(e.toProtoMessage()));
|
Optional.ofNullable(pubKeyRing).ifPresent(e -> builder.setPubKeyRing(e.toProtoMessage()));
|
||||||
Optional.ofNullable(accountAgeWitnessNonce).ifPresent(e -> builder.setAccountAgeWitnessNonce(ByteString.copyFrom(e)));
|
Optional.ofNullable(accountAgeWitnessNonce).ifPresent(e -> builder.setAccountAgeWitnessNonce(ByteString.copyFrom(e)));
|
||||||
Optional.ofNullable(accountAgeWitnessSignature).ifPresent(e -> builder.setAccountAgeWitnessSignature(ByteString.copyFrom(e)));
|
Optional.ofNullable(accountAgeWitnessSignature).ifPresent(e -> builder.setAccountAgeWitnessSignature(ByteString.copyFrom(e)));
|
||||||
|
@ -185,7 +185,7 @@ public final class TradePeer implements PersistablePayload {
|
||||||
tradePeer.setPaymentAccountPayload(proto.hasPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getPaymentAccountPayload()) : null);
|
tradePeer.setPaymentAccountPayload(proto.hasPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getPaymentAccountPayload()) : null);
|
||||||
tradePeer.setPayoutAddressString(ProtoUtil.stringOrNullFromProto(proto.getPayoutAddressString()));
|
tradePeer.setPayoutAddressString(ProtoUtil.stringOrNullFromProto(proto.getPayoutAddressString()));
|
||||||
tradePeer.setContractAsJson(ProtoUtil.stringOrNullFromProto(proto.getContractAsJson()));
|
tradePeer.setContractAsJson(ProtoUtil.stringOrNullFromProto(proto.getContractAsJson()));
|
||||||
tradePeer.setContractSignature(ProtoUtil.stringOrNullFromProto(proto.getContractSignature()));
|
tradePeer.setContractSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getContractSignature()));
|
||||||
tradePeer.setPubKeyRing(proto.hasPubKeyRing() ? PubKeyRing.fromProto(proto.getPubKeyRing()) : null);
|
tradePeer.setPubKeyRing(proto.hasPubKeyRing() ? PubKeyRing.fromProto(proto.getPubKeyRing()) : null);
|
||||||
tradePeer.setAccountAgeWitnessNonce(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessNonce()));
|
tradePeer.setAccountAgeWitnessNonce(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessNonce()));
|
||||||
tradePeer.setAccountAgeWitnessSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignature()));
|
tradePeer.setAccountAgeWitnessSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignature()));
|
||||||
|
|
|
@ -24,6 +24,7 @@ import haveno.common.crypto.PubKeyRing;
|
||||||
import haveno.common.crypto.Sig;
|
import haveno.common.crypto.Sig;
|
||||||
import haveno.common.taskrunner.TaskRunner;
|
import haveno.common.taskrunner.TaskRunner;
|
||||||
import haveno.core.offer.Offer;
|
import haveno.core.offer.Offer;
|
||||||
|
import haveno.core.trade.HavenoUtils;
|
||||||
import haveno.core.trade.Trade;
|
import haveno.core.trade.Trade;
|
||||||
import haveno.core.trade.messages.DepositRequest;
|
import haveno.core.trade.messages.DepositRequest;
|
||||||
import haveno.core.trade.messages.DepositResponse;
|
import haveno.core.trade.messages.DepositResponse;
|
||||||
|
@ -58,7 +59,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||||
// get contract and signature
|
// get contract and signature
|
||||||
String contractAsJson = trade.getContractAsJson();
|
String contractAsJson = trade.getContractAsJson();
|
||||||
DepositRequest request = (DepositRequest) processModel.getTradeMessage(); // TODO (woodser): verify response
|
DepositRequest request = (DepositRequest) processModel.getTradeMessage(); // TODO (woodser): verify response
|
||||||
String signature = request.getContractSignature();
|
byte[] signature = request.getContractSignature();
|
||||||
|
|
||||||
// get trader info
|
// get trader info
|
||||||
TradePeer trader = trade.getTradePeer(processModel.getTempTradePeerNodeAddress());
|
TradePeer trader = trade.getTradePeer(processModel.getTempTradePeerNodeAddress());
|
||||||
|
@ -66,7 +67,9 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||||
PubKeyRing peerPubKeyRing = trader.getPubKeyRing();
|
PubKeyRing peerPubKeyRing = trader.getPubKeyRing();
|
||||||
|
|
||||||
// verify signature
|
// verify signature
|
||||||
if (!Sig.verify(peerPubKeyRing.getSignaturePubKey(), contractAsJson, signature)) throw new RuntimeException("Peer's contract signature is invalid");
|
if (!HavenoUtils.isSignatureValid(peerPubKeyRing, contractAsJson, signature)) {
|
||||||
|
throw new RuntimeException("Peer's contract signature is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
// set peer's signature
|
// set peer's signature
|
||||||
trader.setContractSignature(signature);
|
trader.setContractSignature(signature);
|
||||||
|
|
|
@ -17,10 +17,8 @@
|
||||||
|
|
||||||
package haveno.core.trade.protocol.tasks;
|
package haveno.core.trade.protocol.tasks;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import haveno.common.Timer;
|
import haveno.common.Timer;
|
||||||
import haveno.common.crypto.PubKeyRing;
|
import haveno.common.crypto.PubKeyRing;
|
||||||
import haveno.common.crypto.Sig;
|
|
||||||
import haveno.common.taskrunner.TaskRunner;
|
import haveno.common.taskrunner.TaskRunner;
|
||||||
import haveno.core.network.MessageState;
|
import haveno.core.network.MessageState;
|
||||||
import haveno.core.trade.HavenoUtils;
|
import haveno.core.trade.HavenoUtils;
|
||||||
|
@ -94,7 +92,7 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask
|
||||||
// sign message
|
// sign message
|
||||||
try {
|
try {
|
||||||
String messageAsJson = JsonUtil.objectToJson(message);
|
String messageAsJson = JsonUtil.objectToJson(message);
|
||||||
byte[] sig = Sig.sign(processModel.getP2PService().getKeyRing().getSignatureKeyPair().getPrivate(), messageAsJson.getBytes(Charsets.UTF_8));
|
byte[] sig = HavenoUtils.sign(processModel.getP2PService().getKeyRing(), messageAsJson);
|
||||||
message.setBuyerSignature(sig);
|
message.setBuyerSignature(sig);
|
||||||
processModel.setPaymentSentMessage(message);
|
processModel.setPaymentSentMessage(message);
|
||||||
trade.requestPersistence();
|
trade.requestPersistence();
|
||||||
|
|
|
@ -22,11 +22,10 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import haveno.common.app.Version;
|
import haveno.common.app.Version;
|
||||||
import haveno.common.crypto.Sig;
|
|
||||||
import haveno.common.taskrunner.TaskRunner;
|
import haveno.common.taskrunner.TaskRunner;
|
||||||
import haveno.core.trade.ArbitratorTrade;
|
import haveno.core.trade.ArbitratorTrade;
|
||||||
|
import haveno.core.trade.HavenoUtils;
|
||||||
import haveno.core.trade.MakerTrade;
|
import haveno.core.trade.MakerTrade;
|
||||||
import haveno.core.trade.Trade;
|
import haveno.core.trade.Trade;
|
||||||
import haveno.core.trade.Trade.State;
|
import haveno.core.trade.Trade.State;
|
||||||
|
@ -90,7 +89,7 @@ public class MaybeSendSignContractRequest extends TradeTask {
|
||||||
// maker signs deposit hash nonce to avoid challenge protocol
|
// maker signs deposit hash nonce to avoid challenge protocol
|
||||||
byte[] sig = null;
|
byte[] sig = null;
|
||||||
if (trade instanceof MakerTrade) {
|
if (trade instanceof MakerTrade) {
|
||||||
sig = Sig.sign(processModel.getP2PService().getKeyRing().getSignatureKeyPair().getPrivate(), depositTx.getHash().getBytes(Charsets.UTF_8));
|
sig = HavenoUtils.sign(processModel.getP2PService().getKeyRing(), depositTx.getHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
// create request for peer and arbitrator to sign contract
|
// create request for peer and arbitrator to sign contract
|
||||||
|
|
|
@ -30,10 +30,10 @@ import haveno.common.crypto.Encryption;
|
||||||
import haveno.common.crypto.Hash;
|
import haveno.common.crypto.Hash;
|
||||||
import haveno.common.crypto.PubKeyRing;
|
import haveno.common.crypto.PubKeyRing;
|
||||||
import haveno.common.crypto.ScryptUtil;
|
import haveno.common.crypto.ScryptUtil;
|
||||||
import haveno.common.crypto.Sig;
|
|
||||||
import haveno.common.taskrunner.TaskRunner;
|
import haveno.common.taskrunner.TaskRunner;
|
||||||
import haveno.core.trade.ArbitratorTrade;
|
import haveno.core.trade.ArbitratorTrade;
|
||||||
import haveno.core.trade.Contract;
|
import haveno.core.trade.Contract;
|
||||||
|
import haveno.core.trade.HavenoUtils;
|
||||||
import haveno.core.trade.Trade;
|
import haveno.core.trade.Trade;
|
||||||
import haveno.core.trade.Trade.State;
|
import haveno.core.trade.Trade.State;
|
||||||
import haveno.core.trade.messages.SignContractRequest;
|
import haveno.core.trade.messages.SignContractRequest;
|
||||||
|
@ -85,7 +85,7 @@ public class ProcessSignContractRequest extends TradeTask {
|
||||||
// create and sign contract
|
// create and sign contract
|
||||||
Contract contract = trade.createContract();
|
Contract contract = trade.createContract();
|
||||||
String contractAsJson = JsonUtil.objectToJson(contract);
|
String contractAsJson = JsonUtil.objectToJson(contract);
|
||||||
String signature = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), contractAsJson);
|
byte[] signature = HavenoUtils.sign(processModel.getKeyRing(), contractAsJson);
|
||||||
|
|
||||||
// save contract and signature
|
// save contract and signature
|
||||||
trade.setContract(contract);
|
trade.setContract(contract);
|
||||||
|
|
|
@ -20,8 +20,8 @@ package haveno.core.trade.protocol.tasks;
|
||||||
|
|
||||||
import haveno.common.app.Version;
|
import haveno.common.app.Version;
|
||||||
import haveno.common.crypto.PubKeyRing;
|
import haveno.common.crypto.PubKeyRing;
|
||||||
import haveno.common.crypto.Sig;
|
|
||||||
import haveno.common.taskrunner.TaskRunner;
|
import haveno.common.taskrunner.TaskRunner;
|
||||||
|
import haveno.core.trade.HavenoUtils;
|
||||||
import haveno.core.trade.Trade;
|
import haveno.core.trade.Trade;
|
||||||
import haveno.core.trade.messages.DepositRequest;
|
import haveno.core.trade.messages.DepositRequest;
|
||||||
import haveno.core.trade.messages.SignContractResponse;
|
import haveno.core.trade.messages.SignContractResponse;
|
||||||
|
@ -63,8 +63,8 @@ public class ProcessSignContractResponse extends TradeTask {
|
||||||
|
|
||||||
// verify signature
|
// verify signature
|
||||||
// TODO (woodser): transfer contract for convenient comparison?
|
// TODO (woodser): transfer contract for convenient comparison?
|
||||||
String signature = response.getContractSignature();
|
byte[] signature = response.getContractSignature();
|
||||||
if (!Sig.verify(peerPubKeyRing.getSignaturePubKey(), contractAsJson, signature)) throw new RuntimeException("Peer's contract signature is invalid");
|
if (!HavenoUtils.isSignatureValid(peerPubKeyRing, contractAsJson, signature)) throw new RuntimeException("Peer's contract signature is invalid");
|
||||||
|
|
||||||
// set peer's signature
|
// set peer's signature
|
||||||
peer.setContractSignature(signature);
|
peer.setContractSignature(signature);
|
||||||
|
|
|
@ -22,9 +22,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import haveno.common.crypto.PubKeyRing;
|
import haveno.common.crypto.PubKeyRing;
|
||||||
import haveno.common.crypto.Sig;
|
|
||||||
import haveno.common.taskrunner.TaskRunner;
|
import haveno.common.taskrunner.TaskRunner;
|
||||||
import haveno.core.account.sign.SignedWitness;
|
import haveno.core.account.sign.SignedWitness;
|
||||||
import haveno.core.account.witness.AccountAgeWitnessService;
|
import haveno.core.account.witness.AccountAgeWitnessService;
|
||||||
|
@ -92,7 +90,7 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag
|
||||||
// sign message
|
// sign message
|
||||||
try {
|
try {
|
||||||
String messageAsJson = JsonUtil.objectToJson(message);
|
String messageAsJson = JsonUtil.objectToJson(message);
|
||||||
byte[] sig = Sig.sign(processModel.getP2PService().getKeyRing().getSignatureKeyPair().getPrivate(), messageAsJson.getBytes(Charsets.UTF_8));
|
byte[] sig = HavenoUtils.sign(processModel.getP2PService().getKeyRing(), messageAsJson);
|
||||||
message.setSellerSignature(sig);
|
message.setSellerSignature(sig);
|
||||||
processModel.setPaymentReceivedMessage(message);
|
processModel.setPaymentReceivedMessage(message);
|
||||||
trade.requestPersistence();
|
trade.requestPersistence();
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package haveno.desktop.main.support.dispute.agent;
|
package haveno.desktop.main.support.dispute.agent;
|
||||||
|
|
||||||
import haveno.common.UserThread;
|
import haveno.common.UserThread;
|
||||||
|
import haveno.common.util.Utilities;
|
||||||
import haveno.core.locale.Res;
|
import haveno.core.locale.Res;
|
||||||
import haveno.core.offer.OpenOfferManager;
|
import haveno.core.offer.OpenOfferManager;
|
||||||
import haveno.core.offer.SignedOffer;
|
import haveno.core.offer.SignedOffer;
|
||||||
|
@ -379,7 +380,7 @@ public class SignedOfferView extends ActivatableView<VBox, Void> {
|
||||||
public void updateItem(final SignedOffer item, boolean empty) {
|
public void updateItem(final SignedOffer item, boolean empty) {
|
||||||
super.updateItem(item, empty);
|
super.updateItem(item, empty);
|
||||||
if (item != null && !empty)
|
if (item != null && !empty)
|
||||||
setText(item.getArbitratorSignature());
|
setText(Utilities.bytesAsHexString(item.getArbitratorSignature()));
|
||||||
else
|
else
|
||||||
setText("");
|
setText("");
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,7 +165,7 @@ message OfferAvailabilityResponse {
|
||||||
AvailabilityResult availability_result = 2;
|
AvailabilityResult availability_result = 2;
|
||||||
repeated int32 supported_capabilities = 3;
|
repeated int32 supported_capabilities = 3;
|
||||||
string uid = 4;
|
string uid = 4;
|
||||||
string maker_signature = 5;
|
bytes maker_signature = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RefreshOfferMessage {
|
message RefreshOfferMessage {
|
||||||
|
@ -233,7 +233,7 @@ message InitTradeRequest {
|
||||||
string reserve_tx_hex = 17;
|
string reserve_tx_hex = 17;
|
||||||
string reserve_tx_key = 18;
|
string reserve_tx_key = 18;
|
||||||
string payout_address = 19;
|
string payout_address = 19;
|
||||||
string maker_signature = 20;
|
bytes maker_signature = 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
message InitMultisigRequest {
|
message InitMultisigRequest {
|
||||||
|
@ -261,7 +261,7 @@ message SignContractResponse {
|
||||||
string uid = 2;
|
string uid = 2;
|
||||||
int64 current_date = 3;
|
int64 current_date = 3;
|
||||||
string contract_as_json = 4;
|
string contract_as_json = 4;
|
||||||
string contract_signature = 5;
|
bytes contract_signature = 5;
|
||||||
bytes encrypted_payment_account_payload = 6;
|
bytes encrypted_payment_account_payload = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ message DepositRequest {
|
||||||
string trade_id = 1;
|
string trade_id = 1;
|
||||||
string uid = 2;
|
string uid = 2;
|
||||||
int64 current_date = 3;
|
int64 current_date = 3;
|
||||||
string contract_signature = 4;
|
bytes contract_signature = 4;
|
||||||
string deposit_tx_hex = 5;
|
string deposit_tx_hex = 5;
|
||||||
string deposit_tx_key = 6;
|
string deposit_tx_key = 6;
|
||||||
bytes payment_account_key = 7;
|
bytes payment_account_key = 7;
|
||||||
|
@ -636,7 +636,7 @@ message OfferPayload {
|
||||||
int32 protocol_version = 34;
|
int32 protocol_version = 34;
|
||||||
|
|
||||||
NodeAddress arbitrator_signer = 1001;
|
NodeAddress arbitrator_signer = 1001;
|
||||||
string arbitrator_signature = 1002;
|
bytes arbitrator_signature = 1002;
|
||||||
repeated string reserve_tx_key_images = 1003;
|
repeated string reserve_tx_key_images = 1003;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,8 +696,8 @@ message Dispute {
|
||||||
string deposit_tx_id = 14;
|
string deposit_tx_id = 14;
|
||||||
string payout_tx_id = 15;
|
string payout_tx_id = 15;
|
||||||
string contract_as_json = 16;
|
string contract_as_json = 16;
|
||||||
string maker_contract_signature = 17;
|
bytes maker_contract_signature = 17;
|
||||||
string taker_contract_signature = 18;
|
bytes taker_contract_signature = 18;
|
||||||
PaymentAccountPayload maker_payment_account_payload = 19;
|
PaymentAccountPayload maker_payment_account_payload = 19;
|
||||||
PaymentAccountPayload taker_payment_account_payload = 20;
|
PaymentAccountPayload taker_payment_account_payload = 20;
|
||||||
PubKeyRing agent_pub_key_ring = 21;
|
PubKeyRing agent_pub_key_ring = 21;
|
||||||
|
@ -1356,7 +1356,7 @@ message SignedOffer {
|
||||||
string reserve_tx_hex = 7;
|
string reserve_tx_hex = 7;
|
||||||
repeated string reserve_tx_key_images = 8;
|
repeated string reserve_tx_key_images = 8;
|
||||||
uint64 reserve_tx_miner_fee = 9;
|
uint64 reserve_tx_miner_fee = 9;
|
||||||
string arbitrator_signature = 10;
|
bytes arbitrator_signature = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
message OpenOffer {
|
message OpenOffer {
|
||||||
|
@ -1531,7 +1531,7 @@ message ProcessModel {
|
||||||
int64 funds_needed_for_trade = 7;
|
int64 funds_needed_for_trade = 7;
|
||||||
string payment_sent_message_state = 8;
|
string payment_sent_message_state = 8;
|
||||||
bool deposits_confirmed_messages_delivered = 9;
|
bool deposits_confirmed_messages_delivered = 9;
|
||||||
string maker_signature = 10;
|
bytes maker_signature = 10;
|
||||||
TradePeer maker = 11;
|
TradePeer maker = 11;
|
||||||
TradePeer taker = 12;
|
TradePeer taker = 12;
|
||||||
TradePeer arbitrator = 13;
|
TradePeer arbitrator = 13;
|
||||||
|
@ -1557,7 +1557,7 @@ message TradePeer {
|
||||||
PaymentAccountPayload payment_account_payload = 9;
|
PaymentAccountPayload payment_account_payload = 9;
|
||||||
string payout_address_string = 10;
|
string payout_address_string = 10;
|
||||||
string contract_as_json = 11;
|
string contract_as_json = 11;
|
||||||
string contract_signature = 12;
|
bytes contract_signature = 12;
|
||||||
bytes account_age_witness_nonce = 18;
|
bytes account_age_witness_nonce = 18;
|
||||||
bytes account_age_witness_signature = 19;
|
bytes account_age_witness_signature = 19;
|
||||||
AccountAgeWitness account_age_witness = 20;
|
AccountAgeWitness account_age_witness = 20;
|
||||||
|
|
Loading…
Reference in a new issue