mirror of
https://github.com/sonr-io/crypto.git
synced 2026-08-02 15:31:38 +00:00
No commit suggestions generated
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
//
|
||||
// Copyright Coinbase, Inc. All Rights Reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package fp
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"sync"
|
||||
|
||||
"github.com/sonr-io/sonr/crypto/core/curves/native"
|
||||
)
|
||||
|
||||
var (
|
||||
p256FpInitonce sync.Once
|
||||
p256FpParams native.FieldParams
|
||||
)
|
||||
|
||||
func P256FpNew() *native.Field {
|
||||
return &native.Field{
|
||||
Value: [native.FieldLimbs]uint64{},
|
||||
Params: getP256FpParams(),
|
||||
Arithmetic: p256FpArithmetic{},
|
||||
}
|
||||
}
|
||||
|
||||
func p256FpParamsInit() {
|
||||
// See FIPS 186-3, section D.2.3
|
||||
p256FpParams = native.FieldParams{
|
||||
R: [native.FieldLimbs]uint64{
|
||||
0x0000000000000001,
|
||||
0xffffffff00000000,
|
||||
0xffffffffffffffff,
|
||||
0x00000000fffffffe,
|
||||
},
|
||||
R2: [native.FieldLimbs]uint64{
|
||||
0x0000000000000003,
|
||||
0xfffffffbffffffff,
|
||||
0xfffffffffffffffe,
|
||||
0x00000004fffffffd,
|
||||
},
|
||||
R3: [native.FieldLimbs]uint64{
|
||||
0xfffffffd0000000a,
|
||||
0xffffffedfffffff7,
|
||||
0x00000005fffffffc,
|
||||
0x0000001800000001,
|
||||
},
|
||||
Modulus: [native.FieldLimbs]uint64{
|
||||
0xffffffffffffffff,
|
||||
0x00000000ffffffff,
|
||||
0x0000000000000000,
|
||||
0xffffffff00000001,
|
||||
},
|
||||
BiModulus: new(big.Int).SetBytes([]byte{
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func getP256FpParams() *native.FieldParams {
|
||||
p256FpInitonce.Do(p256FpParamsInit)
|
||||
return &p256FpParams
|
||||
}
|
||||
|
||||
// p256FpArithmetic is a struct with all the methods needed for working
|
||||
// in mod q
|
||||
type p256FpArithmetic struct{}
|
||||
|
||||
// ToMontgomery converts this field to montgomery form
|
||||
func (f p256FpArithmetic) ToMontgomery(out, arg *[native.FieldLimbs]uint64) {
|
||||
ToMontgomery((*MontgomeryDomainFieldElement)(out), (*NonMontgomeryDomainFieldElement)(arg))
|
||||
}
|
||||
|
||||
// FromMontgomery converts this field from montgomery form
|
||||
func (f p256FpArithmetic) FromMontgomery(out, arg *[native.FieldLimbs]uint64) {
|
||||
FromMontgomery((*NonMontgomeryDomainFieldElement)(out), (*MontgomeryDomainFieldElement)(arg))
|
||||
}
|
||||
|
||||
// Neg performs modular negation
|
||||
func (f p256FpArithmetic) Neg(out, arg *[native.FieldLimbs]uint64) {
|
||||
Opp((*MontgomeryDomainFieldElement)(out), (*MontgomeryDomainFieldElement)(arg))
|
||||
}
|
||||
|
||||
// Square performs modular square
|
||||
func (f p256FpArithmetic) Square(out, arg *[native.FieldLimbs]uint64) {
|
||||
Square((*MontgomeryDomainFieldElement)(out), (*MontgomeryDomainFieldElement)(arg))
|
||||
}
|
||||
|
||||
// Mul performs modular multiplication
|
||||
func (f p256FpArithmetic) Mul(out, arg1, arg2 *[native.FieldLimbs]uint64) {
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(out),
|
||||
(*MontgomeryDomainFieldElement)(arg1),
|
||||
(*MontgomeryDomainFieldElement)(arg2),
|
||||
)
|
||||
}
|
||||
|
||||
// Add performs modular addition
|
||||
func (f p256FpArithmetic) Add(out, arg1, arg2 *[native.FieldLimbs]uint64) {
|
||||
Add(
|
||||
(*MontgomeryDomainFieldElement)(out),
|
||||
(*MontgomeryDomainFieldElement)(arg1),
|
||||
(*MontgomeryDomainFieldElement)(arg2),
|
||||
)
|
||||
}
|
||||
|
||||
// Sub performs modular subtraction
|
||||
func (f p256FpArithmetic) Sub(out, arg1, arg2 *[native.FieldLimbs]uint64) {
|
||||
Sub(
|
||||
(*MontgomeryDomainFieldElement)(out),
|
||||
(*MontgomeryDomainFieldElement)(arg1),
|
||||
(*MontgomeryDomainFieldElement)(arg2),
|
||||
)
|
||||
}
|
||||
|
||||
// Sqrt performs modular square root
|
||||
func (f p256FpArithmetic) Sqrt(wasSquare *int, out, arg *[native.FieldLimbs]uint64) {
|
||||
// Use p = 3 mod 4 by Euler's criterion means
|
||||
// arg^((p+1)/4 mod p
|
||||
var t, c [native.FieldLimbs]uint64
|
||||
c1 := [native.FieldLimbs]uint64{
|
||||
0x0000_0000_0000_0000,
|
||||
0x0000_0000_4000_0000,
|
||||
0x4000_0000_0000_0000,
|
||||
0x3fff_ffff_c000_0000,
|
||||
}
|
||||
native.Pow(&t, arg, &c1, getP256FpParams(), f)
|
||||
Square((*MontgomeryDomainFieldElement)(&c), (*MontgomeryDomainFieldElement)(&t))
|
||||
*wasSquare = (&native.Field{Value: c, Params: getP256FpParams(), Arithmetic: f}).Equal(
|
||||
&native.Field{
|
||||
Value: *arg, Params: getP256FpParams(), Arithmetic: f,
|
||||
},
|
||||
)
|
||||
Selectznz(out, uint1(*wasSquare), out, &t)
|
||||
}
|
||||
|
||||
// Invert performs modular inverse
|
||||
func (f p256FpArithmetic) Invert(wasInverted *int, out, arg *[native.FieldLimbs]uint64) {
|
||||
// Fermat's Little Theorem
|
||||
// a ^ (p - 2) mod p
|
||||
//
|
||||
// The exponent pattern (from high to low) is:
|
||||
// - 32 bits of value 1
|
||||
// - 31 bits of value 0
|
||||
// - 1 bit of value 1
|
||||
// - 96 bits of value 0
|
||||
// - 94 bits of value 1
|
||||
// - 1 bit of value 0
|
||||
// - 1 bit of value 1
|
||||
// To speed up the square-and-multiply algorithm, precompute a^(2^31-1).
|
||||
//
|
||||
// Courtesy of Thomas Pornin
|
||||
//
|
||||
var t, r [native.FieldLimbs]uint64
|
||||
copy(t[:], arg[:])
|
||||
|
||||
for i := 0; i < 30; i++ {
|
||||
f.Square(&t, &t)
|
||||
f.Mul(&t, &t, arg)
|
||||
}
|
||||
copy(r[:], t[:])
|
||||
for i := 224; i >= 0; i-- {
|
||||
f.Square(&r, &r)
|
||||
switch i {
|
||||
case 0:
|
||||
fallthrough
|
||||
case 2:
|
||||
fallthrough
|
||||
case 192:
|
||||
fallthrough
|
||||
case 224:
|
||||
f.Mul(&r, &r, arg)
|
||||
case 3:
|
||||
fallthrough
|
||||
case 34:
|
||||
fallthrough
|
||||
case 65:
|
||||
f.Mul(&r, &r, &t)
|
||||
}
|
||||
}
|
||||
|
||||
*wasInverted = (&native.Field{
|
||||
Value: *arg,
|
||||
Params: getP256FpParams(),
|
||||
Arithmetic: f,
|
||||
}).IsNonZero()
|
||||
Selectznz(out, uint1(*wasInverted), out, &r)
|
||||
}
|
||||
|
||||
// FromBytes converts a little endian byte array into a field element
|
||||
func (f p256FpArithmetic) FromBytes(out *[native.FieldLimbs]uint64, arg *[native.FieldBytes]byte) {
|
||||
FromBytes(out, arg)
|
||||
}
|
||||
|
||||
// ToBytes converts a field element to a little endian byte array
|
||||
func (f p256FpArithmetic) ToBytes(out *[native.FieldBytes]byte, arg *[native.FieldLimbs]uint64) {
|
||||
ToBytes(out, arg)
|
||||
}
|
||||
|
||||
// Selectznz performs conditional select.
|
||||
// selects arg1 if choice == 0 and arg2 if choice == 1
|
||||
func (f p256FpArithmetic) Selectznz(out, arg1, arg2 *[native.FieldLimbs]uint64, choice int) {
|
||||
Selectznz(out, uint1(choice), arg1, arg2)
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
//
|
||||
// Copyright Coinbase, Inc. All Rights Reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package fp
|
||||
|
||||
import (
|
||||
crand "crypto/rand"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/sonr-io/sonr/crypto/core/curves/native"
|
||||
"github.com/sonr-io/sonr/crypto/internal"
|
||||
)
|
||||
|
||||
func TestFpSetOne(t *testing.T) {
|
||||
fq := P256FpNew().SetOne()
|
||||
require.NotNil(t, fq)
|
||||
require.Equal(t, fq.Value, getP256FpParams().R)
|
||||
}
|
||||
|
||||
func TestFpSetUint64(t *testing.T) {
|
||||
act := P256FpNew().SetUint64(1 << 60)
|
||||
require.NotNil(t, act)
|
||||
// Remember it will be in montgomery form
|
||||
require.Equal(t, act.Value[0], uint64(0x100000000fffffff))
|
||||
}
|
||||
|
||||
func TestFpAdd(t *testing.T) {
|
||||
lhs := P256FpNew().SetOne()
|
||||
rhs := P256FpNew().SetOne()
|
||||
exp := P256FpNew().SetUint64(2)
|
||||
res := P256FpNew().Add(lhs, rhs)
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, 1, res.Equal(exp))
|
||||
|
||||
// Fuzz test
|
||||
for i := 0; i < 25; i++ {
|
||||
// Divide by 4 to prevent overflow false errors
|
||||
l := rand.Uint64() >> 2
|
||||
r := rand.Uint64() >> 2
|
||||
e := l + r
|
||||
lhs.SetUint64(l)
|
||||
rhs.SetUint64(r)
|
||||
exp.SetUint64(e)
|
||||
|
||||
a := P256FpNew().Add(lhs, rhs)
|
||||
require.NotNil(t, a)
|
||||
require.Equal(t, exp, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFpSub(t *testing.T) {
|
||||
lhs := P256FpNew().SetOne()
|
||||
rhs := P256FpNew().SetOne()
|
||||
exp := P256FpNew().SetZero()
|
||||
res := P256FpNew().Sub(lhs, rhs)
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, 1, res.Equal(exp))
|
||||
|
||||
// Fuzz test
|
||||
for i := 0; i < 25; i++ {
|
||||
// Divide by 4 to prevent overflow false errors
|
||||
l := rand.Uint64() >> 2
|
||||
r := rand.Uint64() >> 2
|
||||
if l < r {
|
||||
l, r = r, l
|
||||
}
|
||||
e := l - r
|
||||
lhs.SetUint64(l)
|
||||
rhs.SetUint64(r)
|
||||
exp.SetUint64(e)
|
||||
|
||||
a := P256FpNew().Sub(lhs, rhs)
|
||||
require.NotNil(t, a)
|
||||
require.Equal(t, exp, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFpMul(t *testing.T) {
|
||||
lhs := P256FpNew().SetOne()
|
||||
rhs := P256FpNew().SetOne()
|
||||
exp := P256FpNew().SetOne()
|
||||
res := P256FpNew().Mul(lhs, rhs)
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, 1, res.Equal(exp))
|
||||
|
||||
// Fuzz test
|
||||
for i := 0; i < 25; i++ {
|
||||
// Divide by 4 to prevent overflow false errors
|
||||
l := rand.Uint32()
|
||||
r := rand.Uint32()
|
||||
e := uint64(l) * uint64(r)
|
||||
lhs.SetUint64(uint64(l))
|
||||
rhs.SetUint64(uint64(r))
|
||||
exp.SetUint64(e)
|
||||
|
||||
a := P256FpNew().Mul(lhs, rhs)
|
||||
require.NotNil(t, a)
|
||||
require.Equal(t, exp, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFpDouble(t *testing.T) {
|
||||
a := P256FpNew().SetUint64(2)
|
||||
e := P256FpNew().SetUint64(4)
|
||||
require.Equal(t, e, P256FpNew().Double(a))
|
||||
|
||||
for i := 0; i < 25; i++ {
|
||||
tv := rand.Uint32()
|
||||
ttv := uint64(tv) * 2
|
||||
a = P256FpNew().SetUint64(uint64(tv))
|
||||
e = P256FpNew().SetUint64(ttv)
|
||||
require.Equal(t, e, P256FpNew().Double(a))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFpSquare(t *testing.T) {
|
||||
a := P256FpNew().SetUint64(4)
|
||||
e := P256FpNew().SetUint64(16)
|
||||
require.Equal(t, e, a.Square(a))
|
||||
|
||||
for i := 0; i < 25; i++ {
|
||||
j := rand.Uint32()
|
||||
exp := uint64(j) * uint64(j)
|
||||
e.SetUint64(exp)
|
||||
a.SetUint64(uint64(j))
|
||||
require.Equal(t, e, a.Square(a))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFpNeg(t *testing.T) {
|
||||
g := P256FpNew().SetUint64(7)
|
||||
a := P256FpNew().SetOne()
|
||||
a.Neg(a)
|
||||
e := P256FpNew().SetRaw(&[native.FieldLimbs]uint64{0xfffffffffffffffe, 0x00000001ffffffff, 0x0000000000000000, 0xfffffffe00000002})
|
||||
require.Equal(t, e, a)
|
||||
a.Neg(g)
|
||||
e = P256FpNew().SetRaw(&[native.FieldLimbs]uint64{0xfffffffffffffff8, 0x00000007ffffffff, 0x0000000000000000, 0xfffffff800000008})
|
||||
require.Equal(t, e, a)
|
||||
}
|
||||
|
||||
func TestFpExp(t *testing.T) {
|
||||
e := P256FpNew().SetUint64(8)
|
||||
a := P256FpNew().SetUint64(2)
|
||||
by := P256FpNew().SetUint64(3)
|
||||
require.Equal(t, e, a.Exp(a, by))
|
||||
}
|
||||
|
||||
func TestFpSqrt(t *testing.T) {
|
||||
t1 := P256FpNew().SetUint64(2)
|
||||
t2 := P256FpNew().Neg(t1)
|
||||
t3 := P256FpNew().Square(t1)
|
||||
_, wasSquare := t3.Sqrt(t3)
|
||||
|
||||
require.True(t, wasSquare)
|
||||
require.Equal(t, 1, t1.Equal(t3)|t2.Equal(t3))
|
||||
t1.SetUint64(3)
|
||||
_, wasSquare = P256FpNew().Sqrt(t1)
|
||||
require.False(t, wasSquare)
|
||||
}
|
||||
|
||||
func TestFpInvert(t *testing.T) {
|
||||
twoInv := P256FpNew().SetRaw(&[native.FieldLimbs]uint64{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x8000000000000000})
|
||||
two := P256FpNew().SetUint64(2)
|
||||
a, inverted := P256FpNew().Invert(two)
|
||||
require.True(t, inverted)
|
||||
require.Equal(t, a, twoInv)
|
||||
|
||||
rootOfUnity := P256FpNew().SetLimbs(&[native.FieldLimbs]uint64{0x8619a9e760c01d0c, 0xa883c4fba37998df, 0x45607580b6eabd98, 0xf252b002544b2f99})
|
||||
rootOfUnityInv := P256FpNew().SetRaw(&[native.FieldLimbs]uint64{0x2609d8ab477f96d1, 0x6e5f128fb20a0f24, 0xe4d636874d99643b, 0x376080cc1f2a3735})
|
||||
a, inverted = P256FpNew().Invert(rootOfUnity)
|
||||
require.True(t, inverted)
|
||||
require.Equal(t, a, rootOfUnityInv)
|
||||
|
||||
lhs := P256FpNew().SetUint64(9)
|
||||
rhs := P256FpNew().SetUint64(3)
|
||||
rhsInv, inverted := P256FpNew().Invert(rhs)
|
||||
require.True(t, inverted)
|
||||
require.Equal(t, rhs, P256FpNew().Mul(lhs, rhsInv))
|
||||
|
||||
rhs.SetZero()
|
||||
_, inverted = P256FpNew().Invert(rhs)
|
||||
require.False(t, inverted)
|
||||
}
|
||||
|
||||
func TestFpCMove(t *testing.T) {
|
||||
t1 := P256FpNew().SetUint64(5)
|
||||
t2 := P256FpNew().SetUint64(10)
|
||||
require.Equal(t, t1, P256FpNew().CMove(t1, t2, 0))
|
||||
require.Equal(t, t2, P256FpNew().CMove(t1, t2, 1))
|
||||
}
|
||||
|
||||
func TestFpBytes(t *testing.T) {
|
||||
t1 := P256FpNew().SetUint64(99)
|
||||
seq := t1.Bytes()
|
||||
t2, err := P256FpNew().SetBytes(&seq)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, t1, t2)
|
||||
|
||||
for i := 0; i < 25; i++ {
|
||||
t1.SetUint64(rand.Uint64())
|
||||
seq = t1.Bytes()
|
||||
_, err = t2.SetBytes(&seq)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, t1, t2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFpCmp(t *testing.T) {
|
||||
tests := []struct {
|
||||
a *native.Field
|
||||
b *native.Field
|
||||
e int
|
||||
}{
|
||||
{
|
||||
a: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{2731658267414164836, 14655288906067898431, 6537465423330262322, 8306191141697566219}),
|
||||
b: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{6472764012681988529, 10848812988401906064, 2961825807536828898, 4282183981941645679}),
|
||||
e: 1,
|
||||
},
|
||||
{
|
||||
a: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{8023004109510539223, 4652004072850285717, 1877219145646046927, 383214385093921911}),
|
||||
b: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{10099384440823804262, 16139476942229308465, 8636966320777393798, 5435928725024696785}),
|
||||
e: -1,
|
||||
},
|
||||
{
|
||||
a: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{3741840066202388211, 12165774400417314871, 16619312580230515379, 16195032234110087705}),
|
||||
b: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{3905865991286066744, 543690822309071825, 17963103015950210055, 3745476720756119742}),
|
||||
e: 1,
|
||||
},
|
||||
{
|
||||
a: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{16660853697936147788, 7799793619412111108, 13515141085171033220, 2641079731236069032}),
|
||||
b: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{17790588295388238399, 571847801379669440, 14537208974498222469, 12792570372087452754}),
|
||||
e: -1,
|
||||
},
|
||||
{
|
||||
a: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{3912839285384959186, 2701177075110484070, 6453856448115499033, 6475797457962597458}),
|
||||
b: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{1282566391665688512, 13503640416992806563, 2962240104675990153, 3374904770947067689}),
|
||||
e: 1,
|
||||
},
|
||||
{
|
||||
a: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{5716631803409360103, 7859567470082614154, 12747956220853330146, 18434584096087315020}),
|
||||
b: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{16317076441459028418, 12854146980376319601, 2258436689269031143, 9531877130792223752}),
|
||||
e: 1,
|
||||
},
|
||||
{
|
||||
a: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{17955191469941083403, 10350326247207200880, 17263512235150705075, 12700328451238078022}),
|
||||
b: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{6767595547459644695, 7146403825494928147, 12269344038346710612, 9122477829383225603}),
|
||||
e: 1,
|
||||
},
|
||||
{
|
||||
a: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{17099388671847024438, 6426264987820696548, 10641143464957227405, 7709745403700754098}),
|
||||
b: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{10799154372990268556, 17178492485719929374, 5705777922258988797, 8051037767683567782}),
|
||||
e: -1,
|
||||
},
|
||||
{
|
||||
a: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{4567139260680454325, 1629385880182139061, 16607020832317899145, 1261011562621553200}),
|
||||
b: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{13487234491304534488, 17872642955936089265, 17651026784972590233, 9468934643333871559}),
|
||||
e: -1,
|
||||
},
|
||||
{
|
||||
a: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{18071070103467571798, 11787850505799426140, 10631355976141928593, 4867785203635092610}),
|
||||
b: P256FpNew().SetRaw(&[native.FieldLimbs]uint64{12596443599426461624, 10176122686151524591, 17075755296887483439, 6726169532695070719}),
|
||||
e: -1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
require.Equal(t, test.e, test.a.Cmp(test.b))
|
||||
require.Equal(t, -test.e, test.b.Cmp(test.a))
|
||||
require.Equal(t, 0, test.a.Cmp(test.a))
|
||||
require.Equal(t, 0, test.b.Cmp(test.b))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFpBigInt(t *testing.T) {
|
||||
t1 := P256FpNew().SetBigInt(big.NewInt(9999))
|
||||
t2 := P256FpNew().SetBigInt(t1.BigInt())
|
||||
require.Equal(t, t1, t2)
|
||||
|
||||
e := P256FpNew().SetRaw(&[native.FieldLimbs]uint64{0x515151513f3f3f3e, 0xc9c9c9cb36363636, 0xb7b7b7b79c9c9c9c, 0xfffffffeaeaeaeaf})
|
||||
b := new(
|
||||
big.Int,
|
||||
).SetBytes([]byte{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9})
|
||||
t1.SetBigInt(b)
|
||||
require.Equal(t, e, t1)
|
||||
e.Value[0] = 0xaeaeaeaec0c0c0c1
|
||||
e.Value[1] = 0x36363635c9c9c9c9
|
||||
e.Value[2] = 0x4848484863636363
|
||||
e.Value[3] = 0x0000000051515151
|
||||
b.Neg(b)
|
||||
t1.SetBigInt(b)
|
||||
require.Equal(t, e, t1)
|
||||
}
|
||||
|
||||
func TestFpSetBytesWide(t *testing.T) {
|
||||
e := P256FpNew().SetRaw(&[native.FieldLimbs]uint64{0xccdefd48c77805bc, 0xe935dc2db86364d6, 0xca8ee6e5870a020e, 0x4c94bf4467f3b5bf})
|
||||
|
||||
a := P256FpNew().SetBytesWide(&[64]byte{
|
||||
0x69, 0x23, 0x5a, 0x0b, 0xce, 0x0c, 0xa8, 0x64,
|
||||
0x3c, 0x78, 0xbc, 0x01, 0x05, 0xef, 0xf2, 0x84,
|
||||
0xde, 0xbb, 0x6b, 0xc8, 0x63, 0x5e, 0x6e, 0x69,
|
||||
0x62, 0xcc, 0xc6, 0x2d, 0xf5, 0x72, 0x40, 0x92,
|
||||
0x28, 0x11, 0xd6, 0xc8, 0x07, 0xa5, 0x88, 0x82,
|
||||
0xfe, 0xe3, 0x97, 0xf6, 0x1e, 0xfb, 0x2e, 0x3b,
|
||||
0x27, 0x5f, 0x85, 0x06, 0x8d, 0x99, 0xa4, 0x75,
|
||||
0xc0, 0x2c, 0x71, 0x69, 0x9e, 0x58, 0xea, 0x52,
|
||||
})
|
||||
require.Equal(t, e, a)
|
||||
}
|
||||
|
||||
func TestFpSetBytesWideBigInt(t *testing.T) {
|
||||
params := getP256FpParams()
|
||||
var tv2 [64]byte
|
||||
for i := 0; i < 25; i++ {
|
||||
_, _ = crand.Read(tv2[:])
|
||||
e := new(big.Int).SetBytes(tv2[:])
|
||||
e.Mod(e, params.BiModulus)
|
||||
|
||||
tv := internal.ReverseScalarBytes(tv2[:])
|
||||
copy(tv2[:], tv)
|
||||
a := P256FpNew().SetBytesWide(&tv2)
|
||||
require.Equal(t, 0, e.Cmp(a.BigInt()))
|
||||
}
|
||||
}
|
||||
Executable
+1463
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,510 @@
|
||||
//
|
||||
// Copyright Coinbase, Inc. All Rights Reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package fq
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"sync"
|
||||
|
||||
"github.com/sonr-io/sonr/crypto/core/curves/native"
|
||||
)
|
||||
|
||||
var (
|
||||
p256FqInitonce sync.Once
|
||||
p256FqParams native.FieldParams
|
||||
)
|
||||
|
||||
func P256FqNew() *native.Field {
|
||||
return &native.Field{
|
||||
Value: [native.FieldLimbs]uint64{},
|
||||
Params: getP256FqParams(),
|
||||
Arithmetic: p256FqArithmetic{},
|
||||
}
|
||||
}
|
||||
|
||||
func p256FqParamsInit() {
|
||||
// See FIPS 186-3, section D.2.3
|
||||
p256FqParams = native.FieldParams{
|
||||
R: [native.FieldLimbs]uint64{
|
||||
0x0c46353d039cdaaf,
|
||||
0x4319055258e8617b,
|
||||
0x0000000000000000,
|
||||
0x00000000ffffffff,
|
||||
},
|
||||
R2: [native.FieldLimbs]uint64{
|
||||
0x83244c95be79eea2,
|
||||
0x4699799c49bd6fa6,
|
||||
0x2845b2392b6bec59,
|
||||
0x66e12d94f3d95620,
|
||||
},
|
||||
R3: [native.FieldLimbs]uint64{
|
||||
0xac8ebec90b65a624,
|
||||
0x111f28ae0c0555c9,
|
||||
0x2543b9246ba5e93f,
|
||||
0x503a54e76407be65,
|
||||
},
|
||||
Modulus: [native.FieldLimbs]uint64{
|
||||
0xf3b9cac2fc632551,
|
||||
0xbce6faada7179e84,
|
||||
0xffffffffffffffff,
|
||||
0xffffffff00000000,
|
||||
},
|
||||
BiModulus: new(big.Int).SetBytes([]byte{
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func getP256FqParams() *native.FieldParams {
|
||||
p256FqInitonce.Do(p256FqParamsInit)
|
||||
return &p256FqParams
|
||||
}
|
||||
|
||||
// p256FqArithmetic is a struct with all the methods needed for working
|
||||
// in mod q
|
||||
type p256FqArithmetic struct{}
|
||||
|
||||
// ToMontgomery converts this field to montgomery form
|
||||
func (f p256FqArithmetic) ToMontgomery(out, arg *[native.FieldLimbs]uint64) {
|
||||
ToMontgomery((*MontgomeryDomainFieldElement)(out), (*NonMontgomeryDomainFieldElement)(arg))
|
||||
}
|
||||
|
||||
// FromMontgomery converts this field from montgomery form
|
||||
func (f p256FqArithmetic) FromMontgomery(out, arg *[native.FieldLimbs]uint64) {
|
||||
FromMontgomery((*NonMontgomeryDomainFieldElement)(out), (*MontgomeryDomainFieldElement)(arg))
|
||||
}
|
||||
|
||||
// Neg performs modular negation
|
||||
func (f p256FqArithmetic) Neg(out, arg *[native.FieldLimbs]uint64) {
|
||||
Opp((*MontgomeryDomainFieldElement)(out), (*MontgomeryDomainFieldElement)(arg))
|
||||
}
|
||||
|
||||
// Square performs modular square
|
||||
func (f p256FqArithmetic) Square(out, arg *[native.FieldLimbs]uint64) {
|
||||
Square((*MontgomeryDomainFieldElement)(out), (*MontgomeryDomainFieldElement)(arg))
|
||||
}
|
||||
|
||||
// Mul performs modular multiplication
|
||||
func (f p256FqArithmetic) Mul(out, arg1, arg2 *[native.FieldLimbs]uint64) {
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(out),
|
||||
(*MontgomeryDomainFieldElement)(arg1),
|
||||
(*MontgomeryDomainFieldElement)(arg2),
|
||||
)
|
||||
}
|
||||
|
||||
// Add performs modular addition
|
||||
func (f p256FqArithmetic) Add(out, arg1, arg2 *[native.FieldLimbs]uint64) {
|
||||
Add(
|
||||
(*MontgomeryDomainFieldElement)(out),
|
||||
(*MontgomeryDomainFieldElement)(arg1),
|
||||
(*MontgomeryDomainFieldElement)(arg2),
|
||||
)
|
||||
}
|
||||
|
||||
// Sub performs modular subtraction
|
||||
func (f p256FqArithmetic) Sub(out, arg1, arg2 *[native.FieldLimbs]uint64) {
|
||||
Sub(
|
||||
(*MontgomeryDomainFieldElement)(out),
|
||||
(*MontgomeryDomainFieldElement)(arg1),
|
||||
(*MontgomeryDomainFieldElement)(arg2),
|
||||
)
|
||||
}
|
||||
|
||||
// Sqrt performs modular square root
|
||||
func (f p256FqArithmetic) Sqrt(wasSquare *int, out, arg *[native.FieldLimbs]uint64) {
|
||||
// See sqrt_ts_ct at
|
||||
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-I.4
|
||||
// c1 := s
|
||||
// c2 := (q - 1) / (2^c1)
|
||||
// c2 := [4]uint64{
|
||||
// 0x4f3b9cac2fc63255,
|
||||
// 0xfbce6faada7179e8,
|
||||
// 0x0fffffffffffffff,
|
||||
// 0x0ffffffff0000000,
|
||||
// }
|
||||
// c3 := (c2 - 1) / 2
|
||||
c3 := [native.FieldLimbs]uint64{
|
||||
0x279dce5617e3192a,
|
||||
0xfde737d56d38bcf4,
|
||||
0x07ffffffffffffff,
|
||||
0x07fffffff8000000,
|
||||
}
|
||||
// c4 := generator
|
||||
// c5 := new(Fq).pow(generator, c2)
|
||||
c5 := [native.FieldLimbs]uint64{
|
||||
0x1015708f7e368fe1,
|
||||
0x31c6c5456ecc4511,
|
||||
0x5281fe8998a19ea1,
|
||||
0x0279089e10c63fe8,
|
||||
}
|
||||
var z, t, b, c, tv [native.FieldLimbs]uint64
|
||||
|
||||
native.Pow(&z, arg, &c3, getP256FqParams(), f)
|
||||
Square((*MontgomeryDomainFieldElement)(&t), (*MontgomeryDomainFieldElement)(&z))
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&t),
|
||||
(*MontgomeryDomainFieldElement)(&t),
|
||||
(*MontgomeryDomainFieldElement)(arg),
|
||||
)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&z),
|
||||
(*MontgomeryDomainFieldElement)(&z),
|
||||
(*MontgomeryDomainFieldElement)(arg),
|
||||
)
|
||||
|
||||
copy(b[:], t[:])
|
||||
copy(c[:], c5[:])
|
||||
|
||||
for i := s; i >= 2; i-- {
|
||||
for j := 1; j <= i-2; j++ {
|
||||
Square((*MontgomeryDomainFieldElement)(&b), (*MontgomeryDomainFieldElement)(&b))
|
||||
}
|
||||
// if b == 1 flag = 0 else flag = 1
|
||||
flag := -(&native.Field{
|
||||
Value: b,
|
||||
Params: getP256FqParams(),
|
||||
Arithmetic: f,
|
||||
}).IsOne() + 1
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tv),
|
||||
(*MontgomeryDomainFieldElement)(&z),
|
||||
(*MontgomeryDomainFieldElement)(&c),
|
||||
)
|
||||
Selectznz(&z, uint1(flag), &z, &tv)
|
||||
Square((*MontgomeryDomainFieldElement)(&c), (*MontgomeryDomainFieldElement)(&c))
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tv),
|
||||
(*MontgomeryDomainFieldElement)(&t),
|
||||
(*MontgomeryDomainFieldElement)(&c),
|
||||
)
|
||||
Selectznz(&t, uint1(flag), &t, &tv)
|
||||
copy(b[:], t[:])
|
||||
}
|
||||
Square((*MontgomeryDomainFieldElement)(&c), (*MontgomeryDomainFieldElement)(&z))
|
||||
*wasSquare = (&native.Field{
|
||||
Value: c,
|
||||
Params: getP256FqParams(),
|
||||
Arithmetic: f,
|
||||
}).Equal(&native.Field{
|
||||
Value: *arg,
|
||||
Params: getP256FqParams(),
|
||||
Arithmetic: f,
|
||||
})
|
||||
Selectznz(out, uint1(*wasSquare), out, &z)
|
||||
}
|
||||
|
||||
// Invert performs modular inverse
|
||||
func (f p256FqArithmetic) Invert(wasInverted *int, out, arg *[native.FieldLimbs]uint64) {
|
||||
// Using an addition chain from
|
||||
// https://briansmith.org/ecc-inversion-addition-chains-01#p256_field_inversion
|
||||
var x1, x10, x11, x101, x111, x1010, x1111, x10101, x101010, x101111 [native.FieldLimbs]uint64
|
||||
var x6, x8, x16, x32, tmp [native.FieldLimbs]uint64
|
||||
|
||||
copy(x1[:], arg[:])
|
||||
native.Pow2k(&x10, arg, 1, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&x11),
|
||||
(*MontgomeryDomainFieldElement)(&x10),
|
||||
(*MontgomeryDomainFieldElement)(&x1),
|
||||
)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&x101),
|
||||
(*MontgomeryDomainFieldElement)(&x10),
|
||||
(*MontgomeryDomainFieldElement)(&x11),
|
||||
)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&x111),
|
||||
(*MontgomeryDomainFieldElement)(&x10),
|
||||
(*MontgomeryDomainFieldElement)(&x101),
|
||||
)
|
||||
native.Pow2k(&x1010, &x101, 1, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&x1111),
|
||||
(*MontgomeryDomainFieldElement)(&x101),
|
||||
(*MontgomeryDomainFieldElement)(&x1010),
|
||||
)
|
||||
native.Pow2k(&x10101, &x1010, 1, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&x10101),
|
||||
(*MontgomeryDomainFieldElement)(&x10101),
|
||||
(*MontgomeryDomainFieldElement)(&x1),
|
||||
)
|
||||
native.Pow2k(&x101010, &x10101, 1, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&x101111),
|
||||
(*MontgomeryDomainFieldElement)(&x101),
|
||||
(*MontgomeryDomainFieldElement)(&x101010),
|
||||
)
|
||||
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&x6),
|
||||
(*MontgomeryDomainFieldElement)(&x10101),
|
||||
(*MontgomeryDomainFieldElement)(&x101010),
|
||||
)
|
||||
|
||||
native.Pow2k(&x8, &x6, 2, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&x8),
|
||||
(*MontgomeryDomainFieldElement)(&x8),
|
||||
(*MontgomeryDomainFieldElement)(&x11),
|
||||
)
|
||||
|
||||
native.Pow2k(&x16, &x8, 8, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&x16),
|
||||
(*MontgomeryDomainFieldElement)(&x16),
|
||||
(*MontgomeryDomainFieldElement)(&x8),
|
||||
)
|
||||
|
||||
native.Pow2k(&x32, &x16, 16, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&x32),
|
||||
(*MontgomeryDomainFieldElement)(&x32),
|
||||
(*MontgomeryDomainFieldElement)(&x16),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &x32, 64, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x32),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 32, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x32),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 6, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x101111),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 5, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x111),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 4, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x11),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 5, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x1111),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 5, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x10101),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 4, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x101),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 3, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x101),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 3, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x101),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 5, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x111),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 9, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x101111),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 6, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x1111),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 2, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x1),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 5, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x1),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 6, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x1111),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 5, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x111),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 4, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x111),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 5, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x111),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 5, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x101),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 3, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x11),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 10, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x101111),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 2, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x11),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 5, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x11),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 5, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x11),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 3, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x1),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 7, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x10101),
|
||||
)
|
||||
|
||||
native.Pow2k(&tmp, &tmp, 6, f)
|
||||
Mul(
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&tmp),
|
||||
(*MontgomeryDomainFieldElement)(&x1111),
|
||||
)
|
||||
|
||||
*wasInverted = (&native.Field{
|
||||
Value: *arg,
|
||||
Params: getP256FqParams(),
|
||||
Arithmetic: f,
|
||||
}).IsNonZero()
|
||||
Selectznz(out, uint1(*wasInverted), out, &tmp)
|
||||
}
|
||||
|
||||
// FromBytes converts a little endian byte array into a field element
|
||||
func (f p256FqArithmetic) FromBytes(out *[native.FieldLimbs]uint64, arg *[native.FieldBytes]byte) {
|
||||
FromBytes(out, arg)
|
||||
}
|
||||
|
||||
// ToBytes converts a field element to a little endian byte array
|
||||
func (f p256FqArithmetic) ToBytes(out *[native.FieldBytes]byte, arg *[native.FieldLimbs]uint64) {
|
||||
ToBytes(out, arg)
|
||||
}
|
||||
|
||||
// Selectznz performs conditional select.
|
||||
// selects arg1 if choice == 0 and arg2 if choice == 1
|
||||
func (f p256FqArithmetic) Selectznz(out, arg1, arg2 *[native.FieldLimbs]uint64, choice int) {
|
||||
Selectznz(out, uint1(choice), arg1, arg2)
|
||||
}
|
||||
|
||||
// generator = 7 mod q is a generator of the `q - 1` order multiplicative
|
||||
// subgroup, or in other words a primitive element of the field.
|
||||
// generator^t where t * 2^s + 1 = q
|
||||
var generator = &[native.FieldLimbs]uint64{
|
||||
0x55eb74ab1949fac9,
|
||||
0xd5af25406e5aaa5d,
|
||||
0x0000000000000001,
|
||||
0x00000006fffffff9,
|
||||
}
|
||||
|
||||
// s satisfies the equation 2^s * t = q - 1 with t odd.
|
||||
var s = 4
|
||||
|
||||
// rootOfUnity
|
||||
var rootOfUnity = &[native.FieldLimbs]uint64{
|
||||
0x0592d7fbb41e6602,
|
||||
0x1546cad004378daf,
|
||||
0xba807ace842a3dfc,
|
||||
0xffc97f062a770992,
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
//
|
||||
// Copyright Coinbase, Inc. All Rights Reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package fq
|
||||
|
||||
import (
|
||||
crand "crypto/rand"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/sonr-io/sonr/crypto/core/curves/native"
|
||||
"github.com/sonr-io/sonr/crypto/internal"
|
||||
)
|
||||
|
||||
func TestFqSetOne(t *testing.T) {
|
||||
fq := P256FqNew().SetOne()
|
||||
require.NotNil(t, fq)
|
||||
require.Equal(t, fq.Value, getP256FqParams().R)
|
||||
}
|
||||
|
||||
func TestFqSetUint64(t *testing.T) {
|
||||
act := P256FqNew().SetUint64(1 << 60)
|
||||
require.NotNil(t, act)
|
||||
// Remember it will be in montgomery form
|
||||
require.Equal(t, act.Value[0], uint64(0xb3f3986dec632551))
|
||||
}
|
||||
|
||||
func TestFqAdd(t *testing.T) {
|
||||
lhs := P256FqNew().SetOne()
|
||||
rhs := P256FqNew().SetOne()
|
||||
exp := P256FqNew().SetUint64(2)
|
||||
res := P256FqNew().Add(lhs, rhs)
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, 1, res.Equal(exp))
|
||||
|
||||
// Fuzz test
|
||||
for i := 0; i < 25; i++ {
|
||||
// Divide by 4 to prevent overflow false errors
|
||||
l := rand.Uint64() >> 2
|
||||
r := rand.Uint64() >> 2
|
||||
e := l + r
|
||||
lhs.SetUint64(l)
|
||||
rhs.SetUint64(r)
|
||||
exp.SetUint64(e)
|
||||
|
||||
a := P256FqNew().Add(lhs, rhs)
|
||||
require.NotNil(t, a)
|
||||
require.Equal(t, exp, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFqSub(t *testing.T) {
|
||||
lhs := P256FqNew().SetOne()
|
||||
rhs := P256FqNew().SetOne()
|
||||
exp := P256FqNew().SetZero()
|
||||
res := P256FqNew().Sub(lhs, rhs)
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, 1, res.Equal(exp))
|
||||
|
||||
// Fuzz test
|
||||
for i := 0; i < 25; i++ {
|
||||
// Divide by 4 to prevent overflow false errors
|
||||
l := rand.Uint64() >> 2
|
||||
r := rand.Uint64() >> 2
|
||||
if l < r {
|
||||
l, r = r, l
|
||||
}
|
||||
e := l - r
|
||||
lhs.SetUint64(l)
|
||||
rhs.SetUint64(r)
|
||||
exp.SetUint64(e)
|
||||
|
||||
a := P256FqNew().Sub(lhs, rhs)
|
||||
require.NotNil(t, a)
|
||||
require.Equal(t, exp, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFqMul(t *testing.T) {
|
||||
lhs := P256FqNew().SetOne()
|
||||
rhs := P256FqNew().SetOne()
|
||||
exp := P256FqNew().SetOne()
|
||||
res := P256FqNew().Mul(lhs, rhs)
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, 1, res.Equal(exp))
|
||||
|
||||
// Fuzz test
|
||||
for i := 0; i < 25; i++ {
|
||||
// Divide by 4 to prevent overflow false errors
|
||||
l := rand.Uint32()
|
||||
r := rand.Uint32()
|
||||
e := uint64(l) * uint64(r)
|
||||
lhs.SetUint64(uint64(l))
|
||||
rhs.SetUint64(uint64(r))
|
||||
exp.SetUint64(e)
|
||||
|
||||
a := P256FqNew().Mul(lhs, rhs)
|
||||
require.NotNil(t, a)
|
||||
require.Equal(t, exp, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFqDouble(t *testing.T) {
|
||||
a := P256FqNew().SetUint64(2)
|
||||
e := P256FqNew().SetUint64(4)
|
||||
require.Equal(t, e, P256FqNew().Double(a))
|
||||
|
||||
for i := 0; i < 25; i++ {
|
||||
tv := rand.Uint32()
|
||||
ttv := uint64(tv) * 2
|
||||
a = P256FqNew().SetUint64(uint64(tv))
|
||||
e = P256FqNew().SetUint64(ttv)
|
||||
require.Equal(t, e, P256FqNew().Double(a))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFqSquare(t *testing.T) {
|
||||
a := P256FqNew().SetUint64(4)
|
||||
e := P256FqNew().SetUint64(16)
|
||||
require.Equal(t, e, a.Square(a))
|
||||
|
||||
for i := 0; i < 25; i++ {
|
||||
j := rand.Uint32()
|
||||
exp := uint64(j) * uint64(j)
|
||||
e.SetUint64(exp)
|
||||
a.SetUint64(uint64(j))
|
||||
require.Equal(t, e, a.Square(a))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFqNeg(t *testing.T) {
|
||||
g := P256FqNew().SetRaw(generator)
|
||||
a := P256FqNew().SetOne()
|
||||
a.Neg(a)
|
||||
e := P256FqNew().SetRaw(&[native.FieldLimbs]uint64{0xe7739585f8c64aa2, 0x79cdf55b4e2f3d09, 0xffffffffffffffff, 0xfffffffe00000001})
|
||||
require.Equal(t, e, a)
|
||||
a.Neg(g)
|
||||
e = P256FqNew().SetRaw(&[native.FieldLimbs]uint64{0x9dce5617e3192a88, 0xe737d56d38bcf427, 0xfffffffffffffffd, 0xfffffff800000007})
|
||||
require.Equal(t, e, a)
|
||||
}
|
||||
|
||||
func TestFqExp(t *testing.T) {
|
||||
e := P256FqNew().SetUint64(8)
|
||||
a := P256FqNew().SetUint64(2)
|
||||
by := P256FqNew().SetUint64(3)
|
||||
require.Equal(t, e, a.Exp(a, by))
|
||||
}
|
||||
|
||||
func TestFqSqrt(t *testing.T) {
|
||||
t1 := P256FqNew().SetUint64(2)
|
||||
t2 := P256FqNew().Neg(t1)
|
||||
t3 := P256FqNew().Square(t1)
|
||||
_, wasSquare := t3.Sqrt(t3)
|
||||
|
||||
require.True(t, wasSquare)
|
||||
require.Equal(t, 1, t1.Equal(t3)|t2.Equal(t3))
|
||||
t1.SetUint64(7)
|
||||
_, wasSquare = t3.Sqrt(t1)
|
||||
require.False(t, wasSquare)
|
||||
}
|
||||
|
||||
func TestFqInvert(t *testing.T) {
|
||||
twoInv := P256FqNew().SetRaw(&[native.FieldLimbs]uint64{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x8000000000000000})
|
||||
two := P256FqNew().SetUint64(2)
|
||||
a, inverted := P256FqNew().Invert(two)
|
||||
require.True(t, inverted)
|
||||
require.Equal(t, a, twoInv)
|
||||
|
||||
rootOfUnityInv := P256FqNew().SetRaw(&[native.FieldLimbs]uint64{0xcfbf53b9618acf96, 0xf17e5c39df7bd05b, 0xc7acb1f83e3ad9ad, 0x4659a42b394ff7df})
|
||||
rootOU := P256FqNew().SetRaw(rootOfUnity)
|
||||
a, inverted = P256FqNew().Invert(rootOU)
|
||||
require.True(t, inverted)
|
||||
require.Equal(t, a, rootOfUnityInv)
|
||||
|
||||
lhs := P256FqNew().SetUint64(9)
|
||||
rhs := P256FqNew().SetUint64(3)
|
||||
rhsInv, inverted := P256FqNew().Invert(rhs)
|
||||
require.True(t, inverted)
|
||||
require.Equal(t, rhs, P256FqNew().Mul(lhs, rhsInv))
|
||||
|
||||
rhs.SetZero()
|
||||
_, inverted = P256FqNew().Invert(rhs)
|
||||
require.False(t, inverted)
|
||||
}
|
||||
|
||||
func TestFqCMove(t *testing.T) {
|
||||
t1 := P256FqNew().SetUint64(5)
|
||||
t2 := P256FqNew().SetUint64(10)
|
||||
require.Equal(t, t1, P256FqNew().CMove(t1, t2, 0))
|
||||
require.Equal(t, t2, P256FqNew().CMove(t1, t2, 1))
|
||||
}
|
||||
|
||||
func TestFqBytes(t *testing.T) {
|
||||
t1 := P256FqNew().SetUint64(99)
|
||||
seq := t1.Bytes()
|
||||
t2, err := P256FqNew().SetBytes(&seq)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, t1, t2)
|
||||
|
||||
for i := 0; i < 25; i++ {
|
||||
t1.SetUint64(rand.Uint64())
|
||||
seq = t1.Bytes()
|
||||
_, err = t2.SetBytes(&seq)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, t1, t2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFqCmp(t *testing.T) {
|
||||
tests := []struct {
|
||||
a *native.Field
|
||||
b *native.Field
|
||||
e int
|
||||
}{
|
||||
{
|
||||
a: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{2731658267414164836, 14655288906067898431, 6537465423330262322, 8306191141697566219}),
|
||||
b: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{6472764012681988529, 10848812988401906064, 2961825807536828898, 4282183981941645679}),
|
||||
e: 1,
|
||||
},
|
||||
{
|
||||
a: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{8023004109510539223, 4652004072850285717, 1877219145646046927, 383214385093921911}),
|
||||
b: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{10099384440823804262, 16139476942229308465, 8636966320777393798, 5435928725024696785}),
|
||||
e: -1,
|
||||
},
|
||||
{
|
||||
a: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{3741840066202388211, 12165774400417314871, 16619312580230515379, 16195032234110087705}),
|
||||
b: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{3905865991286066744, 543690822309071825, 17963103015950210055, 3745476720756119742}),
|
||||
e: 1,
|
||||
},
|
||||
{
|
||||
a: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{16660853697936147788, 7799793619412111108, 13515141085171033220, 2641079731236069032}),
|
||||
b: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{17790588295388238399, 571847801379669440, 14537208974498222469, 12792570372087452754}),
|
||||
e: -1,
|
||||
},
|
||||
{
|
||||
a: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{3912839285384959186, 2701177075110484070, 6453856448115499033, 6475797457962597458}),
|
||||
b: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{1282566391665688512, 13503640416992806563, 2962240104675990153, 3374904770947067689}),
|
||||
e: 1,
|
||||
},
|
||||
{
|
||||
a: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{5716631803409360103, 7859567470082614154, 12747956220853330146, 18434584096087315020}),
|
||||
b: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{16317076441459028418, 12854146980376319601, 2258436689269031143, 9531877130792223752}),
|
||||
e: 1,
|
||||
},
|
||||
{
|
||||
a: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{17955191469941083403, 10350326247207200880, 17263512235150705075, 12700328451238078022}),
|
||||
b: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{6767595547459644695, 7146403825494928147, 12269344038346710612, 9122477829383225603}),
|
||||
e: 1,
|
||||
},
|
||||
{
|
||||
a: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{17099388671847024438, 6426264987820696548, 10641143464957227405, 7709745403700754098}),
|
||||
b: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{10799154372990268556, 17178492485719929374, 5705777922258988797, 8051037767683567782}),
|
||||
e: -1,
|
||||
},
|
||||
{
|
||||
a: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{4567139260680454325, 1629385880182139061, 16607020832317899145, 1261011562621553200}),
|
||||
b: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{13487234491304534488, 17872642955936089265, 17651026784972590233, 9468934643333871559}),
|
||||
e: -1,
|
||||
},
|
||||
{
|
||||
a: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{18071070103467571798, 11787850505799426140, 10631355976141928593, 4867785203635092610}),
|
||||
b: P256FqNew().SetRaw(&[native.FieldLimbs]uint64{12596443599426461624, 10176122686151524591, 17075755296887483439, 6726169532695070719}),
|
||||
e: -1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
require.Equal(t, test.e, test.a.Cmp(test.b))
|
||||
require.Equal(t, -test.e, test.b.Cmp(test.a))
|
||||
require.Equal(t, 0, test.a.Cmp(test.a))
|
||||
require.Equal(t, 0, test.b.Cmp(test.b))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFqBigInt(t *testing.T) {
|
||||
t1 := P256FqNew().SetBigInt(big.NewInt(9999))
|
||||
t2 := P256FqNew().SetBigInt(t1.BigInt())
|
||||
require.Equal(t, t1, t2)
|
||||
|
||||
e := P256FqNew().SetRaw(&[native.FieldLimbs]uint64{0x21dcaaadf1cb6aa0, 0x568de5f5990a98d7, 0x354f43b0d837fac5, 0x3e02532cb23f481a})
|
||||
b := new(
|
||||
big.Int,
|
||||
).SetBytes([]byte{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9})
|
||||
t1.SetBigInt(b)
|
||||
require.Equal(t, e, t1)
|
||||
e.Value[0] = 0xd1dd20150a97bab1
|
||||
e.Value[1] = 0x665914b80e0d05ad
|
||||
e.Value[2] = 0xcab0bc4f27c8053a
|
||||
e.Value[3] = 0xc1fdacd24dc0b7e6
|
||||
b.Neg(b)
|
||||
t1.SetBigInt(b)
|
||||
require.Equal(t, e, t1)
|
||||
}
|
||||
|
||||
func TestFqSetBytesWide(t *testing.T) {
|
||||
e := P256FqNew().SetRaw(&[native.FieldLimbs]uint64{0xe2b8d4b0e576c8fa, 0x9d2b215f85d3bdf7, 0xf6070a872442640c, 0xcf15d1e49c990b88})
|
||||
|
||||
a := P256FqNew().SetBytesWide(&[64]byte{
|
||||
0x69, 0x23, 0x5a, 0x0b, 0xce, 0x0c, 0xa8, 0x64,
|
||||
0x3c, 0x78, 0xbc, 0x01, 0x05, 0xef, 0xf2, 0x84,
|
||||
0xde, 0xbb, 0x6b, 0xc8, 0x63, 0x5e, 0x6e, 0x69,
|
||||
0x62, 0xcc, 0xc6, 0x2d, 0xf5, 0x72, 0x40, 0x92,
|
||||
0x28, 0x11, 0xd6, 0xc8, 0x07, 0xa5, 0x88, 0x82,
|
||||
0xfe, 0xe3, 0x97, 0xf6, 0x1e, 0xfb, 0x2e, 0x3b,
|
||||
0x27, 0x5f, 0x85, 0x06, 0x8d, 0x99, 0xa4, 0x75,
|
||||
0xc0, 0x2c, 0x71, 0x69, 0x9e, 0x58, 0xea, 0x52,
|
||||
})
|
||||
require.Equal(t, e, a)
|
||||
}
|
||||
|
||||
func TestFpSetBytesWideBigInt(t *testing.T) {
|
||||
params := getP256FqParams()
|
||||
var tv2 [64]byte
|
||||
for i := 0; i < 25; i++ {
|
||||
_, _ = crand.Read(tv2[:])
|
||||
e := new(big.Int).SetBytes(tv2[:])
|
||||
e.Mod(e, params.BiModulus)
|
||||
|
||||
tv := internal.ReverseScalarBytes(tv2[:])
|
||||
copy(tv2[:], tv)
|
||||
a := P256FqNew().SetBytesWide(&tv2)
|
||||
require.Equal(t, 0, e.Cmp(a.BigInt()))
|
||||
}
|
||||
}
|
||||
Executable
+1651
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,350 @@
|
||||
package p256
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/sonr-io/sonr/crypto/core/curves/native"
|
||||
"github.com/sonr-io/sonr/crypto/core/curves/native/p256/fp"
|
||||
"github.com/sonr-io/sonr/crypto/internal"
|
||||
)
|
||||
|
||||
var (
|
||||
p256PointInitonce sync.Once
|
||||
p256PointParams native.EllipticPointParams
|
||||
p256PointSswuInitOnce sync.Once
|
||||
p256PointSswuParams native.SswuParams
|
||||
)
|
||||
|
||||
func P256PointNew() *native.EllipticPoint {
|
||||
return &native.EllipticPoint{
|
||||
X: fp.P256FpNew(),
|
||||
Y: fp.P256FpNew(),
|
||||
Z: fp.P256FpNew(),
|
||||
Params: getP256PointParams(),
|
||||
Arithmetic: &p256PointArithmetic{},
|
||||
}
|
||||
}
|
||||
|
||||
func p256PointParamsInit() {
|
||||
// How these values were derived
|
||||
// left for informational purposes
|
||||
// params := elliptic.P256().Params()
|
||||
// a := big.NewInt(-3)
|
||||
// a.Mod(a, params.P)
|
||||
// capA := fp.P256FpNew().SetBigInt(a)
|
||||
// capB := fp.P256FpNew().SetBigInt(params.B)
|
||||
// gx := fp.P256FpNew().SetBigInt(params.Gx)
|
||||
// gy := fp.P256FpNew().SetBigInt(params.Gy)
|
||||
|
||||
p256PointParams = native.EllipticPointParams{
|
||||
A: fp.P256FpNew().
|
||||
SetRaw(&[native.FieldLimbs]uint64{0xfffffffffffffffc, 0x00000003ffffffff, 0x0000000000000000, 0xfffffffc00000004}),
|
||||
B: fp.P256FpNew().
|
||||
SetRaw(&[native.FieldLimbs]uint64{0xd89cdf6229c4bddf, 0xacf005cd78843090, 0xe5a220abf7212ed6, 0xdc30061d04874834}),
|
||||
Gx: fp.P256FpNew().
|
||||
SetRaw(&[native.FieldLimbs]uint64{0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6}),
|
||||
Gy: fp.P256FpNew().
|
||||
SetRaw(&[native.FieldLimbs]uint64{0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325, 0x8571ff1825885d85}),
|
||||
BitSize: 256,
|
||||
Name: "P256",
|
||||
}
|
||||
}
|
||||
|
||||
func getP256PointParams() *native.EllipticPointParams {
|
||||
p256PointInitonce.Do(p256PointParamsInit)
|
||||
return &p256PointParams
|
||||
}
|
||||
|
||||
func getP256PointSswuParams() *native.SswuParams {
|
||||
p256PointSswuInitOnce.Do(p256PointSswuParamsInit)
|
||||
return &p256PointSswuParams
|
||||
}
|
||||
|
||||
func p256PointSswuParamsInit() {
|
||||
// How these values were derived
|
||||
// left for informational purposes
|
||||
//params := elliptic.P256().Params()
|
||||
//
|
||||
//// c1 = (q - 3) / 4
|
||||
//c1 := new(big.Int).Set(params.P)
|
||||
//c1.Sub(c1, big.NewInt(3))
|
||||
//c1.Rsh(c1, 2)
|
||||
//
|
||||
//a := big.NewInt(-3)
|
||||
//a.Mod(a, params.P)
|
||||
//b := new(big.Int).Set(params.B)
|
||||
//z := big.NewInt(-10)
|
||||
//z.Mod(z, params.P)
|
||||
//// sqrt(-Z^3)
|
||||
//zTmp := new(big.Int).Exp(z, big.NewInt(3), nil)
|
||||
//zTmp = zTmp.Neg(zTmp)
|
||||
//zTmp.Mod(zTmp, params.P)
|
||||
//c2 := new(big.Int).ModSqrt(zTmp, params.P)
|
||||
//
|
||||
//var capC1Bytes [32]byte
|
||||
//c1.FillBytes(capC1Bytes[:])
|
||||
//capC1 := fp.P256FpNew().SetRaw(&[native.FieldLimbs]uint64{
|
||||
// binary.BigEndian.Uint64(capC1Bytes[24:]),
|
||||
// binary.BigEndian.Uint64(capC1Bytes[16:24]),
|
||||
// binary.BigEndian.Uint64(capC1Bytes[8:16]),
|
||||
// binary.BigEndian.Uint64(capC1Bytes[:8]),
|
||||
//})
|
||||
//capC2 := fp.P256FpNew().SetBigInt(c2)
|
||||
//capA := fp.P256FpNew().SetBigInt(a)
|
||||
//capB := fp.P256FpNew().SetBigInt(b)
|
||||
//capZ := fp.P256FpNew().SetBigInt(z)
|
||||
|
||||
p256PointSswuParams = native.SswuParams{
|
||||
C1: [native.FieldLimbs]uint64{
|
||||
0xffffffffffffffff,
|
||||
0x000000003fffffff,
|
||||
0x4000000000000000,
|
||||
0x3fffffffc0000000,
|
||||
},
|
||||
C2: [native.FieldLimbs]uint64{
|
||||
0x53e43951f64fdbe7,
|
||||
0xb2806c63966a1a66,
|
||||
0x1ac5d59c3298bf50,
|
||||
0xa3323851ba997e27,
|
||||
},
|
||||
A: [native.FieldLimbs]uint64{
|
||||
0xfffffffffffffffc,
|
||||
0x00000003ffffffff,
|
||||
0x0000000000000000,
|
||||
0xfffffffc00000004,
|
||||
},
|
||||
B: [native.FieldLimbs]uint64{
|
||||
0xd89cdf6229c4bddf,
|
||||
0xacf005cd78843090,
|
||||
0xe5a220abf7212ed6,
|
||||
0xdc30061d04874834,
|
||||
},
|
||||
Z: [native.FieldLimbs]uint64{
|
||||
0xfffffffffffffff5,
|
||||
0x0000000affffffff,
|
||||
0x0000000000000000,
|
||||
0xfffffff50000000b,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type p256PointArithmetic struct{}
|
||||
|
||||
func (k p256PointArithmetic) Hash(
|
||||
out *native.EllipticPoint,
|
||||
hash *native.EllipticPointHasher,
|
||||
msg, dst []byte,
|
||||
) error {
|
||||
var u []byte
|
||||
sswuParams := getP256PointSswuParams()
|
||||
|
||||
switch hash.Type() {
|
||||
case native.XMD:
|
||||
u = native.ExpandMsgXmd(hash, msg, dst, 96)
|
||||
case native.XOF:
|
||||
u = native.ExpandMsgXof(hash, msg, dst, 96)
|
||||
}
|
||||
var buf [64]byte
|
||||
copy(buf[:48], internal.ReverseScalarBytes(u[:48]))
|
||||
u0 := fp.P256FpNew().SetBytesWide(&buf)
|
||||
copy(buf[:48], internal.ReverseScalarBytes(u[48:]))
|
||||
u1 := fp.P256FpNew().SetBytesWide(&buf)
|
||||
|
||||
q0x, q0y := sswuParams.Osswu3mod4(u0)
|
||||
q1x, q1y := sswuParams.Osswu3mod4(u1)
|
||||
out.X = q0x
|
||||
out.Y = q0y
|
||||
out.Z.SetOne()
|
||||
tv := &native.EllipticPoint{
|
||||
X: q1x,
|
||||
Y: q1y,
|
||||
Z: fp.P256FpNew().SetOne(),
|
||||
}
|
||||
k.Add(out, out, tv)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k p256PointArithmetic) Double(out, arg *native.EllipticPoint) {
|
||||
// Addition formula from Renes-Costello-Batina 2015
|
||||
// (https://eprint.iacr.org/2015/1060 Algorithm 6)
|
||||
var xx, yy, zz, xy2, yz2, xz2, bzz, bzz3 [native.FieldLimbs]uint64
|
||||
var yyMBzz3, yyPBzz3, yFrag, xFrag, zz3 [native.FieldLimbs]uint64
|
||||
var bxz2, bxz6, xx3Mzz3, x, y, z [native.FieldLimbs]uint64
|
||||
b := getP256PointParams().B.Value
|
||||
f := arg.X.Arithmetic
|
||||
|
||||
f.Square(&xx, &arg.X.Value)
|
||||
f.Square(&yy, &arg.Y.Value)
|
||||
f.Square(&zz, &arg.Z.Value)
|
||||
|
||||
f.Mul(&xy2, &arg.X.Value, &arg.Y.Value)
|
||||
f.Add(&xy2, &xy2, &xy2)
|
||||
|
||||
f.Mul(&yz2, &arg.Y.Value, &arg.Z.Value)
|
||||
f.Add(&yz2, &yz2, &yz2)
|
||||
|
||||
f.Mul(&xz2, &arg.X.Value, &arg.Z.Value)
|
||||
f.Add(&xz2, &xz2, &xz2)
|
||||
|
||||
f.Mul(&bzz, &b, &zz)
|
||||
f.Sub(&bzz, &bzz, &xz2)
|
||||
|
||||
f.Add(&bzz3, &bzz, &bzz)
|
||||
f.Add(&bzz3, &bzz3, &bzz)
|
||||
|
||||
f.Sub(&yyMBzz3, &yy, &bzz3)
|
||||
f.Add(&yyPBzz3, &yy, &bzz3)
|
||||
f.Mul(&yFrag, &yyPBzz3, &yyMBzz3)
|
||||
f.Mul(&xFrag, &yyMBzz3, &xy2)
|
||||
|
||||
f.Add(&zz3, &zz, &zz)
|
||||
f.Add(&zz3, &zz3, &zz)
|
||||
|
||||
f.Mul(&bxz2, &b, &xz2)
|
||||
f.Sub(&bxz2, &bxz2, &zz3)
|
||||
f.Sub(&bxz2, &bxz2, &xx)
|
||||
|
||||
f.Add(&bxz6, &bxz2, &bxz2)
|
||||
f.Add(&bxz6, &bxz6, &bxz2)
|
||||
|
||||
f.Add(&xx3Mzz3, &xx, &xx)
|
||||
f.Add(&xx3Mzz3, &xx3Mzz3, &xx)
|
||||
f.Sub(&xx3Mzz3, &xx3Mzz3, &zz3)
|
||||
|
||||
f.Mul(&x, &bxz6, &yz2)
|
||||
f.Sub(&x, &xFrag, &x)
|
||||
|
||||
f.Mul(&y, &xx3Mzz3, &bxz6)
|
||||
f.Add(&y, &yFrag, &y)
|
||||
|
||||
f.Mul(&z, &yz2, &yy)
|
||||
f.Add(&z, &z, &z)
|
||||
f.Add(&z, &z, &z)
|
||||
|
||||
out.X.Value = x
|
||||
out.Y.Value = y
|
||||
out.Z.Value = z
|
||||
}
|
||||
|
||||
func (k p256PointArithmetic) Add(out, arg1, arg2 *native.EllipticPoint) {
|
||||
// Addition formula from Renes-Costello-Batina 2015
|
||||
// (https://eprint.iacr.org/2015/1060 Algorithm 4).
|
||||
var xx, yy, zz, zz3, bxz, bxz3 [native.FieldLimbs]uint64
|
||||
var tv1, xyPairs, yzPairs, xzPairs [native.FieldLimbs]uint64
|
||||
var bzz, bzz3, yyMBzz3, yyPBzz3 [native.FieldLimbs]uint64
|
||||
var xx3Mzz3, x, y, z [native.FieldLimbs]uint64
|
||||
f := arg1.X.Arithmetic
|
||||
b := getP256PointParams().B.Value
|
||||
|
||||
f.Mul(&xx, &arg1.X.Value, &arg2.X.Value)
|
||||
f.Mul(&yy, &arg1.Y.Value, &arg2.Y.Value)
|
||||
f.Mul(&zz, &arg1.Z.Value, &arg2.Z.Value)
|
||||
|
||||
f.Add(&tv1, &arg2.X.Value, &arg2.Y.Value)
|
||||
f.Add(&xyPairs, &arg1.X.Value, &arg1.Y.Value)
|
||||
f.Mul(&xyPairs, &xyPairs, &tv1)
|
||||
f.Sub(&xyPairs, &xyPairs, &xx)
|
||||
f.Sub(&xyPairs, &xyPairs, &yy)
|
||||
|
||||
f.Add(&tv1, &arg2.Y.Value, &arg2.Z.Value)
|
||||
f.Add(&yzPairs, &arg1.Y.Value, &arg1.Z.Value)
|
||||
f.Mul(&yzPairs, &yzPairs, &tv1)
|
||||
f.Sub(&yzPairs, &yzPairs, &yy)
|
||||
f.Sub(&yzPairs, &yzPairs, &zz)
|
||||
|
||||
f.Add(&tv1, &arg2.X.Value, &arg2.Z.Value)
|
||||
f.Add(&xzPairs, &arg1.X.Value, &arg1.Z.Value)
|
||||
f.Mul(&xzPairs, &xzPairs, &tv1)
|
||||
f.Sub(&xzPairs, &xzPairs, &xx)
|
||||
f.Sub(&xzPairs, &xzPairs, &zz)
|
||||
|
||||
f.Mul(&bzz, &b, &zz)
|
||||
f.Sub(&bzz, &xzPairs, &bzz)
|
||||
|
||||
f.Add(&bzz3, &bzz, &bzz)
|
||||
f.Add(&bzz3, &bzz3, &bzz)
|
||||
|
||||
f.Sub(&yyMBzz3, &yy, &bzz3)
|
||||
f.Add(&yyPBzz3, &yy, &bzz3)
|
||||
|
||||
f.Add(&zz3, &zz, &zz)
|
||||
f.Add(&zz3, &zz3, &zz)
|
||||
|
||||
f.Mul(&bxz, &b, &xzPairs)
|
||||
f.Sub(&bxz, &bxz, &zz3)
|
||||
f.Sub(&bxz, &bxz, &xx)
|
||||
|
||||
f.Add(&bxz3, &bxz, &bxz)
|
||||
f.Add(&bxz3, &bxz3, &bxz)
|
||||
|
||||
f.Add(&xx3Mzz3, &xx, &xx)
|
||||
f.Add(&xx3Mzz3, &xx3Mzz3, &xx)
|
||||
f.Sub(&xx3Mzz3, &xx3Mzz3, &zz3)
|
||||
|
||||
f.Mul(&tv1, &yzPairs, &bxz3)
|
||||
f.Mul(&x, &yyPBzz3, &xyPairs)
|
||||
f.Sub(&x, &x, &tv1)
|
||||
|
||||
f.Mul(&tv1, &xx3Mzz3, &bxz3)
|
||||
f.Mul(&y, &yyPBzz3, &yyMBzz3)
|
||||
f.Add(&y, &y, &tv1)
|
||||
|
||||
f.Mul(&tv1, &xyPairs, &xx3Mzz3)
|
||||
f.Mul(&z, &yyMBzz3, &yzPairs)
|
||||
f.Add(&z, &z, &tv1)
|
||||
|
||||
e1 := arg1.Z.IsZero()
|
||||
e2 := arg2.Z.IsZero()
|
||||
|
||||
// If arg1 is identity set it to arg2
|
||||
f.Selectznz(&z, &z, &arg2.Z.Value, e1)
|
||||
f.Selectznz(&y, &y, &arg2.Y.Value, e1)
|
||||
f.Selectznz(&x, &x, &arg2.X.Value, e1)
|
||||
// If arg2 is identity set it to arg1
|
||||
f.Selectznz(&z, &z, &arg1.Z.Value, e2)
|
||||
f.Selectznz(&y, &y, &arg1.Y.Value, e2)
|
||||
f.Selectznz(&x, &x, &arg1.X.Value, e2)
|
||||
|
||||
out.X.Value = x
|
||||
out.Y.Value = y
|
||||
out.Z.Value = z
|
||||
}
|
||||
|
||||
func (k p256PointArithmetic) IsOnCurve(arg *native.EllipticPoint) bool {
|
||||
affine := P256PointNew()
|
||||
k.ToAffine(affine, arg)
|
||||
lhs := fp.P256FpNew().Square(affine.Y)
|
||||
rhs := fp.P256FpNew()
|
||||
k.RhsEq(rhs, affine.X)
|
||||
return lhs.Equal(rhs) == 1
|
||||
}
|
||||
|
||||
func (k p256PointArithmetic) ToAffine(out, arg *native.EllipticPoint) {
|
||||
var wasInverted int
|
||||
var zero, x, y, z [native.FieldLimbs]uint64
|
||||
f := arg.X.Arithmetic
|
||||
|
||||
f.Invert(&wasInverted, &z, &arg.Z.Value)
|
||||
f.Mul(&x, &arg.X.Value, &z)
|
||||
f.Mul(&y, &arg.Y.Value, &z)
|
||||
|
||||
out.Z.SetOne()
|
||||
// If point at infinity this does nothing
|
||||
f.Selectznz(&x, &zero, &x, wasInverted)
|
||||
f.Selectznz(&y, &zero, &y, wasInverted)
|
||||
f.Selectznz(&z, &zero, &out.Z.Value, wasInverted)
|
||||
|
||||
out.X.Value = x
|
||||
out.Y.Value = y
|
||||
out.Z.Value = z
|
||||
out.Params = arg.Params
|
||||
out.Arithmetic = arg.Arithmetic
|
||||
}
|
||||
|
||||
func (k p256PointArithmetic) RhsEq(out, x *native.Field) {
|
||||
// Elliptic curve equation for p256 is: y^2 = x^3 ax + b
|
||||
out.Square(x)
|
||||
out.Mul(out, x)
|
||||
out.Add(out, getP256PointParams().B)
|
||||
out.Add(out, fp.P256FpNew().Mul(getP256PointParams().A, x))
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package p256_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/sonr-io/sonr/crypto/core/curves"
|
||||
"github.com/sonr-io/sonr/crypto/core/curves/native"
|
||||
"github.com/sonr-io/sonr/crypto/core/curves/native/p256"
|
||||
"github.com/sonr-io/sonr/crypto/core/curves/native/p256/fp"
|
||||
)
|
||||
|
||||
func TestP256PointArithmetic_Double(t *testing.T) {
|
||||
g := p256.P256PointNew().Generator()
|
||||
pt1 := p256.P256PointNew().Double(g)
|
||||
pt2 := p256.P256PointNew().Add(g, g)
|
||||
pt3 := p256.P256PointNew().Mul(g, fp.P256FpNew().SetUint64(2))
|
||||
|
||||
e1 := pt1.Equal(pt2)
|
||||
e2 := pt1.Equal(pt3)
|
||||
e3 := pt2.Equal(pt3)
|
||||
require.Equal(t, 1, e1)
|
||||
require.Equal(t, 1, e2)
|
||||
require.Equal(t, 1, e3)
|
||||
}
|
||||
|
||||
func TestP256PointArithmetic_Hash(t *testing.T) {
|
||||
var b [32]byte
|
||||
sc, err := p256.P256PointNew().Hash(b[:], native.EllipticPointHasherSha256())
|
||||
sc1 := curves.P256().NewIdentityPoint().Hash(b[:])
|
||||
fmt.Printf("%v\n", sc1)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.True(t, !sc.IsIdentity())
|
||||
require.True(t, sc.IsOnCurve())
|
||||
}
|
||||
Reference in New Issue
Block a user