I've been learning about the elliptic curves and how they work, and their usage in cryptography, and I'm trying to figure out how to use them using Go.

  1. Where is the 'a' parameter from my ECC equation y^2 = x^3 + a*x + b, in this CurveParams structure? https://golang.org/pkg/crypto/elliptic/#CurveParams To verify I am understanding well please correct me if I am wrong:
  • 'P' parameter represents the order of the finite field
  • 'N' is the minimum prime number such that N*G result is the infinity point
  • 'B' is the constant 'b' in my ECC equation
  • 'Gx','Gy' represents the base point (which for example is used for calculating public keys using your chosen private key and multiplying it with G, or in the example above where N*G is used to calculate the infinity point)
  • 'BitSize' this is where I'm not sure what this actually represents. I understand that in the P256 (secp256k1 BTC) curve this is equal to 256 and so it represents the length of the private key. What I do not understand is where in the math does this number actually appear from? Or is it actually just the binary length of the 'P' ?
  • The biggest question here is where is 'a' parameter from the elliptic curve equation? How can elliptic curves actually be defined if I don't decide this parameter?
  1. What happens if you use the Double() function using a point that is not on the curve, or using the infinity point? I tried to search for some point that is not found on the curve to call the function with it but didn't find any (for the P256 curve, i searched on google) https://golang.org/pkg/crypto/elliptic/#CurveParams.Double

  2. What happens if you use the Add() function using points that are not on the curve, or using the infinity point + on curve point, or infinity point + not on curve point? https://golang.org/pkg/crypto/elliptic/#CurveParams.Add

  3. Why are private keys returned in byte types? What's the deal with the byte type? I see it used in a lot of places. Why do we not use the big int type? I see them being used in GenerateKey(), Marshal(), MarshalCompressed(), UnmarshalCompressed(), ScalarBaseMult(), ScalarMult().

For all the questions above, I am interested also from the math and programming point of view, but especially programming. If you do not have the answers for all of them, please provide any answer to any question you have answer/s for.


  • question 1 partially answered. BitSize still needs to be explained
  • $\begingroup$ As far I understood, [] bytes can represent integer of size arbitrary long. The choice here seems to make no restriction to the size of the integer in ScalarMult, because it's well defined for any positive integer. And theoretically, for some specific curves; the order of the goup can be bigger than the order of the base field, then it's possible that big_int would be not enough big to represent the private key. $\endgroup$
    – Ievgeni
    Jun 11, 2021 at 11:54
  • 1
    $\begingroup$ @levegni ok it kinda makes sense. $\endgroup$
    – brewandrew
    Jun 11, 2021 at 12:07
  • 1
    $\begingroup$ no, the big.Int type can also represent an arbitrary sized integer. The reason to use of bytes to represent values is made clear in the documentation for Marshall, etc. There are standard formats for interchange that are defined in terms of bytes, as bytes (actually 'octets' is more accurate) are the standard unit of storage and network transmission. As to why ScalarMult and similar use the []byte form you'd have to ask the programmer, but they likely thought it would be more convenient. The big.Int type has methods to convert to and from []byte so in practice it's not an issue. $\endgroup$ Jun 12, 2021 at 15:38
  • $\begingroup$ You seem to fear about the invalid point attack. The validation is necessary. The private key is a big integer that is stored as a byte object. No worries, the library handles that for you and the conversion is easy. $\endgroup$
    – kelalaka
    Jun 20, 2021 at 19:03

1 Answer 1


Because you know one point of the curve (the base point). you can compute $a$ :

$$a = \frac{(Gy)^2 -(Gx)^3 -b}{Gx} \mod p$$

Notice that this computation requires $Gx \neq 0 \mod p$.

About the infinity point : The infinity point is supposed to be the neutral element, then by definition of the neutral element : $(x,y)+\mathcal{O}=\mathcal{O}+(x,y) = (x,y)$, it implies thus that $2\mathcal{O}=\mathcal{O}$

And thus, Double($\mathcal{O}$) will return you the same point $\mathcal{O}$. And for the same reason, Add$(\mathcal{O}, \cdot)$, Add$(\cdot, \mathcal{O})$ are both the identity function for the set of the points of the curve.

You're not supposed to use the functions on points which are not in the curve, thus I'm assuming it should return an error, if you do that (otherwise it should).

  • 1
    $\begingroup$ ok so this partially answeres my first 3 questions $\endgroup$
    – brewandrew
    Jun 11, 2021 at 10:52
  • 3
    $\begingroup$ "You're not supposed to use the functions on points which are not in the curve, thus I'm assuming it should return an error" - ECC routines generally don't. Yes, they could check; however the time that would take would be a significant fraction of the point addition time, hence they generally don't bother for intermediate results. They really should check when you initially import the values (and when they know the initial values are on the curve, all intermediate ones will be as well); in my experience, even that isn't universal $\endgroup$
    – poncho
    Jun 11, 2021 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.