ethereum / go-ethereum

Go implementation of the Ethereum protocol
https://geth.ethereum.org
GNU Lesser General Public License v3.0
47.58k stars 20.14k forks source link

The github.com/ethereum/go-ethereum/crypto VerifySignature seems to have bugs: in some cases the VerifySignature returns false while crypto/ecdsa Verify returns true #26869

Closed bebest2010 closed 1 year ago

bebest2010 commented 1 year ago

System information

Geth version: github.com/ethereum/go-ethereum v1.11.4 OS & Version: OSX Commit hash : (if develop)

Expected behaviour

The github.com/ethereum/go-ethereum/crypto VerifySignature returns true

Actual behaviour

The github.com/ethereum/go-ethereum/crypto VerifySignature returns false

Steps to reproduce the behaviour

Here is the test code.

package main

import ( "encoding/hex" "fmt" "math/big"

"crypto/ecdsa"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/ethereum/go-ethereum/crypto"

)

func signExample1() { x, := big.NewInt(0).SetString("76785203906991777797684397410501169849327846585229208311984763079669484269631", 10) y, := big.NewInt(0).SetString("16812059161579487500779982331821013164130672304045077872759268734159679782128", 10) pubkey := &ecdsa.PublicKey{ Curve: btcec.S256(), X: x, Y: y, }

r, _ := big.NewInt(0).SetString("88218413336037610958554673653599049158519054029442919292537418735704670262545", 10)
s, _ := big.NewInt(0).SetString("74914193155219528067532743379505651551089265350258831425975188832127433393044", 10)

n := btcec.S256().Params().N
fmt.Printf("n %v, r %v, s %v\n", n, r, s)
r = big.NewInt(0).Mod(r, n)
s = big.NewInt(0).Mod(s, n)
fmt.Printf("n %v, r %v, s %v\n", n, r, s)
testmsg, _ := hex.DecodeString("97c045f3c1c523a26e8242d56fa265badaf550f1aae3dc165772ef6cbd4ea211")
isCorrectSig := ecdsa.Verify(pubkey, testmsg, r, s)
fmt.Println("00 check valid  ", isCorrectSig)

testpubkey, _ := hex.DecodeString("02a9c2e2a222d2063142c619461410a7c0462524769110ee8b2e37cdae0faeb03f")
// 04a9c2e2a222d2063142c619461410a7c0462524769110ee8b2e37cdae0faeb03f
//   252b49cc7a7fecbfd9f30ce1aa8465a33428f0fac82019aabe5ce7a92e35fcf0
//   252b49cc7a7fecbfd9f30ce1aa8465a33428f0fac82019aabe5ce7a92e35fcf0

pubkey1, err := crypto.DecompressPubkey(testpubkey)
if err != nil {
    fmt.Println("DecompressPubkey err ", err)
    return
}

isCorrectSig = ecdsa.Verify(pubkey1, testmsg, r, s)
fmt.Println("01 check valid  ", isCorrectSig)

rBytes := r.Bytes()
for len(rBytes) < 32 {
    rBytes = append([]byte{0}, rBytes...)
}
sBytes := s.Bytes()
for len(sBytes) < 32 {
    sBytes = append([]byte{0}, sBytes...)
}
var signature []byte
signature = append(signature, rBytes...)
signature = append(signature, sBytes...)
if len(testmsg) != 32 || len(signature) != 64 || len(testpubkey) == 0 {
    fmt.Println("invalid signatyre")
    return
}
checkValid := crypto.VerifySignature(testpubkey, testmsg, signature)
fmt.Println("02 check valid  ", checkValid)

signature = append(signature, byte(0))
pubkeyStr, err := crypto.SigToPub(testmsg, signature)
fmt.Printf("testsig pubkeyStr %v ,err %v\n", pubkeyStr, err)

}

go.mod go 1.19

require github.com/ethereum/go-ethereum v1.11.4

require ( github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect golang.org/x/crypto v0.1.0 // indirect golang.org/x/sys v0.5.0 // indirect )

Backtrace

[backtrace]

When submitting logs: please submit them as text and not screenshots.

bebest2010 commented 1 year ago

find the problem: s < N/2