class Enchaine

Constants

BIP39EN
CONTENT
TITLE

TODO: Improve this method of specification

VERSION

Public Class Methods

new(difficulty: "00", genesis: "", digest: "sha256", format: "hex", method: "simple", truncate: -1, which: CONTENT) click to toggle source
# File lib/enchaine.rb, line 32
def initialize(difficulty: "00", genesis: "", digest: "sha256",
               format: "hex", method: "simple", truncate: -1,
               which: CONTENT)
  @difficulty = difficulty
  @genesis = genesis
  @digest = set_digest(digest)
  @format = set_format(format)
  @method = set_method(method)
  @truncate = truncate
  @which = which
end

Public Instance Methods

bin_to_base58(bytes) click to toggle source
# File lib/enchaine.rb, line 126
def bin_to_base58(bytes)
  Base58.encode(bytes)
end
bin_to_base64(bytes) click to toggle source
# File lib/enchaine.rb, line 122
def bin_to_base64(bytes)
  Base64.strict_encode64 bytes
end
bin_to_binary(bytes) click to toggle source
# File lib/enchaine.rb, line 114
def bin_to_binary(bytes)
  bytes.each_byte.map { |b| b.to_s(2).rjust(8, '0') }.join
end
bin_to_bip39(bytes) click to toggle source

FIXME: Not actually Bip0039. And loses some bits if data is not % 11

# File lib/enchaine.rb, line 132
def bin_to_bip39(bytes)
  data = binToBinary bytes
  words = BIP39EN.split
  result = []
  for i in 0..((data.length.div 11) - 1)
    idx = data[(i * 11)...((i + 1) * 11)].to_i 2
    result << words[idx]
  end
  result.join ' '
end
bin_to_hex(bytes) click to toggle source
# File lib/enchaine.rb, line 118
def bin_to_hex(bytes)
  bytes.each_byte.map { |b| b.to_s(16).rjust(2,'0') }.join
end
block_hash(sections) click to toggle source
# File lib/enchaine.rb, line 211
def block_hash sections
  previous = @digest.hexdigest(@genesis)
  sections.map{|section|
    title, content = section
    nonce = 0
    digest = ""
    loop do
      digest = format_identifier(title, content, nonce.to_s)
      break if digest.start_with? @difficulty
      nonce += 1
    end
    previous = digest
    "# " + digest + "\n\n" + content + "\n"
  }.join("\n")
end
cumulative_hash(sections) click to toggle source
# File lib/enchaine.rb, line 175
def cumulative_hash sections
  sections.map{|section|
    title, content = section
    "# " + format_identifier_cumulative(title, content) + "\n\n" + content +
      "\n"
  }.join("\n")
end
difficulty=(difficulty) click to toggle source
# File lib/enchaine.rb, line 44
def difficulty=(difficulty)
  @difficulty = difficulty
end
difficulty_hash(sections) click to toggle source
# File lib/enchaine.rb, line 183
def difficulty_hash sections
  sections.map{|section|
    title, content = section
    nonce = 0
    digest = ""
    loop do
      digest = format_identifier(title, content, nonce.to_s)
      break if digest.start_with? @difficulty
      nonce += 1
    end
    "# " + digest + "\n\n" + content + "\n"
  }.join("\n")
end
difficulty_hash_with_nonce(sections) click to toggle source
# File lib/enchaine.rb, line 197
def difficulty_hash_with_nonce sections
  sections.map{|section|
    title, content = section
    nonce = 0
    digest = ""
    loop do
      digest = format_identifier(title, content, nonce.to_s)
      break if digest.start_with? @difficulty
      nonce += 1
    end
    "# " + digest + " (" + nonce.to_s + ")\n\n" + content + "\n"
  }.join("\n")
end
enchaine(input) click to toggle source
# File lib/enchaine.rb, line 109
def enchaine input
  sections = input.split(/(#\s+.+$|^.+\n=+)/).map {|x| x.strip }.delete_if {|x| x == ''''}.each_slice(2).to_a
  return @method.call sections
end
entropy_hash(sections) click to toggle source
# File lib/enchaine.rb, line 227
def entropy_hash sections
  sections.map{|section|
    puts section
    title, content = section
    bytes = SecureRandom.random_bytes(32)
    "# " + @format.call(bytes)[0..@truncate] + "\n\n" + content + "\n"
  }.join("\n")
end
format_dentifier_cumulative(title, content, nonce='') click to toggle source
# File lib/enchaine.rb, line 158
def format_dentifier_cumulative(title, content, nonce='')
  if(@which)
    data = content
  else
    data = title
  end
  @digest << data + nonce
  @format.call(@digest.digest)[0..@truncate]
end
format_identifier(title, content, nonce='') click to toggle source
# File lib/enchaine.rb, line 148
def format_identifier(title, content, nonce='')
  if(@which)
    data = content
  else
    data = title_without_markup title
  end
  digest = @digest.digest(data + nonce)
  @format.call(digest[0..@truncate])
end
genesis=(genesis) click to toggle source
# File lib/enchaine.rb, line 48
def genesis=(genesis)
  @genesis = genesis
end
set_digest(spec) click to toggle source
# File lib/enchaine.rb, line 56
def set_digest spec
  case spec
  when 'sha256'
    @digest = Digest::SHA256.new
  when 'rmd160'
    @digest = Digest::RMD160.new
  when 'hmac'
    @digest = Digest::HMAC.new
  when 'md5'
    @digest = Digest::MD5.new
  end
end
set_format(spec) click to toggle source
# File lib/enchaine.rb, line 69
def set_format spec
  case spec
  when 'binary'
    @format = self.method(:bin_to_binary)
  when 'hex'
    @format = self.method(:bin_to_hex)
  when 'base58'
    @format = self.method(:bin_to_base58)
  when 'base64'
    @format = self.method(:bin_to_base64)
  when 'bip39'
    @format = self.method(:bin_to_bip39)
  end
end
set_method(spec) click to toggle source
# File lib/enchaine.rb, line 84
def set_method spec
  case spec
  when 'simple'
    @method = self.method(:simple_hash)
  when 'cumulative'
    @method = self.method(:cumulative_hash)
  when 'difficulty'
    @method = self.method(:difficulty_hash)
  when 'difficultynonce'
    @method = self.method(:difficulty_hash_with_nonce)
  when 'block'
    @method = self.method(:block_hash)
  when 'entropy'
    @method = self.method(:entropy_hash)
  end
end
set_which(which) click to toggle source
# File lib/enchaine.rb, line 101
def set_which which
  if arg == 'title'
    @which = TITLE
  else
    @which = CONTENT
  end
end
simple_hash(sections) click to toggle source
# File lib/enchaine.rb, line 168
def simple_hash sections
  sections.map{|section|
    title, content = section
    "# " + format_identifier(title, content) + "\n\n" + content + "\n"
  }.join("\n")
end
title_without_markup(str) click to toggle source
# File lib/enchaine.rb, line 143
def title_without_markup str
  matches = str.match(/(#\s+(.+)$|^(.+)\n=+)/)
  return matches[2] || matches[3]
end
truncate=(truncate) click to toggle source
# File lib/enchaine.rb, line 52
def truncate=(truncate)
  @truncate = truncate
end