I'm trying to generate Bitcoin addresses in ruby.
Here's the class I'm using:
require 'openssl'
require 'ecdsa'
require 'securerandom'
require 'base58'
class BitcoinAddressGenerator
ADDRESS_VERSION = '00'
def self.generate_address
# Bitcoin uses the secp256k1 curve
curve = OpenSSL::PKey::EC.new('secp256k1')
# Now we generate the public and private key together
curve.generate_key
private_key_hex = curve.private_key.to_s(16)
puts "private_key_hex: #{private_key_hex}"
public_key_hex = curve.public_key.to_bn.to_s(16)
puts "public_key_hex: #{public_key_hex}"
pub_key_hash = public_key_hash(public_key_hex)
puts "pub_key_hash: #{pub_key_hash}"
address = generate_address_from_public_key_hash(public_key_hash(public_key_hex))
puts "address: #{address}"
end
def self.generate_address_from_public_key_hash(pub_key_hash)
pk = ADDRESS_VERSION + pub_key_hash
encode_base58(pub_key_hash + checksum(pub_key_hash))
end
def self.int_to_base58(int_val, leading_zero_bytes=0)
alpha = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
base58_val, base = '', alpha.size
while int_val > 0
int_val, remainder = int_val.divmod(base)
base58_val = alpha[remainder] + base58_val
end
base58_val
end
def self.encode_base58(hex)
leading_zero_bytes = (hex.match(/^([0]+)/) ? $1 : '').size / 2
("1"*leading_zero_bytes) + int_to_base58( hex.to_i(16) )
end
def self.checksum(hex)
sha256(sha256(hex))[0...8]
end
# RIPEMD-160 (160 bit) hash
def self.rmd160(hex)
Digest::RMD160.hexdigest([hex].pack("H*"))
end
def self.sha256(hex)
Digest::SHA256.hexdigest([hex].pack("H*"))
end
# Turns public key into the 160 bit public key hash
def self.public_key_hash(hex)
rmd160(sha256(hex))
end
end
It returns an invalid address.
Any suggestions?