Module: BTC::Base58

Extended by:
Base58
Included in:
Base58
Defined in:
lib/btc/base58.rb

Overview

Base58 is used for compact human-friendly representation of Bitcoin addresses and private keys. Typically Base58-encoded text also contains a checksum (so-called “Base58Check”). Addresses look like 19FGfswVqxNubJbh1NW8A4t51T9x9RDVWQ. Private keys look like 5KQntKuhYWSRXNqp2yhdXzjekYAR7US3MT1715Mbv5CyUKV6hVe.

Here is what Satoshi said about Base58: Why base-58 instead of standard base-64 encoding?

  • Don’t want 0OIl characters that look the same in some fonts and

    could be used to create visually identical looking account numbers.
    
  • A string with non-alphanumeric characters is not as easily accepted as an account number.

  • E-mail usually won’t line-break if there’s no punctuation to break at.

  • Double-clicking selects the whole number as one word if it’s all alphanumeric.

Constant Summary collapse

ALPHABET =
'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

Instance Method Summary collapse

Instance Method Details

#base58_from_data(data) ⇒ Object

Converts binary string into its Base58 representation. If string is empty returns an empty string. If string is nil raises ArgumentError

Raises:

  • (ArgumentError)


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/btc/base58.rb', line 25

def base58_from_data(data)
  raise ArgumentError, 'Data is missing' unless data
  leading_zeroes = 0
  int = 0
  base = 1
  data.bytes.reverse_each do |byte|
    if byte == 0
      leading_zeroes += 1
    else
      leading_zeroes = 0
      int += base * byte
    end
    base *= 256
  end
  ('1' * leading_zeroes) + base58_from_int(int)
end

#base58check_from_data(data) ⇒ Object

Raises:

  • (ArgumentError)


63
64
65
66
# File 'lib/btc/base58.rb', line 63

def base58check_from_data(data)
  raise ArgumentError, 'Data is missing' unless data
  base58_from_data(data + BTC.hash256(data)[0, 4])
end

#data_from_base58(string) ⇒ Object

Converts binary string into its Base58 representation. If string is empty returns an empty string. If string is nil raises ArgumentError.

Raises:

  • (ArgumentError)


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/btc/base58.rb', line 45

def data_from_base58(string)
  raise ArgumentError, 'String is missing' unless string
  int = int_from_base58(string)
  bytes = []
  while int > 0
    remainder = int % 256
    int /= 256
    bytes.unshift(remainder)
  end
  data = BTC::Data.data_from_bytes(bytes)
  byte_for_1 = '1'.bytes.first
  BTC::Data.ensure_ascii_compatible_encoding(string).bytes.each do |byte|
    break if byte != byte_for_1
    data = "\x00" + data
  end
  data
end

#data_from_base58check(string) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/btc/base58.rb', line 68

def data_from_base58check(string)
  data = data_from_base58(string)
  if data.bytesize < 4
    raise FormatError, "Invalid Base58Check string: too short string #{string.inspect}"
  end
  payload_size = data.bytesize - 4
  payload = data[0, payload_size]
  checksum = data[payload_size, 4]
  if checksum != BTC.hash256(payload)[0, 4]
    raise FormatError, "Invalid Base58Check string: checksum invalid in #{string.inspect}"
  end
  payload
end