mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
signer, accounts: remove duplicated code, pass hash preimages to signing
This commit is contained in:
parent
a51bea0cb9
commit
38ff1c570c
3 changed files with 28 additions and 44 deletions
|
|
@ -24,8 +24,8 @@ import (
|
||||||
ethereum "github.com/ethereum/go-ethereum"
|
ethereum "github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"golang.org/x/crypto/sha3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Account represents an Ethereum account located at a specific location defined
|
// Account represents an Ethereum account located at a specific location defined
|
||||||
|
|
@ -175,9 +175,20 @@ type Backend interface {
|
||||||
//
|
//
|
||||||
// This gives context to the signed message and prevents signing of transactions.
|
// This gives context to the signed message and prevents signing of transactions.
|
||||||
func TextHash(data []byte) []byte {
|
func TextHash(data []byte) []byte {
|
||||||
hash := sha3.NewLegacyKeccak256()
|
hash, _ := TextAndHash(data)
|
||||||
fmt.Fprintf(hash, "\x19Ethereum Signed Message:\n%d%s", len(data), data)
|
return hash
|
||||||
return hash.Sum(nil)
|
}
|
||||||
|
|
||||||
|
// TextAndHash is a helper function that calculates a hash for the given message that can be
|
||||||
|
// safely used to calculate a signature from.
|
||||||
|
//
|
||||||
|
// The hash is calulcated as
|
||||||
|
// keccak256("\x19Ethereum Signed Message:\n"${message length}${message}).
|
||||||
|
//
|
||||||
|
// This gives context to the signed message and prevents signing of transactions.
|
||||||
|
func TextAndHash(data []byte) ([]byte, string) {
|
||||||
|
msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), string(data))
|
||||||
|
return crypto.Keccak256([]byte(msg)), msg
|
||||||
}
|
}
|
||||||
|
|
||||||
// WalletEventType represents the different event types that can be fired by
|
// WalletEventType represents the different event types that can be fired by
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ type (
|
||||||
SignDataRequest struct {
|
SignDataRequest struct {
|
||||||
ContentType string `json:"content_type"`
|
ContentType string `json:"content_type"`
|
||||||
Address common.MixedcaseAddress `json:"address"`
|
Address common.MixedcaseAddress `json:"address"`
|
||||||
Rawdata interface{} `json:"raw_data"`
|
Rawdata []byte `json:"raw_data"`
|
||||||
Message []*NameValueType `json:"message"`
|
Message []*NameValueType `json:"message"`
|
||||||
Hash hexutil.Bytes `json:"hash"`
|
Hash hexutil.Bytes `json:"hash"`
|
||||||
Meta Metadata `json:"meta"`
|
Meta Metadata `json:"meta"`
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ var typedDataReferenceTypeRegexp = regexp.MustCompile(`^[A-Z](\w*)(\[\])?$`)
|
||||||
|
|
||||||
// Note, the produced signature conforms to the secp256k1 curve R, S and V values,
|
// Note, the produced signature conforms to the secp256k1 curve R, S and V values,
|
||||||
// where the V value will be 27 or 28 for legacy reasons.
|
// where the V value will be 27 or 28 for legacy reasons.
|
||||||
func (api *SignerAPI) sign(ctx context.Context, addr common.MixedcaseAddress, req *SignDataRequest) (hexutil.Bytes, error) {
|
func (api *SignerAPI) sign(addr common.MixedcaseAddress, req *SignDataRequest) (hexutil.Bytes, error) {
|
||||||
|
|
||||||
// We make the request prior to looking up if we actually have the account, to prevent
|
// We make the request prior to looking up if we actually have the account, to prevent
|
||||||
// account-enumeration via the API
|
// account-enumeration via the API
|
||||||
|
|
@ -158,7 +158,7 @@ func (api *SignerAPI) SignData(ctx context.Context, contentType string, addr com
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
signature, err := api.sign(ctx, addr, req)
|
signature, err := api.sign(addr, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.UI.ShowError(err.Error())
|
api.UI.ShowError(err.Error())
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -198,7 +198,7 @@ func (api *SignerAPI) determineSignatureFormat(ctx context.Context, contentType
|
||||||
Value: msg,
|
Value: msg,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
req = &SignDataRequest{ContentType: mediaType, Rawdata: validatorData, Message: message, Hash: sighash}
|
req = &SignDataRequest{ContentType: mediaType, Rawdata: []byte(msg), Message: message, Hash: sighash}
|
||||||
case ApplicationClique.Mime:
|
case ApplicationClique.Mime:
|
||||||
// Clique is the Ethereum PoA standard
|
// Clique is the Ethereum PoA standard
|
||||||
cliqueData, err := hexutil.Decode(data.(string))
|
cliqueData, err := hexutil.Decode(data.(string))
|
||||||
|
|
@ -209,6 +209,8 @@ func (api *SignerAPI) determineSignatureFormat(ctx context.Context, contentType
|
||||||
if err := rlp.DecodeBytes(cliqueData, header); err != nil {
|
if err := rlp.DecodeBytes(cliqueData, header); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// Get back the rlp data, encoded by us
|
||||||
|
cliqueData = clique.CliqueRLP(header)
|
||||||
sighash, err := SignCliqueHeader(header)
|
sighash, err := SignCliqueHeader(header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -228,7 +230,7 @@ func (api *SignerAPI) determineSignatureFormat(ctx context.Context, contentType
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
sighash, msg := SignTextPlain(plainData)
|
sighash, msg := accounts.TextAndHash(plainData)
|
||||||
message := []*NameValueType{
|
message := []*NameValueType{
|
||||||
{
|
{
|
||||||
Name: "message",
|
Name: "message",
|
||||||
|
|
@ -236,7 +238,7 @@ func (api *SignerAPI) determineSignatureFormat(ctx context.Context, contentType
|
||||||
Value: msg,
|
Value: msg,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
req = &SignDataRequest{ContentType: mediaType, Rawdata: plainData, Message: message, Hash: sighash}
|
req = &SignDataRequest{ContentType: mediaType, Rawdata: []byte(msg), Message: message, Hash: sighash}
|
||||||
}
|
}
|
||||||
return req, nil
|
return req, nil
|
||||||
|
|
||||||
|
|
@ -263,40 +265,10 @@ func SignCliqueHeader(header *types.Header) (hexutil.Bytes, error) {
|
||||||
if len(header.Extra) < 65 {
|
if len(header.Extra) < 65 {
|
||||||
return nil, fmt.Errorf("clique header extradata too short, %d < 65", len(header.Extra))
|
return nil, fmt.Errorf("clique header extradata too short, %d < 65", len(header.Extra))
|
||||||
}
|
}
|
||||||
//hasher := sha3.NewLegacyKeccak256()
|
|
||||||
hash := clique.SealHash(header)
|
hash := clique.SealHash(header)
|
||||||
//rlp.Encode(hasher, []interface{}{
|
|
||||||
// header.ParentHash,
|
|
||||||
// header.UncleHash,
|
|
||||||
// header.Coinbase,
|
|
||||||
// header.Root,
|
|
||||||
// header.TxHash,
|
|
||||||
// header.ReceiptHash,
|
|
||||||
// header.Bloom,
|
|
||||||
// header.Difficulty,
|
|
||||||
// header.Number,
|
|
||||||
// header.GasLimit,
|
|
||||||
// header.GasUsed,
|
|
||||||
// header.Time,
|
|
||||||
// header.Extra[:len(header.Extra)-65],
|
|
||||||
// header.MixDigest,
|
|
||||||
// header.Nonce,
|
|
||||||
//})
|
|
||||||
//hasher.Sum(hash[:0])
|
|
||||||
return hash.Bytes(), nil
|
return hash.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignTextPlain is a helper function that calculates a hash for the given message that can be
|
|
||||||
// safely used to calculate a signature from. This gives context to the signed message and prevents
|
|
||||||
// signing of transactions.
|
|
||||||
// hash = keccak256("\x19$Ethereum Signed Message:\n"${message length}${message}).
|
|
||||||
func SignTextPlain(data hexutil.Bytes) (hexutil.Bytes, string) {
|
|
||||||
// The letter `E` is \x45 in hex, retrofitting
|
|
||||||
// https://github.com/ethereum/go-ethereum/pull/2940/commits
|
|
||||||
msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), string(data))
|
|
||||||
return crypto.Keccak256([]byte(msg)), msg
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignTypedData signs EIP-712 conformant typed data
|
// SignTypedData signs EIP-712 conformant typed data
|
||||||
// hash = keccak256("\x19${byteVersion}${domainSeparator}${hashStruct(message)}")
|
// hash = keccak256("\x19${byteVersion}${domainSeparator}${hashStruct(message)}")
|
||||||
func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAddress, typedData TypedData) (hexutil.Bytes, error) {
|
func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAddress, typedData TypedData) (hexutil.Bytes, error) {
|
||||||
|
|
@ -308,10 +280,11 @@ func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
sighash := crypto.Keccak256([]byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash))))
|
rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash)))
|
||||||
|
sighash := crypto.Keccak256(rawData)
|
||||||
message := typedData.Format()
|
message := typedData.Format()
|
||||||
req := &SignDataRequest{ContentType: DataTyped.Mime, Rawdata: typedData.Map(), Message: message, Hash: sighash}
|
req := &SignDataRequest{ContentType: DataTyped.Mime, Rawdata: rawData, Message: message, Hash: sighash}
|
||||||
signature, err := api.sign(ctx, addr, req)
|
signature, err := api.sign(addr, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.UI.ShowError(err.Error())
|
api.UI.ShowError(err.Error())
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -569,7 +542,7 @@ func (api *SignerAPI) EcRecover(ctx context.Context, data hexutil.Bytes, sig hex
|
||||||
return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)")
|
return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)")
|
||||||
}
|
}
|
||||||
sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1
|
sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1
|
||||||
hash, _ := SignTextPlain(data)
|
hash := accounts.TextHash(data)
|
||||||
rpk, err := crypto.SigToPub(hash, sig)
|
rpk, err := crypto.SigToPub(hash, sig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Address{}, err
|
return common.Address{}, err
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue