Skip to content

Commit 318bad3

Browse files
committed
feat: new structured-data-prefix and test vectors
1 parent 839f1ee commit 318bad3

File tree

1 file changed

+17
-14
lines changed

1 file changed

+17
-14
lines changed

sips/sip-018/sip-018-signed-structured-data.md

+17-14
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,9 @@ To obtain a signature _S_ of structured data _D_ using private key _K_:
112112
`secp256k1` signature of a message hash using private key _K_; and,
113113

114114
- `messageHash(D) = sha256(structuredDataPrefix || domainHash || structuredDataHash(D))`;
115-
where `structuredDataPrefix` is a static value of `"\xC0"`, and `domainHash`
116-
and `structuredDataHash` are as described below.
115+
where `structuredDataPrefix` is a static value of `"\x53\x49\x50\x30\x31\x38"`
116+
(which spells "SIP018" in ASCII), and `domainHash` and `structuredDataHash`
117+
are as described below.
117118

118119
**Definition of** `domainHash`
119120

@@ -178,17 +179,19 @@ A future SIP may define standard types of Structured Data.
178179

179180
Structured Data hashes do not collide with _presign-sighashes_ as currently no
180181
Clarity Value in wire format forms a valid Stacks transaction. Furthermore, the
181-
`0xC0` byte prefix ensures that the input always differs in the first byte, as
182-
Stacks transactions start with a version byte of `0x00` (mainnet) or `0x80`
183-
(testnet). A Clarity Value in wire format starts with a byte in the range of
184-
`[0x00, 0x0C]`.
182+
`0x534950303138` byte prefix ensures that the input always differs in the first
183+
six bytes, as Stacks transactions start with a version byte of `0x00` (mainnet)
184+
or `0x80` (testnet), a four byte chain ID, and end with an authorisation type
185+
that must be `0x04` or `0x05` in order to be valid. A Clarity Value in wire
186+
format starts with a byte in the range of `[0x00, 0x0C]`. The prefix is easy to
187+
remember because it spells "SIP018" in ASCII.
185188

186189
Replay attacks across applications, forks, and other signature-compatible chains
187190
are mitigated by prepending a `domainHash` to the `messageHash`. A `domainHash`
188191
is calculated by hashing a `domain` Clarity Value tuple containing the
189192
application name, version, and chain ID.
190193

191-
This SIP is about signing and verifying application and chain specific
194+
This SIP is about signing and verifying application and chain-specific
192195
structured data. Replay protection on the application level is out of scope for
193196
the standard. Application developers need to make sure that their applications
194197
behave properly when they receive the same signed structured data more than
@@ -212,7 +215,7 @@ import {
212215
} from "@stacks/transactions";
213216
import { createHash } from "crypto";
214217

215-
const structuredDataPrefix = Buffer.from([0xC0]);
218+
const structuredDataPrefix = Buffer.from([0x53, 0x49, 0x50, 0x30, 0x31, 0x38]);
216219

217220
const chainIds = {
218221
mainnet: 1,
@@ -256,7 +259,7 @@ whether the signature is valid.
256259

257260
```clojure
258261
(define-constant chain-id u1)
259-
(define-constant structured-data-prefix 0xc0)
262+
(define-constant structured-data-prefix 0x534950303138)
260263

261264
(define-constant message-domain-hash (sha256 (to-consensus-buff
262265
{
@@ -346,12 +349,12 @@ Using `structuredDataHash(CV)` with an input Clarity Value.
346349
Using `messageHash(CV)`, which is
347350
`sha256(Prefix || structuredDataHash(Domain) || structuredDataHash(CV))`.
348351

349-
- Prefix = `0xC0` (constant value)
352+
- Prefix = `0x534950303138` (constant value)
350353
- Domain =
351354
`tupleCV({"name": asciiCV("Test App"), "version": asciiCV("1.0.0"), "chain-id": uintCV(1)})`
352355
- CV = `asciiCV("Hello World")`
353356
- Message hash:
354-
`c6ace1349f59b024dec0925df0a15baf8d27fc43a357ce61f48fdc8fa461e7b9`
357+
`1bfdab6d4158313ce34073fbb8d6b0fc32c154d439def12247a0f44bb2225259`
355358

356359
## Message signing
357360

@@ -369,15 +372,15 @@ And the following inputs to obtain the message hash for signing:
369372
`tupleCV({"name": asciiCV("Test App"), "version": asciiCV("1.0.0"), "chain-id": uintCV(1)})`
370373
- CV = `asciiCV("Hello World")`
371374
- (Message hash:
372-
`c6ace1349f59b024dec0925df0a15baf8d27fc43a357ce61f48fdc8fa461e7b9`)
375+
`1bfdab6d4158313ce34073fbb8d6b0fc32c154d439def12247a0f44bb2225259`)
373376

374377
Produces the following signature:
375378

376-
- `fd1c62aae1b12c07571d6c7e379a20c3858005877306914da80ae6ee8c748a6d133fcd9169cac5684fe635a5a375960827bf2184849f6cde6ed828b370c72d1b00`
379+
- `8b94e45701d857c9f1d1d70e8b2ca076045dae4920fb0160be0642a68cd78de072ab527b5c5277a593baeb2a8b657c216b99f7abb5d14af35b4bf12ba6460ba401`
377380

378381
Which can be verified in Clarity:
379382

380383
```clarity
381-
(secp256k1-verify 0xc6ace1349f59b024dec0925df0a15baf8d27fc43a357ce61f48fdc8fa461e7b9 0xfd1c62aae1b12c07571d6c7e379a20c3858005877306914da80ae6ee8c748a6d133fcd9169cac5684fe635a5a375960827bf2184849f6cde6ed828b370c72d1b00 0x0390a5cac7c33fda49f70bc1b0866fa0ba7a9440d9de647fecb8132ceb76a94dfa)
384+
(secp256k1-verify 0x1bfdab6d4158313ce34073fbb8d6b0fc32c154d439def12247a0f44bb2225259 0x8b94e45701d857c9f1d1d70e8b2ca076045dae4920fb0160be0642a68cd78de072ab527b5c5277a593baeb2a8b657c216b99f7abb5d14af35b4bf12ba6460ba401 0x0390a5cac7c33fda49f70bc1b0866fa0ba7a9440d9de647fecb8132ceb76a94dfa)
382385
true
383386
```

0 commit comments

Comments
 (0)