mirror of
https://github.com/arnaucube/arbo.git
synced 2026-01-06 22:11:28 +01:00
Add HashFunction interface (w/ Poseidon & Sha256)
This commit is contained in:
87
hash.go
Normal file
87
hash.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package arbo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/iden3/go-iden3-crypto/poseidon"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// TypeHashSha256 represents the label for the HashFunction of Sha256
|
||||||
|
TypeHashSha256 = []byte("sha256")
|
||||||
|
// TypeHashPoseidon represents the label for the HashFunction of
|
||||||
|
// Poseidon
|
||||||
|
TypeHashPoseidon = []byte("poseidon")
|
||||||
|
|
||||||
|
// HashFunctionSha256 contains the HashSha256 struct which implements
|
||||||
|
// the HashFunction interface
|
||||||
|
HashFunctionSha256 HashSha256
|
||||||
|
// HashFunctionPoseidon contains the HashPoseidon struct which implements
|
||||||
|
// the HashFunction interface
|
||||||
|
HashFunctionPoseidon HashPoseidon
|
||||||
|
)
|
||||||
|
|
||||||
|
// Once Generics are at Go, this will be updated (August 2021
|
||||||
|
// https://blog.golang.org/generics-next-step)
|
||||||
|
|
||||||
|
// HashFunction defines the interface that is expected for a hash function to be
|
||||||
|
// used in a generic way in the Tree.
|
||||||
|
type HashFunction interface {
|
||||||
|
Type() []byte
|
||||||
|
Len() int
|
||||||
|
Hash(...[]byte) ([]byte, error)
|
||||||
|
// CheckInputs checks if the inputs are valid without computing the hash
|
||||||
|
// CheckInputs(...[]byte) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashSha256 implements the HashFunction interface for the Sha256 hash
|
||||||
|
type HashSha256 struct{}
|
||||||
|
|
||||||
|
// Type returns the type of HashFunction for the HashSha256
|
||||||
|
func (f HashSha256) Type() []byte {
|
||||||
|
return TypeHashSha256
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the length of the Hash output
|
||||||
|
func (f HashSha256) Len() int {
|
||||||
|
return 32 //nolint:gomnd
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash implements the hash method for the HashFunction HashSha256
|
||||||
|
func (f HashSha256) Hash(b ...[]byte) ([]byte, error) {
|
||||||
|
var toHash []byte
|
||||||
|
for i := 0; i < len(b); i++ {
|
||||||
|
toHash = append(toHash, b[i]...)
|
||||||
|
}
|
||||||
|
h := sha256.Sum256(toHash)
|
||||||
|
return h[:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashPoseidon implements the HashFunction interface for the Poseidon hash
|
||||||
|
type HashPoseidon struct{}
|
||||||
|
|
||||||
|
// Type returns the type of HashFunction for the HashPoseidon
|
||||||
|
func (f HashPoseidon) Type() []byte {
|
||||||
|
return TypeHashPoseidon
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the length of the Hash output
|
||||||
|
func (f HashPoseidon) Len() int {
|
||||||
|
return 32 //nolint:gomnd
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash implements the hash method for the HashFunction HashPoseidon
|
||||||
|
func (f HashPoseidon) Hash(b ...[]byte) ([]byte, error) {
|
||||||
|
var toHash []*big.Int
|
||||||
|
for i := 0; i < len(b); i++ {
|
||||||
|
bi := BytesToBigInt(b[i])
|
||||||
|
toHash = append(toHash, bi)
|
||||||
|
}
|
||||||
|
h, err := poseidon.Hash(toHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hB := BigIntToBytes(h)
|
||||||
|
return hB, nil
|
||||||
|
}
|
||||||
38
hash_test.go
Normal file
38
hash_test.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package arbo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHashSha256(t *testing.T) {
|
||||||
|
// Sha256 hash
|
||||||
|
hashFunc := &HashSha256{}
|
||||||
|
b := []byte("test")
|
||||||
|
h, err := hashFunc.Hash(b)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t,
|
||||||
|
"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
|
||||||
|
hex.EncodeToString(h))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHashPoseidon(t *testing.T) {
|
||||||
|
// Poseidon hash
|
||||||
|
hashFunc := &HashPoseidon{}
|
||||||
|
h, err := hashFunc.Hash(
|
||||||
|
BigIntToBytes(big.NewInt(1)),
|
||||||
|
BigIntToBytes(big.NewInt(2)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
hBI := BytesToBigInt(h)
|
||||||
|
// value checked with circomlib
|
||||||
|
assert.Equal(t,
|
||||||
|
"7853200120776062878684798364095072458815029376092732009249414926327459813530",
|
||||||
|
hBI.String())
|
||||||
|
}
|
||||||
25
utils.go
Normal file
25
utils.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package arbo
|
||||||
|
|
||||||
|
import "math/big"
|
||||||
|
|
||||||
|
// SwapEndianness swaps the order of the bytes in the byte slice.
|
||||||
|
func SwapEndianness(b []byte) []byte {
|
||||||
|
o := make([]byte, len(b))
|
||||||
|
for i := range b {
|
||||||
|
o[len(b)-1-i] = b[i]
|
||||||
|
}
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// BigIntToBytes converts a *big.Int into a byte array in Little-Endian
|
||||||
|
func BigIntToBytes(bi *big.Int) []byte {
|
||||||
|
var b [32]byte
|
||||||
|
copy(b[:], SwapEndianness(bi.Bytes()))
|
||||||
|
return b[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesToBigInt converts a byte array in Little-Endian representation into
|
||||||
|
// *big.Int
|
||||||
|
func BytesToBigInt(b []byte) *big.Int {
|
||||||
|
return new(big.Int).SetBytes(SwapEndianness(b))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user