I'm trying to have Python (2.7) and JS solutions for ECDSA signing (with secp256k1 curve) where ideally signatures generated by one side can be verified by the other.

For the python side, I'm using the ecdsa library:

from ecdsa import SigningKey
from ecdsa.curves import SECP256k1
ecdsakey = "59b1ad799522457fa5ed171cb850800fe511e55181d81250e66d42ff536427a1"
sk = SigningKey.from_string(ecdsa_privkey, curve=SECP256k1)
hash = "b93b25c03a2238e749272a99d8a47dbcc19c2db65b9b27671f1ec6b5defd279b"
hash = codecs.decode(hash, 'hex')

sig = sk.sign_deterministic(hash)
print(codecs.encode(sig, 'hex'))
vk = sk.get_verifying_key()
print(vk.verify(sig, hash))

For JS, I'm using secp256k1:

let hash = "b93b25c03a2238e749272a99d8a47dbcc19c2db65b9b27671f1ec6b5defd279b";
hash = Buffer.from(hash, 'hex');

// generate privKey
let privKey = "59b1ad799522457fa5ed171cb850800fe511e55181d81250e66d42ff536427a1";
privKey = Buffer.from(privKey, 'hex');

// sign the message
const sigObj = secp256k1.sign(msg, privKey)


// get the public key in a compressed format
const pubKey = secp256k1.publicKeyCreate(privKey)

// verify the signature
console.log(secp256k1.verify(msg, sigObj.signature, pubKey))

Both of the above work fine on their own, the signature is verified as expected. The problem arises when I try to get the signature from JS and verify it using Python or vice versa.

The signature generated by Python is: 3fa041c044403331c19767e2c4ff3a44e764ec7bdbb7fffa190157ffbe3f9ba317c1ff5254fef28597862a7adec3699cb0fda0ec003b3d9d28b554b321006ee8 So I feed it into secp256k1.verify:

let signature = "3fa041c044403331c19767e2c4ff3a44e764ec7bdbb7fffa190157ffbe3f9ba317c1ff5254fef28597862a7adec3699cb0fda0ec003b3d9d28b554b321006ee8";
signature = Buffer.from(signature, 'hex');
console.log(secp256k1.verify(msg, signature, pubKey))

The signature generated by JS is: 062a87f01f86a540c6c28dcfb7b59ed85ea72ef3549bc1ddff8bb08cbabcc6b444a13bab43c82521cf3440db8619ab1ac14d46b4b696dd506fd5b104c06366dc So I feed it into the verifying key:

sig = "062a87f01f86a540c6c28dcfb7b59ed85ea72ef3549bc1ddff8bb08cbabcc6b444a13bab43c82521cf3440db8619ab1ac14d46b4b696dd506fd5b104c06366dc"
sig = codecs.decode(sig, 'hex')
print(vk.verify(sig, hash))

Above throws BadSignatureError

So my question is: is there any setting or something else I'm missing that I need to set in order to have the two solutions be cross-compatible?


closed as off-topic by Maarten Bodewes, Ella Rose, e-sushi Sep 9 '18 at 15:08

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Programming questions are off-topic even if you are writing or debugging cryptographic code. Unless your question is specifically about how the cryptographic algorithm, protocol or side-channel (mitigation) works, you should look into asking on Stack Overflow instead." – Maarten Bodewes, Ella Rose, e-sushi
If this question can be reworded to fit the rules in the help center, please edit the question.


It seems that the python library is actually re-hashing the hash you're passing it, since you are using the verify method of a VerifyingKey object, which is performing a hash computation on the data you're passing to it. You might want to try passing the hash's pre-image to Python, or try hashing that hash again for JS, to have them interoperate...

You can also read this part about OpenSSL compatibility for Python's ecdsa lib.

I'm not really sure what secp256k1 library you are using for JS, but my answer assumes that the library is directly signing the data you're passing it, without hashing it first, or that the hash used by default by both library is not the same.

  • $\begingroup$ Thanks! I ended up having to write my own hashfunc and passing it to both the sign and verify methods in Python. $\endgroup$ – Stormy Dan Sep 7 '18 at 4:28

Not the answer you're looking for? Browse other questions tagged or ask your own question.