Comments (14)
If our expectation is that most messages will be less than a certain value X (e.g. 60 characters), and that their length won't require users to "click too much" (e.g. <4 clicks), then any cap we put into place for that will be irrelevant for most users.
For the few users that do encounter longer messages and more clicks, my sense is that it's better to show the full message and require more clicks, without requiring the extra step of enabling "expert mode" (and without limiting the display to only the first X characters). That way there is no possibility of "blind signing" even part of the message.
Of course, some subset of these few users may encounter many clicks (10+?) if they're signing something particular complex. But presumably that increased complexity will correlate with one's increased desire to verify the complete message and increased tolerance for clicks?
from ledger-stacks.
thanks for this clear explanation. in our case, because of the limitation the device has in regards to the characters that can be shown on the display, the ledger app only processes ASCII string messages, So users would be able to see the message they are signing. .. trying to sign a message like the one you described would cause an error.
from ledger-stacks.
Thanks for reporting @MarvinJanssen.
If you can help me understand the varint prefix, Stacks Signed Message:\n
is 24 chars, so wouldn't that make the prefix \x18
in little endian encoding?
You describe off-chain order signing as an example of how message signing is used, but as we follow the message prefix scheme, doesn't that mute the ability to build features like this and thus prevent any similarly related attacks? What would be an abuse vector of the sign_msg
function as is, or are you more concerned about the practice of signing raw input messages in general?
from ledger-stacks.
If you can help me understand the varint prefix, Stacks Signed Message:\n is 24 chars, so wouldn't that make the prefix \x18 in little endian encoding?
actually, the variant prefix is \x19
from ledger-stacks.
@neithanmo I see. That makes things better. In that case I suggest the JS lib to enforce this and not have it sent to the Ledger at all if there are non-printable characters present in the message. I did not dive into the Ledger code and made the report solely on the linked PR so my apologies for not going deeper.
I think the length as ASCII should still be fixed. If you make it a (var)int then you can easily determine where the actual message starts.
Counting digits does not work if the users inputs a message like "00"
, you end up with \x19Stacks Signed Message:\n200
.
@kyranjamie you're right, stupid mistake on my part, 24 == \x18
.
To answer your question, I was unaware that the message signing function in the firmware rejects non-ASCII messages. personal_sign
was at some point in the past (ab)used to sign hashes of data structures. The ASCII prefix had nothing to do with it. They did it by hashing an ABI encoded struct and requesting a signature from the user. So the final message would look like: \x19Ethereum Signed Message:\n32<32 bytes here>
. Then on the contract they would reconstruct that message to verify the signature.
Here is one such example (that I even made myself):
My concern with it is that users cannot verify what they are signing. But now that I know that the Ledger app won't accept non-ASCII messages, this is less of an issue as developers will be hard pressed to (ab)use msg_sign
in the same way as Eth devs did with personal_sign
.
Having said all that, I still wonder what the usefulness of msg_sign
is. What are the use-cases? Even more so now I heard that Hiro is working on a SIP018(-like) implementation for Hiro Wallet. You could use SIP018 to sign a string-ascii
CV if you want a text message.
from ledger-stacks.
@neithanmo I see. That makes things better. In that case I suggest the JS lib to enforce this and not have it sent to the Ledger at all if there are non-printable characters present in the message. I did not dive into the Ledger code and made the report solely on the linked PR so my apologies for not going deeper.
we can add this double check as well.
I think the length as ASCII should still be fixed. If you make it a (var)int then you can easily determine where the actual message starts.
Counting digits does not work if the user's inputs a message like
"00"
, you end up with\x19Stacks Signed Message:\n200
.
@MarvinJanssen we considered that case as it is clearly described in the EIP-712 documentation as a possible flaw, that is why the parser verifies if \x19Stacks Signed Message:\n200
correspond to a str.len = 200
or a str = "00"
with length=2
. for this message the device will show the user the string "00" and will ask the user if they want to sign it.
the case for strings starting with numbers is also considered, and last but not least, trailing zeros are also invalid(there are tests for each).
there is one important thing. because of the small screen in ledger devices, and considering that string_messages can be huge. we limited the number of characters the device is going to show on the screen, which means that depending on the size of the screen and the message length, the message users see might not be a full message.
from ledger-stacks.
@MarvinJanssen we considered that case as it is clearly described in the EIP-712 documentation as a possible flaw, that is why the parser verifies if \x19Stacks Signed Message:\n200 correspond to a str.len = 200 or a str = "00" with length=2. for this message the device will show the user the string "00" and will ask the user if they want to sign it.
You have the opportunity to fix it, so why not fix it? There is no reason for parity with Ethereum's personal_sign
.
there is one important thing. because of the small screen in ledger devices, and considering that string_messages can be huge. we limited the number of characters the device is going to show on the screen, which means that depending on the size of the screen and the message length, the message users see might not be a full message.
That sounds a little scary. Perhaps it is better if the user has to explicitly enable it, like with "blind signing" for the Ethereum Ledger app. What is the limit of how many pages of text you can show?
As an aside, what kind of huge string messages are you expecting?
from ledger-stacks.
You have the opportunity to fix it, so why not fix it? There is no reason for parity with Ethereum's
personal_sign
.
we have already fixed that, it is how the parser was implemented.
That sounds a little scary. Perhaps it is better if the user has to explicitly enable it, like with "blind signing" for the Ethereum Ledger app. What is the limit of how many pages of text you can show?
we can show the complete message but it would be annoying the number of times users have to click..for any message we are going to show only the first 60 characters (header not included).
What we could do for cases where strings.len > 60
is to process them only if expert mode was configured on the device. but what is a proper limit here ?
As an aside, what kind of huge string messages are you expecting?
not sure, fixing a number maybe just too much or too few for some users
from ledger-stacks.
What we could do for cases where strings.len > 60 is to process them only if expert mode was configured on the device. but what is a proper limit here ?
Good question. I am not sure what the feature is meant for so maybe @kyranjamie can shed light on a good limit.
from ledger-stacks.
@MarvinJanssen @neithanmo leather-wallet/extension#1051
I believe this issue prompted the ask of this feature.
from ledger-stacks.
i opened another issue to restrict signing messages that are longer than X bytes. If the app is in expert mode, such messages can be signed as long as they are valid. users know what they are doing so, the restriction of showing only the first X characters could remain active in both modes(I do not see an expert doing a lot of clicks)?.
To summarize:
- in normal mode, any message longer than X would fail
- if in expert mode longer messages are allowed.
- in both modes, only the first X bytes are shown.
for now X = 60. the election of this number considered the nanoS screen, so a message with this length would require around ~3 clicks.
from ledger-stacks.
Although some upper bound surely is necessary still, lest dapps may try to send very large strings to be signed.
from ledger-stacks.
@kyranjamie @markmhx is there anything pending here?
should this result in some actions/tasks?
from ledger-stacks.
we agreed on showing the complete message to users..
please reopen if it makes sense or to start a discussion in regards to an alternative approach.
from ledger-stacks.
Related Issues (20)
- Wrong/unknown error code for `AppDoesNotSeemToBeOpen`
- Support JWT signing for Stacks authentication HOT 5
- Unable to retrieve keys for `m/888'` derivations paths
- Publish js app `v0.22.3` HOT 1
- Update data key derivation path HOT 1
- NPM published version is different than github HOT 2
- Display Domain name when signing JWT messages HOT 1
- Structured message signing support HOT 7
- Issues signing `principalCV` clarity types HOT 2
- Adjust `Stacks Signed Message` length prefix HOT 1
- Use varuint encoding for message prefix HOT 2
- Rename & publish npm package under `@zondax/ledger-stacks` HOT 2
- Replace buffer usage with Uint8Array HOT 1
- Message signing: payloads not accepted, line break issues HOT 3
- Contract principal not displayed properly on Ledger screen HOT 4
- Ledger Nano S screen showing incorrect address (40 instead of 41 characters) HOT 4
- Reduce the app size
- Fix CI HOT 1
- Update zxlib HOT 1
- Add new S+ sdk HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ledger-stacks.