来自go-ethereum和ethereumjs.utils的不同签名结果



我在go-ethereum和ethereumjs.utils中使用相同的私钥对同一字符串进行签名得到了不同的结果。ts 中使用的键前面有"0x",因为该函数需要十六进制键才能具有该指示器。

Crytpo 库来自 github.com/go-ethereum/crypto,而不是标准库加密

package main
import (
    "bytes"
    "crypto/ecdsa"
    "fmt"
    "log"
    "github.com/ethereum/go-ethereum/common/hexutil"
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/crypto"
)
func hash(data []byte) common.Hash {
    return crypto.Keccak256Hash(data)
}
func signMsg(msg, privKeyHex string) ([]byte, ecdsa.PublicKey) {
    privKeyECDSA, err := crypto.HexToECDSA(privKeyHex)
    if err != nil {
        log.Fatal(err)
    }
    msgHash := hash([]byte(msg))
    signature, err := crypto.Sign(msgHash.Bytes(), privKeyECDSA)
    if err != nil {
        log.Fatal(err)
    }
    return signature, privKeyECDSA.PublicKey
}
func verifyMsg(msg string, sig []byte, publicKey ecdsa.PublicKey) bool {
    msgHash := hash([]byte(msg))
    publicKeyBytes := crypto.FromECDSAPub(&publicKey)
    sigPubKey, err := crypto.Ecrecover(msgHash.Bytes(), sig)
    if err != nil {
        log.Fatal(err)
    }
    matches := bytes.Equal(sigPubKey, publicKeyBytes)
    return matches
}
var fakeP = "3a1076bf45ab87712ad64ccb3b10217737f7faacbf2872e88fdd9a537d8fe266"
func main() {
    sig, pubKey := signMsg("Hiya!", fakeP)
    fmt.Println(verifyMsg("Hiya!", sig, pubKey))
    fmt.Println("signature", hexutil.Encode(sig))
}

输出为

hexed sig message 0xea0b35bf34b27ce98736cd68ce6203743ac84c31bac0ac228e9c8d3dd8381c845aa3c2a32a7cc591e28fca1f9e9e51d7da9a6820d39f48bf3df439714934f81c00

和 TS/JS

function Sign(message , hexKey) {
    // hash the message
    let hash = utils.hashPersonalMessage(Buffer.from(message));
    console.log("hashed message:", hash)
    // signing the message
    let signature = utils.ecsign(hash, utils.toBuffer(hexKey));
    console.log("signature", signature)
    // Hexing the signature
    let hexedSig = utils.toRpcSig(signature.v, signature.r, signature.s);
    console.log(hexedSig)
}

输出为

hashed message: <Buffer 9f 7a b3 b9 75 da 1f 2c 64 67 2a 05 47 26 ec d4 01 51 48 13 5c 5d 60 77 e8 19 61 ed 2f 1e 0d e6>
signature { r:
   <Buffer 8d 2e 69 3a ea 62 7c 05 ce 49 d4 b1 11 08 f4 93 e8 17 6b 12 62 a3 92 33 94 7c e6 97 97 64 04 2e>,
  s:
   <Buffer 55 31 49 92 ec da c9 4c 44 5a 24 d1 8e ea 47 6c 80 16 1d ea 61 11 2b 5d f2 c8 f2 9e 61 e5 e7 06>,
  v: 28 }
0x8d2e693aea627c05ce49d4b11108f493e8176b1262a39233947ce6979764042e55314992ecdac94c445a24d18eea476c80161dea61112b5df2c8f29e61e5e7061c

我认为这可能与散列消息有关,所以我看了两个单独的散列函数,但无法弄清楚。

ethereumjs/utils.hashPersonalMessagehttps://github.com/ethereumjs/ethereumjs-util/blob/9396416913125711e526a05591e3ce8471c3a528/index.js#L369-L372

去以太坊/加密。标志https://github.com/ethereum/go-ethereum/blob/master/crypto/crypto.go#L55

正如smarx在评论中所说,以太坊中的hashPersonalMessage函数为签名数据添加了前缀。

所以上面的哈希函数需要更改为

func prefixHash(data []byte) common.Hash {
    msg := fmt.Sprintf("x19Ethereum Signed Message:n%d%s", len(data), data)
    return crypto.Keccak256Hash([]byte(msg))
}

以添加前缀。我花了一段时间才弄清楚不要添加在 js 函数的前缀中找到的两个 0,并将前缀添加到字节中,而不是直接将其添加到字符串中。

输出现在相同

 //golang 
0x8d2e693aea627c05ce49d4b11108f493e8176b1262a39233947ce6979764042e55314992ecdac94c445a24d18eea476c80161dea61112b5df2c8f29e61e5e7061c
 //ts 
0x8d2e693aea627c05ce49d4b11108f493e8176b1262a39233947ce6979764042e55314992ecdac94c445a24d18eea476c80161dea61112b5df2c8f29e61e5e7061c

最新更新