From a60275a159f670757d78d305fe840b72ffc05419 Mon Sep 17 00:00:00 2001 From: Jonathan Chappelow Date: Thu, 17 Mar 2022 15:26:27 -0500 Subject: [PATCH] client/core: recognize sigs of hashed messages --- client/core/core.go | 22 ++++++++++++++++++---- client/core/types.go | 4 +--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/client/core/core.go b/client/core/core.go index 521f4cb057..f92e045bcb 100644 --- a/client/core/core.go +++ b/client/core/core.go @@ -6,6 +6,7 @@ package core import ( "bytes" "context" + "crypto/sha256" "encoding/binary" "encoding/hex" "errors" @@ -2906,6 +2907,9 @@ func (c *Core) register(dc *dexConnection, assetID uint32) (regRes *msgjson.Regi if !bytes.Equal(dc.acct.dexPubKey.SerializeCompressed(), regRes.DEXPubKey) { return nil, false, false, fmt.Errorf("different pubkeys reported by dex in 'config' and 'register' responses") } + // Insert our pubkey back into the register result since it is excluded + // from the JSON serialization. + regRes.ClientPubKey = acctPubKey // Check the DEX server's signature. msg := regRes.Serialize() err = checkSigS256(msg, regRes.DEXPubKey, regRes.Sig) @@ -6277,17 +6281,27 @@ func checkSigS256(msg, pkBytes, sigBytes []byte) error { if err != nil { return fmt.Errorf("error decoding secp256k1 Signature from bytes: %w", err) } - if !signature.Verify(msg, pubKey) { - return fmt.Errorf("secp256k1 signature verification failed") + hash := sha256.Sum256(msg) + if !signature.Verify(hash[:], pubKey) { + // Might be an older buggy server. (V0PURGE) + if !signature.Verify(msg, pubKey) { + return fmt.Errorf("secp256k1 signature verification failed") + } } return nil } +// signMsg signs the message with provided private key. +func signMsg(privKey *secp256k1.PrivateKey, msg []byte) []byte { + // NOTE: legacy servers will not accept this signature: + // hash := sha256.Sum256(msg) + return ecdsa.Sign(privKey, msg).Serialize() +} + // sign signs the msgjson.Signable with the provided private key. func sign(privKey *secp256k1.PrivateKey, payload msgjson.Signable) { sigMsg := payload.Serialize() - sig := ecdsa.Sign(privKey, sigMsg) // should we be signing the *hash* of the payload? - payload.SetSig(sig.Serialize()) + payload.SetSig(signMsg(privKey, sigMsg)) } // stampAndSign time stamps the msgjson.Stampable, and signs it with the given diff --git a/client/core/types.go b/client/core/types.go index 278a802dc5..1c9ad25682 100644 --- a/client/core/types.go +++ b/client/core/types.go @@ -22,7 +22,6 @@ import ( "decred.org/dcrdex/dex/order" "decred.org/dcrdex/server/account" "github.com/decred/dcrd/dcrec/secp256k1/v4" - "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" "github.com/decred/dcrd/hdkeychain/v3" ) @@ -769,8 +768,7 @@ func (a *dexAccount) sign(msg []byte) ([]byte, error) { if a.privKey == nil { return nil, fmt.Errorf("account locked") } - sig := ecdsa.Sign(a.privKey, msg) - return sig.Serialize(), nil + return signMsg(a.privKey, msg), nil } // checkSig checks the signature against the message and the DEX pubkey.