github.com/lbryio/lbcd@v0.22.119/btcec/gensecp256k1.go (about)

     1  // Copyright (c) 2014-2015 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  // This file is ignored during the regular build due to the following build tag.
     6  // This build tag is set during go generate.
     7  //go:build gensecp256k1
     8  // +build gensecp256k1
     9  
    10  package btcec
    11  
    12  // References:
    13  //   [GECC]: Guide to Elliptic Curve Cryptography (Hankerson, Menezes, Vanstone)
    14  
    15  import (
    16  	"encoding/binary"
    17  	"math/big"
    18  )
    19  
    20  // secp256k1BytePoints are dummy points used so the code which generates the
    21  // real values can compile.
    22  var secp256k1BytePoints = ""
    23  
    24  // getDoublingPoints returns all the possible G^(2^i) for i in
    25  // 0..n-1 where n is the curve's bit size (256 in the case of secp256k1)
    26  // the coordinates are recorded as Jacobian coordinates.
    27  func (curve *KoblitzCurve) getDoublingPoints() [][3]fieldVal {
    28  	doublingPoints := make([][3]fieldVal, curve.BitSize)
    29  
    30  	// initialize px, py, pz to the Jacobian coordinates for the base point
    31  	px, py := curve.bigAffineToField(curve.Gx, curve.Gy)
    32  	pz := new(fieldVal).SetInt(1)
    33  	for i := 0; i < curve.BitSize; i++ {
    34  		doublingPoints[i] = [3]fieldVal{*px, *py, *pz}
    35  		// P = 2*P
    36  		curve.doubleJacobian(px, py, pz, px, py, pz)
    37  	}
    38  	return doublingPoints
    39  }
    40  
    41  // SerializedBytePoints returns a serialized byte slice which contains all of
    42  // the possible points per 8-bit window.  This is used to when generating
    43  // secp256k1.go.
    44  func (curve *KoblitzCurve) SerializedBytePoints() []byte {
    45  	doublingPoints := curve.getDoublingPoints()
    46  
    47  	// Segregate the bits into byte-sized windows
    48  	serialized := make([]byte, curve.byteSize*256*3*10*4)
    49  	offset := 0
    50  	for byteNum := 0; byteNum < curve.byteSize; byteNum++ {
    51  		// Grab the 8 bits that make up this byte from doublingPoints.
    52  		startingBit := 8 * (curve.byteSize - byteNum - 1)
    53  		computingPoints := doublingPoints[startingBit : startingBit+8]
    54  
    55  		// Compute all points in this window and serialize them.
    56  		for i := 0; i < 256; i++ {
    57  			px, py, pz := new(fieldVal), new(fieldVal), new(fieldVal)
    58  			for j := 0; j < 8; j++ {
    59  				if i>>uint(j)&1 == 1 {
    60  					curve.addJacobian(px, py, pz, &computingPoints[j][0],
    61  						&computingPoints[j][1], &computingPoints[j][2], px, py, pz)
    62  				}
    63  			}
    64  			for i := 0; i < 10; i++ {
    65  				binary.LittleEndian.PutUint32(serialized[offset:], px.n[i])
    66  				offset += 4
    67  			}
    68  			for i := 0; i < 10; i++ {
    69  				binary.LittleEndian.PutUint32(serialized[offset:], py.n[i])
    70  				offset += 4
    71  			}
    72  			for i := 0; i < 10; i++ {
    73  				binary.LittleEndian.PutUint32(serialized[offset:], pz.n[i])
    74  				offset += 4
    75  			}
    76  		}
    77  	}
    78  
    79  	return serialized
    80  }
    81  
    82  // sqrt returns the square root of the provided big integer using Newton's
    83  // method.  It's only compiled and used during generation of pre-computed
    84  // values, so speed is not a huge concern.
    85  func sqrt(n *big.Int) *big.Int {
    86  	// Initial guess = 2^(log_2(n)/2)
    87  	guess := big.NewInt(2)
    88  	guess.Exp(guess, big.NewInt(int64(n.BitLen()/2)), nil)
    89  
    90  	// Now refine using Newton's method.
    91  	big2 := big.NewInt(2)
    92  	prevGuess := big.NewInt(0)
    93  	for {
    94  		prevGuess.Set(guess)
    95  		guess.Add(guess, new(big.Int).Div(n, guess))
    96  		guess.Div(guess, big2)
    97  		if guess.Cmp(prevGuess) == 0 {
    98  			break
    99  		}
   100  	}
   101  	return guess
   102  }
   103  
   104  // EndomorphismVectors runs the first 3 steps of algorithm 3.74 from [GECC] to
   105  // generate the linearly independent vectors needed to generate a balanced
   106  // length-two representation of a multiplier such that k = k1 + k2λ (mod N) and
   107  // returns them.  Since the values will always be the same given the fact that N
   108  // and λ are fixed, the final results can be accelerated by storing the
   109  // precomputed values with the curve.
   110  func (curve *KoblitzCurve) EndomorphismVectors() (a1, b1, a2, b2 *big.Int) {
   111  	bigMinus1 := big.NewInt(-1)
   112  
   113  	// This section uses an extended Euclidean algorithm to generate a
   114  	// sequence of equations:
   115  	//  s[i] * N + t[i] * λ = r[i]
   116  
   117  	nSqrt := sqrt(curve.N)
   118  	u, v := new(big.Int).Set(curve.N), new(big.Int).Set(curve.lambda)
   119  	x1, y1 := big.NewInt(1), big.NewInt(0)
   120  	x2, y2 := big.NewInt(0), big.NewInt(1)
   121  	q, r := new(big.Int), new(big.Int)
   122  	qu, qx1, qy1 := new(big.Int), new(big.Int), new(big.Int)
   123  	s, t := new(big.Int), new(big.Int)
   124  	ri, ti := new(big.Int), new(big.Int)
   125  	a1, b1, a2, b2 = new(big.Int), new(big.Int), new(big.Int), new(big.Int)
   126  	found, oneMore := false, false
   127  	for u.Sign() != 0 {
   128  		// q = v/u
   129  		q.Div(v, u)
   130  
   131  		// r = v - q*u
   132  		qu.Mul(q, u)
   133  		r.Sub(v, qu)
   134  
   135  		// s = x2 - q*x1
   136  		qx1.Mul(q, x1)
   137  		s.Sub(x2, qx1)
   138  
   139  		// t = y2 - q*y1
   140  		qy1.Mul(q, y1)
   141  		t.Sub(y2, qy1)
   142  
   143  		// v = u, u = r, x2 = x1, x1 = s, y2 = y1, y1 = t
   144  		v.Set(u)
   145  		u.Set(r)
   146  		x2.Set(x1)
   147  		x1.Set(s)
   148  		y2.Set(y1)
   149  		y1.Set(t)
   150  
   151  		// As soon as the remainder is less than the sqrt of n, the
   152  		// values of a1 and b1 are known.
   153  		if !found && r.Cmp(nSqrt) < 0 {
   154  			// When this condition executes ri and ti represent the
   155  			// r[i] and t[i] values such that i is the greatest
   156  			// index for which r >= sqrt(n).  Meanwhile, the current
   157  			// r and t values are r[i+1] and t[i+1], respectively.
   158  
   159  			// a1 = r[i+1], b1 = -t[i+1]
   160  			a1.Set(r)
   161  			b1.Mul(t, bigMinus1)
   162  			found = true
   163  			oneMore = true
   164  
   165  			// Skip to the next iteration so ri and ti are not
   166  			// modified.
   167  			continue
   168  
   169  		} else if oneMore {
   170  			// When this condition executes ri and ti still
   171  			// represent the r[i] and t[i] values while the current
   172  			// r and t are r[i+2] and t[i+2], respectively.
   173  
   174  			// sum1 = r[i]^2 + t[i]^2
   175  			rSquared := new(big.Int).Mul(ri, ri)
   176  			tSquared := new(big.Int).Mul(ti, ti)
   177  			sum1 := new(big.Int).Add(rSquared, tSquared)
   178  
   179  			// sum2 = r[i+2]^2 + t[i+2]^2
   180  			r2Squared := new(big.Int).Mul(r, r)
   181  			t2Squared := new(big.Int).Mul(t, t)
   182  			sum2 := new(big.Int).Add(r2Squared, t2Squared)
   183  
   184  			// if (r[i]^2 + t[i]^2) <= (r[i+2]^2 + t[i+2]^2)
   185  			if sum1.Cmp(sum2) <= 0 {
   186  				// a2 = r[i], b2 = -t[i]
   187  				a2.Set(ri)
   188  				b2.Mul(ti, bigMinus1)
   189  			} else {
   190  				// a2 = r[i+2], b2 = -t[i+2]
   191  				a2.Set(r)
   192  				b2.Mul(t, bigMinus1)
   193  			}
   194  
   195  			// All done.
   196  			break
   197  		}
   198  
   199  		ri.Set(r)
   200  		ti.Set(t)
   201  	}
   202  
   203  	return a1, b1, a2, b2
   204  }