如何在python中使用ecdsa签名和验证签名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34451214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 15:00:14  来源:igfitidea点击:

How to sign and verify signature with ecdsa in python

pythonecdsa

提问by Jorky10

I need to sign a hash of 256 bits with ECDSA using a private key of 256 bits, just as bitcoin does, and I am reaching desperation because of the lack of documentation of ecdsa in python.

我需要使用 256 位的私钥用 ECDSA 签署一个 256 位的散列,就像比特币一样,由于 python 中缺少 ecdsa 的文档,我感到绝望。

I found a lot of codes on the internet, but there was nothing as easy as just ecdsa.sign(msg, privkey)or similar, everything I found is a lot of code of mathematical stuff I don't understand, but yet they use the ecdsa library (I don't know why they wouldn't add a signing function in a library that is going to be used to sign stuff, instead a page of code is needed when using the library?).

我在互联网上找到了很多代码,但没有什么比这更简单ecdsa.sign(msg, privkey)或类似的了,我发现的一切都是我不理解的大量数学代码,但它们使用了 ecdsa 库(我不知道为什么他们不会在用于签名的库中添加签名函数,而是在使用库时需要一页代码?)。

This is the best code I 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 a code like that because I have no idea what it does. Also, the comments in ecdsa_sign says that returns a signature given the value, the secret exponent, and a nonce. It says its very important to have a nonce, but I just can't figure out where that nonce is.

但我不能相信这样的代码,因为我不知道它的作用。此外, ecdsa_sign 中的注释说,返回给定值、秘密指数和 nonce的签名。它说拥有一个 nonce 非常重要,但我就是不知道那个 nonce 在哪里。

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

是否有任何简单的单行方式使用 Windows 上的 Python 中的任何受信任库来签署和验证 ECDSA 签名?

回答by k26dr

You can try using the python ecdsa package, using Python3:

您可以尝试使用 python ecdsa 包,使用 Python3:

pip3 install ecdsa

Usage:

用法:

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 signature with a public key:

要使用公钥验证现有签名:

import ecdsa
from hashlib import sha256
message = b"message"
public_key = '98cedbb266d9fc38e41a169362708e0509e06b3040a5dfff6e08196f8d9e49cebfb4f4cb12aa7ac34b19f3b29a17f4e5464873f151fd699c2524e0b7843eb383'
sig = '740894121e1c7f33b174153a7349f6899d0a1d2730e9cc59f674921d8aef73532f63edb9c5dba4877074a937448a37c5c485e0d53419297967e95e9b1bef630d'

vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(public_key), curve=ecdsa.SECP256k1, hashfunc=sha256) # the default is sha1
vk.verify(bytes.fromhex(sig), message) # True

The package is compatible with Python 2 as well

该软件包也与 Python 2 兼容

回答by GraphicalDot

you can also use sep256k1 library in Python to ecdsa sign and verify. The public and private keys are the keys generated from Bip32 specifications and seed from Bip39 specifications.

您还可以使用 Python 中的 sep256k1 库来进行 ecdsa 签名和验证。公钥和私钥是由 Bip32 规范生成的密钥和来自 Bip39 规范的种子。

 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 upon the verification. i have used uint32(typings) or int as a nonce, but any byte array or string can be used. strings need to be converted to bytes.

结果将是 True 或 False 取决于验证。我使用 uint32(typings) 或 int 作为随机数,但可以使用任何字节数组或字符串。字符串需要转换为字节。

回答by rcmstark

How to install it:

如何安装它:

pip install starkbank-ecdsa

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 reference: https://github.com/starkbank/ecdsa-python

完整参考:https: //github.com/starkbank/ecdsa-python