module XRBP::Crypto
The Crypto
module defines methods to create XRPL compliant keys and subsequent entities (accounts, nodes, validators).
Public Class Methods
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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