mirror of
https://github.com/arnaucube/go-iden3-crypto.git
synced 2026-02-07 03:26:39 +01:00
Poseidon Sponge Hash with different frame sizes (#52)
* Poseidon Sponge Hash with different frame sizes * Update deps. Bump go version * Update & fix linter. * Refactor a bit. * Reduce gc pressure
This commit is contained in:
committed by
GitHub
parent
edc36bfa52
commit
e5cf066b8b
22
.github/workflows/lint.yml
vendored
22
.github/workflows/lint.yml
vendored
@@ -1,16 +1,18 @@
|
||||
name: Lint
|
||||
on: [ push, pull_request ]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.16.x
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Lint
|
||||
run: |
|
||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0
|
||||
$(go env GOPATH)/bin/golangci-lint run --timeout=5m -c .golangci.yml
|
||||
go-version: 1.20.x
|
||||
- uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: v1.51.1
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -4,7 +4,7 @@ jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 1.16.x, 1.17.x ]
|
||||
go-version: [ 1.18.x, 1.19.x, 1.20.x ]
|
||||
goarch: [ "amd64", "386" ]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -1,17 +1,77 @@
|
||||
issues:
|
||||
max-same-issues: 0
|
||||
exclude-use-default: false
|
||||
service:
|
||||
golangci-lint-version: 1.51.x
|
||||
|
||||
run:
|
||||
timeout: 2m
|
||||
skip-dirs:
|
||||
- vendor
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
revive:
|
||||
min-confidence: 0.1
|
||||
rules:
|
||||
- name: package-comments
|
||||
disabled: true
|
||||
maligned:
|
||||
suggest-new: true
|
||||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 2
|
||||
misspell:
|
||||
locale: US
|
||||
lll:
|
||||
line-length: 140
|
||||
gocritic:
|
||||
enabled-tags:
|
||||
- performance
|
||||
- style
|
||||
- experimental
|
||||
disabled-checks:
|
||||
- hugeParam
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- whitespace
|
||||
- gosec
|
||||
- gci
|
||||
- bodyclose
|
||||
- megacheck
|
||||
- revive
|
||||
- govet
|
||||
- unconvert
|
||||
- megacheck
|
||||
- gas
|
||||
- gocyclo
|
||||
- dupl
|
||||
- misspell
|
||||
- gomnd
|
||||
- gofmt
|
||||
- goimports
|
||||
- lll
|
||||
- golint
|
||||
linters-settings:
|
||||
lll:
|
||||
line-length: 100
|
||||
- unparam
|
||||
- typecheck
|
||||
- ineffassign
|
||||
- stylecheck
|
||||
- exportloopref
|
||||
- nakedret
|
||||
- gosimple
|
||||
- prealloc
|
||||
- unused
|
||||
|
||||
## format - fill free to fix
|
||||
# - errcheck
|
||||
# - gofmt
|
||||
# - goimports
|
||||
fast: false
|
||||
disable-all: true
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
# - Fix and remove
|
||||
- text: "at least one file in a package should have a package comment"
|
||||
linters:
|
||||
- stylecheck
|
||||
# - Fix and remove
|
||||
- text: "should have a package comment, unless it's in another file for this package"
|
||||
linters:
|
||||
- revive
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gosec
|
||||
- dupl
|
||||
exclude-use-default: false
|
||||
|
||||
@@ -87,7 +87,7 @@ func (p *PointProjective) Affine() *Point {
|
||||
|
||||
// Add computes the addition of two points in projective coordinates
|
||||
// representation
|
||||
func (p *PointProjective) Add(q *PointProjective, o *PointProjective) *PointProjective {
|
||||
func (p *PointProjective) Add(q, o *PointProjective) *PointProjective {
|
||||
// add-2008-bbjlp
|
||||
// https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
|
||||
a := ff.NewElement().Mul(q.Z, o.Z)
|
||||
@@ -209,7 +209,7 @@ func PointCoordSign(c *big.Int) bool {
|
||||
func PackSignY(sign bool, y *big.Int) [32]byte {
|
||||
leBuf := utils.BigIntLEBytes(y)
|
||||
if sign {
|
||||
leBuf[31] = leBuf[31] | 0x80 //nolint:gomnd
|
||||
leBuf[31] |= 0x80 //nolint:gomnd
|
||||
}
|
||||
return leBuf
|
||||
}
|
||||
@@ -225,7 +225,7 @@ func UnpackSignY(leBuf [32]byte) (bool, *big.Int) {
|
||||
y := big.NewInt(0)
|
||||
if (leBuf[31] & 0x80) != 0x00 { //nolint:gomnd
|
||||
sign = true
|
||||
leBuf[31] = leBuf[31] & 0x7F //nolint:gomnd
|
||||
leBuf[31] &= 0x7F //nolint:gomnd
|
||||
}
|
||||
utils.SetBigIntFromLEBytes(y, leBuf[:])
|
||||
return sign, y
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Package babyjub eddsa implements the EdDSA over the BabyJubJub curve
|
||||
//
|
||||
//nolint:gomnd
|
||||
package babyjub
|
||||
|
||||
@@ -16,9 +17,9 @@ import (
|
||||
// pruneBuffer prunes the buffer during key generation according to RFC 8032.
|
||||
// https://tools.ietf.org/html/rfc8032#page-13
|
||||
func pruneBuffer(buf *[32]byte) *[32]byte {
|
||||
buf[0] = buf[0] & 0xF8
|
||||
buf[31] = buf[31] & 0x7F
|
||||
buf[31] = buf[31] | 0x40
|
||||
buf[0] &= 0xF8
|
||||
buf[31] &= 0x7F
|
||||
buf[31] |= 0x40
|
||||
return buf
|
||||
}
|
||||
|
||||
@@ -210,7 +211,7 @@ func (sComp *SignatureComp) Scan(src interface{}) error {
|
||||
if len(srcB) != 64 {
|
||||
return fmt.Errorf("can't scan []byte of len %d into Signature, want %d", len(srcB), 64)
|
||||
}
|
||||
copy(sComp[:], srcB[:])
|
||||
copy(sComp[:], srcB)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -229,7 +230,7 @@ func (s *Signature) Scan(src interface{}) error {
|
||||
return fmt.Errorf("can't scan []byte of len %d into Signature, want %d", len(srcB), 64)
|
||||
}
|
||||
buf := [64]byte{}
|
||||
copy(buf[:], srcB[:])
|
||||
copy(buf[:], srcB)
|
||||
_, err := s.Decompress(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
// the original blake from the SHA3 competition and not the new blake2 version.
|
||||
func Blake512(m []byte) []byte {
|
||||
h := blake512.New()
|
||||
_, err := h.Write(m[:])
|
||||
_, err := h.Write(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -1,31 +1,19 @@
|
||||
package constants
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
const qString = "21888242871839275222246405745257275088548364400416034343698204186575808495617"
|
||||
|
||||
// Q is the order of the integer field (Zq) that fits inside the SNARK.
|
||||
var Q *big.Int
|
||||
var Q, _ = new(big.Int).SetString(qString, 10)
|
||||
|
||||
// Zero is 0.
|
||||
var Zero *big.Int
|
||||
var Zero = big.NewInt(0)
|
||||
|
||||
// One is 1.
|
||||
var One *big.Int
|
||||
var One = big.NewInt(1)
|
||||
|
||||
// MinusOne is -1.
|
||||
var MinusOne *big.Int
|
||||
|
||||
func init() {
|
||||
Zero = big.NewInt(0)
|
||||
One = big.NewInt(1)
|
||||
MinusOne = big.NewInt(-1)
|
||||
|
||||
qString := "21888242871839275222246405745257275088548364400416034343698204186575808495617"
|
||||
var ok bool
|
||||
Q, ok = new(big.Int).SetString(qString, 10) //nolint:gomnd
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Bad base 10 string %s", qString))
|
||||
}
|
||||
}
|
||||
var MinusOne = big.NewInt(-1)
|
||||
|
||||
19
go.mod
19
go.mod
@@ -1,14 +1,17 @@
|
||||
module github.com/iden3/go-iden3-crypto
|
||||
|
||||
go 1.16
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/dchest/blake512 v1.0.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
|
||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||
github.com/leanovate/gopter v0.2.9 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
github.com/leanovate/gopter v0.2.9
|
||||
github.com/stretchr/testify v1.8.2
|
||||
golang.org/x/crypto v0.7.0
|
||||
golang.org/x/sys v0.6.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
30
go.sum
30
go.sum
@@ -1,5 +1,6 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchest/blake512 v1.0.0 h1:oDFEQFIqFSeuA34xLtXZ/rWxCXdSjirjzPhey5EUvmA=
|
||||
github.com/dchest/blake512 v1.0.0/go.mod h1:FV1x7xPPLWukZlpDpWQ88rF/SFwZ5qbskrzhLMB92JI=
|
||||
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
|
||||
@@ -7,21 +8,18 @@ github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -3,9 +3,13 @@ package poseidon
|
||||
import "github.com/iden3/go-iden3-crypto/ffg"
|
||||
|
||||
const (
|
||||
NROUNDSF = 8 //nolint:golint
|
||||
NROUNDSP = 22 //nolint:golint
|
||||
CAPLEN = 4 //nolint:golint
|
||||
// NROUNDSF const from original paper
|
||||
NROUNDSF = 8
|
||||
// NROUNDSP const from original paper
|
||||
NROUNDSP = 22
|
||||
// CAPLEN const
|
||||
CAPLEN = 4
|
||||
// mLen const
|
||||
mLen = 12
|
||||
)
|
||||
|
||||
|
||||
@@ -10,9 +10,11 @@ func zero() *ffg.Element {
|
||||
return ffg.NewElement()
|
||||
}
|
||||
|
||||
var big7 = big.NewInt(7)
|
||||
|
||||
// exp7 performs x^7 mod p
|
||||
func exp7(a *ffg.Element) {
|
||||
a.Exp(*a, big.NewInt(7)) //nolint:gomnd
|
||||
a.Exp(*a, big7)
|
||||
}
|
||||
|
||||
// exp7state perform exp7 for whole state
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package poseidon
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/iden3/go-iden3-crypto/poseidon"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -99,32 +97,11 @@ func TestPoseidonHashCompare(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
func BenchmarkPoseidonHash12Inputs(b *testing.B) {
|
||||
bigArray12 := []*big.Int{
|
||||
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),
|
||||
big.NewInt(10),
|
||||
big.NewInt(11),
|
||||
big.NewInt(12),
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
poseidon.Hash(bigArray12) //nolint:errcheck,gosec
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNeptuneHash(b *testing.B) {
|
||||
inp := [NROUNDSF]uint64{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
cap := [CAPLEN]uint64{10, 11, 12, 13}
|
||||
_cap := [CAPLEN]uint64{10, 11, 12, 13}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
Hash(inp, cap) //nolint:errcheck,gosec
|
||||
_, _ = Hash(inp, _cap)
|
||||
}
|
||||
}
|
||||
|
||||
21
keccak256/keccac256_test.go
Normal file
21
keccak256/keccac256_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package keccak256
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestKeccak256(t *testing.T) {
|
||||
const SEED = "mimc"
|
||||
res := Hash([]byte(SEED))
|
||||
assert.Equal(t,
|
||||
"b6e489e6b37224a50bebfddbe7d89fa8fdcaa84304a70bd13f79b5d9f7951e9e",
|
||||
hex.EncodeToString(res))
|
||||
c := new(big.Int).SetBytes(Hash([]byte(SEED)))
|
||||
assert.Equal(t,
|
||||
"82724731331859054037315113496710413141112897654334566532528783843265082629790",
|
||||
c.String())
|
||||
}
|
||||
@@ -23,22 +23,22 @@ type constantsData struct {
|
||||
}
|
||||
|
||||
func generateConstantsData() constantsData {
|
||||
var constants constantsData
|
||||
var consts constantsData
|
||||
|
||||
constants.seedHash = new(big.Int).SetBytes(keccak256.Hash([]byte(SEED)))
|
||||
consts.seedHash = new(big.Int).SetBytes(keccak256.Hash([]byte(SEED)))
|
||||
c := new(big.Int).SetBytes(keccak256.Hash([]byte(SEED + "_iv")))
|
||||
constants.iv = new(big.Int).Mod(c, _constants.Q)
|
||||
consts.iv = new(big.Int).Mod(c, _constants.Q)
|
||||
|
||||
constants.nRounds = 91
|
||||
cts := getConstants(SEED, constants.nRounds)
|
||||
constants.cts = cts
|
||||
return constants
|
||||
consts.nRounds = 91
|
||||
cts := getConstants(SEED, consts.nRounds)
|
||||
consts.cts = cts
|
||||
return consts
|
||||
}
|
||||
|
||||
func getConstants(seed string, nRounds int) []*ff.Element {
|
||||
cts := make([]*ff.Element, nRounds)
|
||||
cts[0] = ff.NewElement()
|
||||
c := new(big.Int).SetBytes(keccak256.Hash([]byte(SEED)))
|
||||
c := new(big.Int).SetBytes(keccak256.Hash([]byte(seed)))
|
||||
for i := 1; i < nRounds; i++ {
|
||||
c = new(big.Int).SetBytes(keccak256.Hash(c.Bytes()))
|
||||
|
||||
|
||||
@@ -5,21 +5,9 @@ import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/iden3/go-iden3-crypto/keccak256"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestKeccak256(t *testing.T) {
|
||||
res := keccak256.Hash([]byte(SEED))
|
||||
assert.Equal(t,
|
||||
"b6e489e6b37224a50bebfddbe7d89fa8fdcaa84304a70bd13f79b5d9f7951e9e",
|
||||
hex.EncodeToString(res))
|
||||
c := new(big.Int).SetBytes(keccak256.Hash([]byte(SEED)))
|
||||
assert.Equal(t,
|
||||
"82724731331859054037315113496710413141112897654334566532528783843265082629790",
|
||||
c.String())
|
||||
}
|
||||
|
||||
func TestMIMC7Generic(t *testing.T) {
|
||||
b1 := big.NewInt(int64(1))
|
||||
b2 := big.NewInt(int64(2))
|
||||
@@ -36,7 +24,7 @@ func TestMIMC7Generic(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t,
|
||||
"6464402164086696096195815557694604139393321133243036833927490113253119343397",
|
||||
(*big.Int)(hg).String())
|
||||
hg.String())
|
||||
}
|
||||
|
||||
func TestMIMC7(t *testing.T) {
|
||||
@@ -51,7 +39,7 @@ func TestMIMC7(t *testing.T) {
|
||||
h1, err := Hash(bigArray1, nil)
|
||||
assert.Nil(t, err)
|
||||
// same hash value than the iden3js and circomlib tests:
|
||||
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h1).Bytes()),
|
||||
assert.Equal(t, "0x"+hex.EncodeToString(h1.Bytes()),
|
||||
"0x237c92644dbddb86d8a259e0e923aaab65a93f1ec5758b8799988894ac0958fd")
|
||||
|
||||
// h2a, hash of 2 elements
|
||||
@@ -60,7 +48,7 @@ func TestMIMC7(t *testing.T) {
|
||||
h2a, err := Hash(bigArray2a, nil)
|
||||
assert.Nil(t, err)
|
||||
// same hash value than the iden3js and circomlib tests:
|
||||
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h2a).Bytes()),
|
||||
assert.Equal(t, "0x"+hex.EncodeToString(h2a.Bytes()),
|
||||
"0x067f3202335ea256ae6e6aadcd2d5f7f4b06a00b2d1e0de903980d5ab552dc70")
|
||||
|
||||
// h2b, hash of 2 elements
|
||||
@@ -68,13 +56,13 @@ func TestMIMC7(t *testing.T) {
|
||||
|
||||
mh2b := MIMC7Hash(b12, b45)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(mh2b).Bytes()),
|
||||
assert.Equal(t, "0x"+hex.EncodeToString(mh2b.Bytes()),
|
||||
"0x2ba7ebad3c6b6f5a20bdecba2333c63173ca1a5f2f49d958081d9fa7179c44e4")
|
||||
|
||||
h2b, err := Hash(bigArray2b, nil)
|
||||
assert.Nil(t, err)
|
||||
// same hash value than the iden3js and circomlib tests:
|
||||
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h2b).Bytes()),
|
||||
assert.Equal(t, "0x"+hex.EncodeToString(h2b.Bytes()),
|
||||
"0x15ff7fe9793346a17c3150804bcb36d161c8662b110c50f55ccb7113948d8879")
|
||||
|
||||
// h4, hash of 4 elements
|
||||
@@ -83,7 +71,7 @@ func TestMIMC7(t *testing.T) {
|
||||
h4, err := Hash(bigArray4, nil)
|
||||
assert.Nil(t, err)
|
||||
// same hash value than the iden3js and circomlib tests:
|
||||
assert.Equal(t, "0x"+hex.EncodeToString((*big.Int)(h4).Bytes()),
|
||||
assert.Equal(t, "0x"+hex.EncodeToString(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.") //nolint:lll
|
||||
@@ -101,6 +89,6 @@ func BenchmarkMIMC7(b *testing.B) {
|
||||
bigArray4 := []*big.Int{b12, b45, b78, b41}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
Hash(bigArray4, nil) //nolint:errcheck,gosec
|
||||
_, _ = Hash(bigArray4, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:lll
|
||||
//nolint:lll,dupl // long lines, duplicated parts
|
||||
var cs = constantsStr{
|
||||
C: [][]string{{
|
||||
"9c46e9ec68e9bd4fe1faaba294cba38a71aa177534cdd1b6c7dc0dbd0abd7a7",
|
||||
|
||||
@@ -9,9 +9,11 @@ import (
|
||||
"github.com/iden3/go-iden3-crypto/utils"
|
||||
)
|
||||
|
||||
const NROUNDSF = 8 //nolint:golint
|
||||
// NROUNDSF constant from Poseidon paper
|
||||
const NROUNDSF = 8
|
||||
|
||||
var NROUNDSP = []int{56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68} //nolint:golint
|
||||
// NROUNDSP constant from Poseidon paper
|
||||
var NROUNDSP = []int{56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68}
|
||||
|
||||
const spongeChunkSize = 31
|
||||
const spongeInputs = 16
|
||||
@@ -20,10 +22,12 @@ func zero() *ff.Element {
|
||||
return ff.NewElement()
|
||||
}
|
||||
|
||||
var big5 = big.NewInt(5)
|
||||
|
||||
// exp5 performs x^5 mod p
|
||||
// https://eprint.iacr.org/2019/458.pdf page 8
|
||||
func exp5(a *ff.Element) {
|
||||
a.Exp(*a, big.NewInt(5)) //nolint:gomnd
|
||||
a.Exp(*a, big5)
|
||||
}
|
||||
|
||||
// exp5state perform exp5 for whole state
|
||||
@@ -34,7 +38,7 @@ func exp5state(state []*ff.Element) {
|
||||
}
|
||||
|
||||
// ark computes Add-Round Key, from the paper https://eprint.iacr.org/2019/458.pdf
|
||||
func ark(state []*ff.Element, c []*ff.Element, it int) {
|
||||
func ark(state, c []*ff.Element, it int) {
|
||||
for i := 0; i < len(state); i++ {
|
||||
state[i].Add(state[i], c[it+i])
|
||||
}
|
||||
@@ -61,12 +65,12 @@ func mix(state []*ff.Element, t int, m [][]*ff.Element) []*ff.Element {
|
||||
func Hash(inpBI []*big.Int) (*big.Int, error) {
|
||||
t := len(inpBI) + 1
|
||||
if len(inpBI) == 0 || len(inpBI) > len(NROUNDSP) {
|
||||
return nil, fmt.Errorf("invalid inputs length %d, max %d", len(inpBI), len(NROUNDSP)) //nolint:gomnd,lll
|
||||
return nil, fmt.Errorf("invalid inputs length %d, max %d", len(inpBI), len(NROUNDSP))
|
||||
}
|
||||
if !utils.CheckBigIntArrayInField(inpBI[:]) {
|
||||
if !utils.CheckBigIntArrayInField(inpBI) {
|
||||
return nil, errors.New("inputs values not inside Finite Field")
|
||||
}
|
||||
inp := utils.BigIntArrayToElementArray(inpBI[:])
|
||||
inp := utils.BigIntArrayToElementArray(inpBI)
|
||||
|
||||
nRoundsF := NROUNDSF
|
||||
nRoundsP := NROUNDSP[t-2]
|
||||
@@ -77,7 +81,7 @@ func Hash(inpBI []*big.Int) (*big.Int, error) {
|
||||
|
||||
state := make([]*ff.Element, t)
|
||||
state[0] = zero()
|
||||
copy(state[1:], inp[:])
|
||||
copy(state[1:], inp)
|
||||
|
||||
ark(state, C, 0)
|
||||
|
||||
@@ -90,11 +94,12 @@ func Hash(inpBI []*big.Int) (*big.Int, error) {
|
||||
ark(state, C, (nRoundsF/2)*t)
|
||||
state = mix(state, t, P)
|
||||
|
||||
mul := zero()
|
||||
for i := 0; i < nRoundsP; i++ {
|
||||
exp5(state[0])
|
||||
state[0].Add(state[0], C[(nRoundsF/2+1)*t+i])
|
||||
|
||||
mul := zero()
|
||||
mul.SetZero()
|
||||
newState0 := zero()
|
||||
for j := 0; j < len(state); j++ {
|
||||
mul.Mul(S[(t*2-1)*i+j], state[j])
|
||||
@@ -102,7 +107,7 @@ func Hash(inpBI []*big.Int) (*big.Int, error) {
|
||||
}
|
||||
|
||||
for k := 1; k < t; k++ {
|
||||
mul = zero()
|
||||
mul.SetZero()
|
||||
state[k] = state[k].Add(state[k], mul.Mul(state[0], S[(t*2-1)*i+t+k-1]))
|
||||
}
|
||||
state[0] = newState0
|
||||
@@ -124,9 +129,18 @@ func Hash(inpBI []*big.Int) (*big.Int, error) {
|
||||
|
||||
// HashBytes returns a sponge hash of a msg byte slice split into blocks of 31 bytes
|
||||
func HashBytes(msg []byte) (*big.Int, error) {
|
||||
return HashBytesX(msg, spongeInputs)
|
||||
}
|
||||
|
||||
// HashBytesX returns a sponge hash of a msg byte slice split into blocks of 31 bytes
|
||||
func HashBytesX(msg []byte, frameSize int) (*big.Int, error) {
|
||||
if frameSize < 2 || frameSize > 16 {
|
||||
return nil, errors.New("incorrect frame size")
|
||||
}
|
||||
|
||||
// not used inputs default to zero
|
||||
inputs := make([]*big.Int, spongeInputs)
|
||||
for j := 0; j < spongeInputs; j++ {
|
||||
inputs := make([]*big.Int, frameSize)
|
||||
for j := 0; j < frameSize; j++ {
|
||||
inputs[j] = new(big.Int)
|
||||
}
|
||||
dirty := false
|
||||
@@ -137,15 +151,15 @@ func HashBytes(msg []byte) (*big.Int, error) {
|
||||
for i := 0; i < len(msg)/spongeChunkSize; i++ {
|
||||
dirty = true
|
||||
inputs[k].SetBytes(msg[spongeChunkSize*i : spongeChunkSize*(i+1)])
|
||||
if k == spongeInputs-1 {
|
||||
if k == frameSize-1 {
|
||||
hash, err = Hash(inputs)
|
||||
dirty = false
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inputs = make([]*big.Int, spongeInputs)
|
||||
inputs = make([]*big.Int, frameSize)
|
||||
inputs[0] = hash
|
||||
for j := 1; j < spongeInputs; j++ {
|
||||
for j := 1; j < frameSize; j++ {
|
||||
inputs[j] = new(big.Int)
|
||||
}
|
||||
k = 1
|
||||
@@ -174,3 +188,55 @@ func HashBytes(msg []byte) (*big.Int, error) {
|
||||
|
||||
return hash, nil
|
||||
}
|
||||
|
||||
// SpongeHash returns a sponge hash of inputs (using Poseidon with frame size of 16 inputs)
|
||||
func SpongeHash(inputs []*big.Int) (*big.Int, error) {
|
||||
return SpongeHashX(inputs, spongeInputs)
|
||||
}
|
||||
|
||||
// SpongeHashX returns a sponge hash of inputs using Poseidon with configurable frame size
|
||||
func SpongeHashX(inputs []*big.Int, frameSize int) (*big.Int, error) {
|
||||
if frameSize < 2 || frameSize > 16 {
|
||||
return nil, errors.New("incorrect frame size")
|
||||
}
|
||||
|
||||
// not used frame default to zero
|
||||
frame := make([]*big.Int, frameSize)
|
||||
for j := 0; j < frameSize; j++ {
|
||||
frame[j] = new(big.Int)
|
||||
}
|
||||
dirty := false
|
||||
var hash *big.Int
|
||||
var err error
|
||||
|
||||
k := 0
|
||||
for i := 0; i < len(inputs); i++ {
|
||||
dirty = true
|
||||
frame[k] = inputs[i]
|
||||
if k == frameSize-1 {
|
||||
hash, err = Hash(frame)
|
||||
dirty = false
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frame = make([]*big.Int, frameSize)
|
||||
frame[0] = hash
|
||||
for j := 1; j < frameSize; j++ {
|
||||
frame[j] = new(big.Int)
|
||||
}
|
||||
k = 1
|
||||
} else {
|
||||
k++
|
||||
}
|
||||
}
|
||||
|
||||
if dirty {
|
||||
// we haven't hashed something in the main sponge loop and need to do hash here
|
||||
hash, err = Hash(frame)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return hash, nil
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -46,7 +46,7 @@ func SetBigIntFromLEBytes(v *big.Int, leBuf []byte) *big.Int {
|
||||
return v.SetBytes(beBuf)
|
||||
}
|
||||
|
||||
// Hex is a byte slice type that can be marshalled and unmarshaled in hex
|
||||
// Hex is a byte slice type that can be marshaled and unmarshaled in hex
|
||||
type Hex []byte
|
||||
|
||||
// MarshalText encodes buf as hex
|
||||
@@ -72,7 +72,7 @@ func HexDecode(h string) ([]byte, error) {
|
||||
|
||||
// HexDecodeInto decodes a hex string into an array of bytes (dst), verifying
|
||||
// that the decoded array has the same length as dst.
|
||||
func HexDecodeInto(dst []byte, h []byte) error {
|
||||
func HexDecodeInto(dst, h []byte) error {
|
||||
if bytes.HasPrefix(h, []byte("0x")) {
|
||||
h = h[2:]
|
||||
}
|
||||
@@ -105,21 +105,21 @@ func CheckBigIntArrayInField(arr []*big.Int) bool {
|
||||
|
||||
// BigIntArrayToElementArray converts an array of *big.Int into an array of *ff.Element
|
||||
func BigIntArrayToElementArray(bi []*big.Int) []*ff.Element {
|
||||
var o []*ff.Element
|
||||
o := make([]*ff.Element, len(bi))
|
||||
for i := range bi {
|
||||
o = append(o, ff.NewElement().SetBigInt(bi[i]))
|
||||
o[i] = ff.NewElement().SetBigInt(bi[i])
|
||||
}
|
||||
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
|
||||
o := make([]*big.Int, len(e))
|
||||
for i := range e {
|
||||
ei := e[i]
|
||||
bi := big.NewInt(0)
|
||||
ei.ToBigIntRegular(bi)
|
||||
o = append(o, bi)
|
||||
o[i] = bi
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user