curve.mx raw

   1  // Copyright (c) 2015-2021 The btcsuite developers
   2  // Copyright (c) 2015-2021 The Decred developers
   3  
   4  package btcec
   5  
   6  import (
   7  	"fmt"
   8  
   9  	"crypto/ec/secp256k1"
  10  )
  11  
  12  // JacobianPoint is an element of the group formed by the secp256k1 curve in
  13  // Jacobian projective coordinates and thus represents a point on the curve.
  14  type JacobianPoint = secp256k1.JacobianPoint
  15  
  16  func _infinityPoint() JacobianPoint { return JacobianPoint{} }
  17  
  18  // MakeJacobianPoint returns a Jacobian point with the provided X, Y, and Z
  19  // coordinates.
  20  func MakeJacobianPoint(x, y, z *FieldVal) JacobianPoint {
  21  	return secp256k1.MakeJacobianPoint(x, y, z)
  22  }
  23  
  24  // AddNonConst adds the passed Jacobian points together and stores the result
  25  // in the provided result param in *non-constant* time.
  26  func AddNonConst(p1, p2, result *JacobianPoint) {
  27  	secp256k1.AddNonConst(p1, p2, result)
  28  }
  29  
  30  // DecompressY attempts to calculate the Y coordinate for the given X
  31  // coordinate such that the result pair is a point on the secp256k1 curve. It
  32  // adjusts Y based on the desired oddness and returns whether or not it was
  33  // successful since not all X coordinates are valid.
  34  //
  35  // The magnitude of the provided X coordinate field val must be a max of 8 for
  36  // a correct result. The resulting Y field val will have a max magnitude of 2.
  37  func DecompressY(x *FieldVal, odd bool, resultY *FieldVal) bool {
  38  	return secp256k1.DecompressY(x, odd, resultY)
  39  }
  40  
  41  // DoubleNonConst doubles the passed Jacobian point and stores the result in
  42  // the provided result parameter in *non-constant* time.
  43  //
  44  // NOTE: The point must be normalized for this function to return the correct
  45  // result. The resulting point will be normalized.
  46  func DoubleNonConst(p, result *JacobianPoint) {
  47  	secp256k1.DoubleNonConst(p, result)
  48  }
  49  
  50  // ScalarBaseMultNonConst multiplies k*G where G is the base point of the group
  51  // and k is a big endian integer. The result is stored in Jacobian coordinates
  52  // (x1, y1, z1).
  53  //
  54  // NOTE: The resulting point will be normalized.
  55  func ScalarBaseMultNonConst(k *ModNScalar, result *JacobianPoint) {
  56  	secp256k1.ScalarBaseMultNonConst(k, result)
  57  }
  58  
  59  // ScalarMultNonConst multiplies k*P where k is a big endian integer modulo the
  60  // curve order and P is a point in Jacobian projective coordinates and stores
  61  // the result in the provided Jacobian point.
  62  //
  63  // NOTE: The point must be normalized for this function to return the correct
  64  // result. The resulting point will be normalized.
  65  func ScalarMultNonConst(k *ModNScalar, point, result *JacobianPoint) {
  66  	secp256k1.ScalarMultNonConst(k, point, result)
  67  }
  68  
  69  // ParseJacobian parses a byte slice point as a secp256k1.Publickey and returns the
  70  // pubkey as a JacobianPoint. If the nonce is a zero slice, the infinityPoint
  71  // is returned.
  72  func ParseJacobian(point []byte) (JacobianPoint, error) {
  73  	var result JacobianPoint
  74  	if len(point) != 33 {
  75  		str := fmt.Sprintf(
  76  			"invalid nonce: invalid length: %v",
  77  			len(point),
  78  		)
  79  		return JacobianPoint{}, makeError(secp256k1.ErrPubKeyInvalidLen, str)
  80  	}
  81  	if point[0] == 0x00 {
  82  		return _infinityPoint(), nil
  83  	}
  84  	noncePk, err := secp256k1.ParsePubKey(point)
  85  	if err != nil {
  86  		return JacobianPoint{}, err
  87  	}
  88  	noncePk.AsJacobian(&result)
  89  	return result, nil
  90  }
  91  
  92  // JacobianToByteSlice converts the passed JacobianPoint to a Pubkey
  93  // and serializes that to a byte slice. If the JacobianPoint is the infinity
  94  // point, a zero slice is returned.
  95  func JacobianToByteSlice(point JacobianPoint) []byte {
  96  	inf := _infinityPoint()
  97  	if point.X == inf.X && point.Y == inf.Y {
  98  		return []byte{:33}
  99  	}
 100  	point.ToAffine()
 101  	return NewPublicKey(
 102  		&point.X, &point.Y,
 103  	).SerializeCompressed()
 104  }
 105  
 106  // GeneratorJacobian sets the passed JacobianPoint to the Generator Point.
 107  func GeneratorJacobian(jacobian *JacobianPoint) {
 108  	var k ModNScalar
 109  	k.SetInt(1)
 110  	ScalarBaseMultNonConst(&k, jacobian)
 111  }
 112