From 4f6edce6dc12f68991bb29b8b4ef68a75b84788d Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Fri, 16 Oct 2015 13:39:38 -0400 Subject: [PATCH] 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. --- rpcserver.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index dc4b5beeb9..c03abf612d 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2732,9 +2732,12 @@ func SignMessage(w *wallet.Wallet, chainSvr *chain.Client, icmd interface{}) (in 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, - wire.DoubleSha256([]byte(fullmsg)), ainfo.Compressed()) + messageHash, ainfo.Compressed()) if err != nil { 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. // 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, - wire.DoubleSha256([]byte("Bitcoin Signed Message:\n"+ - cmd.Message))) + expectedMessageHash) if err != nil { return nil, err }