Skip to content

Commit

Permalink
Add secp256k1_tagged_sha256 as defined in BIP-340
Browse files Browse the repository at this point in the history
Gives users the ability to hash messages to 32 byte before they are signed while
allowing efficient domain separation through the tag.
  • Loading branch information
jonasnick committed Jun 27, 2021
1 parent b6c0b72 commit 5a8e499
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
25 changes: 25 additions & 0 deletions include/secp256k1.h
Expand Up @@ -793,6 +793,31 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(
size_t n
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Compute a tagged hash as defined in BIP-340.
*
* This is useful for creating a message hash and achieving domain separation
* through an application-specific tag. This function returns
* SHA256(SHA256(tag)||SHA256(tag)||msg). Therefore, tagged hash
* implementations optimized for a specific tag can precompute the SHA256 state
* after hashing the tag hashes.
*
* Returns 0 if the arguments are invalid and 1 otherwise.
* Args: ctx: pointer to a context object
* Out: hash32: pointer to a 32-byte array to store the resulting hash
* In: tag: pointer to an array containing the tag
* taglen: length of the tag array
* msg: pointer to an array containing the message
* msglen: length of the message array
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_tagged_sha256(
const secp256k1_context* ctx,
unsigned char *hash32,
const unsigned char *tag,
size_t taglen,
const unsigned char *msg,
size_t msglen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);

#ifdef __cplusplus
}
#endif
Expand Down
13 changes: 13 additions & 0 deletions src/secp256k1.c
Expand Up @@ -790,6 +790,19 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *
return 1;
}

int secp256k1_tagged_sha256(const secp256k1_context* ctx, unsigned char *hash32, const unsigned char *tag, size_t taglen, const unsigned char *msg, size_t msglen) {
secp256k1_sha256 sha;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(hash32 != NULL);
ARG_CHECK(tag != NULL);
ARG_CHECK(msg != NULL);

secp256k1_sha256_initialize_tagged(&sha, tag, taglen);
secp256k1_sha256_write(&sha, msg, msglen);
secp256k1_sha256_finalize(&sha, hash32);
return 1;
}

#ifdef ENABLE_MODULE_ECDH
# include "modules/ecdh/main_impl.h"
#endif
Expand Down
33 changes: 33 additions & 0 deletions src/tests.c
Expand Up @@ -564,6 +564,38 @@ void run_rfc6979_hmac_sha256_tests(void) {
secp256k1_rfc6979_hmac_sha256_finalize(&rng);
}

void run_tagged_sha256_tests(void) {
int ecount = 0;
secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
unsigned char tag[32] = { 0 };
unsigned char msg[32] = { 0 };
unsigned char hash32[32];
unsigned char hash_expected[32] = {
0x04, 0x7A, 0x5E, 0x17, 0xB5, 0x86, 0x47, 0xC1,
0x3C, 0xC6, 0xEB, 0xC0, 0xAA, 0x58, 0x3B, 0x62,
0xFB, 0x16, 0x43, 0x32, 0x68, 0x77, 0x40, 0x6C,
0xE2, 0x76, 0x55, 0x9A, 0x3B, 0xDE, 0x55, 0xB3
};

secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);

/* API test */
CHECK(secp256k1_tagged_sha256(none, hash32, tag, sizeof(tag), msg, sizeof(msg)) == 1);
CHECK(secp256k1_tagged_sha256(none, NULL, tag, sizeof(tag), msg, sizeof(msg)) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_tagged_sha256(none, hash32, NULL, 0, msg, sizeof(msg)) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_tagged_sha256(none, hash32, tag, sizeof(tag), NULL, 0) == 0);
CHECK(ecount == 3);

/* Static test vector */
memcpy(tag, "tag", 3);
memcpy(msg, "msg", 3);
CHECK(secp256k1_tagged_sha256(none, hash32, tag, 3, msg, 3) == 1);
CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0);
secp256k1_context_destroy(none);
}

/***** RANDOM TESTS *****/

void test_rand_bits(int rand32, int bits) {
Expand Down Expand Up @@ -6505,6 +6537,7 @@ int main(int argc, char **argv) {
run_sha256_tests();
run_hmac_sha256_tests();
run_rfc6979_hmac_sha256_tests();
run_tagged_sha256_tests();

/* scalar tests */
run_scalar_tests();
Expand Down

0 comments on commit 5a8e499

Please sign in to comment.