Golang's elliptical curve library can derive a secret key given a public coordinate with a X and Y value (uncompressed coordinates).
However, when the point given is a single value in X9.62 compressed form with a given y-bit, how do I uncompress it?
OpenSSL handles this scenario with this method:
There also appears to be a similar question addressing the math involved, but not a best practice for Go, specifically:
How should this be done in Go?
As far as I know there is no point decompression function in the Go standard library (or the “x” packages), so you’d have to do it yourself (or find an existing implementation).
The implementation is not too difficult, although there are a couple of things to looks out for.
Basically, you need plug your
X
value into the curve equationY2 = X3 + aX + b
, and then determine which of the two roots you want using the sign bit. The tricky bit is remembering that all this needs to be done modulo the field prime of the group.I find Go’s big integer package can be a bit odd to use sometimes, because it uses mutable values, but it does have a modular square root function which makes things a lot easier for us. The curve parameters are available in the
crypto/elliptic
package, although you need to know thea
parameter is always-3
for these curves.Assuming you have the compressed point as a
[]byte
(with a leading0x02
or0x03
) incompressed_bytes
, the following should work. This is a pretty direct implementation of the equation, broken up with comments and lots of named variables to attempt to explain what’s going on. Have a look at the source ofCurveParams.IsOnCurve
for a slightly more efficient (and shorter) implementation. It’s basically the same up until the modular square root.