Signature

简介:

https://yuhuajing.github.io/solidity-book/milestone_6/signature-ECDSA-validation.html

sign_sha256

预编译合约地址 0x2 https://yuhuajing.github.io/solidity-book/milestone_5/contracts-precompile.html实现 sha256 哈希校验

package sign

import (
	"crypto/sha256"
	"fmt"
	"github.com/ethereum/go-ethereum/common/hexutil"
	"math/big"
)

func Sha256EncodeNumber(number int64) {
	s := hexutil.EncodeBig(big.NewInt(number))
	prefix := ""
	num := 64 - len(s[2:])
	for index := 0; index < num; index++ {
		prefix += "0"
	}
	s = s[:2] + prefix + s[2:]
	byteD, err := hexutil.Decode(s)
	if err != nil {
		fmt.Println(err)
	}
	h := sha256.New()
	h.Write(byteD)
	bs := h.Sum(nil)
	fmt.Println(hexutil.Encode(bs))
}

sign_ecdsa

  1. 编码 hash 待签名数据
	prefix := []byte(fmt.Sprintf("\x19Ethereum Signed Message:\n%d", len(message)))
	messageBytes := milestone4.UnsafeBytes(message)

	// Hash the prefix and message using Keccak-256
	hash := crypto.Keccak256Hash(prefix, messageBytes)

编码多种类型的代签数据,基于开源库solsha3 "github.com/miguelmota/go-solidity-sha3"

	mes := solsha3.SoliditySHA3(
		[]string{"uint32[]", "uint32", "uint64", "uint64", "uint64", "address", "address", "address"},
		[]interface{}{
			nftId,
			chainId,
			timestamp,
			uuid,
			signId,
			nft,
			sender,
			contract,
		},
	)
	hash := solsha3.SoliditySHA3WithPrefix(mes)
  1. 私钥签名数据hash
	// Sign the hashed message
	sig, err := crypto.Sign(hash.Bytes(), ecdsaPrivateKey)
	if err != nil {
		log.Fatalln(err)
	}

	// Adjust signature ID to Ethereum's format
	sig[64] += 27
  1. 校验数据,根据待签数据和签名逆向反推签名地址
  • 签名不匹配的话,会返回错误的签名地址
func VerifySig(signature, address, message string) bool {
	// Decode the signature into bytes
	sig, err := hexutil.Decode(signature)
	if err != nil {
		log.Fatalln(err)
	}

	// Adjust signature to standard format (remove Ethereum's recovery ID)
	sig[64] = sig[64] - 27

	// Construct the message prefix
	prefix := []byte(fmt.Sprintf("\x19Ethereum Signed Message:\n%d", len(message)))
	data := []byte(message)

	// Hash the prefix and data using Keccak-256
	hash := crypto.Keccak256Hash(prefix, data)

	// Recover the public key bytes from the signature
	sigPublicKeyBytes, err := crypto.Ecrecover(hash.Bytes(), sig)
	if err != nil {
		log.Fatalln(err)
	}
	ecdsaPublicKey, err := crypto.UnmarshalPubkey(sigPublicKeyBytes)
	if err != nil {
		log.Fatalln(err)
	}

	// Derive the address from the recovered public key
	rAddress := crypto.PubkeyToAddress(*ecdsaPublicKey)

	// Check if the recovered address matches the provided address
	isSigner := strings.EqualFold(rAddress.String(), address)

	return isSigner
}