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