Разные результаты подписания от go-ethereum и ethereumjs.utils

Я получаю разные результаты, подписывая одну и ту же строку одним и тем же закрытым ключом в go-ethereum и ethereumjs.utils. Клавиша, используемая в ts, имеет "0x" впереди, потому что для этой функции требуется шестигранный ключ, чтобы иметь этот индикатор.

библиотека crytpo взята с github.com/go-ethereum/crypto, а не из стандартной библиотеки 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.hashPersonalMessage https://github.com/ethereumjs/ethereumjs-util/blob/9396416913125711e526a05591e3ce8471c3a528/index.js#L369-L372

go-ethereum / crypto.Sign https://github.com/ethereum/go-ethereum/blob/master/crypto/crypto.go#L55

1 ответ

Решение

smarx сказал в комментариях smarx, функция hashPersonalMessage в ethereumjs добавляет префикс к подписанным данным.

таким образом, хэш-функция выше должна быть изменена на

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

добавить префикс. Мне потребовалось некоторое время, чтобы понять, не добавлять ли два 0 в префиксе функции js и добавить префикс в байты, а не добавлять его непосредственно в строку.

выходы теперь одинаковы

 //golang 
0x8d2e693aea627c05ce49d4b11108f493e8176b1262a39233947ce6979764042e55314992ecdac94c445a24d18eea476c80161dea61112b5df2c8f29e61e5e7061c
 //ts 
0x8d2e693aea627c05ce49d4b11108f493e8176b1262a39233947ce6979764042e55314992ecdac94c445a24d18eea476c80161dea61112b5df2c8f29e61e5e7061c
Другие вопросы по тегам