github.com/MetalBlockchain/metalgo@v1.11.9/utils/hashing/hashing.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package hashing 5 6 import ( 7 "crypto/sha256" 8 "errors" 9 "fmt" 10 "io" 11 12 "golang.org/x/crypto/ripemd160" 13 ) 14 15 const ( 16 HashLen = sha256.Size 17 AddrLen = ripemd160.Size 18 ) 19 20 var ErrInvalidHashLen = errors.New("invalid hash length") 21 22 // Hash256 A 256 bit long hash value. 23 type Hash256 = [HashLen]byte 24 25 // Hash160 A 160 bit long hash value. 26 type Hash160 = [ripemd160.Size]byte 27 28 // ComputeHash256Array computes a cryptographically strong 256 bit hash of the 29 // input byte slice. 30 func ComputeHash256Array(buf []byte) Hash256 { 31 return sha256.Sum256(buf) 32 } 33 34 // ComputeHash256 computes a cryptographically strong 256 bit hash of the input 35 // byte slice. 36 func ComputeHash256(buf []byte) []byte { 37 arr := ComputeHash256Array(buf) 38 return arr[:] 39 } 40 41 // ComputeHash256Ranges computes a cryptographically strong 256 bit hash of the input 42 // byte slice in the ranges specified. 43 // Example: 44 // ComputeHash256Ranges({1, 2, 4, 8, 16}, {{1, 2}, {3, 5}}) is equivalent to 45 // ComputeHash256({2, 8, 16}). 46 func ComputeHash256Ranges(buf []byte, ranges [][2]int) []byte { 47 hashBuilder := sha256.New() 48 for _, r := range ranges { 49 _, err := hashBuilder.Write(buf[r[0]:r[1]]) 50 if err != nil { 51 panic(err) 52 } 53 } 54 return hashBuilder.Sum(nil) 55 } 56 57 // ComputeHash160Array computes a cryptographically strong 160 bit hash of the 58 // input byte slice. 59 func ComputeHash160Array(buf []byte) Hash160 { 60 h, err := ToHash160(ComputeHash160(buf)) 61 if err != nil { 62 panic(err) 63 } 64 return h 65 } 66 67 // ComputeHash160 computes a cryptographically strong 160 bit hash of the input 68 // byte slice. 69 func ComputeHash160(buf []byte) []byte { 70 ripe := ripemd160.New() 71 _, err := io.Writer(ripe).Write(buf) 72 if err != nil { 73 panic(err) 74 } 75 return ripe.Sum(nil) 76 } 77 78 // Checksum creates a checksum of [length] bytes from the 256 bit hash of the 79 // byte slice. 80 // 81 // Returns: the lower [length] bytes of the hash 82 // Panics if length > 32. 83 func Checksum(bytes []byte, length int) []byte { 84 hash := ComputeHash256Array(bytes) 85 return hash[len(hash)-length:] 86 } 87 88 func ToHash256(bytes []byte) (Hash256, error) { 89 hash := Hash256{} 90 if bytesLen := len(bytes); bytesLen != HashLen { 91 return hash, fmt.Errorf("%w: expected 32 bytes but got %d", ErrInvalidHashLen, bytesLen) 92 } 93 copy(hash[:], bytes) 94 return hash, nil 95 } 96 97 func ToHash160(bytes []byte) (Hash160, error) { 98 hash := Hash160{} 99 if bytesLen := len(bytes); bytesLen != ripemd160.Size { 100 return hash, fmt.Errorf("%w: expected 20 bytes but got %d", ErrInvalidHashLen, bytesLen) 101 } 102 copy(hash[:], bytes) 103 return hash, nil 104 } 105 106 func PubkeyBytesToAddress(key []byte) []byte { 107 return ComputeHash160(ComputeHash256(key)) 108 }