diff options
author | Paul Berg <hello@paulrberg.com> | 2019-02-06 15:30:49 +0800 |
---|---|---|
committer | Martin Holst Swende <martin@swende.se> | 2019-02-06 15:30:49 +0800 |
commit | 572baae10a28da2d02085df7e2f3a282883f5d6e (patch) | |
tree | 3e5424ac64dbeae440604d32aed4293199179c99 /signer/core/api.go | |
parent | 7c60d0a6a2d3925c2862cbbb188988475619fd0d (diff) | |
download | go-tangerine-572baae10a28da2d02085df7e2f3a282883f5d6e.tar go-tangerine-572baae10a28da2d02085df7e2f3a282883f5d6e.tar.gz go-tangerine-572baae10a28da2d02085df7e2f3a282883f5d6e.tar.bz2 go-tangerine-572baae10a28da2d02085df7e2f3a282883f5d6e.tar.lz go-tangerine-572baae10a28da2d02085df7e2f3a282883f5d6e.tar.xz go-tangerine-572baae10a28da2d02085df7e2f3a282883f5d6e.tar.zst go-tangerine-572baae10a28da2d02085df7e2f3a282883f5d6e.zip |
signer, clef: implement EIP191/712 (#17789)
* Named functions and defined a basic EIP191 content type list
* Written basic content type functions
* Added ecRecover method in the clef api
* Updated the extapi changelog and addded indications in the README
* Changed the version of the external API
* Added tests for 0x45
* Implementing UnmarshalJSON() for TypedData
* Working on TypedData
* Solved the auditlog issue
* Changed method to signTypedData
* Changed mimes and implemented the 'encodeType' function for EIP-712
* Polished docstrings, ran goimports and swapped fmt.Errorf with errors.New where possible
* Drafted recursive encodeData
* Ran goimports and gofmt
* Drafted first version of EIP-712, including tests
* Temporarily switched to using common.Address in tests
* Drafted text/validator and and rewritten []byte as hexutil.Bytes
* Solved stringified address encoding issue
* Changed the property type required by signData from bytes to interface{}
* Fixed bugs in 'data/typed' signs
* Brought legal warning back after temporarily disabling it for development
* Added example RPC calls for account_signData and account_signTypedData
* Named functions and defined a basic EIP191 content type list
* Written basic content type functions
* Added ecRecover method in the clef api
* Updated the extapi changelog and addded indications in the README
* Added tests for 0x45
* Implementing UnmarshalJSON() for TypedData
* Working on TypedData
* Solved the auditlog issue
* Changed method to signTypedData
* Changed mimes and implemented the 'encodeType' function for EIP-712
* Polished docstrings, ran goimports and swapped fmt.Errorf with errors.New where possible
* Drafted recursive encodeData
* Ran goimports and gofmt
* Drafted first version of EIP-712, including tests
* Temporarily switched to using common.Address in tests
* Drafted text/validator and and rewritten []byte as hexutil.Bytes
* Solved stringified address encoding issue
* Changed the property type required by signData from bytes to interface{}
* Fixed bugs in 'data/typed' signs
* Brought legal warning back after temporarily disabling it for development
* Added example RPC calls for account_signData and account_signTypedData
* Polished and fixed PR
* Polished and fixed PR
* Solved malformed data panics and also wrote tests
* Solved malformed data panics and also wrote tests
* Added alphabetical sorting to type dependencies
* Added alphabetical sorting to type dependencies
* Added pretty print to data/typed UI
* Added pretty print to data/typed UI
* signer: more tests for typed data
* signer: more tests for typed data
* Fixed TestMalformedData4 errors and renamed IsValid to Validate
* Fixed TestMalformedData4 errors and renamed IsValid to Validate
* Fixed more new failing tests and deanonymised some functions
* Fixed more new failing tests and deanonymised some functions
* Added types to EIP712 output in cliui
* Added types to EIP712 output in cliui
* Fixed regexp issues
* Fixed regexp issues
* Added pseudo-failing test
* Added pseudo-failing test
* Fixed false positive test
* Fixed false positive test
* Added PrettyPrint method
* Added PrettyPrint method
* signer: refactor formatting and UI
* signer: make ui use new message format for signing
* Fixed breaking changes
* Fixed rules_test failing test
* Added extra regexp for reference types
* signer: more hard types
* Fixed failing test, formatted files
* signer: use golang/x keccak
* Fixed goimports error
* clef, signer: address some review concerns
* Implemented latest recommendations
* Fixed comments and uintint256 issue
* accounts, signer: fix mimetypes, add interface to sign data with passphrase
* signer, accounts: remove duplicated code, pass hash preimages to signing
* signer: prevent panic in type assertions, make cliui print rawdata as quotable-safe
* signer: linter fixes, remove deprecated crypto dependency
* accounts: fix goimport
Diffstat (limited to 'signer/core/api.go')
-rw-r--r-- | signer/core/api.go | 74 |
1 files changed, 14 insertions, 60 deletions
diff --git a/signer/core/api.go b/signer/core/api.go index e112df9c7..0521dce47 100644 --- a/signer/core/api.go +++ b/signer/core/api.go @@ -30,7 +30,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/usbwallet" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" @@ -40,9 +39,9 @@ const ( // numberOfAccountsToDerive For hardware wallets, the number of accounts to derive numberOfAccountsToDerive = 10 // ExternalAPIVersion -- see extapi_changelog.md - ExternalAPIVersion = "4.0.0" + ExternalAPIVersion = "5.0.0" // InternalAPIVersion -- see intapi_changelog.md - InternalAPIVersion = "3.0.0" + InternalAPIVersion = "3.1.0" ) // ExternalAPI defines the external API through which signing requests are made. @@ -53,8 +52,12 @@ type ExternalAPI interface { New(ctx context.Context) (accounts.Account, error) // SignTransaction request to sign the specified transaction SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) - // Sign - request to sign the given data (plus prefix) - Sign(ctx context.Context, addr common.MixedcaseAddress, data hexutil.Bytes) (hexutil.Bytes, error) + // SignData - request to sign the given data (plus prefix) + SignData(ctx context.Context, contentType string, addr common.MixedcaseAddress, data interface{}) (hexutil.Bytes, error) + // SignTypedData - request to sign the given structured data (plus prefix) + SignTypedData(ctx context.Context, addr common.MixedcaseAddress, data TypedData) (hexutil.Bytes, error) + // EcRecover - recover public key from given message and signature + EcRecover(ctx context.Context, data hexutil.Bytes, sig hexutil.Bytes) (common.Address, error) // Export - request to export an account Export(ctx context.Context, addr common.Address) (json.RawMessage, error) // Import - request to import an account @@ -177,11 +180,12 @@ type ( NewPassword string `json:"new_password"` } SignDataRequest struct { - Address common.MixedcaseAddress `json:"address"` - Rawdata hexutil.Bytes `json:"raw_data"` - Message string `json:"message"` - Hash hexutil.Bytes `json:"hash"` - Meta Metadata `json:"meta"` + ContentType string `json:"content_type"` + Address common.MixedcaseAddress `json:"address"` + Rawdata []byte `json:"raw_data"` + Message []*NameValueType `json:"message"` + Hash hexutil.Bytes `json:"hash"` + Meta Metadata `json:"meta"` } SignDataResponse struct { Approved bool `json:"approved"` @@ -517,56 +521,6 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth } -// Sign calculates an Ethereum ECDSA signature for: -// keccack256("\x19Ethereum Signed Message:\n" + len(message) + message)) -// -// 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. -// -// The key used to calculate the signature is decrypted with the given password. -// -// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign -func (api *SignerAPI) Sign(ctx context.Context, addr common.MixedcaseAddress, data hexutil.Bytes) (hexutil.Bytes, error) { - sighash, msg := SignHash(data) - // We make the request prior to looking up if we actually have the account, to prevent - // account-enumeration via the API - req := &SignDataRequest{Address: addr, Rawdata: data, Message: msg, Hash: sighash, Meta: MetadataFromContext(ctx)} - res, err := api.UI.ApproveSignData(req) - - if err != nil { - return nil, err - } - if !res.Approved { - return nil, ErrRequestDenied - } - // Look up the wallet containing the requested signer - account := accounts.Account{Address: addr.Address()} - wallet, err := api.am.Find(account) - if err != nil { - return nil, err - } - // Assemble sign the data with the wallet - signature, err := wallet.SignTextWithPassphrase(account, res.Password, data) - if err != nil { - api.UI.ShowError(err.Error()) - return nil, err - } - signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper - return signature, nil -} - -// 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 calculated as -// keccak256("\x19Ethereum Signed Message:\n"${message length}${message}). -// -// This gives context to the signed message and prevents signing of transactions. -func SignHash(data []byte) ([]byte, string) { - msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), data) - return crypto.Keccak256([]byte(msg)), msg -} - // Export returns encrypted private key associated with the given address in web3 keystore format. func (api *SignerAPI) Export(ctx context.Context, addr common.Address) (json.RawMessage, error) { res, err := api.UI.ApproveExport(&ExportRequest{Address: addr, Meta: MetadataFromContext(ctx)}) |