<p>The problem is that you are doing all of the hashing (and putting it into hex) and then having OpenSSL hash it again. <code>openssl dgst</code> will hash the message before signing, but this is incorrect for Bitcoin. Traditionally, in ECDSA, the message is hashed once and then signed. But with Bitcoin, it is actually hashed twice. Another way to think of this is that the message is a hash.</p>
<p>So you have already double hashed the transaction. But OpenSSL will hash it again, making it triple-hashed, which means that you sign a different message. Furthermore, OpenSSL will read your message as binary data, not interpret the hex that you gave it. So really your hashing command should be</p>
<pre><code>printf 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000 | xxd -r -p | sha256sum -b | xxd -r -p &gt; a.txt
</code></pre>
<p>This will hash the sighash message once and put the binary data into a.txt.</p>
<p>Then you can sign it as you did.</p>
<hr />
<p>Alternatively, OpenSSL has a <code>pkeyutl</code> tool that does not do any additional hashing on the data to be signed and instead expects that you have already hashed it. You could use this instead, but you will still need your hash to be binary rather than hex. So you can do</p>
<pre><code>printf 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000 | xxd -r -p | sha256sum -b | xxd -r -p | sha256sum -b | xxd -r -p &gt; a.txt
</code></pre>
<p>to get the double hash. Then do</p>
<pre><code>openssl pkeyutl -inkey chiave_priv_3.pem -sign -in a.txt -pkeyopt digest:sha256 | xxd -p -c 256
</code></pre>
<p>to sign.</p>

CC BY-SA 4.0
2020-02-17T18:55:53.120Z
Thanks for reply, I tried both solutions but I get the same error. the second solution has a little error `openssl pkeyutl -inkey chiave_priv_3.pem -sign -in a.txt -pkeyopt digest:sha256 | xxd -p -c 256`
monkeyUser
CC BY-SA 4.0
2020-02-19T11:16:09.123Z
It works but sometime I get this error `mandatory-script-verify-flag-failed (Non-canonical signature: S value is unnecessarily high) (code 16)`
monkeyUser
CC BY-SA 4.0
2020-02-19T18:05:22.243Z
That's expected. There's a standardness rule that requires the S value to be low. You can tell if the S value is low by checking it's length; it needs to be 32 bytes or less. A high S can be converted into a low S by negating it, but if you don't know how to do that manually, just make signatures until one has a low S. There's a 50% probability that any given signature has a low S.
Ava Chow
CC BY-SA 4.0
2020-02-19T22:07:29.480Z
thanks for your time, I will repeat the signature for now. Next step is sign P2SH custom.
monkeyUser
CC BY-SA 4.0
2020-02-17T17:59:21.410Z
2023-02-21T01:14:07.413Z
2023-02-21T01:14:07.413Z
Ava Chow
<p>I want to understand how Bitcoin sign transactions with Openssl. I saw this <a href="https://bitcoin.stackexchange.com/questions/32628/redeeming-a-raw-transaction-step-by-step-example-required">post</a> But I have some issues.</p>

<p>Above my private and public keys.</p>

<p>Private keys:</p>

<pre><code>$ cat chiave_priv_3.pem 

    -----BEGIN EC PARAMETERS-----
    BgUrgQQACg==
    -----END EC PARAMETERS-----
    -----BEGIN EC PRIVATE KEY-----
    MHQCAQEEIOLcjvH4RhZFl1hthXl7DD3MHXUCWKiI2b/zoYlvBmKboAcGBSuBBAAK
    oUQDQgAE3Qc0PacS/HmhnZjIot48dZ++rvh121Rq+xjreFKrf/QCl2sDXTncDbe0
    wcCtq4yaUpdbmzV9OgrP94EFsEC/1w==
    -----END EC PRIVATE KEY-----
</code></pre>

<p>public key compressed</p>

<pre><code>$ cat chiave_pubblica_compressa_3.txt 
03dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4
</code></pre>

<p>I'm working on regtest and my UTXO is:</p>

<pre><code> {
    "txid": "0c647aadcb4028260ecb753c727e0237658873a0cbdbeb5695b8cb85ea87f98d",
    "vout": 0,
    "address": "myiGTzGG8rJikr2HcVyPYqprh6Ds1kdY7v",
    "label": "",
    "scriptPubKey": "76a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588ac",
    "amount": 49.99900000,
    "confirmations": 6,
    "spendable": true,
    "solvable": true,
    "desc": "pkh([c7960220]03dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4)#5c03vyak",
    "safe": true
  },
</code></pre>

<p>I can create transaction data with this parameters:</p>

<pre><code>TXID=0c647aadcb4028260ecb753c727e0237658873a0cbdbeb5695b8cb85ea87f98d
VOUT=0
AMOUNT=49.998
ADDR_MITT=msPjuNgbmbRSkNGJPvquKJRRmrbzS96s62

bitcoin-cli createrawtransaction '[{"txid":"'$TXID'","vout":'$VOUT'}]' '[{"'$ADDR_MITT'":'$AMOUNT'}]'

02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c0000000000ffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac00000000
</code></pre>

<p>Now I get the scriptPubKey and put in ScriptSig and add SIGHASH in little endian.</p>

<pre><code>02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000
</code></pre>

<p>Where</p>

<pre><code>02000000 
01
8df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c
00000000
19 76a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588ac
ffffffff
01
c0e4022a01000000
19 76a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac
00000000
01000000
</code></pre>

<p>Sha256 twice</p>

<pre><code>$ printf 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000 | xxd -r -p | sha256sum -b | xxd -r -p | sha256sum -b | awk '{ print $1 }' &gt; a.txt
daac47088b7eba5593282013442dbcba59556d095982d470f0a02972269bc0e1 
</code></pre>

<p>Sign with chiave_priv_3.pem </p>

<pre><code>$ openssl dgst -sha256 -hex -sign chiave_priv_3.pem a.txt | sed 's/^.* //'                                                           
304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e
</code></pre>

<p>Add 01 at the end of signature and check the length</p>

<pre><code>printf 304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e01 | wc -c
 142
</code></pre>

<p><code>142 char is 47</code></p>

<p>Debug DER signature</p>

<pre><code>30 DER prefix
44 Length of rest of Signature
02 Marker for r value
20 Length of r value
r = 7071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c2
02 Marker for s value
20 Length of s value
s = 308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e
01 SIGHASH_ALL
</code></pre>

<p>concatenate with public key compressed</p>

<pre><code>47304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e012103dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4
</code></pre>

<p>the whole scriptSig length is: 6A (212 char hex)
Now I can build my transaction:</p>

<pre><code>02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000006A47304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e012103dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4ffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac00000000
</code></pre>

<p>Sendrawtransaction</p>

<pre><code>bitcoin-cli sendrawtransaction 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000006A47304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e012103dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4ffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac00000000
error code: -26
error message:
mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation) (code 16)`
</code></pre>

<transactions><private-key><signature><openssl>
Sign transaction legacy with Openssl
monkeyUser
# Sign transaction legacy with Openssl

(Asked by: username_0 on 2020-02-17)

I want to understand how Bitcoin sign transactions with Openssl. I saw this [post](https://bitcoin.stackexchange.com/questions/32628/redeeming-a-raw-transaction-step-by-step-example-required) But I have some issues.

Above my private and public keys.

Private keys:

```
$ cat chiave_priv_3.pem 

    -----BEGIN EC PARAMETERS-----
    BgUrgQQACg==
    -----END EC PARAMETERS-----
    -----BEGIN EC PRIVATE KEY-----
    MHQCAQEEIOLcjvH4RhZFl1hthXl7DD3MHXUCWKiI2b/zoYlvBmKboAcGBSuBBAAK
    oUQDQgAE3Qc0PacS/HmhnZjIot48dZ++rvh121Rq+xjreFKrf/QCl2sDXTncDbe0
    wcCtq4yaUpdbmzV9OgrP94EFsEC/1w==
    -----END EC PRIVATE KEY-----

```

public key compressed

```
$ cat chiave_pubblica_compressa_3.txt 
03dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4

```

I'm working on regtest and my UTXO is:

```
 {
    "txid": "0c647aadcb4028260ecb753c727e0237658873a0cbdbeb5695b8cb85ea87f98d",
    "vout": 0,
    "address": "myiGTzGG8rJikr2HcVyPYqprh6Ds1kdY7v",
    "label": "",
    "scriptPubKey": "76a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588ac",
    "amount": 49.99900000,
    "confirmations": 6,
    "spendable": true,
    "solvable": true,
    "desc": "pkh([c7960220]03dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4)#5c03vyak",
    "safe": true
  },

```

I can create transaction data with this parameters:

```
TXID=0c647aadcb4028260ecb753c727e0237658873a0cbdbeb5695b8cb85ea87f98d
VOUT=0
AMOUNT=49.998
ADDR_MITT=msPjuNgbmbRSkNGJPvquKJRRmrbzS96s62

bitcoin-cli createrawtransaction '[{"txid":"'$TXID'","vout":'$VOUT'}]' '[{"'$ADDR_MITT'":'$AMOUNT'}]'

02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c0000000000ffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac00000000

```

Now I get the scriptPubKey and put in ScriptSig and add SIGHASH in little endian.

```
02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000

```

Where

```
02000000 
01
8df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c
00000000
19 76a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588ac
ffffffff
01
c0e4022a01000000
19 76a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac
00000000
01000000

```

Sha256 twice

```
$ printf 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000 | xxd -r -p | sha256sum -b | xxd -r -p | sha256sum -b | awk '{ print $1 }' > a.txt
daac47088b7eba5593282013442dbcba59556d095982d470f0a02972269bc0e1 

```

Sign with chiave\_priv\_3.pem

```
$ openssl dgst -sha256 -hex -sign chiave_priv_3.pem a.txt | sed 's/^.* //'                                                           
304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e

```

Add 01 at the end of signature and check the length

```
printf 304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e01 | wc -c
 142

```

`142 char is 47`

Debug DER signature

```
30 DER prefix
44 Length of rest of Signature
02 Marker for r value
20 Length of r value
r = 7071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c2
02 Marker for s value
20 Length of s value
s = 308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e
01 SIGHASH_ALL

```

concatenate with public key compressed

```
47304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e012103dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4

```

the whole scriptSig length is: 6A (212 char hex)
Now I can build my transaction:

```
02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000006A47304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e012103dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4ffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac00000000

```

Sendrawtransaction

```
bitcoin-cli sendrawtransaction 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000006A47304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e012103dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4ffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac00000000
error code: -26
error message:
mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation) (code 16)`

```

**Tags:** transactions, private-key, signature, openssl


---

## 1 answers

### Answer by username_1 on 2020-02-17. Score: 3 | Accepted answer

The problem is that you are doing all of the hashing (and putting it into hex) and then having OpenSSL hash it again. `openssl dgst` will hash the message before signing, but this is incorrect for Bitcoin. Traditionally, in ECDSA, the message is hashed once and then signed. But with Bitcoin, it is actually hashed twice. Another way to think of this is that the message is a hash.

So you have already double hashed the transaction. But OpenSSL will hash it again, making it triple-hashed, which means that you sign a different message. Furthermore, OpenSSL will read your message as binary data, not interpret the hex that you gave it. So really your hashing command should be

```
printf 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000 | xxd -r -p | sha256sum -b | xxd -r -p > a.txt

```

This will hash the sighash message once and put the binary data into a.txt.

Then you can sign it as you did.

---

Alternatively, OpenSSL has a `pkeyutl` tool that does not do any additional hashing on the data to be signed and instead expects that you have already hashed it. You could use this instead, but you will still need your hash to be binary rather than hex. So you can do

```
printf 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000 | xxd -r -p | sha256sum -b | xxd -r -p | sha256sum -b | xxd -r -p > a.txt

```

to get the double hash. Then do

```
openssl pkeyutl -inkey chiave_priv_3.pem -sign -in a.txt -pkeyopt digest:sha256 | xxd -p -c 256

```

to sign.

> **Comments:**
> **username_0**: Thanks for reply, I tried both solutions but I get the same error. the second solution has a little error `openssl pkeyutl -inkey chiave_priv_3.pem -sign -in a.txt -pkeyopt digest:sha256 | xxd -p -c 256`  
> **username_0**: It works but sometime I get this error `mandatory-script-verify-flag-failed (Non-canonical signature: S value is unnecessarily high) (code 16)`  
> **username_1**: That's expected. There's a standardness rule that requires the S value to be low. You can tell if the S value is low by checking it's length; it needs to be 32 bytes or less. A high S can be converted into a low S by negating it, but if you don't know how to do that manually, just make signatures until one has a low S. There's a 50% probability that any given signature has a low S.  
> **username_0**: thanks for your time, I will repeat the signature for now. Next step is sign P2SH custom.  

---

