Skip to content

Commit

Permalink
feat: support bitcoin func signMessage
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhangguiguang committed Apr 8, 2024
1 parent ceb6e1e commit 08783e5
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
50 changes: 50 additions & 0 deletions core/btc/account.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package btc

import (
"bytes"
"encoding/base64"
"fmt"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/centrifuge/go-substrate-rpc-client/v4/types"
"github.com/coming-chat/wallet-SDK/core/base"
"github.com/tyler-smith/go-bip39"
Expand Down Expand Up @@ -251,6 +256,51 @@ func (a *Account) SignHex(messageHex string, password string) (*base.OptionalStr
return nil, base.ErrUnsupportedFunction
}

// SignMessage
// https://developer.bitcoin.org/reference/rpc/signmessage.html
// @param msg The message to create a signature of.
// @return The signature of the message encoded in base64.
func (a *Account) SignMessage(msg string) (*base.OptionalString, error) {
msgHash := messageHash(msg)

signbytes, err := ecdsa.SignCompact(a.privateKey, msgHash, true)
if err != nil {
return nil, err
}
signature := base64.StdEncoding.EncodeToString(signbytes)
return base.NewOptionalString(signature), nil
}

func VerifySignature(pubkey, message, signature string) bool {
signBytes, err := base64.StdEncoding.DecodeString(signature)
if err != nil {
return false
}
pubBytes, err := types.HexDecodeString(pubkey)
if err != nil {
return false
}
pub, err := btcec.ParsePubKey(pubBytes)
if err != nil {
return false
}

msgHash := messageHash(message)
recoverPub, ok, err := ecdsa.RecoverCompact(signBytes, msgHash)
if err != nil || ok == false {
return false
}

return pub.IsEqual(recoverPub)
}

func messageHash(msg string) []byte {
var buf bytes.Buffer
_ = wire.WriteVarString(&buf, 0, "Bitcoin Signed Message:\n")
_ = wire.WriteVarString(&buf, 0, msg)
return chainhash.DoubleHashB(buf.Bytes())
}

// MARK - Implement the protocol AddressUtil

// @param publicKey can start with 0x or not.
Expand Down
17 changes: 17 additions & 0 deletions core/btc/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,20 @@ func TestIsValidPrivateKey(t *testing.T) {
valid := IsValidPrivateKey("cTkZaPpb1pDdor36V5VY4uu5LE6tgzrjRADvrEXimEqWqvwRbfXY")
t.Log(valid)
}

func TestAccount_SignMessage(t *testing.T) {
acc, err := NewAccountWithMnemonic(testcase.M1, ChainMainnet)
require.Nil(t, err)
acc.AddressType = AddressTypeTaproot
t.Log(acc.Address())

// sign message
message := "hello world~"
signature, err := acc.SignMessage(message)
require.Nil(t, err)
t.Log("sign message result: ", signature.Value)

// check signature
valid := VerifySignature(acc.PublicKeyHex(), message, signature.Value)
t.Log("signature is valid: ", valid)
}

0 comments on commit 08783e5

Please sign in to comment.