Skip to content

Commit

Permalink
Merge pull request #106 from kcalvinalvin/2024-01-08-bip340
Browse files Browse the repository at this point in the history
chaincfg: bip340
  • Loading branch information
kcalvinalvin authored Jan 8, 2024
2 parents 2a7760b + 35d5c46 commit 69a9e5f
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions chaincfg/chainhash/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package chainhash

import (
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"encoding/json"
Expand All @@ -19,6 +20,25 @@ const HashSize = 32
// MaxHashStringSize is the maximum length of a Hash hash string.
const MaxHashStringSize = HashSize * 2

var (
// TagBIP0340Challenge is the BIP-0340 tag for challenges.
TagBIP0340Challenge = []byte("BIP0340/challenge")

// TagBIP0340Aux is the BIP-0340 tag for aux data.
TagBIP0340Aux = []byte("BIP0340/aux")

// TagBIP0340Nonce is the BIP-0340 tag for nonces.
TagBIP0340Nonce = []byte("BIP0340/nonce")

// precomputedTags is a map containing the SHA-256 hash of the BIP-0340
// tags.
precomputedTags = map[string]Hash{
string(TagBIP0340Challenge): sha256.Sum256(TagBIP0340Challenge),
string(TagBIP0340Aux): sha256.Sum256(TagBIP0340Aux),
string(TagBIP0340Nonce): sha256.Sum256(TagBIP0340Nonce),
}
)

// ErrHashStrSize describes an error that indicates the caller specified a hash
// string that has too many characters.
var ErrHashStrSize = fmt.Errorf("max hash string length is %v bytes", MaxHashStringSize)
Expand Down Expand Up @@ -103,6 +123,35 @@ 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).
func TaggedHash(tag []byte, msgs ...[]byte) *Hash {
// Check to see if we've already pre-computed the hash of the tag. If
// so then this'll save us an extra sha256 hash.
shaTag, ok := precomputedTags[string(tag)]
if !ok {
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.
Expand Down

0 comments on commit 69a9e5f

Please sign in to comment.