Tagged Hashes
In the last section we tweaked a key with hash(P || contract).
That plain hash() was a simplification. Taproot never uses a bare SHA256. It always uses a tagged hash.
Tagged hashes are used everywhere in the Taproot and Schnorr specification, so this is the first tool we need.
Why Do We Use Tagged Hashes?
Their purpose is to ensure that hashes used in one context can't be used in another.
This means that if you hash the same data in a different context, you won't get the same hash result.
That matters because Taproot hashes a lot of similar-looking things. A leaf, a branch, a tweak and a signature challenge are all 32 bytes of data going into SHA256. Without tags, a hash made for one job could be replayed as another.
How Do Tagged Hashes Work?
Creating tagged hashes is straightforward and involves two steps:
- Prefix the data you want to hash with the tag
tag = sha256(TagName) || sha256(TagName). - Hash as normal:
tagged_hash("TagName", data) = sha256(tag + data).
Why is the tag hashed twice ?
You might wonder why the tag is repeated in step 3: (Repeat tag_hash).
It's a speed trick.
sha256(TagName)is 32 bytes- Repeating it gives 64 bytes
- A SHA256 block is also 64 bytes
So tag || tag fills exactly one block. The tag never changes, so an implementation can compute that first block once, save the internal state, and start every tagged hash from there.
The BIP340 specification makes the same point: the doubled tag is a fixed 64-byte constant matching the SHA256 block size, so optimized implementations can run as plain SHA256 with a modified initial state.
Programming Exercise: Implement a tagged hash function
Complete the implementation of the tagged_hash function in Python.
Solution code
The tags used in Taproot
Every tag belongs to a specific BIP. Keeping that straight will save you a lot of confusion later.
BIP340: Schnorr signatures
| tag | where you'll meet it |
|---|---|
BIP0340/aux | nonce generation |
BIP0340/nonce | nonce generation |
BIP0340/challenge | the e in s = k + e·d |
BIP341: Taproot
| tag | where you'll meet it |
|---|---|
TapTweak | The Taproot Tweak |
TapLeaf | The Script Tree |
TapBranch | The Script Tree |
TapSighash | The Signature Message |
Notice how many of them there are. That's the reason tagging exists: TapLeaf and TapBranch both hash 32 byte values inside the same tree, and the tag is the only thing keeping them apart.
Don't worry if you're still confused, we'll explore where each of these tags is used in the following chapters.
