internal/ethapi: fix hex handling for eth_sign, personal_{sign,recover}
This commit is contained in:
		@@ -28,6 +28,7 @@ import (
 | 
				
			|||||||
	"github.com/ethereum/ethash"
 | 
						"github.com/ethereum/ethash"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/accounts"
 | 
						"github.com/ethereum/go-ethereum/accounts"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/common"
 | 
						"github.com/ethereum/go-ethereum/common"
 | 
				
			||||||
 | 
						"github.com/ethereum/go-ethereum/common/hexutil"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core"
 | 
						"github.com/ethereum/go-ethereum/core"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core/types"
 | 
						"github.com/ethereum/go-ethereum/core/types"
 | 
				
			||||||
	"github.com/ethereum/go-ethereum/core/vm"
 | 
						"github.com/ethereum/go-ethereum/core/vm"
 | 
				
			||||||
@@ -289,14 +290,14 @@ func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// signHash is a helper function that calculates a hash for the given message that can be
 | 
					// signHash 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 with:
 | 
					// safely used to calculate a signature from.
 | 
				
			||||||
// keccak256("\x19Ethereum Signed Message:\n"${message length}${message}).
 | 
					//
 | 
				
			||||||
func signHash(message string) []byte {
 | 
					// The hash is calulcated as
 | 
				
			||||||
	data := common.FromHex(message)
 | 
					//   keccak256("\x19Ethereum Signed Message:\n"${message length}${message}).
 | 
				
			||||||
	// Give context to the signed message. This prevents an adversery to sign a tx.
 | 
					//
 | 
				
			||||||
	// It has no cryptographic purpose.
 | 
					// This gives context to the signed message and prevents signing of transactions.
 | 
				
			||||||
 | 
					func signHash(data []byte) []byte {
 | 
				
			||||||
	msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), data)
 | 
						msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), data)
 | 
				
			||||||
	// Always hash, this prevents choosen plaintext attacks that can extract key information
 | 
					 | 
				
			||||||
	return crypto.Keccak256([]byte(msg))
 | 
						return crypto.Keccak256([]byte(msg))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -306,13 +307,8 @@ func signHash(message string) []byte {
 | 
				
			|||||||
// The key used to calculate the signature is decrypted with the given password.
 | 
					// The key used to calculate the signature is decrypted with the given password.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign
 | 
					// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign
 | 
				
			||||||
func (s *PrivateAccountAPI) Sign(ctx context.Context, message string, addr common.Address, passwd string) (string, error) {
 | 
					func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) {
 | 
				
			||||||
	hash := signHash(message)
 | 
						return s.b.AccountManager().SignWithPassphrase(addr, passwd, signHash(data))
 | 
				
			||||||
	signature, err := s.b.AccountManager().SignWithPassphrase(addr, passwd, hash)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return "0x", err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return common.ToHex(signature), nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EcRecover returns the address for the account that was used to create the signature.
 | 
					// EcRecover returns the address for the account that was used to create the signature.
 | 
				
			||||||
@@ -322,29 +318,20 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, message string, addr commo
 | 
				
			|||||||
// addr = ecrecover(hash, signature)
 | 
					// addr = ecrecover(hash, signature)
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
 | 
					// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
 | 
				
			||||||
func (s *PrivateAccountAPI) EcRecover(ctx context.Context, message string, signature string) (common.Address, error) {
 | 
					func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) {
 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		hash = signHash(message)
 | 
					 | 
				
			||||||
		sig  = common.FromHex(signature)
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if len(sig) != 65 {
 | 
						if len(sig) != 65 {
 | 
				
			||||||
		return common.Address{}, fmt.Errorf("signature must be 65 bytes long")
 | 
							return common.Address{}, fmt.Errorf("signature must be 65 bytes long")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// see crypto.Ecrecover description
 | 
						// see crypto.Ecrecover description
 | 
				
			||||||
	if sig[64] == 27 || sig[64] == 28 {
 | 
						if sig[64] == 27 || sig[64] == 28 {
 | 
				
			||||||
		sig[64] -= 27
 | 
							sig[64] -= 27
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						rpk, err := crypto.Ecrecover(signHash(data), sig)
 | 
				
			||||||
	rpk, err := crypto.Ecrecover(hash, sig)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return common.Address{}, err
 | 
							return common.Address{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	pubKey := crypto.ToECDSAPub(rpk)
 | 
						pubKey := crypto.ToECDSAPub(rpk)
 | 
				
			||||||
	recoveredAddr := crypto.PubkeyToAddress(*pubKey)
 | 
						recoveredAddr := crypto.PubkeyToAddress(*pubKey)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return recoveredAddr, nil
 | 
						return recoveredAddr, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1116,10 +1103,8 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod
 | 
				
			|||||||
// The account associated with addr must be unlocked.
 | 
					// The account associated with addr must be unlocked.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
 | 
					// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
 | 
				
			||||||
func (s *PublicTransactionPoolAPI) Sign(addr common.Address, message string) (string, error) {
 | 
					func (s *PublicTransactionPoolAPI) Sign(addr common.Address, data hexutil.Bytes) (hexutil.Bytes, error) {
 | 
				
			||||||
	hash := signHash(message)
 | 
						return s.b.AccountManager().SignEthereum(addr, signHash(data))
 | 
				
			||||||
	signature, err := s.b.AccountManager().SignEthereum(addr, hash)
 | 
					 | 
				
			||||||
	return common.ToHex(signature), err
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SignTransactionArgs represents the arguments to sign a transaction.
 | 
					// SignTransactionArgs represents the arguments to sign a transaction.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user