Module: Philiprehberger::BaseConvert::Base58

Defined in:
lib/philiprehberger/base_convert/base58.rb

Overview

Base58 encoding and decoding using the Bitcoin alphabet

Alphabet: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

Constant Summary collapse

ALPHABET =
'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
BASE =
ALPHABET.length
DECODE_MAP =
ALPHABET.each_char.with_index.to_h.freeze

Class Method Summary collapse

Class Method Details

.decode(string) ⇒ String

Decode a Base58 string

Parameters:

  • string (String)

    the Base58-encoded string

Returns:

  • (String)

    the decoded string

Raises:

  • (Error)

    if the string contains invalid characters



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/philiprehberger/base_convert/base58.rb', line 39

def self.decode(string)
  return '' if string.empty?

  leading_ones = string.each_char.take_while { |c| c == ALPHABET[0] }.length

  num = 0
  string.each_char do |char|
    value = DECODE_MAP[char]
    raise Error, "invalid Base58 character: #{char}" if value.nil?

    num = (num * BASE) + value
  end

  result = []
  while num.positive?
    num, byte = num.divmod(256)
    result << byte
  end

  ("\x00" * leading_ones) + result.reverse.pack('C*')
end

.encode(string) ⇒ String

Encode a string to Base58

Parameters:

  • string (String)

    the input string

Returns:

  • (String)

    the Base58-encoded string



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/philiprehberger/base_convert/base58.rb', line 17

def self.encode(string)
  return '' if string.empty?

  bytes = string.bytes
  leading_zeros = bytes.take_while(&:zero?).length

  num = bytes.inject(0) { |acc, byte| (acc << 8) | byte }

  result = []
  while num.positive?
    num, remainder = num.divmod(BASE)
    result << ALPHABET[remainder]
  end

  (ALPHABET[0] * leading_zeros) + result.reverse.join
end