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

2024-06-02 00:00:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要用256位的私钥与ECDSA签署256位的散列,就像比特币一样,由于缺少python中ECDSA的文档,我已经绝望了。

我在互联网上发现了很多代码,但没有什么比仅仅ecdsa.sign(msg, privkey)或类似的代码更容易的了,我发现的所有东西都是很多我不懂的数学代码,但是他们使用的是ecdsa库(我不知道他们为什么不在一个库中添加一个签名函数,这个库将被用来签名,而一页代码是使用库时需要吗?)。

这是迄今为止我发现的最好的代码:

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()

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

有没有任何简单的、单行的方法可以在windows上使用python中的可信库对ECDSA签名进行签名和验证?


Tags: 代码newsizesecretiforderk1random
3条回答

如何安装:

pip install starkbank-ecdsa

使用方法:

# 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)

完全引用:https://github.com/starkbank/ecdsa-python

您还可以使用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

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

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

pip3 install ecdsa

用法:

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

要使用公钥验证现有签名,请执行以下操作:

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

这个包也与Python 2兼容

相关问题 更多 >