Verificación de firma en python

Cuando intento implementar OP_CHECKSIG, no puedo averiguar cómo hacer la verificación de firma real en python (python3)

Obtuve la firma, la clave pública y el resumen del mensaje hash de una transacción , y ahora quiero verificar la firma.

message = '692678553d1b85ccf87d4d4443095f276cdf600f2bb7dd44f6effbd7458fd4c2'
pubkey = '042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb'
signature = '30450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e'

Dado que python-ecdsarequiere una entrada de 64 bytes para crear la clave de verificación, yo mismo eliminé el primer byte.

pubkey = pubkey[2:]

También extraje ry sde la firma codificada DER y los concatené para crear una firma de 64 bytes según python-ecdsase requiera.

r = '9908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc413287'
s = '1aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e'
sig = r + s

Sin embargo, cuando intento verificar el mensaje, aparece un mensaje que BadSignatureErrorindica que la verificación falló.

from ecdsa import VerifyingKey, SECP256k1
vk = VerifyingKey.from_string(bytes.fromhex(pubkey), curve=SECP256k1)
vk.verify(bytes.fromhex(sig), bytes.fromhex(message))

Estoy buscando una forma de verificar las firmas que extraje de las transacciones de bitcoin.

Gracias.

Respuestas (1)

La forma en que VerifyingKeyfunciona es que en realidad codificará el mensaje antes de que se verifique. El algoritmo hash predeterminado es sha1, por lo que deberá especificarlo, sha256ya que eso es lo que usa Bitcoin. Además, le está pasando el mensaje totalmente cifrado. Lo que debe hacer es pasar el paso antes de codificar el mensaje. Dado que Bitcoin usa el doble SHA256, debe darle el resultado del primer hash SHA256 y dejar que genere el segundo hash SHA256 por sí mismo.

Así que su mensaje debería ser realmente

083867478cb0d1d8bb864175bbc49728cffcc114bc2e762c6df64f2c965a9a66

y su llamada de verificación debería verse como

vk.verify(bytes.fromhex(sig), bytes.fromhex(message), hashlib.sha256)
Esto funcionó. Siempre pensé que mi error estaba en algún lugar de la parte de bitcoin, pero resultó que estaba en la parte de ecdsa. Gracias.