Browse Source

Add HashFunction interface (w/ Poseidon & Sha256)

master
arnaucube 3 years ago
parent
commit
e1d2173dc9
3 changed files with 150 additions and 0 deletions
  1. +87
    -0
      hash.go
  2. +38
    -0
      hash_test.go
  3. +25
    -0
      utils.go

+ 87
- 0
hash.go

@ -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
- 0
hash_test.go

@ -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
- 0
utils.go

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

Loading…
Cancel
Save