// Initialize Elligator 1 parameters given magic point s func (el *el1param) init(ec *curve, s *big.Int) *el1param { var two, invc, cm1, d nist.Int el.ec = ec el.s.Init(s, &ec.P) // c = 2/s^2 two.Init64(2, &ec.P) el.c.Mul(&el.s, &el.s).Div(&two, &el.c) // r = c+1/c invc.Inv(&el.c) el.r.Add(&el.c, &invc) // Precomputed values el.r2m2.Mul(&el.r, &el.r).Sub(&el.r2m2, &two) // r^2-2 el.invc2.Mul(&invc, &invc) // 1/c^2 el.pp1d4.Add(&ec.P, one).Div(&el.pp1d4, big.NewInt(4)) // (p+1)/4 cm1.Sub(&el.c, &ec.one) el.cm1s.Mul(&cm1, &el.s) // (c-1)s el.m2.Init64(-2, &ec.P) // -2 // 2s(c-1)Chi(c)/r chi(&el.c3x, &el.c) el.c3x.Mul(&el.c3x, &two).Mul(&el.c3x, &el.s).Mul(&el.c3x, &cm1) el.c3x.Div(&el.c3x, &el.r) // Sanity check: d = -(c+1)^2/(c-1)^2 d.Add(&el.c, &ec.one).Div(&d, &cm1).Mul(&d, &d).Neg(&d) if d.Cmp(&ec.d) != 0 { panic("el1 init: d came out wrong") } return el }
// Initialize a twisted Edwards curve with given parameters. // Caller passes pointers to null and base point prototypes to be initialized. func (c *curve) init(self abstract.Group, p *Param, fullGroup bool, null, base point) *curve { c.self = self c.Param = *p c.full = fullGroup c.null = null // Edwards curve parameters as ModInts for convenience c.a.Init(&p.A, &p.P) c.d.Init(&p.D, &p.P) // Cofactor c.cofact.Init64(int64(p.R), &c.P) // Determine the modulus for scalars on this curve. // Note that we do NOT initialize c.order with Init(), // as that would normalize to the modulus, resulting in zero. // Just to be sure it's never used, we leave c.order.M set to nil. // We want it to be in a ModInt so we can pass it to P.Mul(), // but the scalar's modulus isn't needed for point multiplication. if fullGroup { // Scalar modulus is prime-order times the ccofactor c.order.V.SetInt64(int64(p.R)).Mul(&c.order.V, &p.Q) } else { c.order.V.Set(&p.Q) // Prime-order subgroup } // Useful ModInt constants for this curve c.zero.Init64(0, &c.P) c.one.Init64(1, &c.P) // Identity element is (0,1) null.initXY(zero, one, self) // Base point B var bx, by *big.Int if !fullGroup { bx, by = &p.PBX, &p.PBY } else { bx, by = &p.FBX, &p.FBY base.initXY(&p.FBX, &p.FBY, self) } if by.Sign() == 0 { // No standard base point was defined, so pick one. // Find the lowest-numbered y-coordinate that works. //println("Picking base point:") var x, y nist.Int for y.Init64(2, &c.P); ; y.Add(&y, &c.one) { if !c.solveForX(&x, &y) { continue // try another y } if c.coordSign(&x) != 0 { x.Neg(&x) // try positive x first } base.initXY(&x.V, &y.V, self) if c.validPoint(base) { break // got one } x.Neg(&x) // try -bx if c.validPoint(base) { break // got one } } //println("BX: "+x.V.String()) //println("BY: "+y.V.String()) bx, by = &x.V, &y.V } base.initXY(bx, by, self) // Uniform representation encoding methods, // only useful when using the full group. // (Points taken from the subgroup would be trivially recognizable.) if fullGroup { if p.Elligator1s.Sign() != 0 { c.hide = new(el1param).init(c, &p.Elligator1s) } else if p.Elligator2u.Sign() != 0 { c.hide = new(el2param).init(c, &p.Elligator2u) } // XXX Elligator Squared } // Sanity checks if !c.validPoint(null) { panic("invalid identity point " + null.String()) } if !c.validPoint(base) { panic("invalid base point " + base.String()) } return c }
func chi(r, v *nist.Int) { r.Init64(int64(math.Jacobi(&v.V, v.M)), v.M) }