-
Notifications
You must be signed in to change notification settings - Fork 8
Description
The potentially dangerous sign_msg
function introduced in #82 should be removed. It is based on Ethereum's personal_sign
, the use of which is discouraged since the introduction of the much superior EIP712 standard. EIP712 addresses the many issues and shortcomings of personal_sign
. If the function is adopted in Stacks wallets, it will put the entire ecosystem on a perilous path. We should learn from the Ethereum space and skip this function completely.
personal_sign
had two main use cases:
- Signing messages to authenticate with some app/dapp.
- Signing messages that authorise some on-chain action.
When it comes to the first, we already have an authentication scheme. Right now it does not allow us to prove address ownership, but that can be achieved in different ways. (I will come back to this at the end.)
The second one is more important, so I will focus on that. Signed messages have been used for many different things in the Ethereum space. I will take on one such example for brevity: off-chain order signing. 0xProtocol allows users to sign an order, which can later be submitted to a smart contract to make a token trade happen. Early versions of the protocol would hash an order structure and request users to sign the order hash via personal_sign
to authorise the trade.
It first looked like this:
And then this:
Does the user have any idea what he or she is actually signing? Obviously not. The user will just have to trust that the dapp fed the right message to the wallet. The messages are also not domain specific, which means that a malicious app could trick a user into signing something meant for another platform. And since the messages that are passed to the wallet are hashes, there is no way to reconstruct the original message in the wallet. It is just all-round terrible UX and highly dangerous. In hindsight it is obvious that the function should never have existed, but back then it is all we had and such signed messages were cutting edge. They allowed for many new an exciting things. Although personal_sign
was largely left behind, it is still causing longer-lasting damage because it normalised the concept of signing byte strings. Many people are now so used to signing on-chain actions in this way, that they just hit Confirm when that wallet screen pops up. The sign_msg
function opens us up to all of it.
Signing byte strings should not be normalised in the Stacks ecosystem.
I cannot stress that enough. We have so many tools at our disposal to make the UX a lot better and safer. Ethereum did not have the benefit of a human-readable interpreted language like Clarity. There is no good reason to introduce a personal_sign
equivalent for Stacks.
Besides, it seems to be carelessly implemented and actually commits the same mistake as the original personal_sign
implementation.
- The
\x19
is a (Bitcoin)varint
representing the byte length of the prefix, which is correct forEthereum Signed Message:\n
as it's25
, but not forStacks Signed Message:\n
. It seems like it was copy and pasted thoughtlessly. It should have been\x18
. - The message length is appended as an ASCII string, so you have no idea where the actual message starts. They made the same mistake in geth. Sign message is using incorrect prefix ethereum/go-ethereum#14794
The language in #76 almost makes it sound like sign_msg
is a stopgap solution until we have something better. I really do not think that is the right approach. I rather have nothing, over this function, until a good message signing standard arrives. Hiro, as a shepherd of the Stacks ecosystem, should consider very carefully whether adding such a function is worth it.
There is a draft SIP that describes a structured data signing method much like EIP712. It describes a general structured message signing standard that leverages Stacks wire format, while still allowing safe human-readable text message signing. (If people insist.) I would welcome such a standard or one like it. And to go back to proving address ownership, the linked SIP would make that effortless as well.
I hope that all this is convincing enough to remove sign_msg
. For reference, we are building a hardware wallet at Ryder and will not implement an unstructured message signing function such as this one for the reasons laid out above.