From 06f46776fb4623271d970458b021d8d87edc99ff Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 4 Dec 2021 16:01:16 -0800 Subject: [PATCH] chaincfg: add BIP-340 tagged hash implementation In this commit, we add an implementation of the BIP-340 tagged hash scheme. This initial version can be optimized quite a bit, for example, we can hard code the output of frequently used `sha256(tag)` values and save two `sha256` invocations. --- chaincfg/chainhash/hash.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/chaincfg/chainhash/hash.go b/chaincfg/chainhash/hash.go index 2d38c095..15aef84f 100644 --- a/chaincfg/chainhash/hash.go +++ b/chaincfg/chainhash/hash.go @@ -6,6 +6,7 @@ package chainhash import ( + "crypto/sha256" "encoding/binary" "encoding/hex" "encoding/json" @@ -103,6 +104,32 @@ func NewHash(newHash []byte) (*Hash, error) { return &sh, err } +// TaggedHash implements the tagged hash scheme described in BIP-340. We use +// sha-256 to bind a message hash to a specific context using a tag: +// sha256(sha256(tag) || sha256(tag) || msg). +// +// TODO(roasbeef): add fast paths for common known tags +func TaggedHash(tag []byte, msgs ...[]byte) *Hash { + shaTag := sha256.Sum256(tag) + + // h = sha256(sha256(tag) || sha256(tag) || msg) + h := sha256.New() + h.Write(shaTag[:]) + h.Write(shaTag[:]) + + for _, msg := range msgs { + h.Write(msg) + } + + taggedHash := h.Sum(nil) + + // The function can't error out since the above hash is guaranteed to + // be 32 bytes. + hash, _ := NewHash(taggedHash) + + return hash +} + // NewHashFromStr creates a Hash from a hash string. The string should be // the hexadecimal string of a byte-reversed hash, but any missing characters // result in zero padding at the end of the Hash.