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[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 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?
verifymessage
method.verifymessage
for this! Instead, rely onsignrawtransaction
. Unfortunately, I'm having issues with that as well.signrawtransaction
. The one in the example throws an invalid key error, but I can live with that.