<p>I've done some testing with pybitcointools and one of the BitcoinCore test vectors with a SIGHASH of zero.</p>

<p>For <code>SIGHASH =0</code>, the <a href="https://github.com/vbuterin/pybitcointools/blob/master/bitcoin/transaction.py#L178" rel="nofollow">Tx which is signed </a></p>

<p>It's just a matter of appending 4 nullbytes, instead of <code>01000000</code>, to the signing transaction. </p>

<p>The Core software checks for this non-standard hashtype now, however we can see there's no problem in validating these rare transactions since the code only checks for SIGHASH ACP, SINGLE &amp; NONE. <a href="https://github.com/petertodd/python-bitcoinlib/blob/master/bitcoin/core/script.py#L853-L902" rel="nofollow">See Python-Bitcoinlib's code for a Python interpretation</a></p>

<p>See <a href="https://github.com/simcity4242/pybitcointools/blob/master/tests/tx_valid.json#L20-L23" rel="nofollow">this test vector</a>, where the hash being validated is <code>11743b220e9e24e89abd4ff124a2740531fe7d7f9b4e26de14710a532fd543e2</code>.</p>

<p>FWIW, Pybitcointools needs to have the <code>txhash</code> function edited so that instead of <code>if hashcode:</code>, it reads <code>if hashcode is not None:</code>. The else clause in that function was confusing me, but it appears to be for hashing <em>signed</em> transactions (ie to return the TxID)</p>

CC BY-SA 3.0
2015-08-10T05:41:53.723Z
2015-08-18T01:59:08.300Z
2015-08-18T01:59:08.300Z
Wizard Of Ozzie
<p>On the Bitcoin Wiki's <a href="https://en.bitcoin.it/w/index.php?title=OP_CHECKSIG&amp;oldid=57808" rel="nofollow">OP_CHECKSIG documentation</a>:</p>

<blockquote>
  <p>Firstly always this (the default) procedure is applied:</p>
  
  <ol>
  <li>the public key and the signature are popped from the stack, in that order. <strong>If the hash-type value is 0, then it is replaced by the last_byte of the signature. Then the last byte of the signature is always deleted.</strong></li>
  </ol>
</blockquote>

<p>The signature format is:</p>

<blockquote>
  <p>0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash]</p>
</blockquote>

<p>In case if hash type is 0 then we should  get last byte from [S] 
and remove it <strong>I think it will corrupt signature</strong>!</p>

<p>Maybe I don't correctly understand this documentation. Could anybody explain the correct behavior in this case?</p>

CC BY-SA 3.0
2015-08-05T10:54:15.493Z
Methinks it should say copy, not replace.
Nick ODell
CC BY-SA 3.0
2015-08-05T11:17:58.407Z
I this error in specification?
bitaps.com
CC BY-SA 3.0
2015-08-05T15:49:44.110Z
@user15358 I don't see this text in https://en.bitcoin.it/wiki/OP_CHECKSIG anymore.
morsecoder
CC BY-SA 3.0
2015-08-06T02:28:43.077Z
Fair warning, the bitcoin wiki is often the summation of years of unverified brain dumps. A non negligible portion is out of date or was never correct to begin with.
Claris
CC BY-SA 3.0
2015-08-06T07:40:47.750Z
I'm curious to know how this works, as there's a test vector with a SIGHASH of 00 that I can't verify using pybitcointools. It seems changing the 0 to a 1 won't work; there's no real reason why is there?
Wizard Of Ozzie
CC BY-SA 3.0
2015-08-06T14:19:35.097Z
@WizardOfOzzie, changing the SIGHASH type will invalidate the signature, as it changes the hash that is signed.
morsecoder
CC BY-SA 3.0
2015-08-06T14:46:25.937Z
@StephenM347 OK, so that's because the signed Tx form has the hash type appended; but if the SIGHASH type is `0`, why does it act as `1`?
Wizard Of Ozzie
CC BY-SA 3.0
2015-08-06T15:00:39.413Z
@WizardOfOzzie, not sure exactly what Bitcoin Core's behavior is with non-standard sighash types.
morsecoder
CC BY-SA 3.0
2015-08-10T11:32:04.470Z
I've done some testing with pybitcointools and [one of the BitcoinCore test vectors](https://github.com/simcity4242/pybitcointools/blob/master/tests/tx_valid.json#L20-L23) with a SIGHASH of zero. See Pastebin [here](http://pastebin.com/1Bqd0zbc). I have no idea how this works, since we're hashing the **final transaction** (ie including the signature), which returns the TxID `c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73`. This makes no sense whatsoever, anyone know what's going on here?
Wizard Of Ozzie
CC BY-SA 3.0
2015-08-12T09:38:03.047Z
@sipa Can you comment [on the above comment](http://bitcoin.stackexchange.com/questions/38971/op-checksig-signature-hash-type-0#comment45869_38971) of mine?
Wizard Of Ozzie
<script><signature><transaction-verification>
OP_CHECKSIG signature hash type 0
bitaps.com
# OP_CHECKSIG signature hash type 0

(Asked by: username_0 on 2015-08-05)

On the Bitcoin Wiki's [OP\_CHECKSIG documentation](https://en.bitcoin.it/w/index.php?title=OP_CHECKSIG&oldid=57808):

> Firstly always this (the default) procedure is applied:
>
> 1. the public key and the signature are popped from the stack, in that order. **If the hash-type value is 0, then it is replaced by the last\_byte of the signature. Then the last byte of the signature is always deleted.**

The signature format is:

> 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash]

In case if hash type is 0 then we should get last byte from [S]
and remove it **I think it will corrupt signature**!

Maybe I don't correctly understand this documentation. Could anybody explain the correct behavior in this case?

**Tags:** script, signature, transaction-verification

> **Comments:**
> **username_1**: Methinks it should say copy, not replace.  
> **username_0**: I this error in specification?  
> **username_2**: @user15358 I don't see this text in https://en.bitcoin.it/wiki/OP_CHECKSIG anymore.  
> **username_3**: Fair warning, the bitcoin wiki is often the summation of years of unverified brain dumps. A non negligible portion is out of date or was never correct to begin with.  
> **username_4**: I'm curious to know how this works, as there's a test vector with a SIGHASH of 00 that I can't verify using pybitcointools. It seems changing the 0 to a 1 won't work; there's no real reason why is there?  
> **username_2**: @username_4, changing the SIGHASH type will invalidate the signature, as it changes the hash that is signed.  
> **username_4**: @StephenM347 OK, so that's because the signed Tx form has the hash type appended; but if the SIGHASH type is `0`, why does it act as `1`?  
> **username_2**: @username_4, not sure exactly what Bitcoin Core's behavior is with non-standard sighash types.  
> **username_4**: I've done some testing with pybitcointools and [one of the BitcoinCore test vectors](https://github.com/simcity4242/pybitcointools/blob/master/tests/tx_valid.json#L20-L23) with a SIGHASH of zero. See Pastebin [here](http://pastebin.com/1Bqd0zbc). I have no idea how this works, since we're hashing the **final transaction** (ie including the signature), which returns the TxID `c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73`. This makes no sense whatsoever, anyone know what's going on here?  
> **username_4**: @sipa Can you comment [on the above comment](http://bitcoin.stackexchange.com/questions/38971/op-checksig-signature-hash-type-0#comment45869_38971) of mine?  

---

## 1 answers

### Answer by username_4 on 2015-08-10. Score: 2

I've done some testing with pybitcointools and one of the BitcoinCore test vectors with a SIGHASH of zero.

For `SIGHASH =0`, the [Tx which is signed](https://github.com/vbuterin/pybitcointools/blob/master/bitcoin/transaction.py#L178)

It's just a matter of appending 4 nullbytes, instead of `01000000`, to the signing transaction.

The Core software checks for this non-standard hashtype now, however we can see there's no problem in validating these rare transactions since the code only checks for SIGHASH ACP, SINGLE & NONE. [See Python-Bitcoinlib's code for a Python interpretation](https://github.com/petertodd/python-bitcoinlib/blob/master/bitcoin/core/script.py#L853-L902)

See [this test vector](https://github.com/simcity4242/pybitcointools/blob/master/tests/tx_valid.json#L20-L23), where the hash being validated is `11743b220e9e24e89abd4ff124a2740531fe7d7f9b4e26de14710a532fd543e2`.

FWIW, Pybitcointools needs to have the `txhash` function edited so that instead of `if hashcode:`, it reads `if hashcode is not None:`. The else clause in that function was confusing me, but it appears to be for hashing *signed* transactions (ie to return the TxID)


---

