AntonKueltz / fastecdsa

Python library for fast elliptic curve crypto
https://pypi.python.org/pypi/fastecdsa
The Unlicense
263 stars 76 forks source link

getting y public key from compressed public key #92

Closed clon19 closed 8 months ago

clon19 commented 9 months ago

It would be great if you coukld get the y part of the public key from the compressed public key as a function

AntonKueltz commented 9 months ago

You can string together some of the existing functions in the package to get the candidates for y given x. You need to chain y2 = fastecdsa.curve.Curve.evaluate(x) and roots = fastecdsa.util.mod_sqrt(y2, Curve.p). As an example -

In [1]: from fastecdsa.curve import W25519

In [2]: x = W25519.G.x

In [3]: x
Out[3]: 19298681539552699237261830834781317975544997444273427339909597334652188435546

In [4]: y = W25519.G.y

In [5]: y
Out[5]: 43114425171068552920764898935933967039370386198203806730763910166200978582548

In [6]: y2 = W25519.evaluate(x)

In [7]: y2
Out[7]: 39420360

In [8]: from fastecdsa.util import mod_sqrt

In [9]: mod_sqrt(y2, W25519.p)
Out[9]:
(14781619447589544791020593568409986887264606134616475288964881837755586237401,
 43114425171068552920764898935933967039370386198203806730763910166200978582548)

Note that mod_sqrt gives two values (just like normal sqrt). In this case the second value corresponds to the y-coordinate of the generator point of curve W25519. You'll have to look at the public key encoding to determine which root (even or odd) is the correct value.

If you're using SEC1 encoding, a common compressed encoding for public keys, you can use fastecdsa.encoding.sec1.SEC1Encoder.decode_public_key to do this all in one call. The method body should help as a reference for doing this manually. You can also refer to the README as well as the unit tests for usage of the decoder.