<p>Using <a href="https://github.com/mcdallas/cryptotools" rel="nofollow noreferrer">this</a> library:</p>
<pre><code>from cryptotools import Signature, PublicKey, hex_to_bytes

pub = PublicKey.from_hex('025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357')
sig = Signature.from_hex('304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee')
sighash = hex_to_bytes('c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670')

&gt;&gt;&gt; sig.verify_hash(sighash, pub)
True
</code></pre>

CC BY-SA 4.0
2021-06-17T20:00:58.500Z
Wait wait wit. Is the reason why I never see this done with a standard library because the bitcoin signature algorithm is not RFC compliant ?!?!  From here https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm it says the signature is 71-73 bytes for the signature which is not correct. This is mind boggling
noone392
CC BY-SA 4.0
2021-06-17T20:18:45.627Z
@noone392 which RFC are you refering to? Afaik bitcoin signatures follow the DER encoding specification https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#der-encoding
Mike D
CC BY-SA 4.0
2021-06-17T20:25:41.927Z
it is compatible with DER encoding, I mean the actual ECDSA specification like RFC 6979. the signature must be exactly 64 bytes to be SECP256k1 compliant. And the provided signature, while it matches the  wiki on it, is not the correctly length to be compliant. Basically I don't think you can call this ECDSA rather its a bitcoin signature that uses elliptic curve math.
noone392
CC BY-SA 4.0
2021-06-17T20:45:12.927Z
Bitcoin uses ECDSA, with DER-encoded signatures. It follows those specifications exactly. ECDSA is a signature algorithm, not the encoding.
Pieter Wuille
CC BY-SA 4.0
2021-06-17T20:57:31.553Z
@PieterWuille what specification are you referring to exactly? because in my example I DER decode it and use what I believe is the raw 64 byte key portion.
noone392
CC BY-SA 4.0
2021-06-17T21:50:45.193Z
Ok, your conversion from DER to 64-byte signature format is incorrect. A DER signature consists of a 2-byte "struct marker" (saying that a tuple follows), then a 2-byte "integer marker", followed by the R integer (variable number of bytes), then another 2-byte "integer marker", followed by the S integer (variable number of bytes). You need to extract the R and S elements, pad them to 32 bytes each (by prepending/removing zeroes up front), and then concatenate them.
Pieter Wuille
CC BY-SA 4.0
2021-06-17T21:51:30.507Z
You can probably do that with the asn1 module by decoding the "sigscript" variable you get out (not really appropriately named, it's just a tuple of signature elements, no script involved) again with asn1.
Pieter Wuille
CC BY-SA 4.0
2021-06-18T00:59:09.900Z
@PieterWuille Thank you for finding that issue. you help is very appreciated. For some reason I remember ecdsa sig being a single variable.... anyway I have the 2 32 byte pieces connected together now that I am parsing them. Unfortunately it still doesn't verify. I also tried using python's sigdecode=sigdecode_der to provide the der encoded format but also no luck...
noone392
CC BY-SA 4.0
2021-06-18T01:04:52.280Z
The problem is likely that you need to use VerifyingKey.verify_digest rather than .verify. The latter hashes the messages again, while you're already providing a hashed message.
Pieter Wuille
CC BY-SA 4.0
2021-06-18T01:45:39.990Z
@PieterWuille That did it :-D I will post the answer. Thanks again
noone392
CC BY-SA 4.0
2021-06-18T05:12:49.910Z
The standard for ECDSA is X9.62, as clearly stated _in_ RFC6979, and does not specify any encoding for the signature. RFC6979 in 2.4 step 4 notes, correctly, it is "common" to use DER-encoded ASN.1, but that's not a requirement, and it absolutely isn't fixed-length. The sample code in A.3 does DER, but that's only a sample. Bitcoin uses DER for _transaction_ signatures, but the fixed-length 'plain' format for _message_ signatures; see https://bitcoin.stackexchange.com/questions/12554/ and https://bitcoin.stackexchange.com/questions/90799/
dave_thompson_085
CC BY-SA 4.0
2021-06-18T15:55:21.783Z
@dave_thompson_085 Thank you for the clarification
noone392
CC BY-SA 4.0
2021-06-17T19:53:07.043Z
2021-06-17T19:53:07.043Z
Mike D
<p>ok So thanks to PieterWuille I (we) were able to figure out why my code wasn't working and how to use a standard python or openssl library.<br>
These were the following problems</p>
<ol>
<li>the DER decoding for the python library was used incorrectly. We needed to iterate through all the variables and pull the two pieces of the signature (r and s) our separately and recombine them.</li>
<li>Because the standard signing libraries have the hash built into the sign/verify, and bitcoin uses a double hash, to make it work with a standard library, you need to hash 1 time manually then provide it to the library to perform the second hash. This means we could not use sigHash as an input, but rather has to use the hash preImage.
Posted below is about the shortest python script possible showing how to verify the signatures with the examples given in both raw format and DER encoded format:</li>
</ol>
<pre>
import ecdsa
import asn1
import hashlib
#used for der version
from ecdsa.util import sigencode_der, sigdecode_der

#Importing the 3 pieces of data from the example to byte arrays
pub = bytearray.fromhex("025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357")
DerEncodedSig = bytearray.fromhex("304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee")
prehashimage = bytearray.fromhex("0100000096b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd3752b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3bef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a010000001976a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac0046c32300000000ffffffff863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e51100000001000000")

#deocding the DEC encoding
decoder = asn1.Decoder()
decoder.start(bytes(DerEncodedSig))
tag, sigder = decoder.read()

sig1 = sigder[2:34]
sig2 = sigder[36:68]
sig = sig1+sig2

#Now we need to get the single sha256 hash of the preimage
m = hashlib.sha256()
m.update(prehashimage)
singlesighash = m.digest()

#we won't use the double hash for our verify but this shows you it is the same as sigHash in bip143
n = hashlib.sha256()
n.update(singlesighash)
sigHash = n.digest

vk = ecdsa.VerifyingKey.from_string(bytes(pub),  curve=ecdsa.SECP256k1)
#we have to provide the hash lib because the default is not sha256
result = vk.verify(bytes(sig), bytes(singlesighash), hashlib.sha256)
print(result)
#this is the der native way and does not require us to der decode the signature but is compatible with openssl
result = vk.verify(bytes(DerEncodedSig), bytes(singlesighash), hashlib.sha256, sigdecode=sigdecode_der)
print(result)
</pre>

CC BY-SA 4.0
2021-06-18T02:10:34.677Z
2021-06-18T02:10:34.677Z
noone392
<p>In <a href="https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki" rel="nofollow noreferrer">BIP143</a> the first example
has a witness signature and it doesn't appear to validate/be correct?! I wrote a super simple python program to demonstrate</p>
<pre><code>import ecdsa
import asn1

#Importing the 3 pieces of data from the example to byte arrays
pub = bytearray.fromhex(&quot;025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357&quot;)
sighash = bytearray.fromhex(&quot;c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670&quot;)
dersigscript = bytearray.fromhex(&quot;304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee&quot;)

#deocding the DEC encoding
decoder = asn1.Decoder()
decoder.start(bytes(dersigscript))
tag, sigscript = decoder.read()

#stripping off the script  potion so we just have a signature
sig = bytearray(sigscript)[2:66]

vk = ecdsa.VerifyingKey.from_string(pub,  curve=ecdsa.SECP256k1)
vk.verify(sig, sighash)
</code></pre>
<p>If anyone can shed some light on what stupid thing I am doing, or an example reference that breaks it down, so it works, that would be really helpful. I have also tried reversing byte order on all 8 combinations of the 3 inputs. That being said I have used the private and public key posted to do my own signatures/validation, so I am fairly confident they are in correct order, just less sure about the sig.</p>
<p>Thank you!!</p>
<p>----EDIT-----<br>
Just wanted to list other things that were tried for completeness sake</p>
<ol>
<li>as pieter pointed out I was incorrectly decoding the private key. S and R are split up into 2 different variables</li>
</ol>
<pre>304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee
becomes
3044 02 20 <strong>3609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a</strong> 02 20 <strong>573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee</strong>
so the raw 64 byte sig is 609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee
unfortunately that still did not work

Additionally I tried using pythons native der style ecdsa which was still not successful
from ecdsa.util import sigencode_der, sigdecode_der
vk.verify(bytes(sig), bytes(sighash), sigdecode=sigdecode_der)
and 
vk.verify(bytes(sig), bytes(sighash), hashlib.sha256, sigdecode=sigdecode_der)
where sig starts with 0x30:
3044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb
</pre>
<p>what is interesting is the python library didn't give me any errors except bad signature. So I can't seem to find any clues yet as to how to do this with a standard library. If I do figure it out I will post an answer</p>

<segregated-witness><signature><python><bip143>
The example signature in BIP143 doesn't validate?
noone392
# The example signature in BIP143 doesn't validate?

(Asked by: username_0 on 2021-06-17)

In [BIP143](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki) the first example
has a witness signature and it doesn't appear to validate/be correct?! I wrote a super simple python program to demonstrate

```
import ecdsa
import asn1

#Importing the 3 pieces of data from the example to byte arrays
pub = bytearray.fromhex("025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357")
sighash = bytearray.fromhex("c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670")
dersigscript = bytearray.fromhex("304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee")

#deocding the DEC encoding
decoder = asn1.Decoder()
decoder.start(bytes(dersigscript))
tag, sigscript = decoder.read()

#stripping off the script  potion so we just have a signature
sig = bytearray(sigscript)[2:66]

vk = ecdsa.VerifyingKey.from_string(pub,  curve=ecdsa.SECP256k1)
vk.verify(sig, sighash)

```

If anyone can shed some light on what stupid thing I am doing, or an example reference that breaks it down, so it works, that would be really helpful. I have also tried reversing byte order on all 8 combinations of the 3 inputs. That being said I have used the private and public key posted to do my own signatures/validation, so I am fairly confident they are in correct order, just less sure about the sig.

Thank you!!

----EDIT-----  
Just wanted to list other things that were tried for completeness sake

1. as username_2 pointed out I was incorrectly decoding the private key. S and R are split up into 2 different variables

```
304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee
becomes
3044 02 20 3609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a 02 20 573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee
so the raw 64 byte sig is 609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee
unfortunately that still did not work

Additionally I tried using pythons native der style ecdsa which was still not successful
from ecdsa.util import sigencode_der, sigdecode_der
vk.verify(bytes(sig), bytes(sighash), sigdecode=sigdecode_der)
and 
vk.verify(bytes(sig), bytes(sighash), hashlib.sha256, sigdecode=sigdecode_der)
where sig starts with 0x30:
3044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb

```

what is interesting is the python library didn't give me any errors except bad signature. So I can't seem to find any clues yet as to how to do this with a standard library. If I do figure it out I will post an answer

**Tags:** segregated-witness, signature, python, bip143


---

## 2 answers

### Answer by username_1 on 2021-06-17. Score: 3 | Accepted answer

Using [this](https://github.com/mcdallas/cryptotools) library:

```
from cryptotools import Signature, PublicKey, hex_to_bytes

pub = PublicKey.from_hex('025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357')
sig = Signature.from_hex('304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee')
sighash = hex_to_bytes('c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670')

>>> sig.verify_hash(sighash, pub)
True

```

> **Comments:**
> **username_0**: Wait wait wit. Is the reason why I never see this done with a standard library because the bitcoin signature algorithm is not RFC compliant ?!?!  From here https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm it says the signature is 71-73 bytes for the signature which is not correct. This is mind boggling  
> **username_1**: @username_0 which RFC are you refering to? Afaik bitcoin signatures follow the DER encoding specification https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#der-encoding  
> **username_0**: it is compatible with DER encoding, I mean the actual ECDSA specification like RFC 6979. the signature must be exactly 64 bytes to be SECP256k1 compliant. And the provided signature, while it matches the  wiki on it, is not the correctly length to be compliant. Basically I don't think you can call this ECDSA rather its a bitcoin signature that uses elliptic curve math.  
> **username_2**: Bitcoin uses ECDSA, with DER-encoded signatures. It follows those specifications exactly. ECDSA is a signature algorithm, not the encoding.  
> **username_0**: @username_2 what specification are you referring to exactly? because in my example I DER decode it and use what I believe is the raw 64 byte key portion.  
> **username_2**: Ok, your conversion from DER to 64-byte signature format is incorrect. A DER signature consists of a 2-byte "struct marker" (saying that a tuple follows), then a 2-byte "integer marker", followed by the R integer (variable number of bytes), then another 2-byte "integer marker", followed by the S integer (variable number of bytes). You need to extract the R and S elements, pad them to 32 bytes each (by prepending/removing zeroes up front), and then concatenate them.  
> **username_2**: You can probably do that with the asn1 module by decoding the "sigscript" variable you get out (not really appropriately named, it's just a tuple of signature elements, no script involved) again with asn1.  
> **username_0**: @username_2 Thank you for finding that issue. you help is very appreciated. For some reason I remember ecdsa sig being a single variable.... anyway I have the 2 32 byte pieces connected together now that I am parsing them. Unfortunately it still doesn't verify. I also tried using python's sigdecode=sigdecode_der to provide the der encoded format but also no luck...  
> **username_2**: The problem is likely that you need to use VerifyingKey.verify_digest rather than .verify. The latter hashes the messages again, while you're already providing a hashed message.  
> **username_0**: @username_2 That did it :-D I will post the answer. Thanks again  
> **username_3**: The standard for ECDSA is X9.62, as clearly stated _in_ RFC6979, and does not specify any encoding for the signature. RFC6979 in 2.4 step 4 notes, correctly, it is "common" to use DER-encoded ASN.1, but that's not a requirement, and it absolutely isn't fixed-length. The sample code in A.3 does DER, but that's only a sample. Bitcoin uses DER for _transaction_ signatures, but the fixed-length 'plain' format for _message_ signatures; see https://bitcoin.stackexchange.com/questions/12554/ and https://bitcoin.stackexchange.com/questions/90799/  
> **username_0**: @username_3 Thank you for the clarification  

---

### Answer by username_0 on 2021-06-18. Score: 2

ok So thanks to username_2 I (we) were able to figure out why my code wasn't working and how to use a standard python or openssl library.  
These were the following problems

1. the DER decoding for the python library was used incorrectly. We needed to iterate through all the variables and pull the two pieces of the signature (r and s) our separately and recombine them.
2. Because the standard signing libraries have the hash built into the sign/verify, and bitcoin uses a double hash, to make it work with a standard library, you need to hash 1 time manually then provide it to the library to perform the second hash. This means we could not use sigHash as an input, but rather has to use the hash preImage.
   Posted below is about the shortest python script possible showing how to verify the signatures with the examples given in both raw format and DER encoded format:

```

import ecdsa
import asn1
import hashlib
#used for der version
from ecdsa.util import sigencode_der, sigdecode_der

#Importing the 3 pieces of data from the example to byte arrays
pub = bytearray.fromhex("025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357")
DerEncodedSig = bytearray.fromhex("304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee")
prehashimage = bytearray.fromhex("0100000096b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd3752b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3bef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a010000001976a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac0046c32300000000ffffffff863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e51100000001000000")

#deocding the DEC encoding
decoder = asn1.Decoder()
decoder.start(bytes(DerEncodedSig))
tag, sigder = decoder.read()

sig1 = sigder[2:34]
sig2 = sigder[36:68]
sig = sig1+sig2

#Now we need to get the single sha256 hash of the preimage
m = hashlib.sha256()
m.update(prehashimage)
singlesighash = m.digest()

#we won't use the double hash for our verify but this shows you it is the same as sigHash in bip143
n = hashlib.sha256()
n.update(singlesighash)
sigHash = n.digest

vk = ecdsa.VerifyingKey.from_string(bytes(pub),  curve=ecdsa.SECP256k1)
#we have to provide the hash lib because the default is not sha256
result = vk.verify(bytes(sig), bytes(singlesighash), hashlib.sha256)
print(result)
#this is the der native way and does not require us to der decode the signature but is compatible with openssl
result = vk.verify(bytes(DerEncodedSig), bytes(singlesighash), hashlib.sha256, sigdecode=sigdecode_der)
print(result)

```


---

