<p>Done! Here's the resulting <a href="https://gist.github.com/Sjors/5574485" rel="nofollow">script</a>. Although I recommend you use <a href="https://github.com/lian/bitcoin-ruby" rel="nofollow">bitcoin-ruby</a> for anything serious.</p>

<p>There's a couple of things that went wrong. </p>

<p>I introduced a new bug during debugging: I commented out the hash_code_type field in the pre-signed transaction, which I needed to do in order to sign it with the JSON-RPC client. I forgot to undo that, so I was signing the wrong hash half the time. This became clear once I used bitcoin-ruby to create the same transaction and ask it what hash it was about to sign, something you can't (easily) do with the JSON-RPC client.</p>

<p>The little_endian bit is not needed, although I'm still a bit confused as to why not. The correct line is:</p>

<p><code>signature_binary = @keypair.dsa_sign_asn1([SHA_256_HEX_STRING].pack("H*"))</code></p>

<p>In other words, good debugging tools and methodology are really important.</p>

CC BY-SA 3.0
2013-05-14T08:36:45.517Z
2013-05-14T08:36:45.517Z
Sjors Provoost
<p>The binary encoding of the signature cannot be used to determine if you've performed the steps correctly - it will differ for each signature (even with the same private key).</p>

<p>So the signature of a hash signed with the same private key will be different every time. A random number is included in the formula that calculates the signature, so the resulting signature will be different each time. If a random number was not used in the formula, signing two different hashes with the same private key would make it possible to calculate the private key from the two signatures (which is the reason the security of the Sony PlayStation 3 was breached). You can read more about that here: <a href="http://www.johannes-bauer.com/compsci/ecc/" rel="nofollow">http://www.johannes-bauer.com/compsci/ecc/</a></p>

<p>If you want to test whether you've made a valid transaction, then feed it to bitcoind using the sendrawtransaction command. It will spit out an error if the transaction is invalid, and if it's valid you will see the transaction going through.</p>

CC BY-SA 3.0
2013-05-13T17:27:06.217Z
Thanks. I modified my question to take into account that the signature is never the same. Whenever I submit the transaction I get an "Invalid Signature" error. As soon as that stops, I'll have fixed it... By reading the C source code I also learned that the hash is a uint256 which is cast to a char for signing. I think I compensated for that, but it still doesn't work.
Sjors Provoost
CC BY-SA 3.0
2013-05-12T19:57:11.703Z
2013-05-12T19:57:11.703Z
runeks
<p>I'm trying to sign (using secp256k1) a transaction as explained <a href="https://bitcoin.stackexchange.com/questions/3374/how-to-redeem-a-basic-tx">here</a>. I'm using my own private key and an unsigned transaction as the input. </p>

<p>I'm able to sign it using the JSON-RPC client, but when I sign it with my own ruby script and try to submit it using blockchain.info/pushTx it returns "Invalid signature".</p>

<pre><code>@secret = PRIVATE_KEY_IN_HEX
@keypair_array = Bitcoin::OpenSSL_EC.regenerate_key(@secret)
@pubkey =  @keypair_array[1]

@keypair = OpenSSL::PKey::EC.new("secp256k1")
@keypair.private_key = @keypair_array[0].hex
@keypair.public_key = ::OpenSSL::PKey::EC::Point.from_hex(@keypair.group, @pubkey)

sha_little_endian = SHA_256_HEX_STRING.rjust(64,"0").scan(/(..)/).reverse.join()
signature_binary = @keypair.dsa_sign_asn1([sha_little_endian].pack("H*"))

# Alternative (as in bitcoin-ruby)
# signature_binary = @keypair.dsa_sign_asn1([SHA_256_HEX_STRING].pack("H*"))

signature = signature_binary.unpack("H*").first
</code></pre>

<p>First I take the SHA hash, e.g. <code>ABCD...001124</code> and convert it from big endian to little endian: <code>241100....CDAB</code>. I do this because in the BitcoinQT client the hash is represented as an uint256 which is cast to a char array used as an input for signing. The result is just stored as a var so I assume I don't have to reverse it.</p>

<p>You'll need to download <a href="https://raw.github.com/lian/bitcoin-ruby/master/lib/bitcoin/ffi/openssl.rb" rel="nofollow noreferrer">this OpenSSL_EC file</a> and add the following code to reproduce the above steps.</p>

<pre><code>require 'openssl'
require 'ffi'

module Bitcoin
  def self.require_dependency(dummy1, dummy2)
  end  
autoload :OpenSSL_EC, "./openssl"
end  

module ::OpenSSL
  class BN
    def self.from_hex(hex); new(hex, 16); end
    end
  class PKey::EC::Point
    def self.from_hex(group, hex)
      new(group, BN.from_hex(hex))
    end
  end
end
</code></pre>

<p>What am I missing?</p>

CC BY-SA 3.0
2013-05-11T12:28:20.290Z
Armory [can be used](https://bitcointalk.org/index.php?topic=70911.msg813815#msg813815) to manually sign and verify messages, that should prove a useful debugging tool.

In addition BitcoinQT client can be configured to run a JSON-RPC server, which allows you to verify messages using the `verifymessage` method.
Sjors Provoost
CC BY-SA 3.0
2013-05-11T12:59:12.867Z
Experimenting with Armory I learned that unlike sha-256 hashes, every time you generate a secp256k1 signature it's different. I also found that the signature generated by my ruby code was not valid as far as Armory was concerned, even though the validate method in ruby did believe it to be correct. That strongly suggests an encoding issue.
Sjors Provoost
CC BY-SA 3.0
2013-05-11T16:06:49.530Z
Actually, message verification is not the same as transaction verification. So don't use Armory or the `verifymessage` for this! Instead, rely on `signrawtransaction`. Unfortunately, [I'm having issues with that](https://github.com/bitcoin/bitcoin/issues/2639) as well.
Sjors Provoost
CC BY-SA 3.0
2013-05-11T19:57:28.863Z
I'm able to sign my own real transaction using `signrawtransaction`. The one in the example throws an invalid key error, but I can live with that.
Sjors Provoost
CC BY-SA 3.0
2013-05-13T17:28:41.037Z
I studied the original C code of the Bitcoin client. It stores the digest as a uint256, which is cast to a char before signing. The signature itself is a char and doesn't get cast to anything else as far as I can see. I modified my question to reflect that.
Sjors Provoost
CC BY-SA 3.0
2013-05-13T20:55:37.363Z
Getting close now. I was able to [successfully](https://github.com/lian/bitcoin-ruby/issues/15) send a transaction using ruby-bitcoin. This should make it a lot easier to figure out what I'm doing wrong in my own script.
Sjors Provoost
<transactions><signature>
How to sign a transaction hash in ruby?
Sjors Provoost
# How to sign a transaction hash in ruby?

(Asked by: username_0 on 2013-05-10)

I'm trying to sign (using secp256k1) a transaction as explained [here](https://bitcoin.stackexchange.com/questions/3374/how-to-redeem-a-basic-tx). I'm using my own private key and an unsigned transaction as the input.

I'm able to sign it using the JSON-RPC client, but when I sign it with my own ruby script and try to submit it using blockchain.info/pushTx it returns "Invalid signature".

```
@secret = PRIVATE_KEY_IN_HEX
@keypair_array = Bitcoin::OpenSSL_EC.regenerate_key(@secret)
@pubkey =  @keypair_array[1]

@keypair = OpenSSL::PKey::EC.new("secp256k1")
@keypair.private_key = @keypair_array[0].hex
@keypair.public_key = ::OpenSSL::PKey::EC::Point.from_hex(@keypair.group, @pubkey)

sha_little_endian = SHA_256_HEX_STRING.rjust(64,"0").scan(/(..)/).reverse.join()
signature_binary = @keypair.dsa_sign_asn1([sha_little_endian].pack("H*"))

# Alternative (as in bitcoin-ruby)
# signature_binary = @keypair.dsa_sign_asn1([SHA_256_HEX_STRING].pack("H*"))

signature = signature_binary.unpack("H*").first

```

First I take the SHA hash, e.g. `ABCD...001124` and convert it from big endian to little endian: `241100....CDAB`. I do this because in the BitcoinQT client the hash is represented as an uint256 which is cast to a char array used as an input for signing. The result is just stored as a var so I assume I don't have to reverse it.

You'll need to download [this OpenSSL\_EC file](https://raw.github.com/lian/bitcoin-ruby/master/lib/bitcoin/ffi/openssl.rb) and add the following code to reproduce the above steps.

```
require 'openssl'
require 'ffi'

module Bitcoin
  def self.require_dependency(dummy1, dummy2)
  end  
autoload :OpenSSL_EC, "./openssl"
end  

module ::OpenSSL
  class BN
    def self.from_hex(hex); new(hex, 16); end
    end
  class PKey::EC::Point
    def self.from_hex(group, hex)
      new(group, BN.from_hex(hex))
    end
  end
end

```

What am I missing?

**Tags:** transactions, signature

> **Comments:**
> **username_0**: Armory [can be used](https://bitcointalk.org/index.php?topic=70911.msg813815#msg813815) to manually sign and verify messages, that should prove a useful debugging tool.  In addition BitcoinQT client can be configured to run a JSON-RPC server, which allows you to verify messages using the `verifymessage` method.  
> **username_0**: Experimenting with Armory I learned that unlike sha-256 hashes, every time you generate a secp256k1 signature it's different. I also found that the signature generated by my ruby code was not valid as far as Armory was concerned, even though the validate method in ruby did believe it to be correct. That strongly suggests an encoding issue.  
> **username_0**: Actually, message verification is not the same as transaction verification. So don't use Armory or the `verifymessage` for this! Instead, rely on `signrawtransaction`. Unfortunately, [I'm having issues with that](https://github.com/bitcoin/bitcoin/issues/2639) as well.  
> **username_0**: I'm able to sign my own real transaction using `signrawtransaction`. The one in the example throws an invalid key error, but I can live with that.  
> **username_0**: I studied the original C code of the Bitcoin client. It stores the digest as a uint256, which is cast to a char before signing. The signature itself is a char and doesn't get cast to anything else as far as I can see. I modified my question to reflect that.  
> **username_0**: Getting close now. I was able to [successfully](https://github.com/lian/bitcoin-ruby/issues/15) send a transaction using ruby-bitcoin. This should make it a lot easier to figure out what I'm doing wrong in my own script.  

---

## 2 answers

### Answer by username_0 on 2013-05-14. Score: 1 | Accepted answer

Done! Here's the resulting [script](https://gist.github.com/username_0/5574485). Although I recommend you use [bitcoin-ruby](https://github.com/lian/bitcoin-ruby) for anything serious.

There's a couple of things that went wrong.

I introduced a new bug during debugging: I commented out the hash\_code\_type field in the pre-signed transaction, which I needed to do in order to sign it with the JSON-RPC client. I forgot to undo that, so I was signing the wrong hash half the time. This became clear once I used bitcoin-ruby to create the same transaction and ask it what hash it was about to sign, something you can't (easily) do with the JSON-RPC client.

The little\_endian bit is not needed, although I'm still a bit confused as to why not. The correct line is:

`signature_binary = @keypair.dsa_sign_asn1([SHA_256_HEX_STRING].pack("H*"))`

In other words, good debugging tools and methodology are really important.


---

### Answer by username_1 on 2013-05-12. Score: 1

The binary encoding of the signature cannot be used to determine if you've performed the steps correctly - it will differ for each signature (even with the same private key).

So the signature of a hash signed with the same private key will be different every time. A random number is included in the formula that calculates the signature, so the resulting signature will be different each time. If a random number was not used in the formula, signing two different hashes with the same private key would make it possible to calculate the private key from the two signatures (which is the reason the security of the Sony PlayStation 3 was breached). You can read more about that here: <http://www.johannes-bauer.com/compsci/ecc/>

If you want to test whether you've made a valid transaction, then feed it to bitcoind using the sendrawtransaction command. It will spit out an error if the transaction is invalid, and if it's valid you will see the transaction going through.

> **Comments:**
> **username_0**: Thanks. I modified my question to take into account that the signature is never the same. Whenever I submit the transaction I get an "Invalid Signature" error. As soon as that stops, I'll have fixed it... By reading the C source code I also learned that the hash is a uint256 which is cast to a char for signing. I think I compensated for that, but it still doesn't work.  

---

