use byte[] for signatures instead of strings

This commit is contained in:
woodser 2023-03-11 16:09:22 -05:00
parent ead70751dc
commit 4650003838
23 changed files with 265 additions and 255 deletions

View file

@ -20,12 +20,15 @@ package haveno.core.offer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.protobuf.ByteString;
import haveno.common.crypto.Hash;
import haveno.common.crypto.PubKeyRing;
import haveno.common.proto.ProtoUtil;
import haveno.common.util.CollectionUtils;
import haveno.common.util.Hex;
import haveno.common.util.JsonExclude;
import haveno.common.util.Utilities;
import haveno.network.p2p.NodeAddress;
import haveno.network.p2p.storage.payload.ExpirablePayload;
import haveno.network.p2p.storage.payload.ProtectedStoragePayload;
@ -81,7 +84,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
protected NodeAddress arbitratorSigner;
@Setter
@Nullable
protected String arbitratorSignature;
protected byte[] arbitratorSignature;
@Setter
@Nullable
protected List<String> reserveTxKeyImages;
@ -191,7 +194,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
@Nullable Map<String, String> extraDataMap,
int protocolVersion,
@Nullable NodeAddress arbitratorSigner,
@Nullable String arbitratorSignature,
@Nullable byte[] arbitratorSignature,
@Nullable List<String> reserveTxKeyImages) {
this.id = id;
this.date = date;
@ -302,7 +305,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
Optional.ofNullable(acceptedCountryCodes).ifPresent(builder::addAllAcceptedCountryCodes);
Optional.ofNullable(hashOfChallenge).ifPresent(builder::setHashOfChallenge);
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);
return protobuf.StoragePayload.newBuilder().setOfferPayload(builder).build();
@ -352,7 +355,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
extraDataMapMap,
proto.getProtocolVersion(),
proto.hasArbitratorSigner() ? NodeAddress.fromProto(proto.getArbitratorSigner()) : null,
ProtoUtil.stringOrNullFromProto(proto.getArbitratorSignature()),
ProtoUtil.byteArrayOrNullFromProto(proto.getArbitratorSignature()),
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 hash=" + (hash != null ? Hex.encode(hash) : "null") +
",\r\n extraDataMap=" + extraDataMap +
",\r\n arbitratorSigner=" + arbitratorSigner +
",\r\n arbitratorSignature=" + arbitratorSignature +
",\r\n reserveTxKeyImages=" + reserveTxKeyImages +
",\r\n marketPriceMargin=" + marketPriceMarginPct +
",\r\n useMarketBasedPrice=" + useMarketBasedPrice +
@ -398,7 +399,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
",\r\n isPrivateOffer=" + isPrivateOffer +
",\r\n hashOfChallenge='" + hashOfChallenge + '\'' +
",\n arbitratorSigner=" + arbitratorSigner +
",\n arbitratorSignature=" + arbitratorSignature +
",\n arbitratorSignature=" + Utilities.bytesAsHexString(arbitratorSignature) +
"\r\n} ";
}

View file

@ -25,7 +25,6 @@ import haveno.common.app.Capability;
import haveno.common.app.Version;
import haveno.common.crypto.KeyRing;
import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig;
import haveno.common.handlers.ErrorMessageHandler;
import haveno.common.handlers.ResultHandler;
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
String offerPayloadAsJson = JsonUtil.objectToJson(request.getOfferPayload());
String signature = Sig.sign(keyRing.getSignatureKeyPair().getPrivate(), offerPayloadAsJson);
byte[] signature = HavenoUtils.sign(keyRing, offerPayloadAsJson);
OfferPayload signedOfferPayload = request.getOfferPayload();
signedOfferPayload.setArbitratorSignature(signature);
@ -1119,7 +1118,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
try {
Optional<OpenOffer> openOfferOptional = getOpenOfferById(request.offerId);
AvailabilityResult availabilityResult;
String makerSignature = null;
byte[] makerSignature = null;
if (openOfferOptional.isPresent()) {
OpenOffer openOffer = openOfferOptional.get();
if (!apiUserDeniedByOffer(request)) {
@ -1130,7 +1129,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
// maker signs taker's request
String tradeRequestAsJson = JsonUtil.objectToJson(request.getTradeRequest());
makerSignature = Sig.sign(keyRing.getSignatureKeyPair().getPrivate(), tradeRequestAsJson);
makerSignature = HavenoUtils.sign(keyRing, tradeRequestAsJson);
try {
// Check also tradePrice to avoid failures after taker fee is paid caused by a too big difference

View file

@ -17,10 +17,14 @@
package haveno.core.offer;
import haveno.common.proto.ProtoUtil;
import haveno.common.proto.persistable.PersistablePayload;
import haveno.core.util.JsonUtil;
import java.util.List;
import com.google.protobuf.ByteString;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@ -48,7 +52,7 @@ public final class SignedOffer implements PersistablePayload {
@Getter
private final long reserveTxMinerFee;
@Getter
private final String arbitratorSignature;
private final byte[] arbitratorSignature;
public SignedOffer(long timeStamp,
int traderId,
@ -59,7 +63,7 @@ public final class SignedOffer implements PersistablePayload {
String reserveTxHex,
List<String> reserveTxKeyImages,
long reserveTxMinerFee,
String arbitratorSignature) {
byte[] arbitratorSignature) {
this.timeStamp = timeStamp;
this.traderId = traderId;
this.offerId = offerId;
@ -88,7 +92,7 @@ public final class SignedOffer implements PersistablePayload {
.setReserveTxHex(reserveTxHex)
.addAllReserveTxKeyImages(reserveTxKeyImages)
.setReserveTxMinerFee(reserveTxMinerFee)
.setArbitratorSignature(arbitratorSignature);
.setArbitratorSignature(ByteString.copyFrom(arbitratorSignature));
return builder.build();
}
@ -102,7 +106,7 @@ public final class SignedOffer implements PersistablePayload {
proto.getReserveTxHex(),
proto.getReserveTxKeyImagesList(),
proto.getReserveTxMinerFee(),
proto.getArbitratorSignature());
ProtoUtil.byteArrayOrNullFromProto(proto.getArbitratorSignature()));
}

View file

@ -61,7 +61,7 @@ public class OfferAvailabilityModel implements Model {
@Nullable
@Setter
@Getter
private String makerSignature;
private byte[] makerSignature;
// Added in v1.5.5
@Getter

View file

@ -17,9 +17,7 @@
package haveno.core.offer.availability.tasks;
import com.google.common.base.Charsets;
import haveno.common.app.Version;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.Task;
import haveno.common.taskrunner.TaskRunner;
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
// 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
Price price = offer.getPrice();

View file

@ -31,6 +31,8 @@ import lombok.Value;
import javax.annotation.Nullable;
import com.google.protobuf.ByteString;
// We add here the SupportedCapabilitiesMessage interface as that message always predates a direct connection
// to the trading peer
@EqualsAndHashCode(callSuper = true)
@ -41,11 +43,11 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
private final Capabilities supportedCapabilities;
@Nullable
private final String makerSignature;
private byte[] makerSignature;
public OfferAvailabilityResponse(String offerId,
AvailabilityResult availabilityResult,
String makerSignature) {
@Nullable byte[] makerSignature) {
this(offerId,
availabilityResult,
Capabilities.app,
@ -64,7 +66,7 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
@Nullable Capabilities supportedCapabilities,
String messageVersion,
@Nullable String uid,
String makerSignature) {
byte[] makerSignature) {
super(messageVersion, offerId, uid);
this.availabilityResult = availabilityResult;
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(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()
.setOfferAvailabilityResponse(builder)
@ -92,6 +94,6 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
Capabilities.fromIntList(proto.getSupportedCapabilitiesList()),
messageVersion,
proto.getUid().isEmpty() ? null : proto.getUid(),
proto.getMakerSignature().isEmpty() ? null : proto.getMakerSignature());
ProtoUtil.byteArrayOrNullFromProto(proto.getMakerSignature()));
}
}

View file

@ -104,9 +104,9 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
private final String payoutTxId;
private String contractAsJson;
@Nullable
private final String makerContractSignature;
private final byte[] makerContractSignature;
@Nullable
private final String takerContractSignature;
private final byte[] takerContractSignature;
private final PubKeyRing agentPubKeyRing; // dispute agent
private final boolean isSupportTicket;
private final ObservableList<ChatMessage> chatMessages = FXCollections.observableArrayList();
@ -179,8 +179,8 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
@Nullable String depositTxId,
@Nullable String payoutTxId,
String contractAsJson,
@Nullable String makerContractSignature,
@Nullable String takerContractSignature,
@Nullable byte[] makerContractSignature,
@Nullable byte[] takerContractSignature,
@Nullable PaymentAccountPayload makerPaymentAccountPayload,
@Nullable PaymentAccountPayload takerPaymentAccountPayload,
PubKeyRing agentPubKeyRing,
@ -251,8 +251,8 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
Optional.ofNullable(depositTxId).ifPresent(builder::setDepositTxId);
Optional.ofNullable(payoutTxId).ifPresent(builder::setPayoutTxId);
Optional.ofNullable(disputePayoutTxId).ifPresent(builder::setDisputePayoutTxId);
Optional.ofNullable(makerContractSignature).ifPresent(builder::setMakerContractSignature);
Optional.ofNullable(takerContractSignature).ifPresent(builder::setTakerContractSignature);
Optional.ofNullable(makerContractSignature).ifPresent(e -> builder.setMakerContractSignature(ByteString.copyFrom(e)));
Optional.ofNullable(takerContractSignature).ifPresent(e -> builder.setTakerContractSignature(ByteString.copyFrom(e)));
Optional.ofNullable(makerPaymentAccountPayload).ifPresent(e -> builder.setMakerPaymentAccountPayload((protobuf.PaymentAccountPayload) makerPaymentAccountPayload.toProtoMessage()));
Optional.ofNullable(takerPaymentAccountPayload).ifPresent(e -> builder.setTakerPaymentAccountPayload((protobuf.PaymentAccountPayload) takerPaymentAccountPayload.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.getPayoutTxId()),
proto.getContractAsJson(),
ProtoUtil.stringOrNullFromProto(proto.getMakerContractSignature()),
ProtoUtil.stringOrNullFromProto(proto.getTakerContractSignature()),
ProtoUtil.byteArrayOrNullFromProto(proto.getMakerContractSignature()),
ProtoUtil.byteArrayOrNullFromProto(proto.getTakerContractSignature()),
proto.hasMakerPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getMakerPaymentAccountPayload()) : null,
proto.hasTakerPaymentAccountPayload() ? coreProtoResolver.fromProto(proto.getTakerPaymentAccountPayload()) : null,
PubKeyRing.fromProto(proto.getAgentPubKeyRing()),
@ -524,8 +524,8 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
",\n depositTxId='" + depositTxId + '\'' +
",\n payoutTxId='" + payoutTxId + '\'' +
",\n contractAsJson='" + contractAsJson + '\'' +
",\n makerContractSignature='" + makerContractSignature + '\'' +
",\n takerContractSignature='" + takerContractSignature + '\'' +
",\n makerContractSignature='" + Utilities.bytesAsHexString(makerContractSignature) + '\'' +
",\n takerContractSignature='" + Utilities.bytesAsHexString(takerContractSignature) + '\'' +
",\n agentPubKeyRing=" + agentPubKeyRing +
",\n isSupportTicket=" + isSupportTicket +
",\n chatMessages=" + chatMessages +

View file

@ -17,16 +17,14 @@
package haveno.core.support.dispute;
import haveno.common.crypto.CryptoException;
import haveno.common.crypto.Hash;
import haveno.common.crypto.Sig;
import haveno.common.util.Utilities;
import haveno.core.locale.Res;
import haveno.core.support.dispute.agent.DisputeAgent;
import haveno.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
import haveno.core.trade.HavenoUtils;
import haveno.network.p2p.NodeAddress;
import java.security.KeyPair;
import java.security.PublicKey;
import lombok.extern.slf4j.Slf4j;
@ -46,10 +44,10 @@ public class DisputeSummaryVerification {
KeyPair signatureKeyPair = disputeManager.getSignatureKeyPair();
String sigAsHex;
try {
byte[] signature = Sig.sign(signatureKeyPair.getPrivate(), hash);
byte[] signature = HavenoUtils.sign(signatureKeyPair.getPrivate(), hash);
sigAsHex = Utilities.encodeToHex(signature);
disputeResult.setArbitratorSignature(signature);
} catch (CryptoException e) {
} catch (Exception e) {
sigAsHex = "Signing failed";
}
@ -69,19 +67,13 @@ public class DisputeSummaryVerification {
NodeAddress nodeAddress = new NodeAddress(fullAddress);
DisputeAgent disputeAgent = arbitratorMediator.getDisputeAgentByNodeAddress(nodeAddress).orElse(null);
checkNotNull(disputeAgent, "Dispute agent is null");
PublicKey pubKey = disputeAgent.getPubKeyRing().getSignaturePubKey();
String sigString = parts[1].split(SEPARATOR2)[0];
byte[] sig = Utilities.decodeFromHex(sigString);
byte[] hash = Hash.getSha256Hash(textToSign);
try {
boolean result = Sig.verify(pubKey, hash, sig);
if (result) {
return;
} else {
throw new IllegalArgumentException(Res.get("support.sigCheck.popup.failed"));
}
} catch (CryptoException e) {
HavenoUtils.verifySignature(disputeAgent.getPubKeyRing(), hash, sig);
} catch (Exception e) {
throw new IllegalArgumentException(Res.get("support.sigCheck.popup.failed"));
}
} catch (Throwable e) {

View file

@ -18,12 +18,11 @@
package haveno.core.support.dispute;
import haveno.common.config.Config;
import haveno.common.crypto.CryptoException;
import haveno.common.crypto.Hash;
import haveno.common.crypto.Sig;
import haveno.common.util.Tuple3;
import haveno.core.support.SupportType;
import haveno.core.trade.Contract;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.Trade;
import haveno.core.util.JsonUtil;
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()))),
"Invalid contractHash");
try {
// Only the dispute opener has set the signature
String makerContractSignature = dispute.getMakerContractSignature();
if (makerContractSignature != null) {
Sig.verify(contract.getMakerPubKeyRing().getSignaturePubKey(),
dispute.getContractAsJson(),
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());
}
byte[] makerContractSignature = dispute.getMakerContractSignature();
if (makerContractSignature != null) HavenoUtils.verifySignature(contract.getMakerPubKeyRing(), dispute.getContractAsJson(), makerContractSignature);
byte[] takerContractSignature = dispute.getTakerContractSignature();
if (takerContractSignature != null) HavenoUtils.verifySignature(contract.getTakerPubKeyRing(), dispute.getContractAsJson(), takerContractSignature);
} catch (Throwable t) {
throw new ValidationException(dispute, t.getMessage());
}

View file

@ -23,6 +23,7 @@ import com.google.common.base.CaseFormat;
import com.google.common.base.Charsets;
import haveno.common.config.Config;
import haveno.common.crypto.Hash;
import haveno.common.crypto.KeyRing;
import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig;
import haveno.common.util.Utilities;
@ -39,7 +40,7 @@ import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.net.URI;
import java.security.PrivateKey;
import java.math.BigDecimal;
import java.math.BigInteger;
@ -236,6 +237,170 @@ public class HavenoUtils {
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 ------------------------------
@ -282,144 +447,6 @@ public class HavenoUtils {
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) {
try {
latch.await();

View file

@ -19,6 +19,7 @@ package haveno.core.trade.messages;
import com.google.protobuf.ByteString;
import haveno.common.proto.ProtoUtil;
import haveno.common.util.Utilities;
import haveno.core.proto.CoreProtoResolver;
import haveno.network.p2p.DirectMessage;
import java.util.Optional;
@ -30,7 +31,7 @@ import lombok.Value;
@Value
public final class DepositRequest extends TradeMessage implements DirectMessage {
private final long currentDate;
private final String contractSignature;
private final byte[] contractSignature;
private final String depositTxHex;
private final String depositTxKey;
@Nullable
@ -40,7 +41,7 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
String uid,
String messageVersion,
long currentDate,
String contractSignature,
byte[] contractSignature,
String depositTxHex,
String depositTxKey,
@Nullable byte[] paymentAccountKey) {
@ -62,11 +63,11 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
protobuf.DepositRequest.Builder builder = protobuf.DepositRequest.newBuilder()
.setTradeId(tradeId)
.setUid(uid)
.setContractSignature(contractSignature)
.setDepositTxHex(depositTxHex)
.setDepositTxKey(depositTxKey);
builder.setCurrentDate(currentDate);
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();
}
@ -78,7 +79,7 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
proto.getUid(),
messageVersion,
proto.getCurrentDate(),
proto.getContractSignature(),
ProtoUtil.byteArrayOrNullFromProto(proto.getContractSignature()),
proto.getDepositTxHex(),
proto.getDepositTxKey(),
ProtoUtil.byteArrayOrNullFromProto(proto.getPaymentAccountKey()));
@ -88,7 +89,7 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
public String toString() {
return "DepositRequest {" +
",\n currentDate=" + currentDate +
",\n contractSignature=" + contractSignature +
",\n contractSignature=" + Utilities.bytesAsHexString(contractSignature) +
",\n depositTxHex='" + depositTxHex +
",\n depositTxKey='" + depositTxKey +
",\n paymentAccountKey='" + paymentAccountKey +

View file

@ -62,7 +62,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
@Nullable
private final String payoutAddress;
@Nullable
private final String makerSignature;
private final byte[] makerSignature;
public InitTradeRequest(String tradeId,
NodeAddress senderNodeAddress,
@ -84,7 +84,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
@Nullable String reserveTxHex,
@Nullable String reserveTxKey,
@Nullable String payoutAddress,
@Nullable String makerSignature) {
@Nullable byte[] makerSignature) {
super(messageVersion, tradeId, uid);
this.senderNodeAddress = senderNodeAddress;
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(payoutAddress).ifPresent(e -> builder.setPayoutAddress(payoutAddress));
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);
return getNetworkEnvelopeBuilder().setInitTradeRequest(builder).build();
@ -162,7 +162,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
ProtoUtil.stringOrNullFromProto(proto.getReserveTxHex()),
ProtoUtil.stringOrNullFromProto(proto.getReserveTxKey()),
ProtoUtil.stringOrNullFromProto(proto.getPayoutAddress()),
ProtoUtil.stringOrNullFromProto(proto.getMakerSignature()));
ProtoUtil.byteArrayOrNullFromProto(proto.getMakerSignature()));
}
@Override
@ -183,7 +183,7 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
",\n reserveTxHex=" + reserveTxHex +
",\n reserveTxKey=" + reserveTxKey +
",\n payoutAddress=" + payoutAddress +
",\n makerSignature=" + makerSignature +
",\n makerSignature=" + Utilities.byteArrayToInteger(makerSignature) +
"\n} " + super.toString();
}
}

View file

@ -18,11 +18,10 @@
package haveno.core.trade.messages;
import com.google.protobuf.ByteString;
import haveno.common.crypto.PubKeyRing;
import haveno.common.proto.ProtoUtil;
import haveno.common.util.Utilities;
import haveno.core.proto.CoreProtoResolver;
import haveno.network.p2p.DirectMessage;
import haveno.network.p2p.NodeAddress;
import java.util.Optional;
import javax.annotation.Nullable;
import lombok.EqualsAndHashCode;
@ -33,7 +32,7 @@ import lombok.Value;
public final class SignContractResponse extends TradeMessage implements DirectMessage {
private final long currentDate;
private final String contractAsJson;
private final String contractSignature;
private final byte[] contractSignature;
private final byte[] encryptedPaymentAccountPayload;
public SignContractResponse(String tradeId,
@ -41,7 +40,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
String messageVersion,
long currentDate,
String contractAsJson,
String contractSignature,
byte[] contractSignature,
@Nullable byte[] encryptedPaymentAccountPayload) {
super(messageVersion, tradeId, uid);
this.currentDate = currentDate;
@ -62,7 +61,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
.setUid(uid);
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)));
builder.setCurrentDate(currentDate);
@ -78,7 +77,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
messageVersion,
proto.getCurrentDate(),
ProtoUtil.stringOrNullFromProto(proto.getContractAsJson()),
ProtoUtil.stringOrNullFromProto(proto.getContractSignature()),
ProtoUtil.byteArrayOrNullFromProto(proto.getContractSignature()),
proto.getEncryptedPaymentAccountPayload().toByteArray());
}
@ -87,7 +86,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
return "SignContractResponse {" +
",\n currentDate=" + currentDate +
",\n contractAsJson='" + contractAsJson +
",\n contractSignature='" + contractSignature +
",\n contractSignature='" + Utilities.bytesAsHexString(contractSignature) +
"\n} " + super.toString();
}
}

View file

@ -137,7 +137,7 @@ public class ProcessModel implements Model, PersistablePayload {
transient private TradeMessage tradeMessage;
@Getter
@Setter
private String makerSignature;
private byte[] makerSignature;
@Nullable
@Getter
@Setter
@ -220,7 +220,8 @@ public class ProcessModel implements Model, PersistablePayload {
Optional.ofNullable(takeOfferFeeTxId).ifPresent(builder::setTakeOfferFeeTxId);
Optional.ofNullable(payoutTxSignature).ifPresent(e -> builder.setPayoutTxSignature(ByteString.copyFrom(payoutTxSignature)));
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(paymentSentMessage).ifPresent(e -> builder.setPaymentSentMessage(paymentSentMessage.toProtoNetworkEnvelope().getPaymentSentMessage()));
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.setTempTradePeerNodeAddress(proto.hasTempTradePeerNodeAddress() ? NodeAddress.fromProto(proto.getTempTradePeerNodeAddress()) : null);
processModel.setMediatedPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getMediatedPayoutTxSignature()));
processModel.setMakerSignature(proto.getMakerSignature());
processModel.setMakerSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getMakerSignature()));
processModel.setMultisigAddress(ProtoUtil.stringOrNullFromProto(proto.getMultisigAddress()));
String paymentSentMessageStateString = ProtoUtil.stringOrNullFromProto(proto.getPaymentSentMessageState());

View file

@ -79,7 +79,7 @@ public final class TradePeer implements PersistablePayload {
@Nullable
private String contractAsJson;
@Nullable
private String contractSignature;
private byte[] contractSignature;
// added in v 0.6
@Nullable
@ -146,7 +146,7 @@ public final class TradePeer implements PersistablePayload {
Optional.ofNullable(paymentAccountPayload).ifPresent(e -> builder.setPaymentAccountPayload((protobuf.PaymentAccountPayload) e.toProtoMessage()));
Optional.ofNullable(payoutAddressString).ifPresent(builder::setPayoutAddressString);
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(accountAgeWitnessNonce).ifPresent(e -> builder.setAccountAgeWitnessNonce(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.setPayoutAddressString(ProtoUtil.stringOrNullFromProto(proto.getPayoutAddressString()));
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.setAccountAgeWitnessNonce(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessNonce()));
tradePeer.setAccountAgeWitnessSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignature()));

View file

@ -24,6 +24,7 @@ import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner;
import haveno.core.offer.Offer;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.Trade;
import haveno.core.trade.messages.DepositRequest;
import haveno.core.trade.messages.DepositResponse;
@ -58,7 +59,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
// get contract and signature
String contractAsJson = trade.getContractAsJson();
DepositRequest request = (DepositRequest) processModel.getTradeMessage(); // TODO (woodser): verify response
String signature = request.getContractSignature();
byte[] signature = request.getContractSignature();
// get trader info
TradePeer trader = trade.getTradePeer(processModel.getTempTradePeerNodeAddress());
@ -66,7 +67,9 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
PubKeyRing peerPubKeyRing = trader.getPubKeyRing();
// 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
trader.setContractSignature(signature);

View file

@ -17,10 +17,8 @@
package haveno.core.trade.protocol.tasks;
import com.google.common.base.Charsets;
import haveno.common.Timer;
import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner;
import haveno.core.network.MessageState;
import haveno.core.trade.HavenoUtils;
@ -94,7 +92,7 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask
// sign message
try {
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);
processModel.setPaymentSentMessage(message);
trade.requestPersistence();

View file

@ -22,11 +22,10 @@ import java.util.Date;
import java.util.List;
import java.util.UUID;
import com.google.common.base.Charsets;
import haveno.common.app.Version;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner;
import haveno.core.trade.ArbitratorTrade;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.MakerTrade;
import haveno.core.trade.Trade;
import haveno.core.trade.Trade.State;
@ -90,7 +89,7 @@ public class MaybeSendSignContractRequest extends TradeTask {
// maker signs deposit hash nonce to avoid challenge protocol
byte[] sig = null;
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

View file

@ -30,10 +30,10 @@ import haveno.common.crypto.Encryption;
import haveno.common.crypto.Hash;
import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.ScryptUtil;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner;
import haveno.core.trade.ArbitratorTrade;
import haveno.core.trade.Contract;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.Trade;
import haveno.core.trade.Trade.State;
import haveno.core.trade.messages.SignContractRequest;
@ -85,7 +85,7 @@ public class ProcessSignContractRequest extends TradeTask {
// create and sign contract
Contract contract = trade.createContract();
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
trade.setContract(contract);

View file

@ -20,8 +20,8 @@ package haveno.core.trade.protocol.tasks;
import haveno.common.app.Version;
import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.Trade;
import haveno.core.trade.messages.DepositRequest;
import haveno.core.trade.messages.SignContractResponse;
@ -63,8 +63,8 @@ public class ProcessSignContractResponse extends TradeTask {
// verify signature
// TODO (woodser): transfer contract for convenient comparison?
String signature = response.getContractSignature();
if (!Sig.verify(peerPubKeyRing.getSignaturePubKey(), contractAsJson, signature)) throw new RuntimeException("Peer's contract signature is invalid");
byte[] signature = response.getContractSignature();
if (!HavenoUtils.isSignatureValid(peerPubKeyRing, contractAsJson, signature)) throw new RuntimeException("Peer's contract signature is invalid");
// set peer's signature
peer.setContractSignature(signature);

View file

@ -22,9 +22,7 @@ import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Charsets;
import haveno.common.crypto.PubKeyRing;
import haveno.common.crypto.Sig;
import haveno.common.taskrunner.TaskRunner;
import haveno.core.account.sign.SignedWitness;
import haveno.core.account.witness.AccountAgeWitnessService;
@ -92,7 +90,7 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag
// sign message
try {
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);
processModel.setPaymentReceivedMessage(message);
trade.requestPersistence();

View file

@ -18,6 +18,7 @@
package haveno.desktop.main.support.dispute.agent;
import haveno.common.UserThread;
import haveno.common.util.Utilities;
import haveno.core.locale.Res;
import haveno.core.offer.OpenOfferManager;
import haveno.core.offer.SignedOffer;
@ -379,7 +380,7 @@ public class SignedOfferView extends ActivatableView<VBox, Void> {
public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(item.getArbitratorSignature());
setText(Utilities.bytesAsHexString(item.getArbitratorSignature()));
else
setText("");
}

View file

@ -165,7 +165,7 @@ message OfferAvailabilityResponse {
AvailabilityResult availability_result = 2;
repeated int32 supported_capabilities = 3;
string uid = 4;
string maker_signature = 5;
bytes maker_signature = 5;
}
message RefreshOfferMessage {
@ -233,7 +233,7 @@ message InitTradeRequest {
string reserve_tx_hex = 17;
string reserve_tx_key = 18;
string payout_address = 19;
string maker_signature = 20;
bytes maker_signature = 20;
}
message InitMultisigRequest {
@ -261,7 +261,7 @@ message SignContractResponse {
string uid = 2;
int64 current_date = 3;
string contract_as_json = 4;
string contract_signature = 5;
bytes contract_signature = 5;
bytes encrypted_payment_account_payload = 6;
}
@ -269,7 +269,7 @@ message DepositRequest {
string trade_id = 1;
string uid = 2;
int64 current_date = 3;
string contract_signature = 4;
bytes contract_signature = 4;
string deposit_tx_hex = 5;
string deposit_tx_key = 6;
bytes payment_account_key = 7;
@ -636,7 +636,7 @@ message OfferPayload {
int32 protocol_version = 34;
NodeAddress arbitrator_signer = 1001;
string arbitrator_signature = 1002;
bytes arbitrator_signature = 1002;
repeated string reserve_tx_key_images = 1003;
}
@ -696,8 +696,8 @@ message Dispute {
string deposit_tx_id = 14;
string payout_tx_id = 15;
string contract_as_json = 16;
string maker_contract_signature = 17;
string taker_contract_signature = 18;
bytes maker_contract_signature = 17;
bytes taker_contract_signature = 18;
PaymentAccountPayload maker_payment_account_payload = 19;
PaymentAccountPayload taker_payment_account_payload = 20;
PubKeyRing agent_pub_key_ring = 21;
@ -1356,7 +1356,7 @@ message SignedOffer {
string reserve_tx_hex = 7;
repeated string reserve_tx_key_images = 8;
uint64 reserve_tx_miner_fee = 9;
string arbitrator_signature = 10;
bytes arbitrator_signature = 10;
}
message OpenOffer {
@ -1531,7 +1531,7 @@ message ProcessModel {
int64 funds_needed_for_trade = 7;
string payment_sent_message_state = 8;
bool deposits_confirmed_messages_delivered = 9;
string maker_signature = 10;
bytes maker_signature = 10;
TradePeer maker = 11;
TradePeer taker = 12;
TradePeer arbitrator = 13;
@ -1557,7 +1557,7 @@ message TradePeer {
PaymentAccountPayload payment_account_payload = 9;
string payout_address_string = 10;
string contract_as_json = 11;
string contract_signature = 12;
bytes contract_signature = 12;
bytes account_age_witness_nonce = 18;
bytes account_age_witness_signature = 19;
AccountAgeWitness account_age_witness = 20;