Interoperability with python-ecdsa regarding the SECP160r1 curve
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?
@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.
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