mirror of
https://github.com/arnaucube/go-iden3-crypto.git
synced 2026-02-07 11:36:41 +01:00
Compare commits
15 Commits
feature/gi
...
feature/si
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
674e8a6739 | ||
|
|
a86308cb0b | ||
|
|
d91a4261f1 | ||
|
|
327a8175d6 | ||
|
|
833f68a614 | ||
|
|
29a66457f0 | ||
|
|
f22be3cdee | ||
|
|
2c471ab545 | ||
|
|
e134988b1b | ||
|
|
3a9171000b | ||
|
|
b1468fc076 | ||
|
|
d189a6bedc | ||
|
|
14c3144613 | ||
|
|
b98a9fe65a | ||
|
|
4d1bbacd6c |
15
.travis.yml
15
.travis.yml
@@ -1,15 +0,0 @@
|
||||
dist: xenial
|
||||
language: go
|
||||
|
||||
go:
|
||||
- "1.12"
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- name: "Unit Tests 64 bit arch"
|
||||
env: GOARCH="amd64"
|
||||
- name: "Unit Test 32 bit arch"
|
||||
env: GOARCH="386"
|
||||
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
@@ -181,6 +181,14 @@ func (p *Point) Decompress(leBuf [32]byte) (*Point, error) {
|
||||
leBuf[31] = leBuf[31] & 0x7F
|
||||
}
|
||||
utils.SetBigIntFromLEBytes(p.Y, leBuf[:])
|
||||
return PointFromSignAndY(sign, p.Y)
|
||||
}
|
||||
|
||||
// PointFromSignAndY returns a Point from a Sign and the Y coordinate
|
||||
func PointFromSignAndY(sign bool, y *big.Int) (*Point, error) {
|
||||
var p Point
|
||||
p.X = big.NewInt(0)
|
||||
p.Y = y
|
||||
if p.Y.Cmp(constants.Q) >= 0 {
|
||||
return nil, fmt.Errorf("p.y >= Q")
|
||||
}
|
||||
@@ -209,5 +217,5 @@ func (p *Point) Decompress(leBuf [32]byte) (*Point, error) {
|
||||
}
|
||||
p.X.Mod(p.X, constants.Q)
|
||||
|
||||
return p, nil
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
@@ -192,6 +192,20 @@ func TestInSubGroup2(t *testing.T) {
|
||||
assert.Equal(t, true, p.InSubGroup())
|
||||
}
|
||||
|
||||
func TestPointFromSignAndy(t *testing.T) {
|
||||
x := utils.NewIntFromString(
|
||||
"17777552123799933955779906779655732241715742912184938656739573121738514868268")
|
||||
y := utils.NewIntFromString(
|
||||
"2626589144620713026669568689430873010625803728049924121243784502389097019475")
|
||||
p := &Point{X: x, Y: y}
|
||||
|
||||
sign := PointCoordSign(p.X)
|
||||
p2, err := PointFromSignAndY(sign, p.Y)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, p.X.String(), p2.X.String())
|
||||
assert.Equal(t, p.Y.String(), p2.Y.String())
|
||||
}
|
||||
|
||||
func TestCompressDecompress1(t *testing.T) {
|
||||
x := utils.NewIntFromString(
|
||||
"17777552123799933955779906779655732241715742912184938656739573121738514868268")
|
||||
|
||||
@@ -2,6 +2,8 @@ package babyjub
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
|
||||
"github.com/iden3/go-iden3-crypto/mimc7"
|
||||
"github.com/iden3/go-iden3-crypto/poseidon"
|
||||
@@ -36,6 +38,13 @@ func NewRandPrivKey() PrivateKey {
|
||||
// Scalar converts a private key into the scalar value s following the EdDSA
|
||||
// standard, and using blake-512 hash.
|
||||
func (k *PrivateKey) Scalar() *PrivKeyScalar {
|
||||
s := SkToBigInt(k)
|
||||
return NewPrivKeyScalar(s)
|
||||
}
|
||||
|
||||
// SkToBigInt converts a private key into the *big.Int value following the
|
||||
// EdDSA standard, and using blake-512 hash
|
||||
func SkToBigInt(k *PrivateKey) *big.Int {
|
||||
sBuf := Blake512(k[:])
|
||||
sBuf32 := [32]byte{}
|
||||
copy(sBuf32[:], sBuf[:32])
|
||||
@@ -43,7 +52,7 @@ func (k *PrivateKey) Scalar() *PrivKeyScalar {
|
||||
s := new(big.Int)
|
||||
utils.SetBigIntFromLEBytes(s, sBuf32[:])
|
||||
s.Rsh(s, 3)
|
||||
return NewPrivKeyScalar(s)
|
||||
return s
|
||||
}
|
||||
|
||||
// Pub returns the public key corresponding to a private key.
|
||||
@@ -168,6 +177,27 @@ func (s *SignatureComp) Decompress() (*Signature, error) {
|
||||
return new(Signature).Decompress(*s)
|
||||
}
|
||||
|
||||
// Scan implements Scanner for database/sql.
|
||||
func (s *Signature) Scan(src interface{}) error {
|
||||
srcB, ok := src.([]byte)
|
||||
if !ok {
|
||||
return fmt.Errorf("can't scan %T into Signature", src)
|
||||
}
|
||||
if len(srcB) != 64 {
|
||||
return fmt.Errorf("can't scan []byte of len %d into Signature, want %d", len(srcB), 64)
|
||||
}
|
||||
buf := [64]byte{}
|
||||
copy(buf[:], srcB[:])
|
||||
_, err := s.Decompress(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
// Value implements valuer for database/sql.
|
||||
func (s Signature) Value() (driver.Value, error) {
|
||||
comp := s.Compress()
|
||||
return comp[:], nil
|
||||
}
|
||||
|
||||
// SignMimc7 signs a message encoded as a big.Int in Zq using blake-512 hash
|
||||
// for buffer hashing and mimc7 for big.Int hashing.
|
||||
func (k *PrivateKey) SignMimc7(msg *big.Int) *Signature {
|
||||
@@ -224,7 +254,7 @@ func (k *PrivateKey) SignPoseidon(msg *big.Int) *Signature {
|
||||
A := k.Public().Point()
|
||||
|
||||
hmInput := [poseidon.T]*big.Int{R8.X, R8.Y, A.X, A.Y, msg, big.NewInt(int64(0))}
|
||||
hm, err := poseidon.PoseidonHash(hmInput) // hm = H1(8*R.x, 8*R.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)
|
||||
}
|
||||
@@ -241,7 +271,7 @@ func (k *PrivateKey) SignPoseidon(msg *big.Int) *Signature {
|
||||
// using blake-512 hash for buffer hashing and Poseidon for big.Int hashing.
|
||||
func (p *PublicKey) VerifyPoseidon(msg *big.Int, sig *Signature) bool {
|
||||
hmInput := [poseidon.T]*big.Int{sig.R8.X, sig.R8.Y, p.X, p.Y, msg, big.NewInt(int64(0))}
|
||||
hm, err := poseidon.PoseidonHash(hmInput) // hm = H1(8*R.x, 8*R.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)
|
||||
}
|
||||
@@ -253,3 +283,28 @@ func (p *PublicKey) VerifyPoseidon(msg *big.Int, sig *Signature) bool {
|
||||
right.Add(sig.R8, right) // right = 8 * R + 8 * hm * A
|
||||
return (left.X.Cmp(right.X) == 0) && (left.Y.Cmp(right.Y) == 0)
|
||||
}
|
||||
|
||||
// Scan implements Scanner for database/sql.
|
||||
func (p *PublicKey) Scan(src interface{}) error {
|
||||
srcB, ok := src.([]byte)
|
||||
if !ok {
|
||||
return fmt.Errorf("can't scan %T into PublicKey", src)
|
||||
}
|
||||
if len(srcB) != 32 {
|
||||
return fmt.Errorf("can't scan []byte of len %d into PublicKey, want %d", len(srcB), 32)
|
||||
}
|
||||
var comp PublicKeyComp
|
||||
copy(comp[:], srcB)
|
||||
decomp, err := comp.Decompress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*p = *decomp
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements valuer for database/sql.
|
||||
func (p PublicKey) Value() (driver.Value, error) {
|
||||
comp := p.Compress()
|
||||
return comp[:], nil
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
|
||||
"github.com/iden3/go-iden3-crypto/constants"
|
||||
"github.com/iden3/go-iden3-crypto/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -132,6 +135,33 @@ func TestCompressDecompress(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignatureScannerValuer(t *testing.T) {
|
||||
privK := NewRandPrivKey()
|
||||
var value driver.Valuer
|
||||
var scan sql.Scanner
|
||||
value = privK.SignPoseidon(big.NewInt(674238462))
|
||||
scan = privK.SignPoseidon(big.NewInt(1))
|
||||
fromDB, err := value.Value()
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, scan.Scan(fromDB))
|
||||
assert.Equal(t, value, scan)
|
||||
}
|
||||
|
||||
func TestPubKeyScannerValuer(t *testing.T) {
|
||||
privKValue := NewRandPrivKey()
|
||||
pubKValue := privKValue.Public()
|
||||
privKScan := NewRandPrivKey()
|
||||
pubKScan := privKScan.Public()
|
||||
var value driver.Valuer
|
||||
var scan sql.Scanner
|
||||
value = pubKValue
|
||||
scan = pubKScan
|
||||
fromDB, err := value.Value()
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, scan.Scan(fromDB))
|
||||
assert.Equal(t, value, scan)
|
||||
}
|
||||
|
||||
func BenchmarkBabyjubEddsa(b *testing.B) {
|
||||
var k PrivateKey
|
||||
_, err := hex.Decode(k[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||
|
||||
1
go.mod
1
go.mod
@@ -7,4 +7,5 @@ require (
|
||||
github.com/ethereum/go-ethereum v1.9.12
|
||||
github.com/stretchr/testify v1.4.0
|
||||
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
|
||||
)
|
||||
|
||||
10
go.sum
10
go.sum
@@ -50,8 +50,6 @@ github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbT
|
||||
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa h1:XKAhUk/dtp+CV0VO6mhG2V7jA9vbcGcnYF/Ay9NjZrY=
|
||||
github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
|
||||
github.com/ethereum/go-ethereum v1.8.27 h1:d+gkiLaBDk5fn3Pe/xNVaMrB/ozI+AUB2IlVBp29IrY=
|
||||
github.com/ethereum/go-ethereum v1.8.27/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
|
||||
github.com/ethereum/go-ethereum v1.9.12 h1:EPtimwsp/KGDSiXcNunzsI4kefdsMHZGJntKx3fvbaI=
|
||||
github.com/ethereum/go-ethereum v1.9.12/go.mod h1:PvsVkQmhZFx92Y+h2ylythYlheEDt/uBgFbl61Js/jo=
|
||||
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
@@ -76,15 +74,16 @@ github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1
|
||||
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag=
|
||||
github.com/iden3/go-iden3 v0.0.5 h1:NV6HXnLmp+1YmKd2FmymzU6OAP77q1WWDcB/B+BUL9g=
|
||||
github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
@@ -138,8 +137,6 @@ github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:s
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A=
|
||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA=
|
||||
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -154,12 +151,15 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
|
||||
|
||||
@@ -137,7 +137,7 @@ func Hash(arr []*big.Int, key *big.Int) (*big.Int, error) {
|
||||
|
||||
// HashBytes hashes a msg byte slice by blocks of 31 bytes encoded as
|
||||
// little-endian
|
||||
func HashBytes(b []byte) (*big.Int, error) {
|
||||
func HashBytes(b []byte) *big.Int {
|
||||
n := 31
|
||||
bElems := make([]*big.Int, 0, len(b)/n+1)
|
||||
for i := 0; i < len(b)/n; i++ {
|
||||
@@ -150,5 +150,9 @@ func HashBytes(b []byte) (*big.Int, error) {
|
||||
utils.SetBigIntFromLEBytes(v, b[(len(b)/n)*n:])
|
||||
bElems = append(bElems, v)
|
||||
}
|
||||
return Hash(bElems, nil)
|
||||
h, err := Hash(bElems, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
@@ -74,8 +74,7 @@ func TestMIMC7(t *testing.T) {
|
||||
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)
|
||||
hmsg := HashBytes(msg)
|
||||
assert.Equal(t, "16855787120419064316734350414336285711017110414939748784029922801367685456065", hmsg.String())
|
||||
}
|
||||
|
||||
|
||||
@@ -120,8 +120,8 @@ func mix(state [T]*ff.Element, newState [T]*ff.Element, m [T][T]*ff.Element) {
|
||||
}
|
||||
}
|
||||
|
||||
// PoseidonHash computes the Poseidon hash for the given inputs
|
||||
func PoseidonHash(inpBI [T]*big.Int) (*big.Int, error) {
|
||||
// Hash computes the Poseidon hash for the given inputs
|
||||
func Hash(inpBI [T]*big.Int) (*big.Int, error) {
|
||||
if !utils.CheckBigIntArrayInField(inpBI[:]) {
|
||||
return nil, errors.New("inputs values not inside Finite Field")
|
||||
}
|
||||
@@ -148,9 +148,9 @@ func PoseidonHash(inpBI [T]*big.Int) (*big.Int, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Hash performs the Poseidon hash over a ff.Element array
|
||||
// HashSlice performs the Poseidon hash over a ff.Element array
|
||||
// in chunks of 5 elements
|
||||
func Hash(arr []*big.Int) (*big.Int, error) {
|
||||
func HashSlice(arr []*big.Int) (*big.Int, error) {
|
||||
r := big.NewInt(int64(1))
|
||||
for i := 0; i < len(arr); i = i + T - 1 {
|
||||
var toHash [T]*big.Int
|
||||
@@ -167,7 +167,7 @@ func Hash(arr []*big.Int) (*big.Int, error) {
|
||||
toHash[j] = big.NewInt(0)
|
||||
}
|
||||
|
||||
ph, err := PoseidonHash(toHash)
|
||||
ph, err := Hash(toHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -176,22 +176,3 @@ func Hash(arr []*big.Int) (*big.Int, error) {
|
||||
|
||||
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 := big.NewInt(int64(0))
|
||||
utils.SetBigIntFromLEBytes(v, b[n*i:n*(i+1)])
|
||||
bElems = append(bElems, v)
|
||||
|
||||
}
|
||||
if len(b)%n != 0 {
|
||||
v := big.NewInt(int64(0))
|
||||
utils.SetBigIntFromLEBytes(v, b[(len(b)/n)*n:])
|
||||
bElems = append(bElems, v)
|
||||
}
|
||||
return Hash(bElems)
|
||||
}
|
||||
|
||||
@@ -15,16 +15,31 @@ func TestBlake2bVersion(t *testing.T) {
|
||||
assert.Equal(t, "e57ba154fb2c47811dc1a2369b27e25a44915b4e4ece4eb8ec74850cb78e01b1", hex.EncodeToString(h[:]))
|
||||
}
|
||||
|
||||
func TestPoseidon(t *testing.T) {
|
||||
func TestPoseidonHash(t *testing.T) {
|
||||
b0 := big.NewInt(0)
|
||||
b1 := big.NewInt(1)
|
||||
b2 := big.NewInt(2)
|
||||
h, err := Hash([]*big.Int{b1, b2})
|
||||
h, err := Hash([T]*big.Int{b1, b2, b0, b0, b0, b0})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "12242166908188651009877250812424843524687801523336557272219921456462821518061", h.String())
|
||||
|
||||
b3 := big.NewInt(3)
|
||||
b4 := big.NewInt(4)
|
||||
h, err = Hash([T]*big.Int{b3, b4, b0, b0, b0, b0})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "17185195740979599334254027721507328033796809509313949281114643312710535000993", h.String())
|
||||
}
|
||||
|
||||
func TestPoseidonHashArbitraryLen(t *testing.T) {
|
||||
b1 := big.NewInt(1)
|
||||
b2 := big.NewInt(2)
|
||||
h, err := HashSlice([]*big.Int{b1, b2})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "4932297968297298434239270129193057052722409868268166443802652458940273154855", h.String())
|
||||
|
||||
b3 := big.NewInt(3)
|
||||
b4 := big.NewInt(4)
|
||||
h, err = Hash([]*big.Int{b3, b4})
|
||||
h, err = HashSlice([]*big.Int{b3, b4})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "4635491972858758537477743930622086396911540895966845494943021655521913507504", h.String())
|
||||
|
||||
@@ -36,7 +51,7 @@ func TestPoseidon(t *testing.T) {
|
||||
b10 := big.NewInt(10)
|
||||
b11 := big.NewInt(11)
|
||||
b12 := big.NewInt(12)
|
||||
h, err = Hash([]*big.Int{b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12})
|
||||
h, err = HashSlice([]*big.Int{b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "15278801138972282646981503374384603641625274360649669926363020545395022098027", h.String())
|
||||
|
||||
@@ -53,7 +68,7 @@ func TestPoseidon(t *testing.T) {
|
||||
utils.SetBigIntFromLEBytes(v, msg[(len(msg)/n)*n:])
|
||||
msgElems = append(msgElems, v)
|
||||
}
|
||||
hmsg, err := Hash(msgElems)
|
||||
hmsg, err := HashSlice(msgElems)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "16019700159595764790637132363672701294192939959594423814006267756172551741065", hmsg.String())
|
||||
|
||||
@@ -69,34 +84,30 @@ func TestPoseidon(t *testing.T) {
|
||||
utils.SetBigIntFromLEBytes(v, msg2[(len(msg2)/n)*n:])
|
||||
msg2Elems = append(msg2Elems, v)
|
||||
}
|
||||
hmsg2, err := Hash(msg2Elems)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "2978613163687734485261639854325792381691890647104372645321246092227111432722", hmsg2.String())
|
||||
|
||||
hmsg2, err = HashBytes(msg2)
|
||||
hmsg2, err := HashSlice(msg2Elems)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "2978613163687734485261639854325792381691890647104372645321246092227111432722", hmsg2.String())
|
||||
}
|
||||
|
||||
func TestPoseidonBrokenChunks(t *testing.T) {
|
||||
h1, err := Hash([]*big.Int{big.NewInt(0), big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(4),
|
||||
func TestPoseidonHashArbitraryLenBrokenChunks(t *testing.T) {
|
||||
h1, err := HashSlice([]*big.Int{big.NewInt(0), big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(4),
|
||||
big.NewInt(5), big.NewInt(6), big.NewInt(7), big.NewInt(8), big.NewInt(9)})
|
||||
assert.Nil(t, err)
|
||||
h2, err := Hash([]*big.Int{big.NewInt(5), big.NewInt(6), big.NewInt(7), big.NewInt(8), big.NewInt(9),
|
||||
h2, err := HashSlice([]*big.Int{big.NewInt(5), big.NewInt(6), big.NewInt(7), big.NewInt(8), big.NewInt(9),
|
||||
big.NewInt(0), big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(4)})
|
||||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, h1, h2)
|
||||
}
|
||||
|
||||
func TestPoseidonBrokenPadding(t *testing.T) {
|
||||
h1, err := Hash([]*big.Int{big.NewInt(int64(1))})
|
||||
func TestPoseidonHashArbitraryLenBrokenPadding(t *testing.T) {
|
||||
h1, err := HashSlice([]*big.Int{big.NewInt(int64(1))})
|
||||
assert.Nil(t, err)
|
||||
h2, err := Hash([]*big.Int{big.NewInt(int64(1)), big.NewInt(int64(0))})
|
||||
h2, err := HashSlice([]*big.Int{big.NewInt(int64(1)), big.NewInt(int64(0))})
|
||||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, h1, h2)
|
||||
}
|
||||
|
||||
func BenchmarkPoseidon(b *testing.B) {
|
||||
func BenchmarkPoseidonHashSmallValues(b *testing.B) {
|
||||
b12 := big.NewInt(int64(12))
|
||||
b45 := big.NewInt(int64(45))
|
||||
b78 := big.NewInt(int64(78))
|
||||
@@ -104,17 +115,16 @@ func BenchmarkPoseidon(b *testing.B) {
|
||||
bigArray4 := []*big.Int{b12, b45, b78, b41}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
Hash(bigArray4) //nolint:errcheck
|
||||
HashSlice(bigArray4) //nolint:errcheck
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPoseidonLarge(b *testing.B) {
|
||||
b12 := utils.NewIntFromString("11384336176656855268977457483345535180380036354188103142384839473266348197733")
|
||||
b45 := utils.NewIntFromString("11384336176656855268977457483345535180380036354188103142384839473266348197733")
|
||||
b78 := utils.NewIntFromString("11384336176656855268977457483345535180380036354188103142384839473266348197733")
|
||||
b41 := utils.NewIntFromString("11384336176656855268977457483345535180380036354188103142384839473266348197733")
|
||||
func BenchmarkPoseidonHash(b *testing.B) {
|
||||
b0 := big.NewInt(0)
|
||||
b1 := utils.NewIntFromString("12242166908188651009877250812424843524687801523336557272219921456462821518061")
|
||||
b2 := utils.NewIntFromString("12242166908188651009877250812424843524687801523336557272219921456462821518061")
|
||||
|
||||
bigArray4 := []*big.Int{b12, b45, b78, b41}
|
||||
bigArray4 := [T]*big.Int{b1, b2, b0, b0, b0, b0}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
Hash(bigArray4) //nolint:errcheck
|
||||
|
||||
@@ -103,6 +103,7 @@ func CheckBigIntArrayInField(arr []*big.Int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// BigIntArrayToElementArray converts an array of *big.Int into an array of *ff.Element
|
||||
func BigIntArrayToElementArray(bi []*big.Int) []*ff.Element {
|
||||
var o []*ff.Element
|
||||
for i := range bi {
|
||||
@@ -110,3 +111,15 @@ func BigIntArrayToElementArray(bi []*big.Int) []*ff.Element {
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
// ElementArrayToBigIntArray converts an array of *ff.Element into an array of *big.Int
|
||||
func ElementArrayToBigIntArray(e []*ff.Element) []*big.Int {
|
||||
var o []*big.Int
|
||||
for i := range e {
|
||||
ei := e[i]
|
||||
bi := big.NewInt(0)
|
||||
ei.ToBigIntRegular(bi)
|
||||
o = append(o, bi)
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user