mirror of
https://github.com/logos-storage/nim-poseidon2.git
synced 2026-02-17 04:03:17 +00:00
107 lines
2.8 KiB
Nim
107 lines
2.8 KiB
Nim
|
|
import
|
|
constantine/math/arithmetic,
|
|
constantine/math/io/io_fields,
|
|
constantine/math/io/io_bigints
|
|
|
|
import ../poseidon2/types
|
|
import ./roundconst
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
const expo_inv : B = fromHex(B,"0x26b6a528b427b35493736af8679aad17535cb9d394945a0dcfe7f7a98ccccccd")
|
|
|
|
const alpha : F = fromHex(F,"0x146ecffb34a66316fae66609f78d1310bc14ad7208082ca7943afebb1da4aa4a")
|
|
const beta : F = fromHex(F,"0x2b568115d544c7e941eff6ccc935384619b0fb7d2c5ba6c078c34cf81697ee1c")
|
|
|
|
const roundConstArray : array[33, F] = arrayFromHex( roundConstStr )
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
# inplace sbox, x => x^5
|
|
proc pow5(x: var F) : void =
|
|
var y = x
|
|
square(y)
|
|
square(y)
|
|
x *= y
|
|
|
|
# inplace sbox, x => x^(1/5)
|
|
proc powInv5(x: var F) : void =
|
|
x = fastPow(x, expo_inv)
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
proc sbox(x, y, z: var F) =
|
|
x.powInv5()
|
|
y.pow5()
|
|
let u : F = x + y
|
|
var m = beta
|
|
m += sqr(u)
|
|
m += alpha * u # m = u^2 + alpha*u + beta
|
|
z *= m
|
|
|
|
proc addRC(round: int, x, y, z: var F) =
|
|
if (round > 0):
|
|
let j = (round-1) * 3
|
|
x += roundConstArray[ j ]
|
|
y += roundConstArray[ j+1 ]
|
|
z += roundConstArray[ j+2 ]
|
|
|
|
proc linear(x, y, z : var F) =
|
|
var s = x ; s += y ; s += z
|
|
x += s
|
|
y += s
|
|
z += s
|
|
|
|
proc roundFun(round: int, x, y, z: var F) =
|
|
addRC(round,x,y,z)
|
|
sbox(x,y,z)
|
|
linear(x,y,z)
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
# the Griffin permutation (mutable, in-place version)
|
|
proc permInPlace*(x, y, z : var F) =
|
|
linear(x, y, z)
|
|
for j in 0..<12:
|
|
roundFun(j, x, y, z)
|
|
|
|
# the Griffin permutation (pure version)
|
|
func perm*(xyz: S) : S =
|
|
var (x,y,z) = xyz
|
|
permInPlace(x, y, z)
|
|
return (x,y,z)
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
# known-answer test: the expected permutation of (0,1,2)
|
|
const kat: S =
|
|
( F.fromHex("0x2311cdb3076c3a7ee37fd5a271e0f3a8a3cc38057d0cea37b78951f43b1b6ff6")
|
|
, F.fromHex("0x1d3aaed9ea361e899e667abd18e5328555b97b5c3890d52b261f940d6ab4df58")
|
|
, F.fromHex("0x22614a0ac719cb623a636adac3bac1b85b5a7a418fcf8ab3a3ae0787fb4bed9d")
|
|
)
|
|
|
|
proc sanityCheckExpoInv*() =
|
|
let x0 : F = F.fromHex("0x666")
|
|
var x : F = x0
|
|
x.pow5()
|
|
x.powInv5()
|
|
echo "sanity check /a = " & $(x == x0)
|
|
let y0 : F = F.fromHex("0x777017")
|
|
var y : F = y0
|
|
y.powInv5()
|
|
y.pow5()
|
|
echo "sanity check /b = " & $(y == y0)
|
|
|
|
proc testGriffin*() =
|
|
sanityCheckExpoInv()
|
|
let inp: S = (zero,one,two)
|
|
let candidate = perm(inp)
|
|
let (x,y,z) = candidate
|
|
echo "x = " & $x.toDecimal()
|
|
echo "y = " & $y.toDecimal()
|
|
echo "z = " & $z.toDecimal()
|
|
echo "KAT ok = " & $(candidate == kat)
|
|
|
|
#-------------------------------------------------------------------------------
|