Deterministic Bitcoin addresses from string payloads.
Hash tweak turns a payload into seven non-hardened BIP32 child indexes below a supplied extended public key, then encodes the derived public key as a native SegWit address.
- HMAC-SHA256 keyed with hash-tweak
- first 21 bytes are kept
- seven 3-byte child indexes are derived
- final child public key becomes a P2WPKH address
Hash tweak calculator
Convert a string payload and extended public key into a deterministic native SegWit Bitcoin address.
How hash tweak maps payloads to addresses
The payload is interpreted as a UTF-8 string. The HMAC secret is the fixed string hash-tweak. The first 21 bytes of the HMAC are split into seven consecutive 3-byte groups, each read as an unsigned big-endian integer.
digest = HMAC_SHA256(key="hash-tweak", message=utf8(payload)) tweak = digest[0:21] path = [ uint24be(tweak[0:3]), uint24be(tweak[3:6]), uint24be(tweak[6:9]), uint24be(tweak[9:12]), uint24be(tweak[12:15]), uint24be(tweak[15:18]), uint24be(tweak[18:21]) ] child = extended_public_key / path[0] / path[1] / path[2] / path[3] / path[4] / path[5] / path[6] address = p2wpkh(child.publicKey)
Every child index is between 0 and 16,777,215, so the path is entirely non-hardened and can be derived from the extended public key alone. The calculator reports the path relative to the supplied key because the key does not reveal its full parent path.
Luckotto deposit addresses use this same scheme with a payload that includes the partner site ID, public opaque player identifier, and deposit-address nonce.