From 8933f6c70552c83b92d4fc69b7a2872cff40cb0d Mon Sep 17 00:00:00 2001 From: armfazh Date: Thu, 7 May 2020 01:19:47 -0700 Subject: [PATCH] Decaf encoding requires cannon sqrt. --- ecc/goldilocks/decaf.go | 64 +++++++++++++++++++++++++----------- ecc/goldilocks/decaf_test.go | 27 +++++++++++++++ math/fp448/fp.go | 33 +++++++++++++++++-- 3 files changed, 101 insertions(+), 23 deletions(-) create mode 100644 ecc/goldilocks/decaf_test.go diff --git a/ecc/goldilocks/decaf.go b/ecc/goldilocks/decaf.go index 5cdba7a77..315280d1e 100644 --- a/ecc/goldilocks/decaf.go +++ b/ecc/goldilocks/decaf.go @@ -1,6 +1,8 @@ package goldilocks import ( + "fmt" + fp "github.com/cloudflare/circl/math/fp448" ) @@ -10,6 +12,8 @@ type Decaf struct{ c Curve } // Elt is an element of decaf group. type Elt struct{ p *Point } +func (e Elt) String() string { return e.p.String() } + // IsValid is func (d Decaf) IsValid(a *Elt) bool { return d.c.IsOnCurve(a.p) } @@ -17,7 +21,11 @@ func (d Decaf) IsValid(a *Elt) bool { return d.c.IsOnCurve(a.p) } func (d Decaf) Identity() *Elt { return &Elt{d.c.Identity()} } // Generator is -func (d Decaf) Generator() *Elt { return &Elt{d.c.Generator()} } +func (d Decaf) Generator() *Elt { + g := d.c.Generator() + g.Double() + return &Elt{g} +} // Order is func (d Decaf) Order() Scalar { return d.c.Order() } @@ -26,7 +34,7 @@ func (d Decaf) Order() Scalar { return d.c.Order() } func (d Decaf) Add(a, b *Elt) *Elt { return &Elt{d.c.Add(a.p, b.p)} } // Neg is -func (d Decaf) Neg(a *Elt) *Elt { var b Elt; *b.p = *a.p; b.p.Neg(); return &b } +func (d Decaf) Neg(a *Elt) *Elt { x := *a.p; x.Neg(); e := &Elt{&x}; return e } // Mul is func (d Decaf) Mul(a *Elt, n *Scalar) *Elt { return &Elt{d.c.ScalarMult(n, a.p)} } @@ -45,23 +53,35 @@ func (d Decaf) Marshal(a *Elt) []byte { fp.Mul(&t0, &t0, &t1) // t0 = (z+y)*(z-y) fp.Mul(&t0, &t0, &aMinusD) // t0 = (a-d)*(z+y)*(z-y) fp.InvSqrt(r, one, &t0) // r = 1/sqrt( (a-d)*(z+y)*(z-y) ) - fp.Mul(u, r, &aMinusD) // u = (a-d)*r - fp.Mul(&t0, u, &z) // t0 = u*Z - fp.Add(&t0, &t0, &t0) // t0 = 2*u*Z - fp.Neg(&t0, &t0) // t0 = -2*u*Z - b := fp.Sign(&t0) // b = sgn (t0) - fp.Cmov(r, &t0, uint(b)) // r = -r if -2*u*Z is negative - fp.Mul(&t0, &z, &x) // t0 = a*Z*X - fp.Mul(&t1, &y, &ta) // t1 = Y*Ta - fp.Mul(&t1, &t1, &tb) // t1 = Y*Ta*Tb = Y*T - fp.Mul(&t1, &t1, ¶mD) // t1 = d*Y*T - fp.Sub(&t0, &t0, &t1) // t0 = a*Z*X - d*Y*T - fp.Mul(&t0, &t0, r) // t0 = r*(a*Z*X - d*Y*T) - fp.Add(&t0, &t0, &y) // t0 = r*(a*Z*X - d*Y*T) + Y - fp.Mul(s, &t0, u) // s = (u/a)*(r*(a*Z*X - d*Y*T) + Y) - fp.Neg(&t1, s) // t1 = -s - b = fp.Sign(s) // b = sgn(t0) - fp.Cmov(s, &t1, uint(b)) // r = -r if -2*u*Z is negative + + fmt.Println("r0: ", r) + fp.Abs(r) // r = Takes the non-negative root. + fmt.Println("r0: ", r) + fp.Mul(u, r, &aMinusD) // u = (a-d)*r + fp.Mul(&t0, u, &z) // t0 = u*Z + fp.Add(&t0, &t0, &t0) // t0 = 2*u*Z + fp.Neg(&t0, &t0) // t0 = -2*u*Z + isNeg := fp.Parity(&t0) // isNeg = sgn(t0) + fp.Neg(&t1, r) // t1 = -r + fmt.Println("r1: ", r) + fp.Cmov(r, &t1, uint(isNeg)) // if -2*u*Z is negative then r = -r + fmt.Println("r1: ", r) + fp.Mul(&t1, &ta, &tb) // t1 = Ta*Tb = T + fp.Mul(&t1, &t1, &y) // t1 = Y*T + fp.Mul(&t1, &t1, ¶mD) // t1 = d*Y*T + fmt.Println(">t1: ", t1) + fp.Mul(&t0, &z, &x) // t0 = a*Z*X + fp.Sub(&t0, &t0, &t1) // t0 = a*Z*X - d*Y*T + fmt.Println(">t0: ", t0) + fp.Mul(&t0, &t0, r) // t0 = r*(a*Z*X - d*Y*T) + fmt.Println(">t0: ", t0) + fp.Add(&t0, &t0, &y) // t0 = r*(a*Z*X - d*Y*T) + Y + fp.Mul(s, &t0, u) // s = (u/a)*(r*(a*Z*X - d*Y*T) + Y) + fmt.Println("s1: ", s) + isNeg = fp.Parity(s) // isNeg = sgn(s) + fp.Neg(&t1, s) // t1 = -s + fp.Cmov(s, &t1, uint(isNeg)) // if s is negative then s = -s + fmt.Println("s1: ", s) var encS [fp.Size]byte _ = fp.ToBytes(encS[:], s) @@ -69,7 +89,11 @@ func (d Decaf) Marshal(a *Elt) []byte { } // Unmarshal is -func (d Decaf) Unmarshal(b []byte) (*Elt, error) { return nil, nil } +func (d Decaf) Unmarshal(b []byte) (*Elt, error) { + + return nil, nil + +} // IsIdentity is func (d Decaf) IsIdentity(a *Elt) bool { return fp.IsZero(&a.p.x) } diff --git a/ecc/goldilocks/decaf_test.go b/ecc/goldilocks/decaf_test.go new file mode 100644 index 000000000..6f4f8be4a --- /dev/null +++ b/ecc/goldilocks/decaf_test.go @@ -0,0 +1,27 @@ +package goldilocks + +import ( + "encoding/hex" + "fmt" + "testing" +) + +func TestDecafDevel(t *testing.T) { + + var c Curve + G := c.Generator() + // _2G := c.Double(G) + Q := c.push(G) + fmt.Printf("G: %v\n", Q) + var d Decaf + + // fmt.Printf("0: %v\n", hex.EncodeToString(d.Marshal(d.Identity()))) + fmt.Printf("G: %v\n", hex.EncodeToString(d.Marshal(d.Generator()))) + // P := d.Generator() + // fmt.Printf("G:\n%v\n%v\n", P, hex.EncodeToString(d.Marshal(P))) + // for i := 1; i < 2; i++ { + // P = d.Add(P, P) + // fmt.Printf("[2^%v]G:\n%v\n", i, P) + // fmt.Printf("[2^%v]G: %v\n", i, hex.EncodeToString(d.Marshal(P))) + // } +} diff --git a/math/fp448/fp.go b/math/fp448/fp.go index 1881848a3..f89796106 100644 --- a/math/fp448/fp.go +++ b/math/fp448/fp.go @@ -2,6 +2,7 @@ package fp448 import ( + "crypto/subtle" "errors" "github.com/cloudflare/circl/internal/conv" @@ -25,6 +26,15 @@ var p = Elt{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, } +var pMinusOneDivTwo = Elt{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, +} // P returns the prime modulus 2^448-2^224-1. func P() Elt { return p } @@ -45,6 +55,26 @@ func IsZero(x *Elt) bool { Modp(x); return *x == Elt{} } // IsOne returns true if x is equal to 1. func IsOne(x *Elt) bool { Modp(x); return *x == Elt{1} } +// Parity returns the last bit of x. +func Parity(x *Elt) int { Modp(x); return int(x[0] & 1) } + +func isLEQ(x, y *Elt) int { + i := Size - 1 + for i > 0 && x[i] == y[i] { + i-- + } + return subtle.ConstantTimeLessOrEq(int(x[i]), int(y[i])) +} + +// Abs returns |x| where |x| = x if 0 <= x <= (p-1)/2; otherwise |x|=-x mod p. +func Abs(x *Elt) { + var y Elt + Modp(x) + Neg(&y, x) + b := isLEQ(x, &pMinusOneDivTwo) + Cmov(x, &y, uint(1-b)) +} + // SetOne assigns x=1. func SetOne(x *Elt) { *x = Elt{1} } @@ -142,9 +172,6 @@ func powPminus3div4(z, x *Elt) { Mul(z, z, x1) } -// Sign returns 1 if x is positive, and -1 if negative. -func Sign(x *Elt) int { return 0 } - // Cmov assigns y to x if n is 1. func Cmov(x, y *Elt, n uint) { cmov(x, y, n) }