How to sign and verify signature with ecdsa in python

I need to sign a 256-bit hash with ECDSA using a 256-bit private key, just like bitcoin, and I despaired of the lack of ecdsa documentation in python.

I found a lot of codes on the Internet, but it was not as simple as ecdsa.sign(msg, privkey) or the like, all I found was a lot of code of mathematical material, which I do not understand, but still they use ecdsa (I don’t know why they didn’t add a signature function to the library that will be used to sign the material, instead you need a code page when using the library?).

This is the best code I've found so far:

 def ecdsa_sign(val, secret_exponent): """Return a signature for the provided hash, using the provided random nonce. It is absolutely vital that random_k be an unpredictable number in the range [1, self.public_key.point.order()-1]. If an attacker can guess random_k, he can compute our private key from a single signature. Also, if an attacker knows a few high-order bits (or a few low-order bits) of random_k, he can compute our private key from many signatures. The generation of nonces with adequate cryptographic strength is very difficult and far beyond the scope of this comment. May raise RuntimeError, in which case retrying with a new random value k is in order. """ G = ecdsa.SECP256k1 n = G.order() k = deterministic_generate_k(n, secret_exponent, val) p1 = k * G r = p1.x() if r == 0: raise RuntimeError("amazingly unlucky random number r") s = ( ecdsa.numbertheory.inverse_mod( k, n ) * ( val + ( secret_exponent * r ) % n ) ) % n if s == 0: raise RuntimeError("amazingly unlucky random number s") return signature_to_der(r, s) def deterministic_generate_k(generator_order, secret_exponent, val, hash_f=hashlib.sha256): """ Generate K value according to https://tools.ietf.org/html/rfc6979 """ n = generator_order order_size = (bit_length(n) + 7) // 8 hash_size = hash_f().digest_size v = b'\x01' * hash_size k = b'\x00' * hash_size priv = intbytes.to_bytes(secret_exponent, length=order_size) shift = 8 * hash_size - bit_length(n) if shift > 0: val >>= shift if val > n: val -= n h1 = intbytes.to_bytes(val, length=order_size) k = hmac.new(k, v + b'\x00' + priv + h1, hash_f).digest() v = hmac.new(k, v, hash_f).digest() k = hmac.new(k, v + b'\x01' + priv + h1, hash_f).digest() v = hmac.new(k, v, hash_f).digest() while 1: t = bytearray() while len(t) < order_size: v = hmac.new(k, v, hash_f).digest() t.extend(v) k1 = intbytes.from_bytes(bytes(t)) k1 >>= (len(t)*8 - bit_length(n)) if k1 >= 1 and k1 < n: return k1 k = hmac.new(k, v + b'\x00', hash_f).digest() v = hmac.new(k, v, hash_f).digest() 

But I just can’t trust such a code, because I have no idea what it does. In addition, comments in ecdsa_sign say it returns a signature based on value, secret exponent, and nonce . It says that it is very important to have nonce, but I just can't figure out where the nonce is.

Is there a simple, one-line way to sign and verify ECDSA signatures using any trusted library in python in windows?

+11
python ecdsa
source share
3 answers

You can try using the python ecdsa package using Python3:

 pip3 install ecdsa 

Using:

 import ecdsa # SECP256k1 is the Bitcoin elliptic curve sk = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1) vk = sk.get_verifying_key() sig = sk.sign(b"message") vk.verify(sig, b"message") # True 

To verify an existing public key signature:

 import ecdsa message = b"message" public_key = '98cedbb266d9fc38e41a169362708e0509e06b3040a5dfff6e08196f8d9e49cebfb4f4cb12aa7ac34b19f3b29a17f4e5464873f151fd699c2524e0b7843eb383' sig = '740894121e1c7f33b174153a7349f6899d0a1d2730e9cc59f674921d8aef73532f63edb9c5dba4877074a937448a37c5c485e0d53419297967e95e9b1bef630d' vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(public_key), curve=ecdsa.SECP256k1) vk.verify(bytes.fromhex(sig), message) # True 

The package is also compatible with Python 2

+16
source share

You can also use the sep256k1 library in Python to sign and verify ecdsa. Public and private keys are keys generated from Bip32 specifications and seed numbers from Bip39 specifications.

  Private key is 1149ab92fbc40993f21336206ca184a9dc2d5231eb575d2a0a6d56773bf0f356 Public key is 03c7ac999403591bceacca3d37598886f7c41943c8045c7e1cb5a9295d0003cc5b from sawtooth_signing.secp256k1 import Secp256k1PrivateKey from sawtooth_signing.secp256k1 import Secp256k1PublicKey def sign_nonce(hex_private_key): nonce = random.randint(2**10, 2**32) checksum = hashlib.sha3_512(str(nonce).encode()).hexdigest() private_key = Secp256k1PrivateKey.from_hex(hex_private_key) message = private_key.secp256k1_private_key.ecdsa_sign(str(nonce).encode()) serialized_message = private_key.secp256k1_private_key.ecdsa_serialize(message) hex_message = binascii.hexlify(serialized_message) return nonce, checksum, hex_message def verify_nonce(nonce, checksum, message, hex_public_key): ##message is hex encoded message = binascii.unhexlify(message) public_key = Secp256k1PublicKey.from_hex(hex_public_key) unserialized = public_key.secp256k1_public_key.ecdsa_deserialize(message) result = public_key.secp256k1_public_key.ecdsa_verify(str(nonce).encode(), unserialized) return result 

The result will be True or False depending on the check. I used uint32 (typing) or int as a one-time number, but any byte array or string can be used. Strings must be converted to bytes.

0
source share

How to install it:

pip install starkbank-ecdsa

How to use it:

 # Generate Keys privateKey = PrivateKey() publicKey = privateKey.publicKey() message = "My test message" # Generate Signature signature = Ecdsa.sign(message, privateKey) # Verify if signature is valid print Ecdsa.verify(message, signature, publicKey) 

Full link: https://github.com/starkbank/ecdsa-python

0
source share

All Articles