Message Signing
Ledger
Ledger allows users to sign operations, micheline expressions or prehashes. Since a prehash can mean basically anything (disregarding verbose signatures) it would be the least attractive option. The other viable option would be a micheline expression (0x05). Even if Ledger can’t parse this payload, it distinguishes it from operations and prehashes. That will at least give users the certainty that it can’t lose funds from its implicit account or legacy KT1 account in case of a compromise.
Replay attacks
To mitigate the inherited risk of replay attacks with micheline expression, the expression needs to be distinctive enough so the intention is clear. It would also be good to clarify the scope and validity.
Suggested Micheline expression format:
"Tezos Signed Message: <message>"
The message should include a domain (e.g. mydapp.com) and a timestamp of current time (e.g. 2025-01-20T15:16:04Z) to harden it further against reusage.
Example:
"Tezos Signed Message: mydapp.com 2021-01-14T15:16:04Z Hello world!"
{
"string": "Tezos Signed Message: mydapp.com 2021-01-14T15:16:04Z Hello world!"
}
0x05010000004254657a6f73205369676e6564204d6573736167653a206d79646170702e636f6d20323032312d30312d31345431353a31363a30345a2048656c6c6f20776f726c6421
05 = micheline expression
01 = string
00000042 = number of characters (66 in this example)
rest = utf-8 encoded message
Read more about encoding