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

Я использовал следующий код для создания пары ключей 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, который использовался для создания подписи, я обнаружил, что открытые ключи не совпадают. Это не похоже на то, что должно произойти. Есть идеи, где я ошибаюсь?


person Samikshan Bairagya    schedule 30.06.2018    source источник
comment
Это может быть хорошим вопросом, если предоставляется больше кода и ввода / вывода (желательно в шестнадцатеричном формате).   -  person Maarten Bodewes    schedule 01.07.2018


Ответы (1)


Вот полный рабочий пример того, как сгенерировать и проверить подписи с помощью 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
}

Дополнительные примеры использования go-ethereum.

person Miguel Mota    schedule 02.07.2018