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  }