Skip to content

Commit f813bb0

Browse files
schnorrsig: Adapt example to new API
1 parent 99e6568 commit f813bb0

File tree

1 file changed

+32
-16
lines changed

1 file changed

+32
-16
lines changed

examples/schnorr.c

+32-16
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,9 @@
1818
#include "random.h"
1919

2020
int main(void) {
21-
/* Instead of signing the message directly, we must sign a 32-byte hash.
22-
* Here the message is "Hello, world!" and the hash function was SHA-256.
23-
* An actual implementation should just call SHA-256, but this example
24-
* hardcodes the output to avoid depending on an additional library. */
25-
unsigned char msg_hash[32] = {
26-
0x31, 0x5F, 0x5B, 0xDB, 0x76, 0xD0, 0x78, 0xC4,
27-
0x3B, 0x8A, 0xC0, 0x06, 0x4E, 0x4A, 0x01, 0x64,
28-
0x61, 0x2B, 0x1F, 0xCE, 0x77, 0xC8, 0x69, 0x34,
29-
0x5B, 0xFC, 0x94, 0xC7, 0x58, 0x94, 0xED, 0xD3,
30-
};
21+
unsigned char msg[12] = "Hello World!";
22+
unsigned char msg_hash[32];
23+
unsigned char tag[17] = "my_fancy_protocol";
3124
unsigned char seckey[32];
3225
unsigned char randomize[32];
3326
unsigned char auxiliary_rand[32];
@@ -84,18 +77,37 @@ int main(void) {
8477

8578
/*** Signing ***/
8679

80+
/* Instead of signing (possibly very long) messages directly, we sign a
81+
* 32-byte hash of the message in this example.
82+
*
83+
* We use secp256k1_tagged_sha256 to create this hash. This function expects
84+
* a context-specific "tag", which restricts the context in which the signed
85+
* messages should be considered valid. For example, if protocol A mandates
86+
* to use the tag "my_fancy_protocol" and protocol B mandates to use the tag
87+
* "my_boring_protocol", then signed messages from protocol A will never be
88+
* valid in protocol B (and vice versa), even if keys are reused across
89+
* protocols. This implements "domain separation", which is considered good
90+
* practice. It avoids attacks in which users are tricked into signing a
91+
* message that has intended consequences in the intended context (e.g.,
92+
* protocol A) but would have unintended consequences if it were valid in
93+
* some other context (e.g., protocol B). */
94+
return_val = secp256k1_tagged_sha256(ctx, msg_hash, tag, sizeof(tag), msg, sizeof(msg));
95+
assert(return_val);
96+
8797
/* Generate 32 bytes of randomness to use with BIP-340 schnorr signing. */
8898
if (!fill_random(auxiliary_rand, sizeof(auxiliary_rand))) {
8999
printf("Failed to generate randomness\n");
90100
return 1;
91101
}
92102

93-
/* Generate a Schnorr signature `noncefp` and `ndata` allows you to pass a
94-
* custom nonce function, passing `NULL` will use the BIP-340 safe default.
95-
* BIP-340 recommends passing 32 bytes of randomness to the nonce function to
96-
* improve security against side-channel attacks. Signing with a valid
97-
* context, verified keypair and the default nonce function should never
98-
* fail. */
103+
/* Generate a Schnorr signature.
104+
*
105+
* We use the secp256k1_schnorrsig_sign32 function that provides a simple
106+
* interface for signing 32-byte messages (which in our case is a hash of
107+
* the actual message). BIP-340 recommends passing 32 bytes of randomness
108+
* to the signing function to improve security against side-channel attacks.
109+
* Signing with a valid context, a 32-byte message, a verified keypair, and
110+
* any 32 bytes of auxiliary random data should never fail. */
99111
return_val = secp256k1_schnorrsig_sign32(ctx, signature, msg_hash, &keypair, auxiliary_rand);
100112
assert(return_val);
101113

@@ -108,6 +120,10 @@ int main(void) {
108120
return 1;
109121
}
110122

123+
/* Compute the tagged hash on the received messages using the same tag as the signer. */
124+
return_val = secp256k1_tagged_sha256(ctx, msg_hash, tag, sizeof(tag), msg, sizeof(msg));
125+
assert(return_val);
126+
111127
/* Verify a signature. This will return 1 if it's valid and 0 if it's not. */
112128
is_signature_valid = secp256k1_schnorrsig_verify(ctx, signature, msg_hash, 32, &pubkey);
113129

0 commit comments

Comments
 (0)