hash.go raw

   1  // Copyright (c) 2013-2016 The btcsuite developers
   2  // Copyright (c) 2015 The Decred developers
   3  // Use of this source code is governed by an ISC
   4  // license that can be found in the LICENSE file.
   5  
   6  package chainhash
   7  
   8  import (
   9  	"crypto/sha256"
  10  	"encoding/hex"
  11  	"encoding/json"
  12  	"fmt"
  13  )
  14  
  15  // HashSize of array used to store hashes.  See Hash.
  16  const HashSize = 32
  17  
  18  // MaxHashStringSize is the maximum length of a Hash hash string.
  19  const MaxHashStringSize = HashSize * 2
  20  
  21  var (
  22  	// TagBIP0340Challenge is the BIP-0340 tag for challenges.
  23  	TagBIP0340Challenge = []byte("BIP0340/challenge")
  24  
  25  	// TagBIP0340Aux is the BIP-0340 tag for aux data.
  26  	TagBIP0340Aux = []byte("BIP0340/aux")
  27  
  28  	// TagBIP0340Nonce is the BIP-0340 tag for nonces.
  29  	TagBIP0340Nonce = []byte("BIP0340/nonce")
  30  
  31  	// TagTapSighash is the tag used by BIP 341 to generate the sighash
  32  	// flags.
  33  	TagTapSighash = []byte("TapSighash")
  34  
  35  	// TagTagTapLeaf is the message tag prefix used to compute the hash
  36  	// digest of a tapscript leaf.
  37  	TagTapLeaf = []byte("TapLeaf")
  38  
  39  	// TagTapBranch is the message tag prefix used to compute the
  40  	// hash digest of two tap leaves into a taproot branch node.
  41  	TagTapBranch = []byte("TapBranch")
  42  
  43  	// TagTapTweak is the message tag prefix used to compute the hash tweak
  44  	// used to enable a public key to commit to the taproot branch root
  45  	// for the witness program.
  46  	TagTapTweak = []byte("TapTweak")
  47  
  48  	// precomputedTags is a map containing the SHA-256 hash of the BIP-0340
  49  	// tags.
  50  	precomputedTags = map[string]Hash{
  51  		string(TagBIP0340Challenge): sha256.Sum256(TagBIP0340Challenge),
  52  		string(TagBIP0340Aux):       sha256.Sum256(TagBIP0340Aux),
  53  		string(TagBIP0340Nonce):     sha256.Sum256(TagBIP0340Nonce),
  54  		string(TagTapSighash):       sha256.Sum256(TagTapSighash),
  55  		string(TagTapLeaf):          sha256.Sum256(TagTapLeaf),
  56  		string(TagTapBranch):        sha256.Sum256(TagTapBranch),
  57  		string(TagTapTweak):         sha256.Sum256(TagTapTweak),
  58  	}
  59  )
  60  
  61  // ErrHashStrSize describes an error that indicates the caller specified a hash
  62  // string that has too many characters.
  63  var ErrHashStrSize = fmt.Errorf("max hash string length is %v bytes", MaxHashStringSize)
  64  
  65  // ErrHashStrSizeMismatch describes an error that indicates the caller
  66  // specified a hash string that does not meet the exact length required for
  67  // strict parsing.
  68  var ErrHashStrSizeMismatch = fmt.Errorf("hash string must be exactly %d "+
  69  	"characters", MaxHashStringSize)
  70  
  71  // Hash is used in several of the bitcoin messages and common structures.  It
  72  // typically represents the double sha256 of data.
  73  type Hash [HashSize]byte
  74  
  75  // String returns the Hash as the hexadecimal string of the byte-reversed
  76  // hash.
  77  func (hash Hash) String() string {
  78  	for i := 0; i < HashSize/2; i++ {
  79  		hash[i], hash[HashSize-1-i] = hash[HashSize-1-i], hash[i]
  80  	}
  81  	return hex.EncodeToString(hash[:])
  82  }
  83  
  84  // CloneBytes returns a copy of the bytes which represent the hash as a byte
  85  // slice.
  86  //
  87  // NOTE: It is generally cheaper to just slice the hash directly thereby reusing
  88  // the same bytes rather than calling this method.
  89  func (hash *Hash) CloneBytes() []byte {
  90  	newHash := make([]byte, HashSize)
  91  	copy(newHash, hash[:])
  92  
  93  	return newHash
  94  }
  95  
  96  // SetBytes sets the bytes which represent the hash.  An error is returned if
  97  // the number of bytes passed in is not HashSize.
  98  func (hash *Hash) SetBytes(newHash []byte) error {
  99  	nhlen := len(newHash)
 100  	if nhlen != HashSize {
 101  		return fmt.Errorf("invalid hash length of %v, want %v", nhlen,
 102  			HashSize)
 103  	}
 104  	copy(hash[:], newHash)
 105  
 106  	return nil
 107  }
 108  
 109  // IsEqual returns true if target is the same as hash.
 110  func (hash *Hash) IsEqual(target *Hash) bool {
 111  	if hash == nil && target == nil {
 112  		return true
 113  	}
 114  	if hash == nil || target == nil {
 115  		return false
 116  	}
 117  	return *hash == *target
 118  }
 119  
 120  // MarshalJSON serialises the hash as a JSON appropriate string value.
 121  func (hash Hash) MarshalJSON() ([]byte, error) {
 122  	return json.Marshal(hash.String())
 123  }
 124  
 125  // UnmarshalJSON parses the hash with JSON appropriate string value.
 126  func (hash *Hash) UnmarshalJSON(input []byte) error {
 127  	// If the first byte indicates an array, the hash could have been marshalled
 128  	// using the legacy method and e.g. persisted.
 129  	if len(input) > 0 && input[0] == '[' {
 130  		return decodeLegacy(hash, input)
 131  	}
 132  
 133  	var sh string
 134  	err := json.Unmarshal(input, &sh)
 135  	if err != nil {
 136  		return err
 137  	}
 138  	newHash, err := NewHashFromStr(sh)
 139  	if err != nil {
 140  		return err
 141  	}
 142  
 143  	return hash.SetBytes(newHash[:])
 144  }
 145  
 146  // NewHash returns a new Hash from a byte slice.  An error is returned if
 147  // the number of bytes passed in is not HashSize.
 148  func NewHash(newHash []byte) (*Hash, error) {
 149  	var sh Hash
 150  	err := sh.SetBytes(newHash)
 151  	if err != nil {
 152  		return nil, err
 153  	}
 154  	return &sh, err
 155  }
 156  
 157  // TaggedHash implements the tagged hash scheme described in BIP-340. We use
 158  // sha-256 to bind a message hash to a specific context using a tag:
 159  // sha256(sha256(tag) || sha256(tag) || msg).
 160  func TaggedHash(tag []byte, msgs ...[]byte) *Hash {
 161  	// Check to see if we've already pre-computed the hash of the tag. If
 162  	// so then this'll save us an extra sha256 hash.
 163  	shaTag, ok := precomputedTags[string(tag)]
 164  	if !ok {
 165  		shaTag = sha256.Sum256(tag)
 166  	}
 167  
 168  	// h = sha256(sha256(tag) || sha256(tag) || msg)
 169  	h := sha256.New()
 170  	h.Write(shaTag[:])
 171  	h.Write(shaTag[:])
 172  
 173  	for _, msg := range msgs {
 174  		h.Write(msg)
 175  	}
 176  
 177  	taggedHash := h.Sum(nil)
 178  
 179  	// The function can't error out since the above hash is guaranteed to
 180  	// be 32 bytes.
 181  	hash, _ := NewHash(taggedHash)
 182  
 183  	return hash
 184  }
 185  
 186  // NewHashFromStr creates a Hash from a hash string.  The string should be
 187  // the hexadecimal string of a byte-reversed hash, but any missing characters
 188  // result in zero padding at the end of the Hash.
 189  //
 190  // NOTE: This function accepts short and odd-length hex strings and pads them.
 191  // Typical parsing of full txids or block hashes should use NewHashFromStrStrict
 192  // instead.
 193  func NewHashFromStr(hash string) (*Hash, error) {
 194  	ret := new(Hash)
 195  	err := Decode(ret, hash)
 196  	if err != nil {
 197  		return nil, err
 198  	}
 199  	return ret, nil
 200  }
 201  
 202  // NewHashFromStrStrict creates a Hash from a hash string.  The string must be
 203  // the full hexadecimal string of a byte-reversed hash.
 204  func NewHashFromStrStrict(hash string) (*Hash, error) {
 205  	ret := new(Hash)
 206  	err := DecodeStrict(ret, hash)
 207  	if err != nil {
 208  		return nil, err
 209  	}
 210  	return ret, nil
 211  }
 212  
 213  // Decode decodes the byte-reversed hexadecimal string encoding of a Hash to a
 214  // destination.
 215  //
 216  // NOTE: This function accepts short and odd-length hex strings and pads them.
 217  // Typical parsing of full txids or block hashes should use DecodeStrict
 218  // instead.
 219  func Decode(dst *Hash, src string) error {
 220  	// Return error if hash string is too long.
 221  	if len(src) > MaxHashStringSize {
 222  		return ErrHashStrSize
 223  	}
 224  
 225  	// Hex decoder expects the hash to be a multiple of two.  When not, pad
 226  	// with a leading zero.
 227  	var srcBytes []byte
 228  	if len(src)%2 == 0 {
 229  		srcBytes = []byte(src)
 230  	} else {
 231  		srcBytes = make([]byte, 1+len(src))
 232  		srcBytes[0] = '0'
 233  		copy(srcBytes[1:], src)
 234  	}
 235  
 236  	return decodeHash(dst, srcBytes)
 237  }
 238  
 239  // DecodeStrict decodes the byte-reversed hexadecimal string encoding of a Hash
 240  // to a destination.  The source string must be exactly MaxHashStringSize
 241  // bytes, or ErrHashStrSizeMismatch is returned.
 242  func DecodeStrict(dst *Hash, src string) error {
 243  	if len(src) != MaxHashStringSize {
 244  		return ErrHashStrSizeMismatch
 245  	}
 246  
 247  	return decodeHash(dst, []byte(src))
 248  }
 249  
 250  // decodeHash decodes the provided byte-reversed hexadecimal bytes into dst.
 251  // The caller is responsible for applying any caller-specific length validation
 252  // before invoking this helper.
 253  func decodeHash(dst *Hash, src []byte) error {
 254  	// Hex decode the source bytes to a temporary destination.
 255  	var reversedHash Hash
 256  	_, err := hex.Decode(reversedHash[HashSize-hex.DecodedLen(len(src)):], src)
 257  	if err != nil {
 258  		return err
 259  	}
 260  
 261  	// Reverse copy from the temporary hash to destination.  Because the
 262  	// temporary was zeroed, the written result will be correctly padded.
 263  	for i, b := range reversedHash[:HashSize/2] {
 264  		dst[i], dst[HashSize-1-i] = reversedHash[HashSize-1-i], b
 265  	}
 266  
 267  	return nil
 268  }
 269  
 270  // decodeLegacy decodes an Hash that has been encoded with the legacy method
 271  // (i.e. represented as a bytes array) to a destination.
 272  func decodeLegacy(dst *Hash, src []byte) error {
 273  	var hashBytes []byte
 274  	err := json.Unmarshal(src, &hashBytes)
 275  	if err != nil {
 276  		return err
 277  	}
 278  	if len(hashBytes) != HashSize {
 279  		return ErrHashStrSize
 280  	}
 281  	return dst.SetBytes(hashBytes)
 282  }
 283