mirror of
https://github.com/arnaucube/go-iden3-crypto.git
synced 2026-02-07 19:46:41 +01:00
init commit for the golden poseidon
This commit is contained in:
30
ffg/arith.go
Normal file
30
ffg/arith.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2020 ConsenSys Software Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by consensys/gnark-crypto DO NOT EDIT
|
||||
|
||||
package ffg
|
||||
|
||||
import (
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// madd0 hi = a*b + c (discards lo bits)
|
||||
func madd0(a, b, c uint64) (hi uint64) {
|
||||
var carry, lo uint64
|
||||
hi, lo = bits.Mul64(a, b)
|
||||
_, carry = bits.Add64(lo, c, 0)
|
||||
hi, _ = bits.Add64(hi, 0, carry)
|
||||
return
|
||||
}
|
||||
24
ffg/asm.go
Normal file
24
ffg/asm.go
Normal file
@@ -0,0 +1,24 @@
|
||||
//go:build !noadx
|
||||
// +build !noadx
|
||||
|
||||
// Copyright 2020 ConsenSys Software Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by consensys/gnark-crypto DO NOT EDIT
|
||||
|
||||
package ffg
|
||||
|
||||
import "golang.org/x/sys/cpu"
|
||||
|
||||
var supportAdx = cpu.X86.HasADX && cpu.X86.HasBMI2
|
||||
25
ffg/asm_noadx.go
Normal file
25
ffg/asm_noadx.go
Normal file
@@ -0,0 +1,25 @@
|
||||
//go:build noadx
|
||||
// +build noadx
|
||||
|
||||
// Copyright 2020 ConsenSys Software Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by consensys/gnark-crypto DO NOT EDIT
|
||||
|
||||
package ffg
|
||||
|
||||
// note: this is needed for test purposes, as dynamically changing supportAdx doesn't flag
|
||||
// certain errors (like fatal error: missing stackmap)
|
||||
// this ensures we test all asm path.
|
||||
var supportAdx = false
|
||||
43
ffg/doc.go
Normal file
43
ffg/doc.go
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright 2020 ConsenSys Software Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by consensys/gnark-crypto DO NOT EDIT
|
||||
|
||||
// Package ffg contains field arithmetic operations for modulus = 0xffffff...000001.
|
||||
//
|
||||
// The API is similar to math/big (big.Int), but the operations are significantly faster (up to 20x for the modular multiplication on amd64, see also https://hackmd.io/@zkteam/modular_multiplication)
|
||||
//
|
||||
// The modulus is hardcoded in all the operations.
|
||||
//
|
||||
// Field elements are represented as an array, and assumed to be in Montgomery form in all methods:
|
||||
// type Element [1]uint64
|
||||
//
|
||||
// Example API signature
|
||||
// // Mul z = x * y mod q
|
||||
// func (z *Element) Mul(x, y *Element) *Element
|
||||
//
|
||||
// and can be used like so:
|
||||
// var a, b Element
|
||||
// a.SetUint64(2)
|
||||
// b.SetString("984896738")
|
||||
// a.Mul(a, b)
|
||||
// a.Sub(a, a)
|
||||
// .Add(a, b)
|
||||
// .Inv(a)
|
||||
// b.Exp(b, new(big.Int).SetUint64(42))
|
||||
//
|
||||
// Modulus
|
||||
// 0xffffffff00000001 // base 16
|
||||
// 18446744069414584321 // base 10
|
||||
package ffg
|
||||
763
ffg/element.go
Normal file
763
ffg/element.go
Normal file
@@ -0,0 +1,763 @@
|
||||
// Copyright 2020 ConsenSys Software Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by consensys/gnark-crypto DO NOT EDIT
|
||||
|
||||
package ffg
|
||||
|
||||
// /!\ WARNING /!\
|
||||
// this code has not been audited and is provided as-is. In particular,
|
||||
// there is no security guarantees such as constant time implementation
|
||||
// or side-channel attack resistance
|
||||
// /!\ WARNING /!\
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
"math/bits"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Element represents a field element stored on 1 words (uint64)
|
||||
// Element are assumed to be in Montgomery form in all methods
|
||||
// field modulus q =
|
||||
//
|
||||
// 18446744069414584321
|
||||
type Element [1]uint64
|
||||
|
||||
// Limbs number of 64 bits words needed to represent Element
|
||||
const Limbs = 1
|
||||
|
||||
// Bits number bits needed to represent Element
|
||||
const Bits = 64
|
||||
|
||||
// Bytes number bytes needed to represent Element
|
||||
const Bytes = Limbs * 8
|
||||
|
||||
// field modulus stored as big.Int
|
||||
var _modulus big.Int
|
||||
|
||||
// Modulus returns q as a big.Int
|
||||
// q =
|
||||
//
|
||||
// 18446744069414584321
|
||||
func Modulus() *big.Int {
|
||||
return new(big.Int).Set(&_modulus)
|
||||
}
|
||||
|
||||
// q (modulus)
|
||||
var qElement = Element{
|
||||
18446744069414584321,
|
||||
}
|
||||
|
||||
// rSquare
|
||||
var rSquare = Element{
|
||||
18446744065119617025,
|
||||
}
|
||||
|
||||
var bigIntPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(big.Int)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
_modulus.SetString("18446744069414584321", 10)
|
||||
}
|
||||
|
||||
// NewElement returns a new Element
|
||||
func NewElement() *Element {
|
||||
return &Element{}
|
||||
}
|
||||
|
||||
// NewElementFromUint64 returns a new Element from a uint64 value
|
||||
//
|
||||
// it is equivalent to
|
||||
// var v NewElement
|
||||
// v.SetUint64(...)
|
||||
func NewElementFromUint64(v uint64) *Element {
|
||||
z := Element{v}
|
||||
z.Mul(&z, &rSquare)
|
||||
return &z
|
||||
}
|
||||
|
||||
// SetUint64 z = v, sets z LSB to v (non-Montgomery form) and convert z to Montgomery form
|
||||
func (z *Element) SetUint64(v uint64) *Element {
|
||||
*z = Element{v}
|
||||
return z.Mul(z, &rSquare) // z.ToMont()
|
||||
}
|
||||
|
||||
// Set z = x
|
||||
func (z *Element) Set(x *Element) *Element {
|
||||
z[0] = x[0]
|
||||
return z
|
||||
}
|
||||
|
||||
// SetInterface converts provided interface into Element
|
||||
// returns an error if provided type is not supported
|
||||
// supported types: Element, *Element, uint64, int, string (interpreted as base10 integer),
|
||||
// *big.Int, big.Int, []byte
|
||||
func (z *Element) SetInterface(i1 interface{}) (*Element, error) {
|
||||
switch c1 := i1.(type) {
|
||||
case Element:
|
||||
return z.Set(&c1), nil
|
||||
case *Element:
|
||||
return z.Set(c1), nil
|
||||
case uint64:
|
||||
return z.SetUint64(c1), nil
|
||||
case int:
|
||||
return z.SetString(strconv.Itoa(c1)), nil
|
||||
case string:
|
||||
return z.SetString(c1), nil
|
||||
case *big.Int:
|
||||
return z.SetBigInt(c1), nil
|
||||
case big.Int:
|
||||
return z.SetBigInt(&c1), nil
|
||||
case []byte:
|
||||
return z.SetBytes(c1), nil
|
||||
default:
|
||||
return nil, errors.New("can't set ffg.Element from type " + reflect.TypeOf(i1).String())
|
||||
}
|
||||
}
|
||||
|
||||
// SetZero z = 0
|
||||
func (z *Element) SetZero() *Element {
|
||||
z[0] = 0
|
||||
return z
|
||||
}
|
||||
|
||||
// SetOne z = 1 (in Montgomery form)
|
||||
func (z *Element) SetOne() *Element {
|
||||
z[0] = 4294967295
|
||||
return z
|
||||
}
|
||||
|
||||
// Div z = x*y^-1 mod q
|
||||
func (z *Element) Div(x, y *Element) *Element {
|
||||
var yInv Element
|
||||
yInv.Inverse(y)
|
||||
z.Mul(x, &yInv)
|
||||
return z
|
||||
}
|
||||
|
||||
// Bit returns the i'th bit, with lsb == bit 0.
|
||||
// It is the responsability of the caller to convert from Montgomery to Regular form if needed
|
||||
func (z *Element) Bit(i uint64) uint64 {
|
||||
j := i / 64
|
||||
if j >= 1 {
|
||||
return 0
|
||||
}
|
||||
return uint64(z[j] >> (i % 64) & 1)
|
||||
}
|
||||
|
||||
// Equal returns z == x
|
||||
func (z *Element) Equal(x *Element) bool {
|
||||
return (z[0] == x[0])
|
||||
}
|
||||
|
||||
// IsZero returns z == 0
|
||||
func (z *Element) IsZero() bool {
|
||||
return (z[0]) == 0
|
||||
}
|
||||
|
||||
// IsUint64 returns true if z[0] >= 0 and all other words are 0
|
||||
func (z *Element) IsUint64() bool {
|
||||
// return () == 0
|
||||
return true
|
||||
}
|
||||
|
||||
// Cmp compares (lexicographic order) z and x and returns:
|
||||
//
|
||||
// -1 if z < x
|
||||
// 0 if z == x
|
||||
// +1 if z > x
|
||||
//
|
||||
func (z *Element) Cmp(x *Element) int {
|
||||
_z := *z
|
||||
_x := *x
|
||||
_z.FromMont()
|
||||
_x.FromMont()
|
||||
if _z[0] > _x[0] {
|
||||
return 1
|
||||
} else if _z[0] < _x[0] {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// LexicographicallyLargest returns true if this element is strictly lexicographically
|
||||
// larger than its negation, false otherwise
|
||||
func (z *Element) LexicographicallyLargest() bool {
|
||||
// adapted from github.com/zkcrypto/bls12_381
|
||||
// we check if the element is larger than (q-1) / 2
|
||||
// if z - (((q -1) / 2) + 1) have no underflow, then z > (q-1) / 2
|
||||
|
||||
_z := *z
|
||||
_z.FromMont()
|
||||
|
||||
var b uint64
|
||||
_, b = bits.Sub64(_z[0], 9223372034707292161, 0)
|
||||
|
||||
return b == 0
|
||||
}
|
||||
|
||||
// SetRandom sets z to a random element < q
|
||||
func (z *Element) SetRandom() (*Element, error) {
|
||||
var bytes [8]byte
|
||||
if _, err := io.ReadFull(rand.Reader, bytes[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
z[0] = binary.BigEndian.Uint64(bytes[0:8])
|
||||
z[0] %= 18446744069414584321
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(z[0] < 18446744069414584321) {
|
||||
// var b uint64
|
||||
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0)
|
||||
}
|
||||
|
||||
return z, nil
|
||||
}
|
||||
|
||||
// One returns 1 (in montgommery form)
|
||||
func One() Element {
|
||||
var one Element
|
||||
one.SetOne()
|
||||
return one
|
||||
}
|
||||
|
||||
// Halve sets z to z / 2 (mod p)
|
||||
func (z *Element) Halve() {
|
||||
var twoInv Element
|
||||
twoInv.SetOne().Double(&twoInv).Inverse(&twoInv)
|
||||
z.Mul(z, &twoInv)
|
||||
|
||||
}
|
||||
|
||||
// API with assembly impl
|
||||
|
||||
// Mul z = x * y mod q
|
||||
// see https://hackmd.io/@zkteam/modular_multiplication
|
||||
func (z *Element) Mul(x, y *Element) *Element {
|
||||
mul(z, x, y)
|
||||
return z
|
||||
}
|
||||
|
||||
// Square z = x * x mod q
|
||||
// see https://hackmd.io/@zkteam/modular_multiplication
|
||||
func (z *Element) Square(x *Element) *Element {
|
||||
mul(z, x, x)
|
||||
return z
|
||||
}
|
||||
|
||||
// FromMont converts z in place (i.e. mutates) from Montgomery to regular representation
|
||||
// sets and returns z = z * 1
|
||||
func (z *Element) FromMont() *Element {
|
||||
fromMont(z)
|
||||
return z
|
||||
}
|
||||
|
||||
// Add z = x + y mod q
|
||||
func (z *Element) Add(x, y *Element) *Element {
|
||||
add(z, x, y)
|
||||
return z
|
||||
}
|
||||
|
||||
// Double z = x + x mod q, aka Lsh 1
|
||||
func (z *Element) Double(x *Element) *Element {
|
||||
double(z, x)
|
||||
return z
|
||||
}
|
||||
|
||||
// Sub z = x - y mod q
|
||||
func (z *Element) Sub(x, y *Element) *Element {
|
||||
sub(z, x, y)
|
||||
return z
|
||||
}
|
||||
|
||||
// Neg z = q - x
|
||||
func (z *Element) Neg(x *Element) *Element {
|
||||
neg(z, x)
|
||||
return z
|
||||
}
|
||||
|
||||
// Generic (no ADX instructions, no AMD64) versions of multiplication and squaring algorithms
|
||||
|
||||
func _mulGeneric(z, x, y *Element) {
|
||||
|
||||
var t [2]uint64
|
||||
var D uint64
|
||||
var m, C uint64
|
||||
// -----------------------------------
|
||||
// First loop
|
||||
|
||||
C, t[0] = bits.Mul64(y[0], x[0])
|
||||
|
||||
t[1], D = bits.Add64(t[1], C, 0)
|
||||
|
||||
// m = t[0]n'[0] mod W
|
||||
m = t[0] * 18446744069414584319
|
||||
|
||||
// -----------------------------------
|
||||
// Second loop
|
||||
C = madd0(m, 18446744069414584321, t[0])
|
||||
|
||||
t[0], C = bits.Add64(t[1], C, 0)
|
||||
t[1], _ = bits.Add64(0, D, C)
|
||||
|
||||
if t[1] != 0 {
|
||||
// we need to reduce, we have a result on 2 words
|
||||
// var b uint64
|
||||
z[0], _ = bits.Sub64(t[0], 18446744069414584321, 0)
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// copy t into z
|
||||
z[0] = t[0]
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(z[0] < 18446744069414584321) {
|
||||
// var b uint64
|
||||
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func _fromMontGeneric(z *Element) {
|
||||
// the following lines implement z = z * 1
|
||||
// with a modified CIOS montgomery multiplication
|
||||
{
|
||||
// m = z[0]n'[0] mod W
|
||||
m := z[0] * 18446744069414584319
|
||||
C := madd0(m, 18446744069414584321, z[0])
|
||||
z[0] = C
|
||||
}
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(z[0] < 18446744069414584321) {
|
||||
// var b uint64
|
||||
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func _addGeneric(z, x, y *Element) {
|
||||
var carry uint64
|
||||
|
||||
z[0], carry = bits.Add64(x[0], y[0], 0)
|
||||
// if we overflowed the last addition, z >= q
|
||||
// if z >= q, z = z - q
|
||||
if carry != 0 {
|
||||
// we overflowed, so z >= q
|
||||
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0)
|
||||
return
|
||||
}
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(z[0] < 18446744069414584321) {
|
||||
// var b uint64
|
||||
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func _doubleGeneric(z, x *Element) {
|
||||
var carry uint64
|
||||
|
||||
z[0], carry = bits.Add64(x[0], x[0], 0)
|
||||
// if we overflowed the last addition, z >= q
|
||||
// if z >= q, z = z - q
|
||||
if carry != 0 {
|
||||
// we overflowed, so z >= q
|
||||
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0)
|
||||
return
|
||||
}
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(z[0] < 18446744069414584321) {
|
||||
// var b uint64
|
||||
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func _subGeneric(z, x, y *Element) {
|
||||
var b uint64
|
||||
z[0], b = bits.Sub64(x[0], y[0], 0)
|
||||
if b != 0 {
|
||||
// var c uint64
|
||||
z[0], _ = bits.Add64(z[0], 18446744069414584321, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func _negGeneric(z, x *Element) {
|
||||
if x.IsZero() {
|
||||
z.SetZero()
|
||||
return
|
||||
}
|
||||
// var borrow uint64
|
||||
z[0], _ = bits.Sub64(18446744069414584321, x[0], 0)
|
||||
}
|
||||
|
||||
func _reduceGeneric(z *Element) {
|
||||
|
||||
// if z > q --> z -= q
|
||||
// note: this is NOT constant time
|
||||
if !(z[0] < 18446744069414584321) {
|
||||
// var b uint64
|
||||
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func mulByConstant(z *Element, c uint8) {
|
||||
switch c {
|
||||
case 0:
|
||||
z.SetZero()
|
||||
return
|
||||
case 1:
|
||||
return
|
||||
case 2:
|
||||
z.Double(z)
|
||||
return
|
||||
case 3:
|
||||
_z := *z
|
||||
z.Double(z).Add(z, &_z)
|
||||
case 5:
|
||||
_z := *z
|
||||
z.Double(z).Double(z).Add(z, &_z)
|
||||
default:
|
||||
var y Element
|
||||
y.SetUint64(uint64(c))
|
||||
z.Mul(z, &y)
|
||||
}
|
||||
}
|
||||
|
||||
// BatchInvert returns a new slice with every element inverted.
|
||||
// Uses Montgomery batch inversion trick
|
||||
func BatchInvert(a []Element) []Element {
|
||||
res := make([]Element, len(a))
|
||||
if len(a) == 0 {
|
||||
return res
|
||||
}
|
||||
|
||||
zeroes := make([]bool, len(a))
|
||||
accumulator := One()
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
if a[i].IsZero() {
|
||||
zeroes[i] = true
|
||||
continue
|
||||
}
|
||||
res[i] = accumulator
|
||||
accumulator.Mul(&accumulator, &a[i])
|
||||
}
|
||||
|
||||
accumulator.Inverse(&accumulator)
|
||||
|
||||
for i := len(a) - 1; i >= 0; i-- {
|
||||
if zeroes[i] {
|
||||
continue
|
||||
}
|
||||
res[i].Mul(&res[i], &accumulator)
|
||||
accumulator.Mul(&accumulator, &a[i])
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func _butterflyGeneric(a, b *Element) {
|
||||
t := *a
|
||||
a.Add(a, b)
|
||||
b.Sub(&t, b)
|
||||
}
|
||||
|
||||
// BitLen returns the minimum number of bits needed to represent z
|
||||
// returns 0 if z == 0
|
||||
func (z *Element) BitLen() int {
|
||||
return bits.Len64(z[0])
|
||||
}
|
||||
|
||||
// Exp z = x^exponent mod q
|
||||
func (z *Element) Exp(x Element, exponent *big.Int) *Element {
|
||||
var bZero big.Int
|
||||
if exponent.Cmp(&bZero) == 0 {
|
||||
return z.SetOne()
|
||||
}
|
||||
|
||||
z.Set(&x)
|
||||
|
||||
for i := exponent.BitLen() - 2; i >= 0; i-- {
|
||||
z.Square(z)
|
||||
if exponent.Bit(i) == 1 {
|
||||
z.Mul(z, &x)
|
||||
}
|
||||
}
|
||||
|
||||
return z
|
||||
}
|
||||
|
||||
// ToMont converts z to Montgomery form
|
||||
// sets and returns z = z * r^2
|
||||
func (z *Element) ToMont() *Element {
|
||||
return z.Mul(z, &rSquare)
|
||||
}
|
||||
|
||||
// ToRegular returns z in regular form (doesn't mutate z)
|
||||
func (z Element) ToRegular() Element {
|
||||
return *z.FromMont()
|
||||
}
|
||||
|
||||
// String returns the string form of an Element in Montgomery form
|
||||
func (z *Element) String() string {
|
||||
zz := *z
|
||||
zz.FromMont()
|
||||
if zz.IsUint64() {
|
||||
return strconv.FormatUint(zz[0], 10)
|
||||
} else {
|
||||
var zzNeg Element
|
||||
zzNeg.Neg(z)
|
||||
zzNeg.FromMont()
|
||||
if zzNeg.IsUint64() {
|
||||
return "-" + strconv.FormatUint(zzNeg[0], 10)
|
||||
}
|
||||
}
|
||||
vv := bigIntPool.Get().(*big.Int)
|
||||
defer bigIntPool.Put(vv)
|
||||
return zz.ToBigInt(vv).String()
|
||||
}
|
||||
|
||||
// ToBigInt returns z as a big.Int in Montgomery form
|
||||
func (z *Element) ToBigInt(res *big.Int) *big.Int {
|
||||
var b [Limbs * 8]byte
|
||||
binary.BigEndian.PutUint64(b[0:8], z[0])
|
||||
|
||||
return res.SetBytes(b[:])
|
||||
}
|
||||
|
||||
// ToBigIntRegular returns z as a big.Int in regular form
|
||||
func (z Element) ToBigIntRegular(res *big.Int) *big.Int {
|
||||
z.FromMont()
|
||||
return z.ToBigInt(res)
|
||||
}
|
||||
|
||||
// Bytes returns the regular (non montgomery) value
|
||||
// of z as a big-endian byte array.
|
||||
func (z *Element) Bytes() (res [Limbs * 8]byte) {
|
||||
_z := z.ToRegular()
|
||||
binary.BigEndian.PutUint64(res[0:8], _z[0])
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Marshal returns the regular (non montgomery) value
|
||||
// of z as a big-endian byte slice.
|
||||
func (z *Element) Marshal() []byte {
|
||||
b := z.Bytes()
|
||||
return b[:]
|
||||
}
|
||||
|
||||
// SetBytes interprets e as the bytes of a big-endian unsigned integer,
|
||||
// sets z to that value (in Montgomery form), and returns z.
|
||||
func (z *Element) SetBytes(e []byte) *Element {
|
||||
// get a big int from our pool
|
||||
vv := bigIntPool.Get().(*big.Int)
|
||||
vv.SetBytes(e)
|
||||
|
||||
// set big int
|
||||
z.SetBigInt(vv)
|
||||
|
||||
// put temporary object back in pool
|
||||
bigIntPool.Put(vv)
|
||||
|
||||
return z
|
||||
}
|
||||
|
||||
// SetBigInt sets z to v (regular form) and returns z in Montgomery form
|
||||
func (z *Element) SetBigInt(v *big.Int) *Element {
|
||||
z.SetZero()
|
||||
|
||||
var zero big.Int
|
||||
|
||||
// fast path
|
||||
c := v.Cmp(&_modulus)
|
||||
if c == 0 {
|
||||
// v == 0
|
||||
return z
|
||||
} else if c != 1 && v.Cmp(&zero) != -1 {
|
||||
// 0 < v < q
|
||||
return z.setBigInt(v)
|
||||
}
|
||||
|
||||
// get temporary big int from the pool
|
||||
vv := bigIntPool.Get().(*big.Int)
|
||||
|
||||
// copy input + modular reduction
|
||||
vv.Set(v)
|
||||
vv.Mod(v, &_modulus)
|
||||
|
||||
// set big int byte value
|
||||
z.setBigInt(vv)
|
||||
|
||||
// release object into pool
|
||||
bigIntPool.Put(vv)
|
||||
return z
|
||||
}
|
||||
|
||||
// setBigInt assumes 0 <= v < q
|
||||
func (z *Element) setBigInt(v *big.Int) *Element {
|
||||
vBits := v.Bits()
|
||||
|
||||
if bits.UintSize == 64 {
|
||||
for i := 0; i < len(vBits); i++ {
|
||||
z[i] = uint64(vBits[i])
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < len(vBits); i++ {
|
||||
if i%2 == 0 {
|
||||
z[i/2] = uint64(vBits[i])
|
||||
} else {
|
||||
z[i/2] |= uint64(vBits[i]) << 32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return z.ToMont()
|
||||
}
|
||||
|
||||
// SetString creates a big.Int with s (in base 10) and calls SetBigInt on z
|
||||
func (z *Element) SetString(s string) *Element {
|
||||
// get temporary big int from the pool
|
||||
vv := bigIntPool.Get().(*big.Int)
|
||||
|
||||
if _, ok := vv.SetString(s, 10); !ok {
|
||||
panic("Element.SetString failed -> can't parse number in base10 into a big.Int")
|
||||
}
|
||||
z.SetBigInt(vv)
|
||||
|
||||
// release object into pool
|
||||
bigIntPool.Put(vv)
|
||||
|
||||
return z
|
||||
}
|
||||
|
||||
var (
|
||||
_bLegendreExponentElement *big.Int
|
||||
_bSqrtExponentElement *big.Int
|
||||
)
|
||||
|
||||
func init() {
|
||||
_bLegendreExponentElement, _ = new(big.Int).SetString("7fffffff80000000", 16)
|
||||
const sqrtExponentElement = "7fffffff"
|
||||
_bSqrtExponentElement, _ = new(big.Int).SetString(sqrtExponentElement, 16)
|
||||
}
|
||||
|
||||
// Legendre returns the Legendre symbol of z (either +1, -1, or 0.)
|
||||
func (z *Element) Legendre() int {
|
||||
var l Element
|
||||
// z^((q-1)/2)
|
||||
l.Exp(*z, _bLegendreExponentElement)
|
||||
|
||||
if l.IsZero() {
|
||||
return 0
|
||||
}
|
||||
|
||||
// if l == 1
|
||||
if l[0] == 4294967295 {
|
||||
return 1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Sqrt z = √x mod q
|
||||
// if the square root doesn't exist (x is not a square mod q)
|
||||
// Sqrt leaves z unchanged and returns nil
|
||||
func (z *Element) Sqrt(x *Element) *Element {
|
||||
// q ≡ 1 (mod 4)
|
||||
// see modSqrtTonelliShanks in math/big/int.go
|
||||
// using https://www.maa.org/sites/default/files/pdf/upload_library/22/Polya/07468342.di020786.02p0470a.pdf
|
||||
|
||||
var y, b, t, w Element
|
||||
// w = x^((s-1)/2))
|
||||
w.Exp(*x, _bSqrtExponentElement)
|
||||
|
||||
// y = x^((s+1)/2)) = w * x
|
||||
y.Mul(x, &w)
|
||||
|
||||
// b = x^s = w * w * x = y * x
|
||||
b.Mul(&w, &y)
|
||||
|
||||
// g = nonResidue ^ s
|
||||
var g = Element{
|
||||
15733474329512464024,
|
||||
}
|
||||
r := uint64(32)
|
||||
|
||||
// compute legendre symbol
|
||||
// t = x^((q-1)/2) = r-1 squaring of x^s
|
||||
t = b
|
||||
for i := uint64(0); i < r-1; i++ {
|
||||
t.Square(&t)
|
||||
}
|
||||
if t.IsZero() {
|
||||
return z.SetZero()
|
||||
}
|
||||
if !(t[0] == 4294967295) {
|
||||
// t != 1, we don't have a square root
|
||||
return nil
|
||||
}
|
||||
for {
|
||||
var m uint64
|
||||
t = b
|
||||
|
||||
// for t != 1
|
||||
for !(t[0] == 4294967295) {
|
||||
t.Square(&t)
|
||||
m++
|
||||
}
|
||||
|
||||
if m == 0 {
|
||||
return z.Set(&y)
|
||||
}
|
||||
// t = g^(2^(r-m-1)) mod q
|
||||
ge := int(r - m - 1)
|
||||
t = g
|
||||
for ge > 0 {
|
||||
t.Square(&t)
|
||||
ge--
|
||||
}
|
||||
|
||||
g.Square(&t)
|
||||
y.Mul(&y, &t)
|
||||
b.Mul(&b, &g)
|
||||
r = m
|
||||
}
|
||||
}
|
||||
|
||||
// Inverse z = x^-1 mod q
|
||||
// note: allocates a big.Int (math/big)
|
||||
func (z *Element) Inverse(x *Element) *Element {
|
||||
var _xNonMont big.Int
|
||||
x.ToBigIntRegular(&_xNonMont)
|
||||
_xNonMont.ModInverse(&_xNonMont, Modulus())
|
||||
z.SetBigInt(&_xNonMont)
|
||||
return z
|
||||
}
|
||||
113
ffg/element_fuzz.go
Normal file
113
ffg/element_fuzz.go
Normal file
@@ -0,0 +1,113 @@
|
||||
//go:build gofuzz
|
||||
// +build gofuzz
|
||||
|
||||
// Copyright 2020 ConsenSys Software Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by consensys/gnark-crypto DO NOT EDIT
|
||||
|
||||
package ffg
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"math/big"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
const (
|
||||
fuzzInteresting = 1
|
||||
fuzzNormal = 0
|
||||
fuzzDiscard = -1
|
||||
)
|
||||
|
||||
// Fuzz arithmetic operations fuzzer
|
||||
func Fuzz(data []byte) int {
|
||||
r := bytes.NewReader(data)
|
||||
|
||||
var e1, e2 Element
|
||||
e1.SetRawBytes(r)
|
||||
e2.SetRawBytes(r)
|
||||
|
||||
{
|
||||
// mul assembly
|
||||
|
||||
var c, _c Element
|
||||
a, _a, b, _b := e1, e1, e2, e2
|
||||
c.Mul(&a, &b)
|
||||
_mulGeneric(&_c, &_a, &_b)
|
||||
|
||||
if !c.Equal(&_c) {
|
||||
panic("mul asm != mul generic on Element")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// inverse
|
||||
inv := e1
|
||||
inv.Inverse(&inv)
|
||||
|
||||
var bInv, b1, b2 big.Int
|
||||
e1.ToBigIntRegular(&b1)
|
||||
bInv.ModInverse(&b1, Modulus())
|
||||
inv.ToBigIntRegular(&b2)
|
||||
|
||||
if b2.Cmp(&bInv) != 0 {
|
||||
panic("inverse operation doesn't match big int result")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// a + -a == 0
|
||||
a, b := e1, e1
|
||||
b.Neg(&b)
|
||||
a.Add(&a, &b)
|
||||
if !a.IsZero() {
|
||||
panic("a + -a != 0")
|
||||
}
|
||||
}
|
||||
|
||||
return fuzzNormal
|
||||
|
||||
}
|
||||
|
||||
// SetRawBytes reads up to Bytes (bytes needed to represent Element) from reader
|
||||
// and interpret it as big endian uint64
|
||||
// used for fuzzing purposes only
|
||||
func (z *Element) SetRawBytes(r io.Reader) {
|
||||
|
||||
buf := make([]byte, 8)
|
||||
|
||||
for i := 0; i < len(z); i++ {
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
goto eof
|
||||
}
|
||||
z[i] = binary.BigEndian.Uint64(buf[:])
|
||||
}
|
||||
eof:
|
||||
z[0] %= qElement[0]
|
||||
|
||||
if z.BiggerModulus() {
|
||||
var b uint64
|
||||
z[0], b = bits.Sub64(z[0], qElement[0], 0)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (z *Element) BiggerModulus() bool {
|
||||
|
||||
return z[0] >= qElement[0]
|
||||
}
|
||||
17
ffg/element_ops_amd64.go
Normal file
17
ffg/element_ops_amd64.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2020 ConsenSys Software Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by consensys/gnark-crypto DO NOT EDIT
|
||||
|
||||
package ffg
|
||||
75
ffg/element_ops_noasm.go
Normal file
75
ffg/element_ops_noasm.go
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2020 ConsenSys Software Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by consensys/gnark-crypto DO NOT EDIT
|
||||
|
||||
package ffg
|
||||
|
||||
// /!\ WARNING /!\
|
||||
// this code has not been audited and is provided as-is. In particular,
|
||||
// there is no security guarantees such as constant time implementation
|
||||
// or side-channel attack resistance
|
||||
// /!\ WARNING /!\
|
||||
|
||||
// MulBy3 x *= 3
|
||||
func MulBy3(x *Element) {
|
||||
mulByConstant(x, 3)
|
||||
}
|
||||
|
||||
// MulBy5 x *= 5
|
||||
func MulBy5(x *Element) {
|
||||
mulByConstant(x, 5)
|
||||
}
|
||||
|
||||
// MulBy13 x *= 13
|
||||
func MulBy13(x *Element) {
|
||||
mulByConstant(x, 13)
|
||||
}
|
||||
|
||||
// Butterfly sets
|
||||
// a = a + b
|
||||
// b = a - b
|
||||
func Butterfly(a, b *Element) {
|
||||
_butterflyGeneric(a, b)
|
||||
}
|
||||
|
||||
func mul(z, x, y *Element) {
|
||||
_mulGeneric(z, x, y)
|
||||
}
|
||||
|
||||
// FromMont converts z in place (i.e. mutates) from Montgomery to regular representation
|
||||
// sets and returns z = z * 1
|
||||
func fromMont(z *Element) {
|
||||
_fromMontGeneric(z)
|
||||
}
|
||||
|
||||
func add(z, x, y *Element) {
|
||||
_addGeneric(z, x, y)
|
||||
}
|
||||
|
||||
func double(z, x *Element) {
|
||||
_doubleGeneric(z, x)
|
||||
}
|
||||
|
||||
func sub(z, x, y *Element) {
|
||||
_subGeneric(z, x, y)
|
||||
}
|
||||
|
||||
func neg(z, x *Element) {
|
||||
_negGeneric(z, x)
|
||||
}
|
||||
|
||||
func reduce(z *Element) {
|
||||
_reduceGeneric(z)
|
||||
}
|
||||
1833
ffg/element_test.go
Normal file
1833
ffg/element_test.go
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user