module XRBP::Crypto

The Crypto module defines methods to create XRPL compliant keys and subsequent entities (accounts, nodes, validators).

Public Class Methods

account(key=nil) click to toggle source

Generate a new XRPL account.

@param key [Symbol, Hash] key type to generate or key itself (optional) @return [Hash] account details containing id and pub/priv key pair

# File lib/xrbp/crypto/account.rb, line 9
def self.account(key=nil)
  pub = nil
  account_id = nil
  if key == :secp256k1 || key.nil?
    key = Key::secp256k1
    pub = key[:public]

  elsif key == :ed25519
    key = Key::ed25519
    pub = "\xED" + key[:public]

  elsif key.is_a?(Hash)
    if key[:account_id]
      account_id = key[:account_id]
    elsif key[:public]
      pub = key[:public]
    end

  else
    pub = key
    key = {:public => pub}
  end

  raise "must specify pub or account_id" unless pub || account_id

      sha256 = OpenSSL::Digest::SHA256.new
   ripemd160 = OpenSSL::Digest::RIPEMD160.new
  account_id = [Key::TOKEN_TYPES[:account_id]].pack("C") + ripemd160.digest(sha256.digest([pub].pack("H*"))) unless account_id
      chksum = sha256.digest(sha256.digest(account_id))[0..3]

  { :account => Base58.binary_to_base58(account_id  + chksum, :ripple) }.merge(key)
end
account?(account) click to toggle source

Return boolean indicating if the specified account is valid

# File lib/xrbp/crypto/account.rb, line 85
def self.account?(account)
  parse_account(account) != nil
end
account_id(account) click to toggle source

Return the account id for the specified XRP account. This is a simpler version of {parse_account} that just returns the binary account, skipping the token and checksum verifications.

# File lib/xrbp/crypto/account.rb, line 56
def self.account_id(account)
  Base58.base58_to_binary(account, :ripple)[1..-5]
end
no_account() click to toggle source

Account One: xrpl.org/accounts.html#special-addresses

# File lib/xrbp/crypto/account.rb, line 48
def self.no_account
  @no_account ||= account(:account_id => ([0] * 20 + [1]).pack("C*"))[:account]
end
node(key=nil) click to toggle source

Generate a new XRPL node.

@param key [Symbol, Hash] key type to generate or key itself (optional) @return [Hash] node details containing id and pub/priv key pair

# File lib/xrbp/crypto/node.rb, line 9
def self.node(key=nil)
  pub = nil
  if key == :secp256k1 || key.nil?
    key = Key::secp256k1
    pub = key[:public]

  elsif key.is_a?(Hash)
    key = Key::secp256k1(key[:seed]) if key[:seed]
    pub = key[:public]

  else
    pub = key
    key = {:public => pub}
  end

   sha256 = OpenSSL::Digest::SHA256.new
  node_id = [Key::TOKEN_TYPES[:node_public]].pack("C") + [pub].pack("H*")
   chksum = sha256.digest(sha256.digest(node_id))[0..3]

  { :node => Base58.binary_to_base58(node_id + chksum, :ripple) }.merge(key)
end
node?(node) click to toggle source

Return boolean indicating if the specified node is valid

# File lib/xrbp/crypto/node.rb, line 56
def self.node?(node)
  parse_node(node) != nil
end
parse_account(account) click to toggle source

Extract Account ID from Address.

@param account [String] Base58 encoded account address @return [String, nil] unique account id or nil if input

if not an account
# File lib/xrbp/crypto/account.rb, line 65
def self.parse_account(account)
  begin
    bin = Base58.base58_to_binary(account, :ripple)
  rescue ArgumentError
    return nil
  end

  typ = bin[0]
  chk = bin[-4..-1]
  bin = bin[1...-4]

  return nil unless typ.unpack("C*").first == Key::TOKEN_TYPES[:account_id]

  sha256 = OpenSSL::Digest::SHA256.new
  return nil unless sha256.digest(sha256.digest(typ + bin))[0..3] == chk

  return bin
end
parse_node(node) click to toggle source

Extract Node ID from Address.

@param node [String] Base58 encoded node address @return [String, nil] unique node id or nil if input

if not an node
# File lib/xrbp/crypto/node.rb, line 36
def self.parse_node(node)
  begin
    bin = Base58.base58_to_binary(node, :ripple)
  rescue ArgumentError
    return nil
  end

  typ = bin[0]
  chk = bin[-4..-1]
  bin = bin[1...-4]

  return nil unless typ.unpack("C*").first == Key::TOKEN_TYPES[:node_public]

  sha256 = OpenSSL::Digest::SHA256.new
  return nil unless sha256.digest(sha256.digest(typ + bin))[0..3] == chk

  return bin
end
parse_seed(seed) click to toggle source

Extract Seed ID from Encoding.

@param seed [String] Base58 encoded seed @return [String, nil] extracted seed or nil

if not valid
# File lib/xrbp/crypto/seed.rb, line 36
def self.parse_seed(seed)
  bin = Base58.base58_to_binary(seed, :ripple)
  typ = bin[0]
  chk = bin[-4..-1]
  bin = bin[1...-4]

  # TODO also permit ED25519 prefix (?)
  return nil unless typ.unpack("C*").first == Key::TOKEN_TYPES[:family_seed]

  sha256 = OpenSSL::Digest::SHA256.new
  return nil unless sha256.digest(sha256.digest(typ + bin))[0..3] == chk

  return nil unless bin.size == 16

  return bin
end
parse_validator(validator) click to toggle source

Extract Validator ID from Address. Takes same params as {Crypto#parse_node}

# File lib/xrbp/crypto/validator.rb, line 10
def self.parse_validator(validator)
  return parse_node(validator)
end
seed(key=nil) click to toggle source

Generate a new XRPL seed.

@param key [Symbol] key type to generate (optional) @return [Hash] seed details containing encoded seed and key type

# File lib/xrbp/crypto/seed.rb, line 10
def self.seed(key=nil)
  prefix = nil
  if key == :secp256k1 || key.nil?
    prefix = [Key::TOKEN_TYPES[:family_seed]]
    key = { :type => :secp256k1 }

  elsif key == :ed25519
    prefix = [0x01, 0xE1, 0x4B]
    key = { :type => :ed25519 }

  else
    raise ArgumentError, key
  end

  sha256 = OpenSSL::Digest::SHA256.new
  base = SecureRandom.random_bytes(16)
  pref = (prefix + base.bytes).pack("C*")
  chk = sha256.digest(sha256.digest(pref))[0..3]
  { :seed => Base58.binary_to_base58(pref + chk, :ripple) }.merge(key)
end
seed?(seed) click to toggle source

Return boolean indicating if the specified seed is valid

# File lib/xrbp/crypto/seed.rb, line 54
def self.seed?(seed)
  parse_seed(seed) != nil
end
validator(key=nil) click to toggle source

Generate a new XRPL validator. Takes same params as {Crypto#node}

# File lib/xrbp/crypto/validator.rb, line 4
def self.validator(key=nil)
  return node(key)
end
validator?(validator) click to toggle source

Return bool indicating if Validator is valid. Takes same params as {Crypto#node?}

# File lib/xrbp/crypto/validator.rb, line 16
def self.validator?(validator)
  return node?(validator)
end
xrp_account() click to toggle source

Account Zero: xrpl.org/accounts.html#special-addresses

# File lib/xrbp/crypto/account.rb, line 43
def self.xrp_account
  @xrp_account ||= account(:account_id => ([0] * 21).pack("C*"))[:account]
end