mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
accounts/usbwallet: trezor signed message support
This commit is contained in:
parent
e8c9579fb7
commit
24d7201acd
4 changed files with 72 additions and 2 deletions
|
|
@ -168,6 +168,12 @@ func (w *ledgerDriver) SignTx(path accounts.DerivationPath, tx *types.Transactio
|
|||
return w.ledgerSign(path, tx, chainID)
|
||||
}
|
||||
|
||||
// SignData sends a blob of data to the USB device and waits for the user to confirm
|
||||
// or deny the transaction.
|
||||
func (w *ledgerDriver) SignData(path accounts.DerivationPath, hash []byte) (common.Address, []byte, error) {
|
||||
return common.Address{}, nil, accounts.ErrNotSupported
|
||||
}
|
||||
|
||||
// ledgerVersion retrieves the current version of the Ethereum wallet app running
|
||||
// on the Ledger wallet.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -185,6 +185,29 @@ func (w *trezorDriver) SignTx(path accounts.DerivationPath, tx *types.Transactio
|
|||
return w.trezorSign(path, tx, chainID)
|
||||
}
|
||||
|
||||
// SignData sends a blob of data to the xUSB device and waits for the user to confirm
|
||||
// or deny the transaction.
|
||||
func (w *trezorDriver) SignData(path accounts.DerivationPath, hash []byte) (common.Address, []byte, error) {
|
||||
request := &trezor.EthereumSignMessage{
|
||||
AddressN: path,
|
||||
Message: hash,
|
||||
}
|
||||
response := new(trezor.EthereumMessageSignature)
|
||||
if _, err := w.trezorExchange(request, response); err != nil {
|
||||
return common.Address{}, nil, err
|
||||
}
|
||||
|
||||
var address common.Address
|
||||
if addr := response.GetAddressBin(); len(addr) > 0 { // Older firmwares use binary fomats
|
||||
address = common.BytesToAddress(addr)
|
||||
}
|
||||
if addr := response.GetAddressHex(); len(addr) > 0 { // Newer firmwares use hexadecimal fomats
|
||||
address = common.HexToAddress(addr)
|
||||
}
|
||||
|
||||
return address, response.Signature, nil
|
||||
}
|
||||
|
||||
// trezorDerive sends a derivation request to the Trezor device and returns the
|
||||
// Ethereum address located on that path.
|
||||
func (w *trezorDriver) trezorDerive(derivationPath []uint32) (common.Address, error) {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,10 @@ type driver interface {
|
|||
// SignTx sends the transaction to the USB device and waits for the user to confirm
|
||||
// or deny the transaction.
|
||||
SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error)
|
||||
|
||||
// SignData sends a blob of data to the USB device and waits for the user to confirm
|
||||
// or deny the transaction.
|
||||
SignData(path accounts.DerivationPath, hash []byte) (common.Address, []byte, error)
|
||||
}
|
||||
|
||||
// wallet represents the common functionality shared by all USB hardware
|
||||
|
|
@ -515,7 +519,44 @@ func (w *wallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.Chai
|
|||
// signHash implements accounts.Wallet, however signing arbitrary data is not
|
||||
// supported for hardware wallets, so this method will always return an error.
|
||||
func (w *wallet) signHash(account accounts.Account, hash []byte) ([]byte, error) {
|
||||
return nil, accounts.ErrNotSupported
|
||||
w.stateLock.RLock() // Comms have their own mutex
|
||||
defer w.stateLock.RUnlock()
|
||||
|
||||
// If the wallet is closed, abort
|
||||
if w.device == nil {
|
||||
return nil, accounts.ErrWalletClosed
|
||||
}
|
||||
// Make sure the requested account is contained within
|
||||
path, ok := w.paths[account.Address]
|
||||
if !ok {
|
||||
return nil, accounts.ErrUnknownAccount
|
||||
}
|
||||
|
||||
// All infos gathered and metadata checks out, request signing
|
||||
<-w.commsLock
|
||||
defer func() { w.commsLock <- struct{}{} }()
|
||||
|
||||
// Ensure the device isn't screwed with while user confirmation is pending
|
||||
// TODO(karalabe): remove if hotplug lands on Windows
|
||||
w.hub.commsLock.Lock()
|
||||
w.hub.commsPend++
|
||||
w.hub.commsLock.Unlock()
|
||||
|
||||
defer func() {
|
||||
w.hub.commsLock.Lock()
|
||||
w.hub.commsPend--
|
||||
w.hub.commsLock.Unlock()
|
||||
}()
|
||||
|
||||
// Sign the transaction and verify the sender to avoid hardware fault surprises
|
||||
sender, signed, err := w.driver.SignData(path, hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sender != account.Address {
|
||||
return nil, fmt.Errorf("signer mismatch: expected %s, got %s", account.Address.Hex(), sender.Hex())
|
||||
}
|
||||
return signed, nil
|
||||
}
|
||||
|
||||
// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ func (api *SignerAPI) sign(addr common.MixedcaseAddress, req *SignDataRequest, l
|
|||
}
|
||||
pw, err := api.lookupOrQueryPassword(account.Address,
|
||||
"Password for signing",
|
||||
fmt.Sprintf("Please enter password for signing data with account %s", account.Address.Hex()))
|
||||
fmt.Sprintf("Please enter password for signing data with account %s, or just press 'RETURN'", account.Address.Hex()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue