Skip to content

Instantly share code, notes, and snippets.

@dcb9
Last active April 19, 2024 06:00
Show Gist options
  • Star 81 You must be signed in to star a gist
  • Fork 16 You must be signed in to fork a gist
  • Save dcb9/385631846097e1f59e3cba3b1d42f3ed to your computer and use it in GitHub Desktop.
Save dcb9/385631846097e1f59e3cba3b1d42f3ed to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
)
func main() {
fmt.Println(verifySig(
"0x0EaE3eF6CC7176553E6B45d94e9eFDE2Da7B82a5",
"0x34850b7e36e635783df0563c7202c3ac776df59db5015d2b6f0add33955bb5c43ce35efb5ce695a243bc4c5dc4298db40cd765f3ea5612d2d57da1e4933b2f201b",
[]byte("Example `personal_sign` message"),
))
}
func verifySig(from, sigHex string, msg []byte) bool {
sig := hexutil.MustDecode(sigHex)
msg = accounts.TextHash(msg)
if sig[crypto.RecoveryIDOffset] == 27 || sig[crypto.RecoveryIDOffset] == 28 {
sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1
}
recovered, err := crypto.SigToPub(msg, sig)
if err != nil {
return false
}
recoveredAddr := crypto.PubkeyToAddress(*recovered)
return from == recoveredAddr.Hex()
}
@kabaluyot
Copy link

works like a charm

@delaneyj
Copy link

This is godsend!

@0xRampey
Copy link

0xRampey commented Aug 2, 2021

Saved me from more head-breaking. Thank you!

@phuwn
Copy link

phuwn commented Nov 4, 2021

Thank you. geth should use this as an example

@benhenryhunter
Copy link

4 years later this is saving lives.

@jackcpku
Copy link

Worked. Thanks man!

@rht
Copy link

rht commented Feb 22, 2022

Hello internet. Make sure to read the latest version of func (s *PrivateAccountAPI) EcRecover at https://github.com/ethereum/go-ethereum/blob/master/internal/ethapi/api.go.
Notable changes are:

  • The 64 is replaced with crypto.RecoveryIDOffset
  • signHash is replaced with accounts.TextHash

Maybe @dcb9 should update this gist.

@9cat
Copy link

9cat commented Mar 17, 2022

it works, really thanks

@krasi-georgiev
Copy link

krasi-georgiev commented Mar 22, 2022

simplified version

package main

import (
	"fmt"

	"github.com/ethereum/go-ethereum/accounts"
	"github.com/ethereum/go-ethereum/common/hexutil"
	"github.com/ethereum/go-ethereum/crypto"
)

func main() {
	fmt.Println(verifySig(
		"0x0EaE3eF6CC7176553E6B45d94e9eFDE2Da7B82a5",
		"0x34850b7e36e635783df0563c7202c3ac776df59db5015d2b6f0add33955bb5c43ce35efb5ce695a243bc4c5dc4298db40cd765f3ea5612d2d57da1e4933b2f201b",
		[]byte("Example `personal_sign` message"),
	))
}

func verifySig(from, sigHex string, msg []byte) bool {
	sig := hexutil.MustDecode(sigHex)

	msg = accounts.TextHash(msg)
	sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1

	recovered, err := crypto.SigToPub(msg, sig)
	if err != nil {
		return false
	}

	recoveredAddr := crypto.PubkeyToAddress(*recovered)

	return from == recoveredAddr.Hex()
}

@dcb9
Copy link
Author

dcb9 commented Mar 23, 2022

@krasi-georgiev Perfect I copied yours as the latest version
@rht Thanks you so much

@RyoJerryYu
Copy link

It works! Thanks!

@xx444812313
Copy link

Good! helped me a lot!

@chbill8
Copy link

chbill8 commented Aug 24, 2022

Do you have any examples on generating the signature?

@letroglodyte
Copy link

Helped a lot cheers !

@bertho-zero
Copy link

Works fine but I need to replace

	sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1

with

	if sig[crypto.RecoveryIDOffset] == 27 || sig[crypto.RecoveryIDOffset] == 28 {
		sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1
	}

@darshantejani007
Copy link

Amazing! Worked on the first go!

@quiet-node
Copy link

quiet-node commented Nov 14, 2022

OMG You're the absolute life saver! Thanks a lot! Spent up all night long but couldn't find the right answer until seeing this post!

@psmithson
Copy link

In our case, the last line had a bug, in which it needs the address to be lower cased, otherwise the comparison fails. Fix this bug lowering the case of the right parameter, like this:

return from == strings.ToLower(recoveredAddress.Hex())

@memochou1993
Copy link

@NFEL
Copy link

NFEL commented May 12, 2023

@psmithson
in that case you should use something like

return strings.ToLower(from) == strings.ToLower(recoveredAddress.Hex())

@al-maisan
Copy link

@psmithson in that case you should use something like

return strings.ToLower(from) == strings.ToLower(recoveredAddress.Hex())

or even better

return strings.EqualFold(from, recoveredAddr.Hex())

@Spillage
Copy link

Spillage commented Nov 6, 2023

Very helpful!

@al-maisan
Copy link

@valterlobo
Copy link

valterlobo commented Apr 3, 2024

Sign in with Ethereum - frontend
https://docs.metamask.io/wallet/how-to/sign-data/siwe/

Signature checker in backend with go-ethereum with this code.

@dcb9
Copy link
Author

dcb9 commented Apr 4, 2024

@valterlobo Very useful, thanks for sharing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment