hash: add midstate initializer and use it for tagged hashes
What changed, and why it matters
This commit is a straightforward internal cleanup: it introduces a helper function to set up SHA-256 hash states that have already been partially computed (so-called 'midstates') and replaces repeated manual setup code with calls to that helper. It does not change any cryptographic outputs, add new features, or fix a bug. It is not a security patch.
No security action required. Treat as normal code-quality refactor during review.
Security signals we found
No vulnerability signals present
Refactor only: identical midstate constants and byte counts retained
Helper adds defensive VERIFY_CHECK for byte alignment and non-null state pointer
Evidence from the diff
The change adds secp256k1_sha256_initialize_midstate() in src/hash.h and src/hash_impl.h, documents the requirement that the byte counter must be a multiple of 64, and converts all tagged-hash midstate initializers in schnorrsig, musig, and ellswift to use this helper. The helper includes VERIFY_CHECK guards for alignment and non-null state. A new test verifies the helper against the existing tagged-hash test path. The refactor is behavior-preserving: the same constant state values and byte counts are used, just packaged into a const array and passed through a single function.
Changed components
src/hash.hsrc/hash_impl.hsrc/modules/ellswift/main_impl.hsrc/modules/musig/keyagg_impl.hsrc/modules/musig/session_impl.hsrc/modules/schnorrsig/main_impl.hsrc/tests.cInspect captured patch +80 / −118
diff --git a/src/hash.h b/src/hash.h
index 6d903ca..43cdd60 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -17,6 +17,10 @@ typedef struct {
} secp256k1_sha256;
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash);
+/* Initialize a SHA256 hash state with a precomputed midstate.
+ * The byte counter must be a multiple of 64, i.e., there must be no unwritten
+ * bytes in the buffer. */
+static void secp256k1_sha256_initialize_midstate(secp256k1_sha256 *hash, uint64_t bytes, const uint32_t state[8]);
static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size);
static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32);
static void secp256k1_sha256_clear(secp256k1_sha256 *hash);
diff --git a/src/hash_impl.h b/src/hash_impl.h
index 4341917..da3b466 100644
--- a/src/hash_impl.h
+++ b/src/hash_impl.h
@@ -40,6 +40,13 @@ static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) {
hash->bytes = 0;
}
+static void secp256k1_sha256_initialize_midstate(secp256k1_sha256 *hash, uint64_t bytes, const uint32_t state[8]) {
+ VERIFY_CHECK((bytes & 0x3F) == 0);
+ VERIFY_CHECK(state != NULL);
+ memcpy(hash->s, state, sizeof(hash->s));
+ hash->bytes = bytes;
+}
+
/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */
static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* buf) {
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h
index 096f4a3..2a37825 100644
--- a/src/modules/ellswift/main_impl.h
+++ b/src/modules/ellswift/main_impl.h
@@ -383,17 +383,11 @@ static void secp256k1_ellswift_elligatorswift_var(unsigned char *u32, secp256k1_
/** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_encode". */
static void secp256k1_ellswift_sha256_init_encode(secp256k1_sha256* hash) {
- secp256k1_sha256_initialize(hash);
- hash->s[0] = 0xd1a6524bul;
- hash->s[1] = 0x028594b3ul;
- hash->s[2] = 0x96e42f4eul;
- hash->s[3] = 0x1037a177ul;
- hash->s[4] = 0x1b8fcb8bul;
- hash->s[5] = 0x56023885ul;
- hash->s[6] = 0x2560ede1ul;
- hash->s[7] = 0xd626b715ul;
-
- hash->bytes = 64;
+ static const uint32_t midstate[8] = {
+ 0xd1a6524bul, 0x028594b3ul, 0x96e42f4eul, 0x1037a177ul,
+ 0x1b8fcb8bul, 0x56023885ul, 0x2560ede1ul, 0xd626b715ul
+ };
+ secp256k1_sha256_initialize_midstate(hash, 64, midstate);
}
int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64, const secp256k1_pubkey *pubkey, const unsigned char *rnd32) {
@@ -427,17 +421,11 @@ int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64
/** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_create". */
static void secp256k1_ellswift_sha256_init_create(secp256k1_sha256* hash) {
- secp256k1_sha256_initialize(hash);
- hash->s[0] = 0xd29e1bf5ul;
- hash->s[1] = 0xf7025f42ul;
- hash->s[2] = 0x9b024773ul;
- hash->s[3] = 0x094cb7d5ul;
- hash->s[4] = 0xe59ed789ul;
- hash->s[5] = 0x03bc9786ul;
- hash->s[6] = 0x68335b35ul;
- hash->s[7] = 0x4e363b53ul;
-
- hash->bytes = 64;
+ static const uint32_t midstate[8] = {
+ 0xd29e1bf5ul, 0xf7025f42ul, 0x9b024773ul, 0x094cb7d5ul,
+ 0xe59ed789ul, 0x03bc9786ul, 0x68335b35ul, 0x4e363b53ul
+ };
+ secp256k1_sha256_initialize_midstate(hash, 64, midstate);
}
int secp256k1_ellswift_create(const secp256k1_context *ctx, unsigned char *ell64, const unsigned char *seckey32, const unsigned char *auxrnd32) {
@@ -510,17 +498,11 @@ static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsign
/** Set hash state to the BIP340 tagged hash midstate for "bip324_ellswift_xonly_ecdh". */
static void secp256k1_ellswift_sha256_init_bip324(secp256k1_sha256* hash) {
- secp256k1_sha256_initialize(hash);
- hash->s[0] = 0x8c12d730ul;
- hash->s[1] = 0x827bd392ul;
- hash->s[2] = 0x9e4fb2eeul;
- hash->s[3] = 0x207b373eul;
- hash->s[4] = 0x2292bd7aul;
- hash->s[5] = 0xaa5441bcul;
- hash->s[6] = 0x15c3779ful;
- hash->s[7] = 0xcfb52549ul;
-
- hash->bytes = 64;
+ static const uint32_t midstate[8] = {
+ 0x8c12d730ul, 0x827bd392ul, 0x9e4fb2eeul, 0x207b373eul,
+ 0x2292bd7aul, 0xaa5441bcul, 0x15c3779ful, 0xcfb52549ul
+ };
+ secp256k1_sha256_initialize_midstate(hash, 64, midstate);
}
static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) {
diff --git a/src/modules/musig/keyagg_impl.h b/src/modules/musig/keyagg_impl.h
index e412a27..4eb48dd 100644
--- a/src/modules/musig/keyagg_impl.h
+++ b/src/modules/musig/keyagg_impl.h
@@ -62,17 +62,11 @@ static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_k
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("KeyAgg list")||SHA256("KeyAgg list"). */
static void secp256k1_musig_keyagglist_sha256(secp256k1_sha256 *sha) {
- secp256k1_sha256_initialize(sha);
-
- sha->s[0] = 0xb399d5e0ul;
- sha->s[1] = 0xc8fff302ul;
- sha->s[2] = 0x6badac71ul;
- sha->s[3] = 0x07c5b7f1ul;
- sha->s[4] = 0x9701e2eful;
- sha->s[5] = 0x2a72ecf8ul;
- sha->s[6] = 0x201a4c7bul;
- sha->s[7] = 0xab148a38ul;
- sha->bytes = 64;
+ static const uint32_t midstate[8] = {
+ 0xb399d5e0ul, 0xc8fff302ul, 0x6badac71ul, 0x07c5b7f1ul,
+ 0x9701e2eful, 0x2a72ecf8ul, 0x201a4c7bul, 0xab148a38ul
+ };
+ secp256k1_sha256_initialize_midstate(sha, 64, midstate);
}
/* Computes pks_hash = tagged_hash(pk[0], ..., pk[np-1]) */
@@ -97,17 +91,11 @@ static int secp256k1_musig_compute_pks_hash(const secp256k1_context *ctx, unsign
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("KeyAgg coefficient")||SHA256("KeyAgg coefficient"). */
static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) {
- secp256k1_sha256_initialize(sha);
-
- sha->s[0] = 0x6ef02c5aul;
- sha->s[1] = 0x06a480deul;
- sha->s[2] = 0x1f298665ul;
- sha->s[3] = 0x1d1134f2ul;
- sha->s[4] = 0x56a0b063ul;
- sha->s[5] = 0x52da4147ul;
- sha->s[6] = 0xf280d9d4ul;
- sha->s[7] = 0x4484be15ul;
- sha->bytes = 64;
+ static const uint32_t midstate[8] = {
+ 0x6ef02c5aul, 0x06a480deul, 0x1f298665ul, 0x1d1134f2ul,
+ 0x56a0b063ul, 0x52da4147ul, 0xf280d9d4ul, 0x4484be15ul
+ };
+ secp256k1_sha256_initialize_midstate(sha, 64, midstate);
}
/* Compute KeyAgg coefficient which is constant 1 for the second pubkey and
diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h
index 05c9631..42fcd81 100644
--- a/src/modules/musig/session_impl.h
+++ b/src/modules/musig/session_impl.h
@@ -309,31 +309,21 @@ static void secp256k1_nonce_function_musig_helper(secp256k1_sha256 *sha, unsigne
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("MuSig/aux")||SHA256("MuSig/aux"). */
static void secp256k1_nonce_function_musig_sha256_tagged_aux(secp256k1_sha256 *sha) {
- secp256k1_sha256_initialize(sha);
- sha->s[0] = 0xa19e884bul;
- sha->s[1] = 0xf463fe7eul;
- sha->s[2] = 0x2f18f9a2ul;
- sha->s[3] = 0xbeb0f9fful;
- sha->s[4] = 0x0f37e8b0ul;
- sha->s[5] = 0x06ebd26ful;
- sha->s[6] = 0xe3b243d2ul;
- sha->s[7] = 0x522fb150ul;
- sha->bytes = 64;
+ static const uint32_t midstate[8] = {
+ 0xa19e884bul, 0xf463fe7eul, 0x2f18f9a2ul, 0xbeb0f9fful,
+ 0x0f37e8b0ul, 0x06ebd26ful, 0xe3b243d2ul, 0x522fb150ul
+ };
+ secp256k1_sha256_initialize_midstate(sha, 64, midstate);
}
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("MuSig/nonce")||SHA256("MuSig/nonce"). */
static void secp256k1_nonce_function_musig_sha256_tagged(secp256k1_sha256 *sha) {
- secp256k1_sha256_initialize(sha);
- sha->s[0] = 0x07101b64ul;
- sha->s[1] = 0x18003414ul;
- sha->s[2] = 0x0391bc43ul;
- sha->s[3] = 0x0e6258eeul;
- sha->s[4] = 0x29d26b72ul;
- sha->s[5] = 0x8343937eul;
- sha->s[6] = 0xb7a0a4fbul;
- sha->s[7] = 0xff568a30ul;
- sha->bytes = 64;
+ static const uint32_t midstate[8] = {
+ 0x07101b64ul, 0x18003414ul, 0x0391bc43ul, 0x0e6258eeul,
+ 0x29d26b72ul, 0x8343937eul, 0xb7a0a4fbul, 0xff568a30ul
+ };
+ secp256k1_sha256_initialize_midstate(sha, 64, midstate);
}
static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned char *session_secrand, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) {
@@ -543,16 +533,11 @@ int secp256k1_musig_nonce_agg(const secp256k1_context* ctx, secp256k1_musig_aggn
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("MuSig/noncecoef")||SHA256("MuSig/noncecoef"). */
static void secp256k1_musig_compute_noncehash_sha256_tagged(secp256k1_sha256 *sha) {
- secp256k1_sha256_initialize(sha);
- sha->s[0] = 0x2c7d5a45ul;
- sha->s[1] = 0x06bf7e53ul;
- sha->s[2] = 0x89be68a6ul;
- sha->s[3] = 0x971254c0ul;
- sha->s[4] = 0x60ac12d2ul;
- sha->s[5] = 0x72846dcdul;
- sha->s[6] = 0x6c81212ful;
- sha->s[7] = 0xde7a2500ul;
- sha->bytes = 64;
+ static const uint32_t midstate[8] = {
+ 0x2c7d5a45ul, 0x06bf7e53ul, 0x89be68a6ul, 0x971254c0ul,
+ 0x60ac12d2ul, 0x72846dcdul, 0x6c81212ful, 0xde7a2500ul
+ };
+ secp256k1_sha256_initialize_midstate(sha, 64, midstate);
}
/* tagged_hash(aggnonce[0], aggnonce[1], agg_pk, msg) */
diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h
index b410b19..21c1f41 100644
--- a/src/modules/schnorrsig/main_impl.h
+++ b/src/modules/schnorrsig/main_impl.h
@@ -14,33 +14,21 @@
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("BIP0340/nonce")||SHA256("BIP0340/nonce"). */
static void secp256k1_nonce_function_bip340_sha256_tagged(secp256k1_sha256 *sha) {
- secp256k1_sha256_initialize(sha);
- sha->s[0] = 0x46615b35ul;
- sha->s[1] = 0xf4bfbff7ul;
- sha->s[2] = 0x9f8dc671ul;
- sha->s[3] = 0x83627ab3ul;
- sha->s[4] = 0x60217180ul;
- sha->s[5] = 0x57358661ul;
- sha->s[6] = 0x21a29e54ul;
- sha->s[7] = 0x68b07b4cul;
-
- sha->bytes = 64;
+ static const uint32_t midstate[8] = {
+ 0x46615b35ul, 0xf4bfbff7ul, 0x9f8dc671ul, 0x83627ab3ul,
+ 0x60217180ul, 0x57358661ul, 0x21a29e54ul, 0x68b07b4cul
+ };
+ secp256k1_sha256_initialize_midstate(sha, 64, midstate);
}
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("BIP0340/aux")||SHA256("BIP0340/aux"). */
static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 *sha) {
- secp256k1_sha256_initialize(sha);
- sha->s[0] = 0x24dd3219ul;
- sha->s[1] = 0x4eba7e70ul;
- sha->s[2] = 0xca0fabb9ul;
- sha->s[3] = 0x0fa3166dul;
- sha->s[4] = 0x3afbe4b1ul;
- sha->s[5] = 0x4c44df97ul;
- sha->s[6] = 0x4aac2739ul;
- sha->s[7] = 0x249e850aul;
-
- sha->bytes = 64;
+ static const uint32_t midstate[8] = {
+ 0x24dd3219ul, 0x4eba7e70ul, 0xca0fabb9ul, 0x0fa3166dul,
+ 0x3afbe4b1ul, 0x4c44df97ul, 0x4aac2739ul, 0x249e850aul
+ };
+ secp256k1_sha256_initialize_midstate(sha, 64, midstate);
}
/* algo argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340
@@ -104,16 +92,11 @@ const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_
/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
* SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */
static void secp256k1_schnorrsig_sha256_tagged(secp256k1_sha256 *sha) {
- secp256k1_sha256_initialize(sha);
- sha->s[0] = 0x9cecba11ul;
- sha->s[1] = 0x23925381ul;
- sha->s[2] = 0x11679112ul;
- sha->s[3] = 0xd1627e0ful;
- sha->s[4] = 0x97c87550ul;
- sha->s[5] = 0x003cc765ul;
- sha->s[6] = 0x90f61164ul;
- sha->s[7] = 0x33e9b66aul;
- sha->bytes = 64;
+ static const uint32_t midstate[8] = {
+ 0x9cecba11ul, 0x23925381ul, 0x11679112ul, 0xd1627e0ful,
+ 0x97c87550ul, 0x003cc765ul, 0x90f61164ul, 0x33e9b66aul
+ };
+ secp256k1_sha256_initialize_midstate(sha, 64, midstate);
}
static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32)
diff --git a/src/tests.c b/src/tests.c
index e09f5c7..2e85579 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -739,6 +739,19 @@ static void run_tagged_sha256_tests(void) {
CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0);
}
+static void run_sha256_initialize_midstate_tests(void) {
+ /* Midstate for the tagged hash with tag "sha256_midstate_test_tag". */
+ static const unsigned char tag[] = "sha256_midstate_test_tag";
+ static const uint32_t midstate[8] = {
+ 0xa9ec59eaul, 0x9b4c2ffful, 0x400821e2ul, 0x0dcf3847ul,
+ 0xbe7ea179ul, 0xa5772bdcul, 0x7d29bfe3ul, 0xa486b855ul
+ };
+ secp256k1_sha256 sha;
+
+ secp256k1_sha256_initialize_midstate(&sha, 64, midstate);
+ test_sha256_tag_midstate(&sha, tag, sizeof(tag) - 1);
+}
+
/***** MODINV TESTS *****/
/* Compute the modular inverse of (odd) x mod 2^64. */
@@ -7709,6 +7722,7 @@ static const struct tf_test_entry tests_hash[] = {
CASE(hmac_sha256_tests),
CASE(rfc6979_hmac_sha256_tests),
CASE(tagged_sha256_tests),
+ CASE(sha256_initialize_midstate_tests),
};
static const struct tf_test_entry tests_scalar[] = {
@@ -7848,4 +7862,3 @@ int main(int argc, char **argv) {
if (tf_init(&tf, argc, argv) != 0) return EXIT_FAILURE;
return tf_run(&tf);
}
-
Why this scored 14/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.