The New Secure Way To Sign Data In Your Browser

Developer note: This article discusses a new method available to websites viewed with MetaMask and Mist browsers, called personal_sign. This is replacing eth_sign, and that old method now has a big red warning for your users because it was deprecated for security reasons. It’s left in place only to keep sites running that rely on it.

When people get excited about MetaMask, it’s usually because it allows users to interact with the Ethereum blockchain, which usually involves owning some network fuel called Ether, to run programs on a global shared virtual computer, and we think this is great.

However, even without any Ether, MetaMask makes some new things possible for websites, because to interact with the Ethereum blockchain, MetaMask had to add private key management to the browser.

When the modern browser was first created, it was seen as a linked document browser, and so identity and payments weren’t baked in. This led to the world of password management that we have today, where each website holds a database that includes your account, and maybe credit card, and when you connect with them, you prove who you are with a password.

MetaMask lets us reverse this relationship, and explore a web where the browser can secure your identity for you, in the form of a cryptographic key pair.

Called a signature because like a pen signature, it can be used to identify who wrote it.

One of the basic functions of a cryptographic key pair is signing data. When you sign some data, anyone can see that your signature could only be produced by the person who holds your private key. This is powerful, because it means you can compose a message and prove that you authored it (or at least had it at some point).

One example use of this that normal sites could use today, would be for signing a terms of service agreement. The site could submit their terms of service using eth.personal_sign(fromAddress, hexEncodedUtf8Message), and the user will get a MetaMask message like this:

MetaMask can now render plain text for signing, so sites can make their signature challenges human readable. We’d like to offer more rich rendering options in the future, and this is discussed in EIP 185.

Once the user signs it, the site could store that signature, and later on they could use it to prove that the user signed the message.

This means a user doesn’t need to hold any ether to perform a meaningful act with their MetaMask accounts. In the past, when a website would check the current accounts via web3.eth.accounts, the site only really knew that the user intended to appear as that account, but with a simple signature challenge, you can prove they really do control that account. From there, you could give them a browser cookie to stay logged in. That’s account management without any external, third-party services like Facebook Connect or Google tracking your every move.

We’re excited to see what’s possible in a web with accounts baked into the browser, and hope that someday account management like this is baked into every operating system, to enable a seamless, personal, distributed web.

For Developers

I’ve created a sample repository for showing how to submit a message & verify it using MetaMask’s injected APIs. These methods are not yet supported by web3.js (pending this pull request), but that repo has examples for either using the raw provider object directly, or using a new web3 alternative, EthJS.

Security Notice

These methods, personal_sign and its partner, personal_ecRecover have replaced the previous signature methods, eth_sign and eth_recover. That’s because the previous methods signed raw data unmodified, making it vulnerable to chosen ciphertext attacks, as well as potentially signing transactions you didn’t intend to. You can read more about the reasoning behind this change on the go-ethereum repository.

Compatibility Notice

While go-ethereum was first to implement these methods, Parity has also since released the feature, although it is not presently compatible with the Geth version. Since we had to choose one, we went with the original implementation, so our sign & recovery methods are currently bit-compatible with Geth, but not Parity.

We’re as frustrated as you about the lack of unified standards in the application layer of Ethereum, which is why we’re also working towards building an EIP Standards Signaling DAO. If you’d like to see the Ethereum application layer gain stability, you can help move it forward by contributing to the standard RPC spec format proposed in this EIP by Casey Detrio.