2015-12-24 20 views
6

Ich muss einen Hash von 256 Bits mit ECDSA unter Verwendung eines privaten Schlüssels von 256 Bit, wie Bitcoin, und ich bin verzweifelt wegen der fehlenden Dokumentation von Ecdsa erreichen in Python.Wie signieren und verifizieren Signatur mit Ecdsa in Python

Ich fand viele Codes im Internet, aber es gab nichts so einfach wie nur ecdsa.sign(msg, privkey) oder ähnliches, alles, was ich fand, ist eine Menge Code von mathematischen Sachen, die ich nicht verstehe, aber dennoch benutzen sie die Ecdsa-Bibliothek (Ich weiß nicht, warum sie keine Signierfunktion in einer Bibliothek hinzufügen würden, die zum Signieren von Daten verwendet wird, stattdessen wird bei Verwendung der Bibliothek eine Code-Seite benötigt).

Dies ist der beste Code, den ich bisher gefunden:

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

Aber ich kann einfach nicht einen Code wie das vertrauen, weil ich keine Ahnung, was es hat. Die Kommentare in ecdsa_sign sagen auch, dass eine Signatur mit dem Wert, dem geheimen Exponenten, und einer Nonce zurückgegeben wird. Es sagt, es ist sehr wichtig, eine Nonce zu haben, aber ich kann einfach nicht herausfinden, wo diese Nonce ist.

Gibt es eine einfache, einzeilige Möglichkeit, ECDSA-Signaturen zu signieren und zu verifizieren, indem Sie die vertraute Bibliothek in Python in Windows verwenden?

+0

können Sie nicht unter Verwendung von openssl signieren? –

+0

Was sind die Vorteile von OpenSSL über Ecdsa? – Jorky10

+0

Ich stelle mir vor, dass die Ecdsa-Lib openssl verwendet, also gibt es keinen Unterschied, Sie haben Zugang zu allem, was Sie brauchen, mit openssl https://www.openssl.org/docs/manmaster/crypto/ecdsa.html https: //www.guyrutenberg .com/2013/12/28/creating-self-signed-ecdsa-ssl-zertifikat-using-openssl/ –

Antwort

5

Sie können versuchen, den Python ecdsa Paket verwenden, mit Python3:

pip3 install ecdsa 

Verbrauch:

from ecdsa import SigningKey 

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

Um eine vorhandene Signatur mit einem öffentlichen Schlüssel zu überprüfen:

from ecdsa import VerifyingKey 

message = b"message" 
public_key = '98cedbb266d9fc38e41a169362708e0509e06b3040a5dfff6e08196f8d9e49cebfb4f4cb12aa7ac34b19f3b29a17f4e5464873f151fd699c2524e0b7843eb383' 
sig = '740894121e1c7f33b174153a7349f6899d0a1d2730e9cc59f674921d8aef73532f63edb9c5dba4877074a937448a37c5c485e0d53419297967e95e9b1bef630d' 

vk = VerifyingKey.from_string(bytes.fromhex(public_key), curve=ecdsa.SECP256k1) 
vk.verify(bytes.fromhex(sig), message) # True 

Des Paket ist kompatibel mit Python 2 sowie

EDIT: die Antwort früher benötigt SECP256k1 importiert werden, das wurde behoben. Danke an @ chengcheng-zhang für Hinweis darauf

+0

Sie können sign_digest und verify_digest auch für verdaute Daten verwenden, zum Beispiel, wenn Sie einen sha256-Hash im Binärformat übergeben. –

+0

Gibt es eine Möglichkeit, die Schlüssel kleiner zu machen? Zum Beispiel, definieren Sie ihre maximale Größe? –

+0

@Nuclear_Man_D Ich glaube, dass die Schlüsselgröße festgelegt ist. – k26dr