0

I am trying to write a python script that verifies an ECDSA signature and I am having a terrible time trying to do it.

This is the code I use:

public_key = ecdsa.VerifyingKey.from_string(pubkey, curve=ecdsa.SECP256k1)
verified = public_key.verify_digest(signature, val, sigdecode=ecdsa.util.sigdecode_der)

If the signature r and s are positive, it works well, but if either of them is negative, an assertion error raises. I have checked the ecdsa sourcecode, and I saw this line:

nbytes = numberbytes[0] if isinstance(numberbytes[0], integer_types) else ord(numberbytes[0])
assert nbytes < 0x80 # can't support negative numbers yet

https://github.com/warner/python-ecdsa/blob/master/ecdsa/der.py#L105

Why does this happen? Isn't this library something "oficial"? What alternatives do I have? Is it safe to just remove that assertion line?

Jorky10
  • 591
  • 2
  • 6
  • 9
  • You should ask the authors of the software :) – Andrea Corbellini Jan 10 '16 at 15:41
  • 1
    Try inserting one zero (`0x00`) byte to the beginning of the `r` and `s` values (e.g. change `81AABB...` into `0081AABB...`) to ensure the number is interpreted as positive (Note: This _might_ be tricky as you _might_ need to tweak the lengths in the encoded signature -- depends on the way how you pass the `r` and `s` values to the ecdsa library). – vlp Jan 10 '16 at 23:01

1 Answers1

2

ECDSA itself does not use negative numbers, so I would not expect a Python implementation of it to support negative numbers. The types of numbers used by ECDSA are between 0 and some large prime number, and they obey the laws of modular arithmetic.

David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • Then why does my openssl return negative s or r numbers eventually? – Jorky10 Jan 10 '16 at 21:30
  • 1
    @Jorky10 - It depends on the standard. If they are encoded as ASN.1 ***`INTEGER`***, then they will never be negative because there will be a leading 00 octet. If they are ASN.1 ***`OCTET_STRING`*** or a byte string (i.e., 40 bytes for the ***`{r,s}`*** pair when using SHA1, 64 bytes for the ***`{r,s}`*** pair when using SHA256, etc), then Python has a bug in its parser or subroutine. – jww Jan 11 '16 at 13:51
  • I guess there's the trick. Thanks for giving me a path to follow! – Jorky10 Jan 11 '16 at 13:55