Closed SmartLayer closed 6 years ago
I'll have to think about this, the sign_digest
interface python-ecdsa
exposes isn't safe as it allows nonce reuse (and perhaps other ways to misuse ECDSA). Part of the goal of this library is to avoid catastrophic security failures by not giving options to users that allow them to shoot themselves in the foot.
I'm also not sure what you mean by 1. i,e the message being shorter than n
. The current interface allows for arbitrary message lengths, bounded only by the max length the hash function being used can handle (including those shorter than n
). I suppose what you mean is signing messages without the hashing step? If so, that technically isn't ECDSA as formally specified.
I suppose what you mean is signing messages without the hashing step? If so, that technically isn't ECDSA as formally specified.
Correct. However, it saves a bit of gas in smart-contracts, especially in batch validating lots of signatures. Smart-contracts behave like computers in the 80s and gas can be expensive. In my case, for a 256-bit data to be signed without hashing, I did put a header of 128 bits (with it also a short warning message) to avoid the signature being used for other purposes. The use-case is bidding here when the time comes, everyone submits a signed price to a smart-contract hoping to win, a small flood, where the gas-saving can amount to a grand. This actually is less important now because the next version of the software I'm writing will not use it anymore since a batch of signatures isn't as fast as a Merkle Tree.
So, considering the Merkle Tree use case. Merkle Tree root is being signed here, therefore we need to trace to the 1st level nodes to re-generate the list of hashes to feed into ecdsa.verify(), which is a pain. I can, of course, hash the root hash again but that would require changes to the client-side libraries too (there are 2 clients which don't use python).
One design principle of Python, as reflected by not having private classes and private methods, is that we are all adult here. A workaround is to have sign_digest() but does not document it, as those who need to deal with stuff like Merkle Tree also are the people who know how to look into the source code to get what they need.
I think I understand the use case a bit better now. The fastecdsa._ecdsa.sign
function should allow you to fake something like sign_digest
, it is a direct interface to the C code. It will only work for messages whose bit size is less than or equal to the curve order's bit size.
from binascii import hexlify
from fastecdsa import _ecdsa, curve
sign_digest = lambda msg, d, k, curve: _ecdsa.sign(
msg,
str(d),
str(k),
str(curve.p),
str(curve.a),
str(curve.b),
str(curve.q),
str(curve.gx),
str(curve.gy)
)
d = 0xdeadc0de
msg = 'Hello, World!'
# hex encode the msg (below is python3, python2 should be similar or possibly even the same)
msg = hexlify(msg.encode()).decode()
# sign the message
r, s = sign_digest(msg, d, 0xdecafbad, curve.P256)
The interface isn't quite the same as interface python-ecdsa
but should do what you want. There is a similar function for verification, fastecdsa._ecdsa.verify
.
Thanks. That's straightforward and very funny (referring to your choice of private key)
I'm migrating from python-ecdsa to fastecdsa and missed those functions. They are used on a few occasions:
:)