mirror of
https://github.com/arnaucube/go-iden3-crypto.git
synced 2026-02-07 11:36:41 +01:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b1935299c | ||
|
|
0bac1c84ba | ||
|
|
c4b3b7a09c |
@@ -2,9 +2,10 @@ package babyjub
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/iden3/go-iden3-crypto/constants"
|
"github.com/iden3/go-iden3-crypto/constants"
|
||||||
"github.com/iden3/go-iden3-crypto/utils"
|
"github.com/iden3/go-iden3-crypto/utils"
|
||||||
"math/big"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// A is one of the babyjub constants.
|
// A is one of the babyjub constants.
|
||||||
@@ -35,9 +36,9 @@ func init() {
|
|||||||
|
|
||||||
B8 = NewPoint()
|
B8 = NewPoint()
|
||||||
B8.X = utils.NewIntFromString(
|
B8.X = utils.NewIntFromString(
|
||||||
"17777552123799933955779906779655732241715742912184938656739573121738514868268")
|
"5299619240641551281634865583518297030282874472190772894086521144482721001553")
|
||||||
B8.Y = utils.NewIntFromString(
|
B8.Y = utils.NewIntFromString(
|
||||||
"2626589144620713026669568689430873010625803728049924121243784502389097019475")
|
"16950150798460657717958625567821834550301663161624707787222815936182638968203")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Point represents a point of the babyjub curve.
|
// Point represents a point of the babyjub curve.
|
||||||
@@ -74,7 +75,7 @@ func (res *Point) Add(a *Point, b *Point) *Point {
|
|||||||
x2.Mod(x2, constants.Q)
|
x2.Mod(x2, constants.Q)
|
||||||
x2.ModInverse(x2, constants.Q) // x2 = (1 + D * a.x * b.x * a.y * b.y)^-1
|
x2.ModInverse(x2, constants.Q) // x2 = (1 + D * a.x * b.x * a.y * b.y)^-1
|
||||||
|
|
||||||
// y = (a.y * b.y + A * a.x * a.x) * (1 - D * a.x * b.x * a.y * b.y)^-1 mod q
|
// y = (a.y * b.y - A * a.x * b.x) * (1 - D * a.x * b.x * a.y * b.y)^-1 mod q
|
||||||
y1a := new(big.Int).Mul(a.Y, b.Y)
|
y1a := new(big.Int).Mul(a.Y, b.Y)
|
||||||
y1b := new(big.Int).Set(A)
|
y1b := new(big.Int).Set(A)
|
||||||
y1b.Mul(y1b, a.X)
|
y1b.Mul(y1b, a.X)
|
||||||
@@ -170,10 +171,7 @@ func PackPoint(ay *big.Int, sign bool) [32]byte {
|
|||||||
// Compress the point into a 32 byte array that contains the y coordinate in
|
// Compress the point into a 32 byte array that contains the y coordinate in
|
||||||
// little endian and the sign of the x coordinate.
|
// little endian and the sign of the x coordinate.
|
||||||
func (p *Point) Compress() [32]byte {
|
func (p *Point) Compress() [32]byte {
|
||||||
sign := false
|
sign := PointCoordSign(p.X)
|
||||||
if PointCoordSign(p.X) {
|
|
||||||
sign = true
|
|
||||||
}
|
|
||||||
return PackPoint(p.Y, sign)
|
return PackPoint(p.Y, sign)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
|
||||||
"github.com/iden3/go-iden3-crypto/mimc7"
|
"github.com/iden3/go-iden3-crypto/mimc7"
|
||||||
|
"github.com/iden3/go-iden3-crypto/poseidon"
|
||||||
"github.com/iden3/go-iden3-crypto/utils"
|
"github.com/iden3/go-iden3-crypto/utils"
|
||||||
|
|
||||||
"math/big"
|
"math/big"
|
||||||
@@ -179,11 +180,11 @@ func (k *PrivateKey) SignMimc7(msg *big.Int) *Signature {
|
|||||||
r.Mod(r, SubOrder)
|
r.Mod(r, SubOrder)
|
||||||
R8 := NewPoint().Mul(r, B8) // R8 = r * 8 * B
|
R8 := NewPoint().Mul(r, B8) // R8 = r * 8 * B
|
||||||
A := k.Public().Point()
|
A := k.Public().Point()
|
||||||
hmInput, err := mimc7.BigIntsToRElems([]*big.Int{R8.X, R8.Y, A.X, A.Y, msg})
|
hmInput := []*big.Int{R8.X, R8.Y, A.X, A.Y, msg}
|
||||||
|
hm, err := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
hm := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
|
|
||||||
S := new(big.Int).Lsh(k.Scalar().BigInt(), 3)
|
S := new(big.Int).Lsh(k.Scalar().BigInt(), 3)
|
||||||
S = S.Mul(hm, S)
|
S = S.Mul(hm, S)
|
||||||
S.Add(r, S)
|
S.Add(r, S)
|
||||||
@@ -195,11 +196,53 @@ func (k *PrivateKey) SignMimc7(msg *big.Int) *Signature {
|
|||||||
// VerifyMimc7 verifies the signature of a message encoded as a big.Int in Zq
|
// VerifyMimc7 verifies the signature of a message encoded as a big.Int in Zq
|
||||||
// using blake-512 hash for buffer hashing and mimc7 for big.Int hashing.
|
// using blake-512 hash for buffer hashing and mimc7 for big.Int hashing.
|
||||||
func (p *PublicKey) VerifyMimc7(msg *big.Int, sig *Signature) bool {
|
func (p *PublicKey) VerifyMimc7(msg *big.Int, sig *Signature) bool {
|
||||||
hmInput, err := mimc7.BigIntsToRElems([]*big.Int{sig.R8.X, sig.R8.Y, p.X, p.Y, msg})
|
hmInput := []*big.Int{sig.R8.X, sig.R8.Y, p.X, p.Y, msg}
|
||||||
|
hm, err := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
left := NewPoint().Mul(sig.S, B8) // left = s * 8 * B
|
||||||
|
r1 := big.NewInt(8)
|
||||||
|
r1.Mul(r1, hm)
|
||||||
|
right := NewPoint().Mul(r1, p.Point())
|
||||||
|
right.Add(sig.R8, right) // right = 8 * R + 8 * hm * A
|
||||||
|
return (left.X.Cmp(right.X) == 0) && (left.Y.Cmp(right.Y) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignPoseidon signs a message encoded as a big.Int in Zq using blake-512 hash
|
||||||
|
// for buffer hashing and Poseidon for big.Int hashing.
|
||||||
|
func (k *PrivateKey) SignPoseidon(msg *big.Int) *Signature {
|
||||||
|
h1 := Blake512(k[:])
|
||||||
|
msgBuf := utils.BigIntLEBytes(msg)
|
||||||
|
msgBuf32 := [32]byte{}
|
||||||
|
copy(msgBuf32[:], msgBuf[:])
|
||||||
|
rBuf := Blake512(append(h1[32:], msgBuf32[:]...))
|
||||||
|
r := utils.SetBigIntFromLEBytes(new(big.Int), rBuf) // r = H(H_{32..63}(k), msg)
|
||||||
|
r.Mod(r, SubOrder)
|
||||||
|
R8 := NewPoint().Mul(r, B8) // R8 = r * 8 * B
|
||||||
|
A := k.Public().Point()
|
||||||
|
hmInput := []*big.Int{R8.X, R8.Y, A.X, A.Y, msg}
|
||||||
|
hm, err := poseidon.Hash(hmInput) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
S := new(big.Int).Lsh(k.Scalar().BigInt(), 3)
|
||||||
|
S = S.Mul(hm, S)
|
||||||
|
S.Add(r, S)
|
||||||
|
S.Mod(S, SubOrder) // S = r + hm * 8 * s
|
||||||
|
|
||||||
|
return &Signature{R8: R8, S: S}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyPoseidon verifies the signature of a message encoded as a big.Int in Zq
|
||||||
|
// using blake-512 hash for buffer hashing and Poseidon for big.Int hashing.
|
||||||
|
func (p *PublicKey) VerifyPoseidon(msg *big.Int, sig *Signature) bool {
|
||||||
|
hmInput := []*big.Int{sig.R8.X, sig.R8.Y, p.X, p.Y, msg}
|
||||||
|
hm, err := poseidon.Hash(hmInput) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
hm := mimc7.Hash(hmInput, nil) // hm = H1(8*R.x, 8*R.y, A.x, A.y, msg)
|
|
||||||
|
|
||||||
left := NewPoint().Mul(sig.S, B8) // left = s * 8 * B
|
left := NewPoint().Mul(sig.S, B8) // left = s * 8 * B
|
||||||
r1 := big.NewInt(8)
|
r1 := big.NewInt(8)
|
||||||
|
|||||||
@@ -4,13 +4,12 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/iden3/go-iden3-crypto/constants"
|
"github.com/iden3/go-iden3-crypto/constants"
|
||||||
"github.com/iden3/go-iden3-crypto/utils"
|
"github.com/iden3/go-iden3-crypto/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"math/big"
|
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func genInputs() (*PrivateKey, *big.Int) {
|
func genInputs() (*PrivateKey, *big.Int) {
|
||||||
@@ -26,7 +25,7 @@ func genInputs() (*PrivateKey, *big.Int) {
|
|||||||
return &k, msg
|
return &k, msg
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSignVerify1(t *testing.T) {
|
func TestSignVerifyMimc7(t *testing.T) {
|
||||||
var k PrivateKey
|
var k PrivateKey
|
||||||
hex.Decode(k[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
hex.Decode(k[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||||
msgBuf, err := hex.DecodeString("00010203040506070809")
|
msgBuf, err := hex.DecodeString("00010203040506070809")
|
||||||
@@ -37,21 +36,21 @@ func TestSignVerify1(t *testing.T) {
|
|||||||
|
|
||||||
pk := k.Public()
|
pk := k.Public()
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
"2610057752638682202795145288373380503107623443963127956230801721756904484787",
|
"13277427435165878497778222415993513565335242147425444199013288855685581939618",
|
||||||
pk.X.String())
|
pk.X.String())
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
"16617171478497210597712478520507818259149717466230047843969353176573634386897",
|
"13622229784656158136036771217484571176836296686641868549125388198837476602820",
|
||||||
pk.Y.String())
|
pk.Y.String())
|
||||||
|
|
||||||
sig := k.SignMimc7(msg)
|
sig := k.SignMimc7(msg)
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
"4974729414807584049518234760796200867685098748448054182902488636762478901554",
|
"11384336176656855268977457483345535180380036354188103142384839473266348197733",
|
||||||
sig.R8.X.String())
|
sig.R8.X.String())
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
"18714049394522540751536514815950425694461287643205706667341348804546050128733",
|
"15383486972088797283337779941324724402501462225528836549661220478783371668959",
|
||||||
sig.R8.Y.String())
|
sig.R8.Y.String())
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
"2171284143457722024136077617757713039502332290425057126942676527240038689549",
|
"2523202440825208709475937830811065542425109372212752003460238913256192595070",
|
||||||
sig.S.String())
|
sig.S.String())
|
||||||
|
|
||||||
ok := pk.VerifyMimc7(msg, sig)
|
ok := pk.VerifyMimc7(msg, sig)
|
||||||
@@ -62,14 +61,58 @@ func TestSignVerify1(t *testing.T) {
|
|||||||
assert.Equal(t, nil, err)
|
assert.Equal(t, nil, err)
|
||||||
|
|
||||||
assert.Equal(t, ""+
|
assert.Equal(t, ""+
|
||||||
"5dfb6f843c023fe3e52548ccf22e55c81b426f7af81b4f51f7152f2fcfc65f29"+
|
"dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2"+
|
||||||
"0dab19c5a0a75973cd75a54780de0c3a41ede6f57396fe99b5307fff3ce7cc04",
|
"7ed40dab29bf993c928e789d007387998901a24913d44fddb64b1f21fc149405",
|
||||||
hex.EncodeToString(sigBuf[:]))
|
hex.EncodeToString(sigBuf[:]))
|
||||||
|
|
||||||
ok = pk.VerifyMimc7(msg, sig2)
|
ok = pk.VerifyMimc7(msg, sig2)
|
||||||
assert.Equal(t, true, ok)
|
assert.Equal(t, true, ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSignVerifyPoseidon(t *testing.T) {
|
||||||
|
var k PrivateKey
|
||||||
|
hex.Decode(k[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||||
|
msgBuf, err := hex.DecodeString("00010203040506070809")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
msg := utils.SetBigIntFromLEBytes(new(big.Int), msgBuf)
|
||||||
|
|
||||||
|
pk := k.Public()
|
||||||
|
assert.Equal(t,
|
||||||
|
"13277427435165878497778222415993513565335242147425444199013288855685581939618",
|
||||||
|
pk.X.String())
|
||||||
|
assert.Equal(t,
|
||||||
|
"13622229784656158136036771217484571176836296686641868549125388198837476602820",
|
||||||
|
pk.Y.String())
|
||||||
|
|
||||||
|
sig := k.SignPoseidon(msg)
|
||||||
|
assert.Equal(t,
|
||||||
|
"11384336176656855268977457483345535180380036354188103142384839473266348197733",
|
||||||
|
sig.R8.X.String())
|
||||||
|
assert.Equal(t,
|
||||||
|
"15383486972088797283337779941324724402501462225528836549661220478783371668959",
|
||||||
|
sig.R8.Y.String())
|
||||||
|
assert.Equal(t,
|
||||||
|
"248298168863866362217836334079793350221620631973732197668910946177382043688",
|
||||||
|
sig.S.String())
|
||||||
|
|
||||||
|
ok := pk.VerifyPoseidon(msg, sig)
|
||||||
|
assert.Equal(t, true, ok)
|
||||||
|
|
||||||
|
sigBuf := sig.Compress()
|
||||||
|
sig2, err := new(Signature).Decompress(sigBuf)
|
||||||
|
assert.Equal(t, nil, err)
|
||||||
|
|
||||||
|
assert.Equal(t, ""+
|
||||||
|
"dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2"+
|
||||||
|
"28506bce274aa1b3f7e7c2fd7e4fe09bff8f9aa37a42def7994e98f322888c00",
|
||||||
|
hex.EncodeToString(sigBuf[:]))
|
||||||
|
|
||||||
|
ok = pk.VerifyPoseidon(msg, sig2)
|
||||||
|
assert.Equal(t, true, ok)
|
||||||
|
}
|
||||||
|
|
||||||
func TestCompressDecompress(t *testing.T) {
|
func TestCompressDecompress(t *testing.T) {
|
||||||
var k PrivateKey
|
var k PrivateKey
|
||||||
hex.Decode(k[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
hex.Decode(k[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||||
|
|||||||
@@ -2,19 +2,16 @@ package mimc7
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
_constants "github.com/iden3/go-iden3-crypto/constants"
|
_constants "github.com/iden3/go-iden3-crypto/constants"
|
||||||
"github.com/iden3/go-iden3-crypto/field"
|
"github.com/iden3/go-iden3-crypto/field"
|
||||||
|
"github.com/iden3/go-iden3-crypto/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SEED = "mimc"
|
const SEED = "mimc"
|
||||||
|
|
||||||
// RElem is a big.Int of maximum 253 bits
|
|
||||||
type RElem *big.Int
|
|
||||||
|
|
||||||
var constants = generateConstantsData()
|
var constants = generateConstantsData()
|
||||||
|
|
||||||
type constantsData struct {
|
type constantsData struct {
|
||||||
@@ -26,9 +23,6 @@ type constantsData struct {
|
|||||||
cts []*big.Int
|
cts []*big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func getIV(seed string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateConstantsData() constantsData {
|
func generateConstantsData() constantsData {
|
||||||
var constants constantsData
|
var constants constantsData
|
||||||
|
|
||||||
@@ -43,45 +37,12 @@ func generateConstantsData() constantsData {
|
|||||||
constants.iv = new(big.Int).Mod(c, constants.maxFieldVal)
|
constants.iv = new(big.Int).Mod(c, constants.maxFieldVal)
|
||||||
|
|
||||||
constants.nRounds = 91
|
constants.nRounds = 91
|
||||||
cts, err := getConstants(constants.fqR, SEED, constants.nRounds)
|
cts := getConstants(constants.fqR, SEED, constants.nRounds)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
constants.cts = cts
|
constants.cts = cts
|
||||||
return constants
|
return constants
|
||||||
}
|
}
|
||||||
|
|
||||||
// BigIntToRElem checks if given big.Int fits in a Field R element, and returns the RElem type
|
func getConstants(fqR field.Fq, seed string, nRounds int) []*big.Int {
|
||||||
func BigIntToRElem(a *big.Int) (RElem, error) {
|
|
||||||
if a.Cmp(constants.maxFieldVal) != -1 {
|
|
||||||
return RElem(a), errors.New("Given big.Int don't fits in the Finite Field over R")
|
|
||||||
}
|
|
||||||
return RElem(a), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//BigIntsToRElems converts from array of *big.Int to array of RElem
|
|
||||||
func BigIntsToRElems(arr []*big.Int) ([]RElem, error) {
|
|
||||||
o := make([]RElem, len(arr))
|
|
||||||
for i, a := range arr {
|
|
||||||
e, err := BigIntToRElem(a)
|
|
||||||
if err != nil {
|
|
||||||
return o, fmt.Errorf("element in position %v don't fits in Finite Field over R", i)
|
|
||||||
}
|
|
||||||
o[i] = e
|
|
||||||
}
|
|
||||||
return o, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RElemsToBigInts converts from array of RElem to array of *big.Int
|
|
||||||
func RElemsToBigInts(arr []RElem) []*big.Int {
|
|
||||||
o := make([]*big.Int, len(arr))
|
|
||||||
for i, a := range arr {
|
|
||||||
o[i] = a
|
|
||||||
}
|
|
||||||
return o
|
|
||||||
}
|
|
||||||
|
|
||||||
func getConstants(fqR field.Fq, seed string, nRounds int) ([]*big.Int, error) {
|
|
||||||
cts := make([]*big.Int, nRounds)
|
cts := make([]*big.Int, nRounds)
|
||||||
cts[0] = big.NewInt(int64(0))
|
cts[0] = big.NewInt(int64(0))
|
||||||
c := new(big.Int).SetBytes(crypto.Keccak256([]byte(SEED)))
|
c := new(big.Int).SetBytes(crypto.Keccak256([]byte(SEED)))
|
||||||
@@ -91,15 +52,12 @@ func getConstants(fqR field.Fq, seed string, nRounds int) ([]*big.Int, error) {
|
|||||||
n := fqR.Affine(c)
|
n := fqR.Affine(c)
|
||||||
cts[i] = n
|
cts[i] = n
|
||||||
}
|
}
|
||||||
return cts, nil
|
return cts
|
||||||
}
|
}
|
||||||
|
|
||||||
// MIMC7HashGeneric performs the MIMC7 hash over a RElem, in a generic way, where it can be specified the Finite Field over R, and the number of rounds
|
// MIMC7HashGeneric performs the MIMC7 hash over a *big.Int, in a generic way, where it can be specified the Finite Field over R, and the number of rounds
|
||||||
func MIMC7HashGeneric(fqR field.Fq, xIn, k *big.Int, nRounds int) (*big.Int, error) {
|
func MIMC7HashGeneric(fqR field.Fq, xIn, k *big.Int, nRounds int) *big.Int {
|
||||||
cts, err := getConstants(fqR, SEED, nRounds)
|
cts := getConstants(fqR, SEED, nRounds)
|
||||||
if err != nil {
|
|
||||||
return &big.Int{}, err
|
|
||||||
}
|
|
||||||
var r *big.Int
|
var r *big.Int
|
||||||
for i := 0; i < nRounds; i++ {
|
for i := 0; i < nRounds; i++ {
|
||||||
var t *big.Int
|
var t *big.Int
|
||||||
@@ -112,24 +70,26 @@ func MIMC7HashGeneric(fqR field.Fq, xIn, k *big.Int, nRounds int) (*big.Int, err
|
|||||||
t4 := fqR.Square(t2)
|
t4 := fqR.Square(t2)
|
||||||
r = fqR.Mul(fqR.Mul(t4, t2), t)
|
r = fqR.Mul(fqR.Mul(t4, t2), t)
|
||||||
}
|
}
|
||||||
return fqR.Affine(fqR.Add(r, k)), nil
|
return fqR.Affine(fqR.Add(r, k))
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashGeneric performs the MIMC7 hash over a RElem array, in a generic way, where it can be specified the Finite Field over R, and the number of rounds
|
// HashGeneric performs the MIMC7 hash over a *big.Int array, in a generic way, where it can be specified the Finite Field over R, and the number of rounds
|
||||||
func HashGeneric(iv *big.Int, arrEl []RElem, fqR field.Fq, nRounds int) (RElem, error) {
|
func HashGeneric(iv *big.Int, arr []*big.Int, fqR field.Fq, nRounds int) (*big.Int, error) {
|
||||||
arr := RElemsToBigInts(arrEl)
|
if !utils.CheckBigIntArrayInField(arr, constants.fqR.Q) {
|
||||||
|
return nil, errors.New("inputs values not inside Finite Field")
|
||||||
|
}
|
||||||
r := iv
|
r := iv
|
||||||
var err error
|
var err error
|
||||||
for i := 0; i < len(arr); i++ {
|
for i := 0; i < len(arr); i++ {
|
||||||
r, err = MIMC7HashGeneric(fqR, r, arr[i], nRounds)
|
r = MIMC7HashGeneric(fqR, r, arr[i], nRounds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return r, err
|
return r, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return RElem(r), nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MIMC7Hash performs the MIMC7 hash over a RElem, using the Finite Field over R and the number of rounds setted in the `constants` variable
|
// MIMC7Hash performs the MIMC7 hash over a *big.Int, using the Finite Field over R and the number of rounds setted in the `constants` variable
|
||||||
func MIMC7Hash(xIn, k *big.Int) *big.Int {
|
func MIMC7Hash(xIn, k *big.Int) *big.Int {
|
||||||
var r *big.Int
|
var r *big.Int
|
||||||
for i := 0; i < constants.nRounds; i++ {
|
for i := 0; i < constants.nRounds; i++ {
|
||||||
@@ -146,16 +106,17 @@ func MIMC7Hash(xIn, k *big.Int) *big.Int {
|
|||||||
return constants.fqR.Affine(constants.fqR.Add(r, k))
|
return constants.fqR.Affine(constants.fqR.Add(r, k))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash performs the MIMC7 hash over a RElem array
|
// Hash performs the MIMC7 hash over a *big.Int array
|
||||||
func Hash(arrEl []RElem, key *big.Int) RElem {
|
func Hash(arr []*big.Int, key *big.Int) (*big.Int, error) {
|
||||||
arr := RElemsToBigInts(arrEl)
|
if !utils.CheckBigIntArrayInField(arr, constants.fqR.Q) {
|
||||||
|
return nil, errors.New("inputs values not inside Finite Field")
|
||||||
|
}
|
||||||
var r *big.Int
|
var r *big.Int
|
||||||
if key == nil {
|
if key == nil {
|
||||||
r = constants.fqR.Zero()
|
r = constants.fqR.Zero()
|
||||||
} else {
|
} else {
|
||||||
r = key
|
r = key
|
||||||
}
|
}
|
||||||
// r := constants.iv
|
|
||||||
for i := 0; i < len(arr); i++ {
|
for i := 0; i < len(arr); i++ {
|
||||||
r = constants.fqR.Add(
|
r = constants.fqR.Add(
|
||||||
constants.fqR.Add(
|
constants.fqR.Add(
|
||||||
@@ -164,5 +125,5 @@ func Hash(arrEl []RElem, key *big.Int) RElem {
|
|||||||
),
|
),
|
||||||
MIMC7Hash(arr[i], r))
|
MIMC7Hash(arr[i], r))
|
||||||
}
|
}
|
||||||
return RElem(r)
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,42 +5,16 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/iden3/go-iden3-crypto/field"
|
"github.com/iden3/go-iden3-crypto/field"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUtils(t *testing.T) {
|
func TestKeccak256(t *testing.T) {
|
||||||
b1 := big.NewInt(int64(1))
|
res := crypto.Keccak256([]byte(SEED))
|
||||||
b2 := big.NewInt(int64(2))
|
assert.Equal(t, "b6e489e6b37224a50bebfddbe7d89fa8fdcaa84304a70bd13f79b5d9f7951e9e", hex.EncodeToString(res))
|
||||||
b3 := big.NewInt(int64(3))
|
c := new(big.Int).SetBytes(crypto.Keccak256([]byte(SEED)))
|
||||||
arrBigInt := []*big.Int{b1, b2, b3}
|
assert.Equal(t, "82724731331859054037315113496710413141112897654334566532528783843265082629790", c.String())
|
||||||
|
|
||||||
// *big.Int array to RElem array
|
|
||||||
rElems, err := BigIntsToRElems(arrBigInt)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
// RElem array to *big.Int array
|
|
||||||
bElems := RElemsToBigInts(rElems)
|
|
||||||
|
|
||||||
assert.Equal(t, arrBigInt, bElems)
|
|
||||||
|
|
||||||
r, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
|
|
||||||
assert.True(t, ok)
|
|
||||||
|
|
||||||
// greater or equal than R will give error when passing bigInts to RElems, to fit in the R Finite Field
|
|
||||||
overR, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495618", 10)
|
|
||||||
assert.True(t, ok)
|
|
||||||
_, err = BigIntsToRElems([]*big.Int{b1, overR, b2})
|
|
||||||
assert.True(t, err != nil)
|
|
||||||
|
|
||||||
_, err = BigIntsToRElems([]*big.Int{b1, r, b2})
|
|
||||||
assert.True(t, err != nil)
|
|
||||||
|
|
||||||
// smaller than R will not give error when passing bigInts to RElems, to fit in the R Finite Field
|
|
||||||
underR, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495616", 10)
|
|
||||||
assert.True(t, ok)
|
|
||||||
_, err = BigIntsToRElems([]*big.Int{b1, underR, b2})
|
|
||||||
assert.Nil(t, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMIMC7Generic(t *testing.T) {
|
func TestMIMC7Generic(t *testing.T) {
|
||||||
@@ -53,14 +27,11 @@ func TestMIMC7Generic(t *testing.T) {
|
|||||||
fqR := field.NewFq(r)
|
fqR := field.NewFq(r)
|
||||||
|
|
||||||
bigArray := []*big.Int{b1, b2, b3}
|
bigArray := []*big.Int{b1, b2, b3}
|
||||||
elementsArray, err := BigIntsToRElems(bigArray)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
// Generic Hash
|
// Generic Hash
|
||||||
mhg, err := MIMC7HashGeneric(fqR, b1, b2, 91)
|
mhg := MIMC7HashGeneric(fqR, b1, b2, 91)
|
||||||
assert.Nil(t, err)
|
|
||||||
assert.Equal(t, "10594780656576967754230020536574539122676596303354946869887184401991294982664", mhg.String())
|
assert.Equal(t, "10594780656576967754230020536574539122676596303354946869887184401991294982664", mhg.String())
|
||||||
hg, err := HashGeneric(fqR.Zero(), elementsArray, fqR, 91)
|
hg, err := HashGeneric(fqR.Zero(), bigArray, fqR, 91)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, "6464402164086696096195815557694604139393321133243036833927490113253119343397", (*big.Int)(hg).String())
|
assert.Equal(t, "6464402164086696096195815557694604139393321133243036833927490113253119343397", (*big.Int)(hg).String())
|
||||||
}
|
}
|
||||||
@@ -73,48 +44,36 @@ func TestMIMC7(t *testing.T) {
|
|||||||
|
|
||||||
// h1, hash of 1 elements
|
// h1, hash of 1 elements
|
||||||
bigArray1 := []*big.Int{b12}
|
bigArray1 := []*big.Int{b12}
|
||||||
elementsArray1, err := BigIntsToRElems(bigArray1)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
h1 := Hash(elementsArray1, nil)
|
h1, err := Hash(bigArray1, nil)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
// same hash value than the iden3js and circomlib tests:
|
// same hash value than the iden3js and circomlib tests:
|
||||||
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h1).Bytes()), "0x237c92644dbddb86d8a259e0e923aaab65a93f1ec5758b8799988894ac0958fd")
|
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h1).Bytes()), "0x237c92644dbddb86d8a259e0e923aaab65a93f1ec5758b8799988894ac0958fd")
|
||||||
|
|
||||||
// h2a, hash of 2 elements
|
// h2a, hash of 2 elements
|
||||||
bigArray2a := []*big.Int{b78, b41}
|
bigArray2a := []*big.Int{b78, b41}
|
||||||
elementsArray2a, err := BigIntsToRElems(bigArray2a)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
mh2a := MIMC7Hash(b12, b45)
|
h2a, err := Hash(bigArray2a, nil)
|
||||||
assert.Nil(t, err)
|
|
||||||
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(mh2a).Bytes()), "0x2ba7ebad3c6b6f5a20bdecba2333c63173ca1a5f2f49d958081d9fa7179c44e4")
|
|
||||||
|
|
||||||
h2a := Hash(elementsArray2a, nil)
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
// same hash value than the iden3js and circomlib tests:
|
// same hash value than the iden3js and circomlib tests:
|
||||||
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h2a).Bytes()), "0x067f3202335ea256ae6e6aadcd2d5f7f4b06a00b2d1e0de903980d5ab552dc70")
|
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h2a).Bytes()), "0x067f3202335ea256ae6e6aadcd2d5f7f4b06a00b2d1e0de903980d5ab552dc70")
|
||||||
|
|
||||||
// h2b, hash of 2 elements
|
// h2b, hash of 2 elements
|
||||||
bigArray2b := []*big.Int{b12, b45}
|
bigArray2b := []*big.Int{b12, b45}
|
||||||
elementsArray2b, err := BigIntsToRElems(bigArray2b)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
mh2b := MIMC7Hash(b12, b45)
|
mh2b := MIMC7Hash(b12, b45)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(mh2b).Bytes()), "0x2ba7ebad3c6b6f5a20bdecba2333c63173ca1a5f2f49d958081d9fa7179c44e4")
|
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(mh2b).Bytes()), "0x2ba7ebad3c6b6f5a20bdecba2333c63173ca1a5f2f49d958081d9fa7179c44e4")
|
||||||
|
|
||||||
h2b := Hash(elementsArray2b, nil)
|
h2b, err := Hash(bigArray2b, nil)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
// same hash value than the iden3js and circomlib tests:
|
// same hash value than the iden3js and circomlib tests:
|
||||||
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h2b).Bytes()), "0x15ff7fe9793346a17c3150804bcb36d161c8662b110c50f55ccb7113948d8879")
|
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h2b).Bytes()), "0x15ff7fe9793346a17c3150804bcb36d161c8662b110c50f55ccb7113948d8879")
|
||||||
|
|
||||||
// h4, hash of 4 elements
|
// h4, hash of 4 elements
|
||||||
bigArray4 := []*big.Int{b12, b45, b78, b41}
|
bigArray4 := []*big.Int{b12, b45, b78, b41}
|
||||||
elementsArray4, err := BigIntsToRElems(bigArray4)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
h4 := Hash(elementsArray4, nil)
|
h4, err := Hash(bigArray4, nil)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
// same hash value than the iden3js and circomlib tests:
|
// same hash value than the iden3js and circomlib tests:
|
||||||
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h4).Bytes()), "0x284bc1f34f335933a23a433b6ff3ee179d682cd5e5e2fcdd2d964afa85104beb")
|
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h4).Bytes()), "0x284bc1f34f335933a23a433b6ff3ee179d682cd5e5e2fcdd2d964afa85104beb")
|
||||||
@@ -126,12 +85,10 @@ func BenchmarkMIMC7(b *testing.B) {
|
|||||||
b78 := big.NewInt(int64(78))
|
b78 := big.NewInt(int64(78))
|
||||||
b41 := big.NewInt(int64(41))
|
b41 := big.NewInt(int64(41))
|
||||||
bigArray4 := []*big.Int{b12, b45, b78, b41}
|
bigArray4 := []*big.Int{b12, b45, b78, b41}
|
||||||
elementsArray4, err := BigIntsToRElems(bigArray4)
|
|
||||||
assert.Nil(b, err)
|
|
||||||
|
|
||||||
var h4 RElem
|
var h4 *big.Int
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
h4 = Hash(elementsArray4, nil)
|
h4, _ = Hash(bigArray4, nil)
|
||||||
}
|
}
|
||||||
println(h4)
|
println(h4)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user