Stellen Sie den öffentlichen Schlüssel aus der Transaktionssignatur wieder her

Ich habe diese Transaktion:

{
  "blockHash": "0x163ad564b32bf17db9262391c2c9a5f191e4fd0b098ae5ce9d2e3e7dcde4bd70",
  "blockNumber": "0x2",
  "from": "0x55d40a83b8445c004df5964ce4a0e261b599c01a",
  "gas": "0x76c0",
  "gasPrice": "0x9184e72a000",
  "hash": "0x5e97c5377da7864e5b82784c9e5335a2e075adfec3b075f5f2e5705733aacf8b",
  "input": "0x",
  "nonce": "0x8",
  "to": "0x589724c5abf2bce219726477cf0a60fa09321380",
  "transactionIndex": "0x0",
  "value": "0x1",
  "v": "0x1c",
  "r": "0xfe084488847df1cf427f72784c4b1ba86526ed5f8ef0feb6bc51caf450d66e8b",
  "s": "0x6226e5f4dd0d948b7014199faf018c27862c56faad0b49197057816dee9a7fa8"
}

Also habe ich aus den Daten der obigen Transaktion zwei Dateien erstellt: msg (Transaktions-Hash) & sig (r + s + v-27).

[root .eth]# hexdump -C msg
00000000  5e 97 c5 37 7d a7 86 4e  5b 82 78 4c 9e 53 35 a2  |^..7}..N[.xL.S5.|
00000010  e0 75 ad fe c3 b0 75 f5  f2 e5 70 57 33 aa cf 8b  |.u....u...pW3...|
00000020
[root .eth]# hexdump -C sig
00000000  fe 08 44 88 84 7d f1 cf  42 7f 72 78 4c 4b 1b a8  |..D..}..B.rxLK..|
00000010  65 26 ed 5f 8e f0 fe b6  bc 51 ca f4 50 d6 6e 8b  |e&._.....Q..P.n.|
00000020  62 26 e5 f4 dd 0d 94 8b  70 14 19 9f af 01 8c 27  |b&......p......'|
00000030  86 2c 56 fa ad 0b 49 19  70 57 81 6d ee 9a 7f a8  |.,V...I.pW.m....|
00000040  01                                                |.|
00000041

Dann habe ich ein Programm in go geschrieben, um den öffentlichen Schlüssel wiederherzustellen:

[root@v48807 .eth]# cat recover-pk.go
package main

import (
  "io/ioutil"
  "fmt"
  "os"

        secp256k1 "github.com/ethereum/go-ethereum/crypto/secp256k1"
)

func check(e error) {
    if e != nil {
        panic(e)
    }
}

func main() {
        msg, err := ioutil.ReadFile("msg")
  check(err)

        sig, err := ioutil.ReadFile("sig")
  check(err)

  pkbin, err := secp256k1.RecoverPubkey(msg, sig)
  check(err)

        f, err := os.Create("pkbin")
  check(err)
  defer f.Close()
        n, err := f.Write(pkbin)
  check(err)
  fmt.Printf("wrote %d bytes\n", n)
}

Hier ist ein Dump des resultierenden öffentlichen Schlüssels:

[root .eth]# hexdump -C pkbin
00000000  04 bc 63 e4 84 c2 ed 68  56 8d 20 74 b0 ff 2e a1  |..c....hV. t....|
00000010  b0 51 02 3d d9 c8 f2 4c  c0 c2 5d 93 f4 14 2b bc  |.Q.=...L..]...+.|
00000020  40 56 d9 4b 32 dc 1e 65  74 6b c7 0a 3e fe 2a ba  |@V.K2..etk..>.*.|
00000030  db d2 e3 74 d8 ad 9c fd  d1 0c f1 1b 12 74 ef df  |...t.........t..|
00000040  53                                                |S|
00000041

Das Problem ist, dass sich dieser öffentliche Schlüssel von dem unterscheidet, den ich ursprünglich generiert habe:

[root .eth]# cat addr1/address
55d40a83b8445c004df5964ce4a0e261b599c01a
[root .eth]# hexdump -C addr1/pubo-bin
00000000  04 0c 2d 16 2c 3d 76 cd  47 de e5 84 c9 9e 08 80  |..-.,=v.G.......|
00000010  b4 f2 2a 38 3b 7e bc bb  f6 cc bb 25 4a fe 01 b6  |..*8;~.....%J...|
00000020  dd 37 de ee ee b1 06 9a  af 39 f0 e8 c4 6a f7 ca  |.7.......9...j..|
00000030  53 01 5f 8f 73 7e 57 cc  2b 7a 61 32 35 54 e7 9c  |S._.s~W.+za25T..|
00000040  26                                                |&|
00000041

Wie Sie sehen können, stimmt die Ethereum-Adresse (Dateiadresse) mit der Adresse überein, die zum Senden des Ethers in der Transaktion am Anfang der Post verwendet wurde.

Ich habe das Schlüsselpaar wie folgt generiert:

[root .eth]# cat genkey.sh
#!/usr/bin/env bash
openssl ecparam -name secp256k1 -genkey -noout | openssl ec -text -noout > keypair
cat keypair | grep pub -A 5 | tail -n +2 | tr -d '\n[:space:]:' | sed 's/^04//' > pub
cat keypair | grep priv -A 3 | tail -n +2 | tr -d '\n[:space:]:' | sed 's/^00//' > priv
cat pub | keccak-256sum -x -l | tr -d ' -' | tail -c 41 > address
cat priv | xxd -r -p > priv-bin
cat pub | xxd -r -p > pub-bin
#geth account import priv

Was könnte also das Problem sein? Warum stimmt der wiederhergestellte öffentliche Schlüssel nicht mit dem ursprünglichen öffentlichen Schlüssel überein?

Sehen Sie sich github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md an . Der Signatur-Hash unterscheidet sich von dem Transaktions-Hash, den Sie haben.
@smart, super! startGas ist dasselbe wie Gas?
Ja. Auch manchmal genannt gasLimit.

Antworten (1)

Sie verwenden beim Wiederherstellen des öffentlichen Schlüssels einen falschen Hash. Sie haben die gesamte Transaktion einschließlich der Signatur gehasht, aber das macht nicht viel Sinn: Hash, der signiert werden sollte, kann nicht von der Signatur abhängen. Sie müssen nur die Teile der Transaktion hashen, die vor der Unterzeichnung bekannt waren: „to“, „value“, „data“, „nonce“, „gas“ und „gas price“ (EIP-155 fügte „ chain ID " zur Liste). So sehen diese sechs Werte in der RLP-Codierung aus:

// ["0x08","0x09184e72a000","0x76c0","0x589724c5abf2bce219726477cf0a60fa09321380","0x01","0x"]
0xe2088609184e72a0008276c094589724c5abf2bce219726477cf0a60fa093213800180

Hier ist der Hash des Obigen, der gesengt werden soll:

0x7eb00f90181255e010b43c944da6f9c7575e595467a710c0925263921ead9107

Hier ist Ihre Rohtransaktion mit Signatur:

0xf865088609184e72a0008276c094589724c5abf2bce219726477cf0a60fa0932
  138001801ca0fe084488847df1cf427f72784c4b1ba86526ed5f8ef0feb6bc51
  caf450d66e8ba06226e5f4dd0d948b7014199faf018c27862c56faad0b491970
  57816dee9a7fa8

Hier nur die Signatur:

0xfe084488847df1cf427f72784c4b1ba86526ed5f8ef0feb6bc51caf450d66e8b
  6226e5f4dd0d948b7014199faf018c27862c56faad0b49197057816dee9a7fa8
  1c

Und hier ist der öffentliche Schlüssel, der aus der Signatur und dem richtigen Hash stammt:

0x040c2d162c3d76cd47dee584c99e0880b4f22a383b7ebcbbf6ccbb254afe01b6
  dd37deeeeeb1069aaf39f0e8c46af7ca53015f8f737e57cc2b7a61323554e79c
  26

Übrigens habe ich ABDK Toolkit verwendet , um all diese Berechnungen durchzuführen.