I'm trying to sign (using secp256k1) a transaction as explained here. 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 @keypair = OpenSSL::PKey::EC.new("secp256k1") @keypair.private_key = @keypair_array.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 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?