Skip to content

internal/ethapi: add personal_sign method#2940

Merged
fjl merged 5 commits into
ethereum:developfrom
bas-vk:personal_sign
Oct 28, 2016
Merged

internal/ethapi: add personal_sign method#2940
fjl merged 5 commits into
ethereum:developfrom
bas-vk:personal_sign

Conversation

@bas-vk

@bas-vk bas-vk commented Aug 24, 2016

Copy link
Copy Markdown
Member

This PR includes several things:

  1. the behavior of eth_sign is changed. It now accepts an arbitrary message, prepends a known message, hashes the result using keccak256 it calculates the signature of the hash (breaks backwards compatability!).
  2. add personal_sign, same semantics as eth_sign but also accepts a password. The private key used to sign the hash is temporary unlocked in the scope of the request.
  3. add personal_recover, returns the address for the account that created the signature.

personal_recover(message, signature)
personal_sign(hash, address [, password])

The known message added to the input before hashing is

"\x19Ethereum Signed Message:\n" + len(message).

@alexvandesande

@robotally

robotally commented Aug 24, 2016

Copy link
Copy Markdown
Vote Count Reviewers
👍 0
👎 0

Updated: Tue Sep 6 09:00:42 UTC 2016

@mention-bot

Copy link
Copy Markdown

@bas-vk, thanks for your PR! By analyzing the annotation information on this pull request, we identified @karalabe, @zsfelfoldi and @fjl to be potential reviewers

@Arachnid

Copy link
Copy Markdown
Contributor

With the impending advent of hardware wallets, I'm concerned this is overly internal-account-specific; is there any way to avoid hardcoding in passwords as an authentication mechanism? (I don't have a suggestion just yet, just thinking out loud)

@fjl

fjl commented Aug 24, 2016

Copy link
Copy Markdown
Contributor

If you use a hardware wallet, it's better to talk to it on the client side.

@fjl

fjl commented Aug 24, 2016

Copy link
Copy Markdown
Contributor

@bas-vk Can we seize this opportunity to fix some of the other issues with eth_sign?

  • It should hash the input on the server side.
  • There was some issue with the Ethereum-specific +27 v value

@Arachnid

Copy link
Copy Markdown
Contributor

If you use a hardware wallet, it's better to talk to it on the client side.

For signing, perhaps, but I'm thinking more about what sort of interfaces we offer that are backed by accounts, and how those will work if we support accounts other than those whose private keys are held by Geth.

@bas-vk

bas-vk commented Aug 24, 2016

Copy link
Copy Markdown
Member Author

@bas-vk Can we seize this opportunity to fix some of the other issues with eth_sign?

We can, this PR is rather small so I have no problem adding additional changes.

  • It should hash the input on the server side.

Changing this would break backwards compatibility for eth_sign. Exploiting this requires the key to be unlocked. And in that case obtaining the private key is nice but if it's possible to sign arbitrary data a thief basically has full control over the account during the time he can sign data. I will make this change for the new method.

  • There was some issue with the Ethereum-specific +27 v value

I believe the issue was that according to the yellow paper Ethereum hashes should have a signature with v+27 just like bitcoin. eth_sign currently doesn't add 27. Will add 27 to the signature of the new method to make it compliant with the yellow paper and leave eth_sign untouched.

Maybe at some point we can mark eth_sign deprecated.

@fjl

fjl commented Aug 24, 2016

Copy link
Copy Markdown
Contributor

Thanks. I agree that eth_sign should be deprecated, ideally quite soon. We can keep it around for the 1.5 release cycle and remove it in 1.6.

@kumavis

kumavis commented Aug 24, 2016

Copy link
Copy Markdown
Member

@fjl does the api take the hash or the message?
personal_sign(messageHash, signerAddress [, password])
personal_sign(messageBody, signerAddress [, password])

Its important that we pass the message so that the id mgmt layer (mist/metamask) can present the message to the user for approval

@fjl

fjl commented Aug 24, 2016

Copy link
Copy Markdown
Contributor

My proposal is as follows:

personal_sign(message, address [, password]) should sign keccak256(message) with the key that belongs to address and return the signature format that is commonly used in Ethereum (with V + 27). This means that the message would be available for display in MetaMask.

In internal discussions we have considered to prepend "Signed Ethereum Message:\n" to the message
on the server side. This would make it much harder to misuse the API (i.e. you can't sign a transaction this way). The idea of adding the prefix is not set in stone though.

@kumavis

kumavis commented Aug 24, 2016

Copy link
Copy Markdown
Member

I'm not sure how the prefix makes it much harder to misuse the API. can you expand?
If the attacker is trying to find a hash collision with a tx sig, they would just build a rainbow table with that prefix as the 'salt'.

I understand how a salt might be better than none, but maybe a dynamic salt like a timestamp would provide more security.

@fjl

fjl commented Aug 24, 2016

Copy link
Copy Markdown
Contributor

What we are concerned with specifically is the case of a malicious dapp creating (transaction) signatures on behalf of inexperienced users who just click yes.

@kumavis

kumavis commented Aug 24, 2016

Copy link
Copy Markdown
Member

Yes, that is the primary attack vector im worried about.

@fjl

fjl commented Aug 24, 2016

Copy link
Copy Markdown
Contributor

If you have more ideas for making this safer please dump them here. Adding a timestamp sounds nice at first, but keep in mind that something (probably a contract) will need to verify the signature eventually and it needs to add the same prefix. The user would need to submit the timestamp to said contract later and that sounds complicated. But maybe it's the right thing to do.

@kumavis

kumavis commented Aug 24, 2016

Copy link
Copy Markdown
Member

FWIW we are currently using the old version of the eth_sign API and displaying the messages.
We're currently reworking this UI and it will be more clear what exactly you are signing, the size of the message, and have a bunch of warnings not to sign any weird messages.

image

@kumavis

kumavis commented Aug 24, 2016

Copy link
Copy Markdown
Member

or just use a random salt and include it in the serialized message signature

personal_sign( message ){
  salt = random()
  sig = sign( hash( salt + message ) )
  return [sig, salt]
}

@fjl

fjl commented Aug 24, 2016

Copy link
Copy Markdown
Contributor

Yes that looks better (and pragmatic). I'll think about it.

@fjl fjl added this to the 1.5.0 milestone Aug 24, 2016
@fjl fjl added the crypto label Aug 24, 2016
@kumavis

kumavis commented Aug 24, 2016

Copy link
Copy Markdown
Member

requesting comment from @Georgi87 and @mhhf who make use of user message signatures in the https://www.gnosis.pm/ predication market dapp

@kumavis

kumavis commented Aug 24, 2016

Copy link
Copy Markdown
Member

Theres still a problem with signing messages with the same key we use for tx sigs.

given a message signature, theres still a large search space for valid tx hashes that could match the message signature. Tx parameters such as value and toAddress provide a lot of search space that can be explored in parallel to find a hash collision.

evilTx: { value: allYourMoney, to: attacker01 }
evilTx: { value: allYourMoney, to: attacker02 }
evilTx: { value: allYourMoney, to: attacker03 }
...

While significant increasing scope and complexity of this issue, and perhaps breaking compat with existing geth single-key behavior, this could be alleviated by using a different key available on an hd-tree
ethereum/EIPs#84

@fjl

fjl commented Aug 24, 2016

Copy link
Copy Markdown
Contributor

@nagydani would be good to have your input here as well

@danfinlay

Copy link
Copy Markdown

Since we're talking about eth_sign, I'd like to chime in here that I think it would be way more useful if a method allowed signing/decrypting arbitrary lengthed data, not just hashes, and I've expressed this opinion in an EIP that hasn't gotten much of a response.

@kelvin488 kelvin488 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes #

@ricmoo

ricmoo commented Oct 20, 2021

Copy link
Copy Markdown

Late to the game, but FYI:

Does anybody know where the \x19 originally came from?

It is one of the most clever retconed cases I've come across, so I thought I'd share.

The original was from \x18Bitcoin signed message:\n, where \x18 is a Bitcoin VarInt (for small numbers, it's just the same as the value) for 24, which is the length of the string "Bitcoin signed message:\n". So, \x19 is the Bitcoin VarInt for the length of the string `Ethereum signed message:\n".

As it turned out, 0x19 is a value that isn't a valid RLP encoded array, which is what all transactions are encoded as, and so EIP-191 was able to retcon it as the version byte. :)

@jakazoll jakazoll left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hash

@Yhozen

Yhozen commented Nov 23, 2021

Copy link
Copy Markdown

Hash

Hash indeed

// yellow paper. Use the SignEthereum function to calculate a signature
// in Ethereum format.
func (am *Manager) Sign(addr common.Address, hash []byte) ([]byte, error) {
am.mu.RLock()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

@Maryo77 Maryo77 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

]()]()

@mantaray616

Copy link
Copy Markdown

Jump Task

@mantaray616

Copy link
Copy Markdown

2F1.bridge.walletconnect.orghttps://app.jumptask.io/home

if !found {
return nil, ErrLocked
}
return crypto.SignEthereum(hash, unlockedKey.PrivateKey)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

32rzbnjmJfRa4MH8TcpdNtcdzSwkMRzRr9

common.FromHex("5544"),
).WithSignature(
common.Hex2Bytes("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a301"),
common.Hex2Bytes("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a31c"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤙

Comment thread accounts/abi/bind/auth.go
@@ -52,7 +52,7 @@ func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
if address != keyAddr {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accounts/abi/bind/auth.go Asset Amount Asset Type Date Acquired Date Sold Proceeds (USD) Cost Basis (USD) Gain (USD) Type
0.00000229 BTC 12/12/2014 08/26/2017 0.01 0.00 0.01 Long Term
1.00010001 ZEC 12/20/2014 09/19/2017 0.39 0.03 0.36 Long Term
0.00082408 BTC 12/12/2014 09/19/2017 3.22 0.29 2.93 Long Term
4.12723423 XMR 08/20/2017 10/19/2017 538.57 565.08 -26.51 Short Term
0.00000002 BTC 01/28/2015 09/19/2017 0.00 0.00 0.00 Long Term
0.00000001 BTC 01/10/2015 09/19/2017 0.00 0.00 0.00 Long Term
0.10001200 LTC 12/21/2014 09/19/2017 0.04 0.00 0.04 Long Term
0.00004001 BTC 12/23/2014 09/19/2017 0.12 0.01 0.11 Long Term
0.00000100 ETH 12/20/2014 09/19/2017 0.00 0.00 0.00 Long Term

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import priv-keys in confirmation order

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.