Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interoperability with python-ecdsa regarding the SECP160r1 curve #194

Open
t123yh opened this issue Apr 21, 2022 · 2 comments
Open

Interoperability with python-ecdsa regarding the SECP160r1 curve #194

t123yh opened this issue Apr 21, 2022 · 2 comments

Comments

@t123yh
Copy link

t123yh commented Apr 21, 2022

I'm trying to make a signature within my MCU running micro-ecc, and verify the signature with python-ecdsa library. The problem is, when using the SECP160r1 curve, python-ecdsa expects 42 bytes signature, but in micro-ecc, it produces 40 bytes signature.

You can test with the following python code:

from ecdsa import SECP160r1, SigningKey, VerifyingKey
import hashlib

def get_sha(s):
  h = hashlib.new('sha1')
  h.update(s.encode())
  return h.digest()

hash = get_sha("123")
our_sk = SigningKey.generate(curve=SECP160r1)
sign = our_sk.sign(hash)
print("sign:", sign.hex(), "len:", len(sign))

Example output:

sign: 0039090c6e893886b196c9ed3edf77f00cef9f47e70039b82ca31e51e3c2315afab4ca171835bc312faa len: 42

Is there any way to make python-ecdsa and micro-ecc compatible?

@ab-tools
Copy link

@t123yh, did you ever find a solution to this?

I would also like to use it together with this Python library.
Any suggestions (possibly also alternatives that you end up using) would be welcome, thanks.

@vruello
Copy link

vruello commented Nov 1, 2023

I had the same problem and I was able to get it to work :)

As I understand it, uECC outputs by default a 40 byte signature formatted as [r19]...[r0][s19]...[s0], while python-ecdsa expects [r20]...[r0][s20]...[s0]. According to some guy on stackoverflow (no cryptographer here), r20 and s20 are \x00, so you just have to transform the signature a bit before passing it to python-ecdsa : sig = b'\x00' + raw_sig[:20] + b'\x00' + raw_sig[20:].

Also note that VerifyingKey.verify computes a hash of the given data whereas uECC_sign doesn't. If you want to verify the output <sig> of uECC_sign(<pub_key>, DATA, sizeof(DATA), <sig>, <curve>), you need to use VerifyingKey.verify_digest(<sig>, DATA).

I've written a small Python script that verifies a signature created by uECC using secp160r1, given the public key, the signature and the digest (all hex formatted).

import ecdsa
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("pub_key")
parser.add_argument("sig")
parser.add_argument("data")
args = parser.parse_args()

key = ecdsa.VerifyingKey.from_string(bytes.fromhex(args.pub_key), curve=ecdsa.SECP160r1)
raw_sig = bytes.fromhex(args.sig)
data = bytes.fromhex(args.data)

sig = b'\x00' + raw_sig[:20] + b'\x00' + raw_sig[20:]
print(key.verify_digest(sig, data))

Example:

$ python3 check.py 3801ab235453d93bfc7f75a092aed1c22c598a3a4c0419e9269035968d98443ddd4be4268770f70a 7be90347cdfbc01eb7df7a0a8b4eb1a6793e3f8b72640c36a828022effb84118e172f10007e4a333 0b9c2625dc21ef05f6ad4ddf47c5f203837aa32c
True

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants