@ -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 |
|||
} |
@ -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()) |
|||
} |
@ -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)) |
|||
} |