class Beowulf::Wallet

Attributes

cipher_keys[RW]
cipher_type[RW]
name[RW]
private_key[RW]
public_key[RW]
salt[RW]

Public Class Methods

new(options = {}) click to toggle source
# File lib/beowulf/wallet.rb, line 13
def initialize(options = {})
  @name = options[:name] || ''
  @private_key = options[:private_key] || ''
  @public_key = options[:public_key] || ''
  @cipher_keys = options[:cipher_keys] || ''
  @cipher_type = 'aes-256-cbc'
  @salt = options[:salt] || ''
end

Public Instance Methods

decode_wallet(wallet_json_string, password) click to toggle source
# File lib/beowulf/wallet.rb, line 241
def decode_wallet(wallet_json_string, password)
  # Validate inputs
  if wallet_json_string == nil || wallet_json_string.length == 0
    puts "Wallet json is not empty."
    raise WalletError, "Wallet json is not empty."
  end
  wallet_json = JSON.parse(wallet_json_string)
  # Init properties wallet
  @name = wallet_json['name']
  @cipher_keys = wallet_json['cipher_keys']
  # puts "decode_wallet.cipher_keys:", @cipher_keys
  @salt = wallet_json['salt']
  # Create checksum
  new_password = password + @salt
  # puts "new_password:", new_password
  pw_bytes = pakStr(new_password)
  checksum = Digest::SHA512.digest(pw_bytes)
  chs = hexlify(checksum)
  # puts "chs", chs
  # Decrypt data
  data_byte = unhexlify(@cipher_keys)
  # Decrypt AES
  msg_decrypt = decrypt(chs, data_byte)
  # puts "msg_decrypt:", msg_decrypt
  msg_json = JSON.parse(msg_decrypt)
  # puts "msg_json:", msg_json
  dechs = msg_json['checksum']
  if !(chs.eql? dechs)
    puts "Password wrong."
    raise WalletError, "Password wrong."
  end
  keys = msg_json['keys']
  keys.each do |key, value|
    # puts "#{key} is #{value}"
    @public_key = key
    @private_key = value
  end
end
decrypt(key, data) click to toggle source

gist.github.com/andrekandore/3140554

# File lib/beowulf/wallet.rb, line 281
def decrypt(key, data)
  block = key[0..31]
  aes = OpenSSL::Cipher.new('AES-256-CBC')
  aes.decrypt
  last = 31 + aes.block_size
  # puts "last:", last
  aes.iv = key[32..last]
  aes.key = block
  final_msg = aes.update(data) + aes.final
  final_msg
end
encode_wallet(password) click to toggle source
# File lib/beowulf/wallet.rb, line 146
def encode_wallet(password)
  # Validate
  if @name == nil || @name.length == 0
    puts "name is not empty."
    raise WalletError, "name is not empty."
  end

  # Encrypt data
  # Create checksum
  @salt = SecureRandom.alphanumeric(16)
  new_password = password + @salt
  # puts "new_password:", new_password
  pw_bytes = pakStr(new_password)
  checksum = Digest::SHA512.digest(pw_bytes)
  chs = hexlify(checksum)
  # puts "chs", chs
  # Create plain_data
  keys = {@public_key => @private_key}
  # puts "keys:", keys
  plain_keys = {"checksum" => chs, "keys" => keys}
  plain_data = JSON.dump(plain_keys)
  # puts "plain_data:", plain_data

  # Encrypt AES
  msg_encrypt = encrypt(chs, plain_data)
  msg_hex = hexlify(msg_encrypt)
  # puts "msg_hex:", msg_hex
  @cipher_keys = msg_hex

  # Create data save.
  wallet_data = {"cipher_keys" => @cipher_keys, "cipher_type" => @cipher_type, "salt" => @salt, "name" => @name}
  wallet_json = JSON.dump(wallet_data)
  wallet_json
end
encrypt(key, data) click to toggle source

gist.github.com/andrekandore/3140554

# File lib/beowulf/wallet.rb, line 182
def encrypt(key, data)
  block = key[0..31]
  aes = OpenSSL::Cipher.new('AES-256-CBC')
  aes.encrypt
  last = 31 + aes.block_size
  # puts "last:", last
  aes.iv = key[32..last]
  aes.key = block
  final_msg = aes.update(data) + aes.final
  final_msg
end
gen_keys() click to toggle source
# File lib/beowulf/wallet.rb, line 33
def gen_keys
  @private_key = gen_priv
  # puts "priv_key:", @private_key
  @public_key = gen_pub
  # puts "pub_key:", @public_key
end
gen_priv() click to toggle source
# File lib/beowulf/wallet.rb, line 40
def gen_priv
  rd = SecureRandom.alphanumeric(128)
  # puts "rd:", rd
  seed = @name + "owner" + rd
  # puts "seed:", seed
  bytes = pakStr(seed)
  hashSha256 = Digest::SHA256.digest(bytes)
  # create checksum
  pk = unhexlify('80')
  pk << hashSha256
  chs = Digest::SHA256.digest(pk)
  chs = Digest::SHA256.digest(chs)
  # create private key.
  b58 = pk
  b58 << chs[0..3]
  # puts "gen_priv.b58:", hexlify(b58)
  priv_key = Base58.binary_to_base58(b58, :bitcoin)
  priv_key
end
gen_pub() click to toggle source
# File lib/beowulf/wallet.rb, line 60
def gen_pub
  if @private_key.length > 0
    b58 = Base58.base58_to_binary(@private_key, :bitcoin)
    # puts "b58:", hexlify(b58)
    # Get checksum 4-bytes end.
    lb58 = b58.length-4
    chs = b58[lb58..-1]
    # Get raw private key
    hb58 = lb58-1
    tpk = b58[0..hb58]
    # Test checksum private key
    nchs = Digest::SHA256.digest(tpk)
    nchs = Digest::SHA256.digest(nchs)
    achs = hexlify(chs)
    bnchs = hexlify(nchs[0..3])
    if !(achs.eql? bnchs)
      puts achs, bnchs
      puts 'Invalid private key (checksum miss-match)'
      raise WalletError, "Invalid private key (checksum miss-match): #{achs} != #{bnchs}"
    end
    # Create Public Key
    bk = Bitcoin::Key.new(hexlify(tpk[1..-1]), nil, {compressed: true})
    # puts "bk.compressed:", bk.compressed
    public_key_hex = bk.pub
    # puts "public_key_hex.length:", public_key_hex.length
    # puts "public_key_hex:", public_key_hex
    public_key_byte = unhexlify(public_key_hex)
    checksum = OpenSSL::Digest::RIPEMD160.digest(public_key_byte)
    public_key = NETWORKS_BEOWULF_ADDRESS_PREFIX + Base58.binary_to_base58(public_key_byte + checksum[0..3], :bitcoin)
    public_key
  end
end
read_wallet_file(wallet_path_file, password) click to toggle source
# File lib/beowulf/wallet.rb, line 194
def read_wallet_file(wallet_path_file, password)
  # puts "wallet_path_file:", wallet_path_file
  # Validate inputs
  if wallet_path_file == nil || wallet_path_file.length == 0
    puts "Path file wallet is not empty."
    raise WalletError, "Path file wallet is not empty."
  end
  if password == nil || password.length == 0
    puts "Password is not empty."
    raise WalletError, "Password is not empty."
  end
  # Read file wallet
  file = File.read(wallet_path_file)
  wallet_json = JSON.parse(file)
  # puts "wallet_json:", wallet_json
  # Init properties wallet
  @name = wallet_json['name']
  @cipher_keys = wallet_json['cipher_keys']
  # puts "read_wallet_file.cipher_keys:", @cipher_keys
  @salt = wallet_json['salt']
  # Create checksum
  new_password = password + @salt
  # puts "new_password:", new_password
  pw_bytes = pakStr(new_password)
  checksum = Digest::SHA512.digest(pw_bytes)
  chs = hexlify(checksum)
  # puts "chs", chs
  # Decrypt data
  data_byte = unhexlify(@cipher_keys)
  # Decrypt AES
  msg_decrypt = decrypt(chs, data_byte)
  # puts "msg_decrypt:", msg_decrypt
  msg_json = JSON.parse(msg_decrypt)
  # puts "msg_json:", msg_json
  dechs = msg_json['checksum']
  if !(chs.eql? dechs)
    puts "Password wrong."
    raise WalletError, "Password wrong."
  end
  keys = msg_json['keys']
  keys.each do |key, value|
    # puts "#{key} is #{value}"
    @public_key = key
    @private_key = value
  end
end
save_wallet_file(wallet_path, wallet_filename, password) click to toggle source
# File lib/beowulf/wallet.rb, line 93
def save_wallet_file(wallet_path, wallet_filename, password)
  # Validate
  if password == nil || password.length == 0
    puts "Password is not empty."
    raise WalletError, "Password is not empty."
  end
  if password.length < 8
    puts "Password length >= 8 character."
    raise WalletError, "Password length >= 8 character."
  end
  if @name == nil || @name.length == 0
    puts "name is not empty."
    raise WalletError, "name is not empty."
  end

  # Encrypt data
  # Create checksum
  @salt = SecureRandom.alphanumeric(16)
  new_password = password + @salt
  # puts "new_password:", new_password
  pw_bytes = pakStr(new_password)
  checksum = Digest::SHA512.digest(pw_bytes)
  chs = hexlify(checksum)
  # puts "chs", chs
  # Create plain_data
  keys = {@public_key => @private_key}
  # puts "keys:", keys
  plain_keys = {"checksum" => chs, "keys" => keys}
  plain_data = JSON.dump(plain_keys)
  # puts "plain_data:", plain_data

  # Encrypt AES
  msg_encrypt = encrypt(chs, plain_data)
  msg_hex = hexlify(msg_encrypt)
  # puts "msg_hex:", msg_hex
  @cipher_keys = msg_hex

  # Write file
  file_path = wallet_filename
  if wallet_filename.length == 0
    file_path = @name + "-wallet.json"
  end
  if wallet_path.length > 0
    file_path = File.join(wallet_path, file_path)
  end
  # puts "file_path:", file_path
  # Create data save.
  wallet_data = {"cipher_keys" => @cipher_keys, "cipher_type" => @cipher_type, "salt" => @salt, "name" => @name}
  wallet_json = JSON.dump(wallet_data)
  # puts "wallet_json:", wallet_json
  File.open(file_path, "w") { |file| file.puts wallet_json}
end
to_json(options = {}) click to toggle source
# File lib/beowulf/wallet.rb, line 22
def to_json(options = {})
  JSON.dump ({
      :name => @name,
      :private_key => @private_key,
      :public_key => @public_key,
      :cipher_keys => @cipher_keys,
      :cipher_type => @cipher_type,
      :salt => @salt
  })
end