简体   繁体   English

如何在Ruby中生成比特币地址

[英]How to Generate a Bitcoin Address in Ruby

I'm trying to generate Bitcoin addresses in ruby by using this guide: 我正在尝试使用本指南在ruby中生成比特币地址:

https://bhelx.simst.im/articles/generating-bitcoin-keys-from-scratch-with-ruby/ https://bhelx.simst.im/articles/generating-bitcoin-keys-from-scratch-with-ruby/

But something isn't quite right, because the addresses being generated aren't coming out quite right. 但事情并不完全正确,因为生成的地址并不是很正确。

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 outputs something like: 它输出如下:

private_key_hex: C96DE079BAE4877E086288DEDD6F9F70B671862B7E6E4FC0EC401CADB81EDF45
public_key_hex: 0422435DF80F62E643D3CFBA66194052EC9ED0DFB47A1B26A4731079A5FF84FBF98FF0A540B6981D75BA789E6192F3B38BABEF6B0286CAEB4CAFCB51BB96D97B46
public_key_hash: db34927cc5ec0066411f366d9a95f9c6369c6e1d
address: Lz3xnxx6Uh79PEzPpWSMMZJVWR36hJgVL

If I plug this address into blockchain.info and similar tools it says that it's an invalid address. 如果我将此地址插入blockchain.info和类似工具,它会说它是一个无效的地址。

Any help would be greatly appreciated. 任何帮助将不胜感激。

In your generate_address_from_public_key_hash method, the checksum should be over the hash including the address prefix . generate_address_from_public_key_hash方法中,校验和应该在包含地址前缀的哈希上。 You're not actually using the pk variable at all at the moment after you assign it. 在分配之后,您实际上根本没有使用pk变量。 The code should look something like: 代码应该类似于:

def self.generate_address_from_public_key_hash(pub_key_hash)
  pk = ADDRESS_VERSION + pub_key_hash
  encode_base58(pk + checksum(pk)) # Using pk here, not pub_key_hash
end

The mistake seems to also be on the page you link to, I guess the author must have made a copy/paste error. 错误似乎也出现在您链接的页面上,我猜作者必须犯了一个复制/粘贴错误。


As an aside, keeping everything in hex strings and decoding back and forth seems an odd way of doing this. 另外,将所有内容保存在十六进制字符串中并来回解码似乎是一种奇怪的方法。 I would have thought it would be easier to use raw binary strings, and only encode to hex when printing out values. 我原以为使用原始二进制字符串会更容易,并且在打印输出值时只编码为十六进制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM