Search code examples
pythondartcryptographyecdsa

How to encode x, y coords to python ecdsa VerifyingKey format from Dart


I am trying to send verifying key from my flutter app to python server and I can't figure out the format the python ecdsa lib is expecting.

I am using the spec256k1 lib on the dart side (The python side is also using the spec256k1 curve)

import ecdsa
sk = ecdsa.SigningKey.generate()
vk = sk.get_verifying_key()
s_vk = vk.to_string()

# I can't figure out how to create the 's_vk' from x, y croods

string_sent_from_app = "..." # how to create this string on the app side from x, y or you have a better idea?
my_vk = ecdsa.VerifyingKey.from_string(string_sent_from_app)



Solution

  • from_string() allows to import the public key in different formats, including the raw key, which is suitable for you.
    The raw format consists of concatenating the x and y coordinates of the EC point. For secp256k1, x and y are 32 bytes each, so 64 bytes in total. If x is shorter, it must be padded from the left with 0x00 values to 32 bytes (analogously for y).

    Example of importing a raw public EC key:

    import ecdsa
    from hashlib import sha256
    
    rawPublicKey = 'ba11d6acfd759a7a75c662db85015373bf99972f42910391ac0f4e0e6bfdc72e0b282f324b448c637e54e6d0f1f51576f150c559f38b32f2ea7a3d9aaf5c1694'
    signature = '1fe21a18c6e51000e76f7b69ffcb71471067775803d650392ff036cebe314098c6cacf0818e2d646f53699e97efbadd0b6dea9bca5a09cd5b76f42a75004a798'
    message = b'The quick brown fox jumps over the lazy dog'
    
    verifyingKey = ecdsa.VerifyingKey.from_string(bytes.fromhex(rawPublicKey), curve=ecdsa.SECP256k1, hashfunc=sha256, valid_encodings=['raw'])
    verified = verifyingKey.verify(bytes.fromhex(signature), message)
    print(verified) # True
    

    Note that curve and digest must be explicitly specified, since the ecdsa library uses different default values (NIST P-192, denoted as NIST192p, and SHA-1).


    Overall, the library supports a large number of formats for import, e.g. the compressed and uncompressed format (via from_string()) and also the X.509/SPKI format (via from_pem() and from_der() for PEM and DER encoded keys, respectively).
    More information can be found in the documentation, see sec. Usage, and the implementation, especially in keys.py.