group_double_32bit.go raw

   1  //go:build js || wasm || tinygo || wasm32
   2  
   3  package p256k1
   4  
   5  // double sets r = 2*a (point doubling in Jacobian coordinates)
   6  // Uses the half-free Decred-style formula because half() has a carry bug
   7  // in the 10×26-bit limb representation used on 32-bit/WASM.
   8  //   A = X1^2, B = Y1^2, C = B^2, D = 2*((X1+B)^2-A-C)
   9  //   E = 3*A, F = E^2, X3 = F-2*D, Y3 = E*(D-X3)-8*C, Z3 = 2*Y1*Z1
  10  func (r *GroupElementJacobian) double(a *GroupElementJacobian) {
  11  	r.infinity = a.infinity
  12  
  13  	var aa, b, c, d, e, f FieldElement
  14  
  15  	// Z3 = 2*Y1*Z1
  16  	r.z.mul(&a.y, &a.z)
  17  	r.z.mulInt(2)
  18  
  19  	// A = X1^2
  20  	aa.sqr(&a.x)
  21  
  22  	// B = Y1^2
  23  	b.sqr(&a.y)
  24  
  25  	// C = B^2 = Y1^4
  26  	c.sqr(&b)
  27  
  28  	// D = 2*((X1+B)^2 - A - C) = 4*X1*Y1^2
  29  	b.add(&a.x)
  30  	b.sqr(&b)
  31  	d = aa
  32  	d.add(&c)
  33  	d.negate(&d, 2)
  34  	d.add(&b)
  35  	d.mulInt(2)
  36  
  37  	// E = 3*A = 3*X1^2
  38  	e = aa
  39  	e.mulInt(3)
  40  
  41  	// F = E^2
  42  	f.sqr(&e)
  43  
  44  	// X3 = F - 2*D
  45  	r.x = d
  46  	r.x.mulInt(2)
  47  	r.x.negate(&r.x, 16)
  48  	r.x.add(&f)
  49  	r.x.normalize()
  50  
  51  	// Y3 = E*(D-X3) - 8*C
  52  	f.negate(&r.x, 1)
  53  	f.add(&d)
  54  	f.normalize()
  55  	f.mul(&f, &e)
  56  
  57  	c.mulInt(8)
  58  	c.negate(&c, 8)
  59  	r.y = f
  60  	r.y.add(&c)
  61  
  62  	r.x.normalize()
  63  	r.y.normalize()
  64  	r.z.normalize()
  65  }
  66