pyca / pynacl

Python binding to the Networking and Cryptography (NaCl) library
https://pynacl.readthedocs.io/
Apache License 2.0
1.05k stars 228 forks source link

How to obtain ed25519 public keys in compressed Edwards Y format? #781

Closed fgimenez closed 1 year ago

fgimenez commented 1 year ago

I have the following code:


from nacl.public import PrivateKey
from nacl.encoding import HexEncoder

priv_key = PrivateKey(bytes.from_hex('a4421cf8f5594287e6cbc47e6a465d9ba70e20ed28199c8712d59665bb95fdda'))
pub_key = priv_key.public_key

print('priv key: ' + priv_key.encode(HexEncoder).decode('utf-8'))
print('pub key: ' + pub_key.encode(HexEncoder).decode('utf-8'))

this gives me:

priv key: a4421cf8f5594287e6cbc47e6a465d9ba70e20ed28199c8712d59665bb95fdda
pub key: df6187d1ba2e045263f058c5bc921b6518cf975bcab437ba0c5c95bcc450bb4d

but other the libraries (like the rust version used in libp2p) or online tools like https://cyphr.me/ed25519_applet/ed.html#?msg_encoding=Text&msg_type=Msg&key_encoding=Hex give me C737701E24FE1A3449A54F4CA86626B55D0D87CD6546D315F02611D538E5C63C as the public key corresponding to the same private key, I've checked and this is the public key in compressed Edwards Y format.

So, is it possible to obtain this format of the public key using pynacl?

Thanks!

reaperhulk commented 1 year ago

The PrivateKey and PublicKey objects correspond to curve25519, which is birationally equivalent to the ed25519 curve, but is not the same. You want to use SigningKey and VerifyKey in nacl.signing.

from nacl.public import PrivateKey
from nacl.encoding import HexEncoder

sign_key = SigningKey(bytes.fromhex('a4421cf8f5594287e6cbc47e6a465d9ba70e20ed28199c8712d59665bb95fdda'))
verify_key = sign_key.verify_key

print('sign key: ' + sign_key.encode(HexEncoder).decode('utf-8'))
print('verify key: ' + verify_key.encode(HexEncoder).decode('utf-8'))

This should give you the value you expect.

fgimenez commented 1 year ago

Awesome, thank you so much @reaperhulk! :heart: