Fix signmessage RPC to match Core.

AFAICT this function has never worked correctly due to the hash being
signed not matching the hash created by Core.  Core wallet writes
serialized strings to a double-sha256 hashing stream, while we were
using string concatination.  This produced different messages since
the message before hashing did not include compact integers (called
varints in btcsuite code) preceding each string with the string
length.

Tested by creating signed messages from btcwallet and verifying them
with Bitcoin-Qt, as well as creating signatures from Bitcoin-Qt and
verifying them with btcwallet.

Fixes #323.
This commit is contained in:
Josh Rickmar 2015-10-16 13:39:38 -04:00
parent cef002139f
commit 4f6edce6dc

View file

@ -2732,9 +2732,12 @@ func SignMessage(w *wallet.Wallet, chainSvr *chain.Client, icmd interface{}) (in
return nil, err return nil, err
} }
fullmsg := "Bitcoin Signed Message:\n" + cmd.Message var buf bytes.Buffer
wire.WriteVarString(&buf, 0, "Bitcoin Signed Message:\n")
wire.WriteVarString(&buf, 0, cmd.Message)
messageHash := wire.DoubleSha256(buf.Bytes())
sigbytes, err := btcec.SignCompact(btcec.S256(), privKey, sigbytes, err := btcec.SignCompact(btcec.S256(), privKey,
wire.DoubleSha256([]byte(fullmsg)), ainfo.Compressed()) messageHash, ainfo.Compressed())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -3138,9 +3141,12 @@ func VerifyMessage(w *wallet.Wallet, chainSvr *chain.Client, icmd interface{}) (
// Validate the signature - this just shows that it was valid at all. // Validate the signature - this just shows that it was valid at all.
// we will compare it with the key next. // we will compare it with the key next.
var buf bytes.Buffer
wire.WriteVarString(&buf, 0, "Bitcoin Signed Message:\n")
wire.WriteVarString(&buf, 0, cmd.Message)
expectedMessageHash := wire.DoubleSha256(buf.Bytes())
pk, wasCompressed, err := btcec.RecoverCompact(btcec.S256(), sig, pk, wasCompressed, err := btcec.RecoverCompact(btcec.S256(), sig,
wire.DoubleSha256([]byte("Bitcoin Signed Message:\n"+ expectedMessageHash)
cmd.Message)))
if err != nil { if err != nil {
return nil, err return nil, err
} }