mirror of
https://github.com/arnaucube/go-iden3-crypto.git
synced 2026-02-07 11:36:41 +01:00
Compare commits
5 Commits
v0.0.1
...
decompress
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a60e154d86 | ||
|
|
c95c95b7b1 | ||
|
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +203,10 @@ func (p *Point) Decompress(leBuf [32]byte) (*Point, error) {
|
|||||||
xb.ModInverse(xb, constants.Q)
|
xb.ModInverse(xb, constants.Q)
|
||||||
p.X.Mul(xa, xb) // xa / xb
|
p.X.Mul(xa, xb) // xa / xb
|
||||||
p.X.Mod(p.X, constants.Q)
|
p.X.Mod(p.X, constants.Q)
|
||||||
p.X.ModSqrt(p.X, constants.Q)
|
noSqrt := p.X.ModSqrt(p.X, constants.Q)
|
||||||
|
if noSqrt == nil {
|
||||||
|
return nil, fmt.Errorf("x is not a square mod q")
|
||||||
|
}
|
||||||
if (sign && !PointCoordSign(p.X)) || (!sign && PointCoordSign(p.X)) {
|
if (sign && !PointCoordSign(p.X)) || (!sign && PointCoordSign(p.X)) {
|
||||||
p.X.Mul(p.X, constants.MinusOne)
|
p.X.Mul(p.X, constants.MinusOne)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"))
|
||||||
|
|||||||
101
mimc7/mimc7.go
101
mimc7/mimc7.go
@@ -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,23 @@ func Hash(arrEl []RElem, key *big.Int) RElem {
|
|||||||
),
|
),
|
||||||
MIMC7Hash(arr[i], r))
|
MIMC7Hash(arr[i], r))
|
||||||
}
|
}
|
||||||
return RElem(r)
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashBytes hashes a msg byte slice by blocks of 31 bytes encoded as
|
||||||
|
// little-endian
|
||||||
|
func HashBytes(b []byte) (*big.Int, error) {
|
||||||
|
n := 31
|
||||||
|
bElems := make([]*big.Int, 0, len(b)/n+1)
|
||||||
|
for i := 0; i < len(b)/n; i++ {
|
||||||
|
v := new(big.Int)
|
||||||
|
utils.SetBigIntFromLEBytes(v, b[n*i:n*(i+1)])
|
||||||
|
bElems = append(bElems, v)
|
||||||
|
}
|
||||||
|
if len(b)%n != 0 {
|
||||||
|
v := new(big.Int)
|
||||||
|
utils.SetBigIntFromLEBytes(v, b[(len(b)/n)*n:])
|
||||||
|
bElems = append(bElems, v)
|
||||||
|
}
|
||||||
|
return Hash(bElems, 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,51 +44,44 @@ 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")
|
||||||
|
|
||||||
|
msg := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
|
||||||
|
hmsg, err := HashBytes(msg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "16855787120419064316734350414336285711017110414939748784029922801367685456065", hmsg.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkMIMC7(b *testing.B) {
|
func BenchmarkMIMC7(b *testing.B) {
|
||||||
@@ -126,12 +90,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,12 +107,13 @@ func ark(state []*big.Int, c *big.Int) []*big.Int {
|
|||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
// cubic performs x^3 mod p
|
// cubic performs x^5 mod p
|
||||||
|
// https://eprint.iacr.org/2019/458.pdf page 8
|
||||||
func cubic(a *big.Int) *big.Int {
|
func cubic(a *big.Int) *big.Int {
|
||||||
return constants.fqR.Mul(a, constants.fqR.Square(constants.fqR.Square(a)))
|
return constants.fqR.Mul(a, constants.fqR.Square(constants.fqR.Square(a)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// sbox https://eprint.iacr.org/2019/458.pdf pag.6
|
// sbox https://eprint.iacr.org/2019/458.pdf page 6
|
||||||
func sbox(state []*big.Int, i int) []*big.Int {
|
func sbox(state []*big.Int, i int) []*big.Int {
|
||||||
if (i < NROUNDSF/2) || (i >= NROUNDSF/2+NROUNDSP) {
|
if (i < NROUNDSF/2) || (i >= NROUNDSF/2+NROUNDSP) {
|
||||||
for j := 0; j < T; j++ {
|
for j := 0; j < T; j++ {
|
||||||
@@ -133,25 +134,18 @@ func mix(state []*big.Int, m [][]*big.Int) []*big.Int {
|
|||||||
newState[i] = constants.fqR.Add(newState[i], constants.fqR.Mul(m[i][j], state[j]))
|
newState[i] = constants.fqR.Add(newState[i], constants.fqR.Mul(m[i][j], state[j]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(state); i++ {
|
return newState
|
||||||
state[i] = newState[i]
|
|
||||||
}
|
|
||||||
return state
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash computes the Poseidon hash for the given inputs
|
// PoseidonHash computes the Poseidon hash for the given inputs
|
||||||
func Hash(inp []*big.Int) (*big.Int, error) {
|
func PoseidonHash(inp []*big.Int) (*big.Int, error) {
|
||||||
var state []*big.Int
|
|
||||||
if len(inp) == 0 || len(inp) > T {
|
if len(inp) == 0 || len(inp) > T {
|
||||||
return nil, errors.New("wrong inputs length")
|
return nil, errors.New("wrong inputs length")
|
||||||
}
|
}
|
||||||
if !utils.CheckBigIntArrayInField(inp, constants.fqR.Q) {
|
if !utils.CheckBigIntArrayInField(inp, constants.fqR.Q) {
|
||||||
return nil, errors.New("inputs values not inside Finite Field")
|
return nil, errors.New("inputs values not inside Finite Field")
|
||||||
}
|
}
|
||||||
|
state := inp
|
||||||
for i := 0; i < len(inp); i++ {
|
|
||||||
state = append(state, inp[i])
|
|
||||||
}
|
|
||||||
for i := len(inp); i < T; i++ {
|
for i := len(inp); i < T; i++ {
|
||||||
state = append(state, constants.fqR.Zero())
|
state = append(state, constants.fqR.Zero())
|
||||||
}
|
}
|
||||||
@@ -164,3 +158,50 @@ func Hash(inp []*big.Int) (*big.Int, error) {
|
|||||||
}
|
}
|
||||||
return state[0], nil
|
return state[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hash performs the Poseidon hash over a *big.Int array
|
||||||
|
// in chunks of 5 elements
|
||||||
|
func Hash(arr []*big.Int) (*big.Int, error) {
|
||||||
|
if !utils.CheckBigIntArrayInField(arr, constants.fqR.Q) {
|
||||||
|
return nil, errors.New("inputs values not inside Finite Field")
|
||||||
|
}
|
||||||
|
|
||||||
|
r := constants.fqR.Zero()
|
||||||
|
for i := 0; i < len(arr); i = i + 5 {
|
||||||
|
var fiveElems []*big.Int
|
||||||
|
for j := 0; j < 5; j++ {
|
||||||
|
if i+j < len(arr) {
|
||||||
|
fiveElems = append(fiveElems, arr[i+j])
|
||||||
|
} else {
|
||||||
|
fiveElems = append(fiveElems, big.NewInt(int64(0)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ph, err := PoseidonHash(fiveElems)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r = constants.fqR.Add(
|
||||||
|
r,
|
||||||
|
ph)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashBytes hashes a msg byte slice by blocks of 31 bytes encoded as
|
||||||
|
// little-endian
|
||||||
|
func HashBytes(b []byte) (*big.Int, error) {
|
||||||
|
n := 31
|
||||||
|
bElems := make([]*big.Int, 0, len(b)/n+1)
|
||||||
|
for i := 0; i < len(b)/n; i++ {
|
||||||
|
v := new(big.Int)
|
||||||
|
utils.SetBigIntFromLEBytes(v, b[n*i:n*(i+1)])
|
||||||
|
bElems = append(bElems, v)
|
||||||
|
}
|
||||||
|
if len(b)%n != 0 {
|
||||||
|
v := new(big.Int)
|
||||||
|
utils.SetBigIntFromLEBytes(v, b[(len(b)/n)*n:])
|
||||||
|
bElems = append(bElems, v)
|
||||||
|
}
|
||||||
|
return Hash(bElems)
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/iden3/go-iden3-crypto/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"golang.org/x/crypto/blake2b"
|
"golang.org/x/crypto/blake2b"
|
||||||
)
|
)
|
||||||
@@ -26,4 +27,41 @@ func TestPoseidon(t *testing.T) {
|
|||||||
h, err = Hash([]*big.Int{b3, b4})
|
h, err = Hash([]*big.Int{b3, b4})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, "17185195740979599334254027721507328033796809509313949281114643312710535000993", h.String())
|
assert.Equal(t, "17185195740979599334254027721507328033796809509313949281114643312710535000993", h.String())
|
||||||
|
|
||||||
|
msg := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
|
||||||
|
n := 31
|
||||||
|
msgElems := make([]*big.Int, 0, len(msg)/n+1)
|
||||||
|
for i := 0; i < len(msg)/n; i++ {
|
||||||
|
v := new(big.Int)
|
||||||
|
utils.SetBigIntFromLEBytes(v, msg[n*i:n*(i+1)])
|
||||||
|
msgElems = append(msgElems, v)
|
||||||
|
}
|
||||||
|
if len(msg)%n != 0 {
|
||||||
|
v := new(big.Int)
|
||||||
|
utils.SetBigIntFromLEBytes(v, msg[(len(msg)/n)*n:])
|
||||||
|
msgElems = append(msgElems, v)
|
||||||
|
}
|
||||||
|
hmsg, err := Hash(msgElems)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "11821124228916291136371255062457365369197326845706357273715164664419275913793", hmsg.String())
|
||||||
|
|
||||||
|
msg2 := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet.")
|
||||||
|
msg2Elems := make([]*big.Int, 0, len(msg2)/n+1)
|
||||||
|
for i := 0; i < len(msg2)/n; i++ {
|
||||||
|
v := new(big.Int)
|
||||||
|
utils.SetBigIntFromLEBytes(v, msg2[n*i:n*(i+1)])
|
||||||
|
msg2Elems = append(msg2Elems, v)
|
||||||
|
}
|
||||||
|
if len(msg2)%n != 0 {
|
||||||
|
v := new(big.Int)
|
||||||
|
utils.SetBigIntFromLEBytes(v, msg2[(len(msg2)/n)*n:])
|
||||||
|
msg2Elems = append(msg2Elems, v)
|
||||||
|
}
|
||||||
|
hmsg2, err := Hash(msg2Elems)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "10747013384255785702102976082726575658403084163954725275481577373644732938016", hmsg2.String())
|
||||||
|
|
||||||
|
hmsg2, err = HashBytes(msg2)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "10747013384255785702102976082726575658403084163954725275481577373644732938016", hmsg2.String())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user