当前位置: 首页 > 知识库问答 >
问题:

如何签署和验证签名与ecdsa在python

窦伟
2023-03-14

我需要使用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在哪里。

是否有任何简单的,单行的方法来签署和验证ECDSA签名使用任何受信任的库在Python在windows上?

共有3个答案

时恩
2023-03-14

您还可以使用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(键入)或int作为一个名词,但可以使用任何字节数组或字符串。字符串需要转换为字节。

谢和颂
2023-03-14

如何安装:

pip安装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

轩辕嘉平
2023-03-14

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

该包也与Python 2兼容

 类似资料:
  • 我在开发安全系统时遇到了以下问题: 我们收到一些数据,我们必须通过签名进行验证。签名算法是ecdsa-with-SHA256,openssl_verify()似乎没有这个选项。已经尝试过搜索像phpseclib这样的独立PHP库了——也不走运,ecdsa-with-SHA1似乎是他们提供的最佳选择。 对于这个问题,什么是合适的解决方案?也许我错过了一些实现这种功能的库?

  • 我想创建一个签名并使用openssl验证它。我想有我的签名的十六进制输出。 这是我的密码 我得到这个错误: 如果我在创建签名的过程中删除了-hex,它就可以工作了。

  • 我应该如何更改A方法?任何想法都是好的。提前谢谢。

  • 最近,我一直在尝试构建一个Java库来解释和验证NZ Covid传递。在签名验证之前(这个过程中稍微重要的一部分),我已经让代码变得更好或更坏。完整的代码可以在这里找到,但是仍然很粗糙。 验证器本身在这里可用,有一个配套测试。新冠通行证的技术规范在这里。至少有一个相关部分。 在与另一个开发人员合作后,我想我已经确定了解释提供的公钥。下面的代码(删除了调试输出)。公钥详细信息来自这里 该错误可能存在

  • 我正在尝试在python中使用ECDSA验证比特币签名,但发现它非常困难,许多尝试已经失败了。 参数: 注意:我已经根据ECDSA的要求将签名从base64转换为hexstring。每当我试图验证它时,它会说: 预期64字节签名(128十六进制字符串),提供了65字节签名(130十六进制字符串) 我查看了许多关于ECDSA的stackoverflow问题,但没有一个答案与我的qs 100%相关。感

  • 我有一个包含EC私钥的文件: 我有一个证书,它的公钥对应于私钥: 在 pem 格式中: 以txt格式: 我正在努力完成两件事: < li >使用ecdsa-with-SHA256签名算法使用私钥对字节数组进行签名 < li >使用证书中的公钥验证签名是否正确 我尝试过使用充气城堡图书馆。这是我到目前为止所拥有的。我的断言是失败的。