Browse Source

implemented optimized poseidon (#38)

* implemented optimized poseidon

* added comment to poseidon hash function

* deleted poseidonslow
fix/bbjj-err
Mikhail Wall 3 years ago
committed by GitHub
parent
commit
933c28a8d7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24896 additions and 3480 deletions
  1. +24837
    -3448
      poseidon/constants.go
  2. +59
    -32
      poseidon/poseidon.go

+ 24837
- 3448
poseidon/constants.go
File diff suppressed because it is too large
View File


+ 59
- 32
poseidon/poseidon.go

@ -1,7 +1,6 @@
package poseidon package poseidon
import ( import (
"errors"
"fmt" "fmt"
"math/big" "math/big"
@ -17,40 +16,41 @@ func zero() *ff.Element {
return ff.NewElement() return ff.NewElement()
} }
// 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) {
for i := 0; i < len(state); i++ {
state[i].Add(state[i], c[it+i])
}
}
// exp5 performs x^5 mod p // exp5 performs x^5 mod p
// https://eprint.iacr.org/2019/458.pdf page 8 // https://eprint.iacr.org/2019/458.pdf page 8
func exp5(a *ff.Element) { func exp5(a *ff.Element) {
a.Exp(*a, 5) a.Exp(*a, 5)
} }
// sbox https://eprint.iacr.org/2019/458.pdf page 6
func sbox(nRoundsF, nRoundsP int, state []*ff.Element, i int) {
if (i < nRoundsF/2) || (i >= nRoundsF/2+nRoundsP) {
for j := 0; j < len(state); j++ {
exp5(state[j])
}
} else {
exp5(state[0])
// exp5state perform exp5 for whole state
func exp5state(state []*ff.Element) {
for i := 0; i < len(state); i++ {
exp5(state[i])
}
}
// 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) {
for i := 0; i < len(state); i++ {
state[i].Add(state[i], c[it+i])
} }
} }
// mix returns [[matrix]] * [vector] // mix returns [[matrix]] * [vector]
func mix(state []*ff.Element, newState []*ff.Element, m [][]*ff.Element) {
func mix(state []*ff.Element, t int, m [][]*ff.Element) []*ff.Element {
mul := zero() mul := zero()
newState := make([]*ff.Element, t)
for i := 0; i < t; i++ {
newState[i] = zero()
}
for i := 0; i < len(state); i++ { for i := 0; i < len(state); i++ {
newState[i].SetUint64(0) newState[i].SetUint64(0)
for j := 0; j < len(state); j++ { for j := 0; j < len(state); j++ {
mul.Mul(m[i][j], state[j])
mul.Mul(m[j][i], state[j])
newState[i].Add(newState[i], mul) newState[i].Add(newState[i], mul)
} }
} }
return newState
} }
// Hash computes the Poseidon hash for the given inputs // Hash computes the Poseidon hash for the given inputs
@ -59,29 +59,56 @@ func Hash(inpBI []*big.Int) (*big.Int, error) {
if len(inpBI) == 0 || len(inpBI) >= len(NROUNDSP)-1 { if len(inpBI) == 0 || len(inpBI) >= len(NROUNDSP)-1 {
return nil, fmt.Errorf("invalid inputs length %d, max %d", len(inpBI), len(NROUNDSP)-1) return nil, fmt.Errorf("invalid inputs length %d, max %d", len(inpBI), len(NROUNDSP)-1)
} }
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]
C := c.c[t-2]
S := c.s[t-2]
M := c.m[t-2]
P := c.p[t-2]
state := make([]*ff.Element, t) state := make([]*ff.Element, t)
state[0] = zero() state[0] = zero()
copy(state[1:], inp[:]) copy(state[1:], inp[:])
nRoundsF := NROUNDSF
nRoundsP := NROUNDSP[t-2]
ark(state, C, 0)
newState := make([]*ff.Element, t)
for i := 0; i < t; i++ {
newState[i] = zero()
for i := 0; i < nRoundsF/2-1; i++ {
exp5state(state)
ark(state, C, (i+1)*t)
state = mix(state, t, M)
}
exp5state(state)
ark(state, C, (nRoundsF/2)*t)
state = mix(state, t, P)
for i := 0; i < nRoundsP; i++ {
exp5(state[0])
state[0].Add(state[0], C[(nRoundsF/2+1)*t+i])
mul := zero()
newState0 := zero()
for j := 0; j < len(state); j++ {
mul.Mul(S[(t*2-1)*i+j], state[j])
newState0.Add(newState0, mul)
}
for k := 1; k < t; k++ {
mul = zero()
state[k] = state[k].Add(state[k], mul.Mul(state[0], S[(t*2-1)*i+t+k-1]))
}
state[0] = newState0
} }
// ARK --> SBox --> M, https://eprint.iacr.org/2019/458.pdf pag.5
for i := 0; i < nRoundsF+nRoundsP; i++ {
ark(state, c.c[t-2], i*t)
sbox(nRoundsF, nRoundsP, state, i)
mix(state, newState, c.m[t-2])
state, newState = newState, state
for i := 0; i < nRoundsF/2-1; i++ {
exp5state(state)
ark(state, C, (nRoundsF/2+1)*t+nRoundsP+i*t)
state = mix(state, t, M)
} }
exp5state(state)
state = mix(state, t, M)
rE := state[0] rE := state[0]
r := big.NewInt(0) r := big.NewInt(0)
rE.ToBigIntRegular(r) rE.ToBigIntRegular(r)

Loading…
Cancel
Save