github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/btc/hash.go (about)

     1  package btc
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/sha256"
     6  	"encoding"
     7  	"github.com/piotrnar/gocoin/lib/others/ripemd160"
     8  	"hash"
     9  )
    10  
    11  const (
    12  	HASHER_TAPSIGHASH = 0
    13  	HASHER_TAPLEAF    = 1
    14  	HASHER_TAPBRANCH  = 2
    15  	HASHER_TAPTWEAK   = 3
    16  )
    17  
    18  var (
    19  	hash_tags = []string{"TapSighash", "TapLeaf", "TapBranch", "TapTweak"}
    20  	hashers [HASHER_TAPTWEAK + 1][]byte
    21  )
    22  
    23  func _TaggedHash(tag string) hash.Hash {
    24  	sha := sha256.New()
    25  	sha.Write([]byte(tag))
    26  	taghash := sha.Sum(nil)
    27  	sha.Reset()
    28  	sha.Write(taghash)
    29  	sha.Write(taghash)
    30  	return sha
    31  }
    32  
    33  func Hasher(idx int) hash.Hash {
    34  	s := sha256.New()
    35  	unmarshaler, _ := s.(encoding.BinaryUnmarshaler)
    36  	unmarshaler.UnmarshalBinary(hashers[idx])
    37  	return s
    38  }
    39  
    40  func init() {
    41  	for i, t := range hash_tags {
    42  		sha := _TaggedHash(t)
    43  		marshaler, _ := sha.(encoding.BinaryMarshaler)
    44  		hashers[i], _ = marshaler.MarshalBinary()
    45  	}
    46  }
    47  
    48  func ShaHash(b []byte, out []byte) {
    49  	s := sha256.New()
    50  	s.Write(b[:])
    51  	tmp := s.Sum(nil)
    52  	s.Reset()
    53  	s.Write(tmp)
    54  	copy(out[:], s.Sum(nil))
    55  }
    56  
    57  // Sha2Sum returns hash: SHA256( SHA256( data ) ).
    58  // Where possible, using ShaHash() should be a bit faster.
    59  func Sha2Sum(b []byte) (out [32]byte) {
    60  	ShaHash(b, out[:])
    61  	return
    62  }
    63  
    64  func RimpHash(in []byte, out []byte) {
    65  	sha := sha256.New()
    66  	sha.Write(in)
    67  	rim := ripemd160.New()
    68  	rim.Write(sha.Sum(nil)[:])
    69  	copy(out, rim.Sum(nil))
    70  }
    71  
    72  // Rimp160AfterSha256 returns hash: RIMP160( SHA256( data ) ).
    73  // Where possible, using RimpHash() should be a bit faster.
    74  func Rimp160AfterSha256(b []byte) (out [20]byte) {
    75  	RimpHash(b, out[:])
    76  	return
    77  }
    78  
    79  // HashFromMessage is used to sign and verify messages using the Bitcoin standard.
    80  // The second parameter must point to a 32-bytes buffer, where the hash will be stored.
    81  func HashFromMessage(msg []byte, out []byte) {
    82  	b := new(bytes.Buffer)
    83  	WriteVlen(b, uint64(len(MessageMagic)))
    84  	b.Write([]byte(MessageMagic))
    85  	WriteVlen(b, uint64(len(msg)))
    86  	b.Write(msg)
    87  	ShaHash(b.Bytes(), out)
    88  }