arnaucube
arnaucube/arboPublic Self-hosted repository
arbo/hash.go
hash.goRaw
  1package arbo
  2
  3import (
  4	"crypto/sha256"
  5	"math/big"
  6
  7	"github.com/iden3/go-iden3-crypto/poseidon"
  8	"golang.org/x/crypto/blake2b"
  9)
 10
 11var (
 12	// TypeHashSha256 represents the label for the HashFunction of Sha256
 13	TypeHashSha256 = []byte("sha256")
 14	// TypeHashPoseidon represents the label for the HashFunction of
 15	// Poseidon
 16	TypeHashPoseidon = []byte("poseidon")
 17	// TypeHashBlake2b represents the label for the HashFunction of Blake2b
 18	TypeHashBlake2b = []byte("blake2b")
 19
 20	// HashFunctionSha256 contains the HashSha256 struct which implements
 21	// the HashFunction interface
 22	HashFunctionSha256 HashSha256
 23	// HashFunctionPoseidon contains the HashPoseidon struct which implements
 24	// the HashFunction interface
 25	HashFunctionPoseidon HashPoseidon
 26	// HashFunctionBlake2b contains the HashBlake2b struct which implements
 27	// the HashFunction interface
 28	HashFunctionBlake2b HashBlake2b
 29)
 30
 31// Once Generics are at Go, this will be updated (August 2021
 32// https://blog.golang.org/generics-next-step)
 33
 34// HashFunction defines the interface that is expected for a hash function to be
 35// used in a generic way in the Tree.
 36type HashFunction interface {
 37	Type() []byte
 38	Len() int
 39	Hash(...[]byte) ([]byte, error)
 40	// CheckInput checks if the input is valid without computing the hash
 41	// CheckInput(...[]byte) error
 42}
 43
 44// HashSha256 implements the HashFunction interface for the Sha256 hash
 45type HashSha256 struct{}
 46
 47// Type returns the type of HashFunction for the HashSha256
 48func (f HashSha256) Type() []byte {
 49	return TypeHashSha256
 50}
 51
 52// Len returns the length of the Hash output
 53func (f HashSha256) Len() int {
 54	return 32 //nolint:gomnd
 55}
 56
 57// Hash implements the hash method for the HashFunction HashSha256
 58func (f HashSha256) Hash(b ...[]byte) ([]byte, error) {
 59	var toHash []byte
 60	for i := 0; i < len(b); i++ {
 61		toHash = append(toHash, b[i]...)
 62	}
 63	h := sha256.Sum256(toHash)
 64	return h[:], nil
 65}
 66
 67// HashPoseidon implements the HashFunction interface for the Poseidon hash
 68type HashPoseidon struct{}
 69
 70// Type returns the type of HashFunction for the HashPoseidon
 71func (f HashPoseidon) Type() []byte {
 72	return TypeHashPoseidon
 73}
 74
 75// Len returns the length of the Hash output
 76func (f HashPoseidon) Len() int {
 77	return 32 //nolint:gomnd
 78}
 79
 80// Hash implements the hash method for the HashFunction HashPoseidon. It
 81// expects the byte arrays to be little-endian representations of big.Int
 82// values.
 83func (f HashPoseidon) Hash(b ...[]byte) ([]byte, error) {
 84	var toHash []*big.Int
 85	for i := 0; i < len(b); i++ {
 86		bi := BytesToBigInt(b[i])
 87		toHash = append(toHash, bi)
 88	}
 89	h, err := poseidon.Hash(toHash)
 90	if err != nil {
 91		return nil, err
 92	}
 93	hB := BigIntToBytes(f.Len(), h)
 94	return hB, nil
 95}
 96
 97// HashBlake2b implements the HashFunction interface for the Blake2b hash
 98type HashBlake2b struct{}
 99
100// Type returns the type of HashFunction for the HashBlake2b
101func (f HashBlake2b) Type() []byte {
102	return TypeHashBlake2b
103}
104
105// Len returns the length of the Hash output
106func (f HashBlake2b) Len() int {
107	return 32 //nolint:gomnd
108}
109
110// Hash implements the hash method for the HashFunction HashBlake2b
111func (f HashBlake2b) Hash(b ...[]byte) ([]byte, error) {
112	hasher, err := blake2b.New256(nil)
113	if err != nil {
114		return nil, err
115	}
116	for i := 0; i < len(b); i++ {
117		if _, err = hasher.Write(b[i]); err != nil {
118			return nil, err
119		}
120	}
121	return hasher.Sum(nil), nil
122}