Как правильно восстановить открытый ключ ECDSA из хешированного сообщения и подписи в R || S || V формат? - PullRequest
0 голосов
/ 30 июня 2018

Я использовал следующий код для генерации пары ключей ecdsa (privKey и pubKey), кодировал их и затем декодировал обратно: https://stackoverflow.com/a/41315404/1901320.

Далее я создаю хэш для сообщения (txnData.Payload() имеет тип []byte), используя crypto.Keccak256(), и подписываю его, используя crypto.Sign() из криптографического пакета Ethereum (github.com/ethereum/go-ethereum/crypto). Это создает 65-битную подпись ECDSA в R || S || V формат.

    hashData := crypto.Keccak256(txnData.Payload)
    sig, _ := crypto.Sign(hashData, privKey)

    pkey, _ := crypto.Ecrecover(hashData, sig) // This and pubKey do not match

Когда я пытаюсь вернуть открытый ключ из hashData и подпись ECDSA, используя crypto.Ecrecover(), и сравнить его с открытым ключом pubKey, соответствующим privKey, используемому для создания подписи, я нахожу, что открытые ключи не совпадают. Это не похоже на то, что должно произойти. Есть идеи, где я ошибаюсь?

1 Ответ

0 голосов
/ 02 июля 2018

Вот полный рабочий пример того, как генерировать и проверять подписи с помощью go-ethereum.

package main

import (
    "bytes"
    "crypto/ecdsa"
    "fmt"
    "log"

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

func main() {
    privateKey, err := crypto.HexToECDSA("fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19")
    if err != nil {
        log.Fatal(err)
    }

    publicKey := privateKey.PublicKey

    publicKeyBytes := crypto.FromECDSAPub(&publicKey)

    data := []byte("hello")
    hash := crypto.Keccak256Hash(data)
    fmt.Println(hash.Hex()) // 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8

    signature, err := crypto.Sign(hash.Bytes(), privateKey)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(hexutil.Encode(signature)) // 0x789a80053e4927d0a898db8e065e948f5cf086e32f9ccaa54c1908e22ac430c62621578113ddbb62d509bf6049b8fb544ab06d36f916685a2eb8e57ffadde02301

    sigPublicKey, err := crypto.Ecrecover(hash.Bytes(), signature)
    if err != nil {
        log.Fatal(err)
    }

    matches := bytes.Equal(sigPublicKey, publicKeyBytes)
    fmt.Println(matches) // true

    sigPublicKeyECDSA, err := crypto.SigToPub(hash.Bytes(), signature)
    if err != nil {
        log.Fatal(err)
    }

    sigPublicKeyBytes := crypto.FromECDSAPub(sigPublicKeyECDSA)
    matches = bytes.Equal(sigPublicKeyBytes, publicKeyBytes)
    fmt.Println(matches) // true

    signatureNoRecoverID := signature[:len(signature)-1] // remove recovery id
    verified := crypto.VerifySignature(publicKeyBytes, hash.Bytes(), signatureNoRecoverID)
    fmt.Println(verified) // true
}

Ознакомьтесь с путеводителем по Ethereum Development с Go , где приведены дополнительные примеры использования go-ethereum.

...