Skip to content

Commit

Permalink
Decaf encoding requires cannon sqrt.
Browse files Browse the repository at this point in the history
  • Loading branch information
armfazh committed Jul 24, 2020
1 parent 9479b45 commit 8933f6c
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 23 deletions.
64 changes: 44 additions & 20 deletions ecc/goldilocks/decaf.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package goldilocks

import (
"fmt"

fp "github.com/cloudflare/circl/math/fp448"
)

Expand All @@ -10,14 +12,20 @@ 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) }

// Identity is
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() }
Expand All @@ -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)} }
Expand All @@ -45,31 +53,47 @@ 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, &paramD) // 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, &paramD) // 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)
return encS[:]
}

// 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) }
Expand Down
27 changes: 27 additions & 0 deletions ecc/goldilocks/decaf_test.go
Original file line number Diff line number Diff line change
@@ -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)))
// }
}
33 changes: 30 additions & 3 deletions math/fp448/fp.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package fp448

import (
"crypto/subtle"
"errors"

"github.com/cloudflare/circl/internal/conv"
Expand All @@ -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 }
Expand All @@ -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} }

Expand Down Expand Up @@ -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) }

Expand Down

0 comments on commit 8933f6c

Please sign in to comment.