class VChainClient::BlockstackClient
Constants
- MASTER_ECC_PUBLIC_KEY
Public Class Methods
new(config)
click to toggle source
# File lib/vchain_client/blockstack_client.rb, line 15 def initialize(config) @config = config @log = Log4r::Logger["vchain_client"] end
Public Instance Methods
checkBlockstackRecord(blockstack_id, type)
click to toggle source
# File lib/vchain_client/blockstack_client.rb, line 96 def checkBlockstackRecord(blockstack_id, type) if @log.debug? @log.debug("[Blockstack.checkBlockstackRecord] input:") @log.debug("-> blockstack_id: #{blockstack_id}") @log.debug("-> type: #{type}") end record = nil begin record = self.getBlockstackRecord(blockstack_id) rescue => e if @log.error? @log.error("[Blockstack.checkBlockstackRecord] getBlockstackRecord raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") @log.error("--> blockstack_id: #{blockstack_id}") end raise e end if record == nil if @log.error? @log.error("[Blockstack.checkBlockstackRecord] failed to retrieve record") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") @log.error("--> blockstack_id: #{blockstack_id}") end return false end cryptoHelper = VChainClient::Crypto.new(@config) if @log.debug? @log.debug("[Blockstack.checkBlockstackRecord] Crypto initialized") end if record != nil if record.key?("ecc_pubkey") if record.key?("vchain_role") if record["vchain_role"] != type if @log.error? @log.error("[Blockstack.checkBlockstackRecord] type mismatch") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") @log.error("--> '"+ record["vchain_role"] +"'") end return false end if !record.key?("validator_blockstack_id") if @log.error? @log.error("[Blockstack.checkBlockstackRecord] record doesn't have 'validator_blockstack_id' field") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") end return false end validator_blockstack_id = record["validator_blockstack_id"] if @log.debug? @log.debug("[Blockstack.checkBlockstackRecord] record's vchain_role is '"+ record["vchain_role"] +"'") end if record["vchain_role"] != 'validator' if @log.debug? @log.debug("[Blockstack.checkBlockstackRecord] going to check validator for #{blockstack_id}, validator_id: #{validator_blockstack_id}") end begin if !self.checkValidator(validator_blockstack_id) if @log.error? @log.error("[Blockstack.checkBlockstackRecord] failed to check validator") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") @log.error("--> validator_blockstack_id: #{validator_blockstack_id}") end return false end rescue => e if @log.error? @log.error("[Blockstack.checkBlockstackRecord] checkValidator raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") @log.error("--> validator_blockstack_id: #{validator_blockstack_id}") end raise e end end validator_ecc_pub_key = nil if record["vchain_role"] != 'validator' begin validator_ecc_pub_key = self.getPublicKeyECC(validator_blockstack_id) rescue => e if @log.error? @log.error("[Blockstack.checkBlockstackRecord] getPublicKeyECC raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") @log.error("--> validator_blockstack_id: #{validator_blockstack_id}") end raise e end else validator_ecc_pub_key = MASTER_ECC_PUBLIC_KEY; end if validator_ecc_pub_key == nil if @log.error? @log.error("[Blockstack.checkBlockstackRecord] failed to retrieve public key:") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") @log.error("--> validator_blockstack_id: #{validator_blockstack_id}") end return false end # check client's sig version 1 client_sig = record["client_sig"] validator_sig = record["validator_sig"] client_sig_to_check = record["vchain_id"] + record["vchain_role"] + blockstack_id + record["ecc_pubkey"] + record["sig_version"]; validator_sig_to_check = record["vchain_id"] + record["vchain_role"] + blockstack_id + record["ecc_pubkey"] + record["sig_version"] + record["validator_vchain_id"] + validator_blockstack_id # client's sig versions 2 && 3 if record["sig_version"] == "2" || record["sig_version"] == "3" # need to retrieve RSA key if !record.key?("rsa_pubkey") if @log.error? @log.error("[Blockstack.checkBlockstackRecord] record doesn't have 'rsa_pubkey' field") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") end return false end if record["sig_version"] == "2" # sig version 2 client_sig = record["client_sig_v2"] validator_sig = record["validator_sig_v2"] client_sig_to_check = record["vchain_id"] + record["vchain_role"] + blockstack_id + record["ecc_pubkey"] + record["rsa_pubkey"] + record["sig_version"]; validator_sig_to_check = record["vchain_id"] + record["vchain_role"] + blockstack_id + record["ecc_pubkey"].gsub(/\n/, "") + record["rsa_pubkey"].gsub(/\n/, "") + record["sig_version"] + record["validator_vchain_id"] + validator_blockstack_id elsif record["sig_version"] == "3" # sig version 3 client_sig = record["client_sig_v3"] validator_sig = record["validator_sig_v3"] client_sig_to_check = record["vchain_id"] + record["vchain_role"] + blockstack_id + record["ecc_pubkey"].gsub(/\n/, "") + record["rsa_pubkey"].gsub(/\n/, "") + record["sig_version"]; validator_sig_to_check = record["vchain_id"] + record["vchain_role"] + blockstack_id + record["ecc_pubkey"].gsub(/\n/, "") + record["rsa_pubkey"].gsub(/\n/, "") + record["sig_version"] + record["validator_vchain_id"] + validator_blockstack_id end end begin if cryptoHelper.verifySignature(client_sig_to_check, client_sig, record["ecc_pubkey"]) # check validator's sig begin if cryptoHelper.verifySignature(validator_sig_to_check, validator_sig, validator_ecc_pub_key) return true; else if @log.error? @log.error("[Blockstack.checkBlockstackRecord] failed to verify validator_sig") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") @log.error("--> validator_sig_to_check: #{validator_sig_to_check}") @log.error("--> validator_sig: "+ Base64.encode64(record["validator_sig"])) @log.error("--> validator_ecc_pub_key: #{validator_ecc_pub_key}") end return false end rescue => e if @log.error? @log.error("[Blockstack.checkBlockstackRecord] verifySignature for validator_sig raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") @log.error("--> validator_sig_to_check: #{validator_sig_to_check}") @log.error("--> validator_sig: "+ Base64.encode64(record["validator_sig"])) @log.error("--> validator_ecc_pub_key: #{validator_ecc_pub_key}") end raise e end else if @log.error? @log.error("[Blockstack.checkBlockstackRecord] failed to verify client_sig") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") @log.error("--> client_sig_to_check: #{client_sig_to_check}") @log.error("--> client_sig: "+ Base64.encode64(record["client_sig"])) @log.error("--> ecc_pubkey: "+ record["ecc_pubkey"]) end return false end rescue => e if @log.error? @log.error("[Blockstack.checkBlockstackRecord] verifySignature for client_sig raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") @log.error("--> client_sig_to_check: #{client_sig_to_check}") @log.error("--> client_sig: "+ Base64.encode64(record["client_sig"])) @log.error("--> ecc_pubkey: "+ record["ecc_pubkey"]) end raise e end else if @log.error? @log.error("[Blockstack.checkBlockstackRecord] record doesn't have 'vchain_role' field") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") end end else if @log.error? @log.error("[Blockstack.checkBlockstackRecord] record doesn't have 'ecc_pubkey' field") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") end end else if @log.error? @log.error("[Blockstack.checkBlockstackRecord] record is null") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("-> type: #{type}") end end return false end
checkFederativeServer(federative_server_id)
click to toggle source
# File lib/vchain_client/blockstack_client.rb, line 21 def checkFederativeServer(federative_server_id) if @log.debug? @log.debug("[Blockstack.checkFederativeServer] input:") @log.debug("-> federative_server_id: #{federative_server_id}") end begin return self.checkBlockstackRecord(federative_server_id, 'federative_server') rescue => e if @log.error? @log.error("[Blockstack.checkFederativeServer] checkBlockstackRecord raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> federative_server_id: #{federative_server_id}") @log.error("--> federative_server_id: #{federative_server_id}") @log.error("--> type: federative_server") end raise e end end
checkValidator(validator_id)
click to toggle source
# File lib/vchain_client/blockstack_client.rb, line 71 def checkValidator(validator_id) if @log.debug? @log.debug("[Blockstack.checkValidator] input:") @log.debug("-> validator_id: #{validator_id}") end begin return self.checkBlockstackRecord(validator_id, 'validator') rescue => e if @log.error? @log.error("[Blockstack.checkValidator] checkBlockstackRecord raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> validator_id: #{validator_id}") @log.error("--> validator_id: #{validator_id}") @log.error("--> type: validator") end raise e end end
checkVerificator(verificator_id)
click to toggle source
# File lib/vchain_client/blockstack_client.rb, line 46 def checkVerificator(verificator_id) if @log.debug? @log.debug("[Blockstack.checkVerificator] input:") @log.debug("-> verificator_id: #{verificator_id}") end begin return self.checkBlockstackRecord(verificator_id, 'verificator') rescue => e if @log.error? @log.error("[Blockstack.checkVerificator] checkBlockstackRecord raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> verificator_id: #{verificator_id}") @log.error("--> verificator_id: #{verificator_id}") @log.error("--> type: verificator") end raise e end end
getBlockstackRecord(blockstack_id, force_refresh=false)
click to toggle source
# File lib/vchain_client/blockstack_client.rb, line 508 def getBlockstackRecord(blockstack_id, force_refresh=false) if @log.debug? @log.debug("[Blockstack.getBlockstackRecord] input:") @log.debug("-> blockstack_id: #{blockstack_id}") end if !force_refresh if @@recs_cache.key?(blockstack_id) if @log.debug? @log.debug("[Blockstack.getBlockstackRecord] '#{blockstack_id}' is in a cache") end return @@recs_cache[blockstack_id] end end blockstack_path = @config["blockstack"]["path"] cmd_init = blockstack_path +" set_advanced_mode on" cmd = blockstack_path +" get_name_zonefile "+ blockstack_id if @log.debug? @log.debug("[Blockstack.getBlockstackRecord] using '#{blockstack_path}' as a Blockstack path") @log.debug("[Blockstack.getBlockstackRecord] running '#{cmd}'") end ret = nil begin `#{cmd_init}` ret = `#{cmd}` rescue => e if @log.error? @log.error("[Blockstack.getBlockstackRecord] cmd call '#{cmd}' raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("--> '#{cmd}'") end raise e end if ret == nil if @log.error? @log.error("[Blockstack.getBlockstackRecord] failed to retrieve record from cmd call") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("--> '#{cmd}'") end return nil end if @log.debug? @log.debug("[Blockstack.getBlockstackRecord] cmd call return:") @log.debug(ret) end ret = JSON.parse ret @log.debug(ret) lines = ret["zonefile"].split("\n") fz = {} lines.each { |line| recs = line.split(" ") if recs.size == 3 if recs[0] == "A1" || recs[0] == "A2" || recs[0] == "A3" || recs[0] == "A4" || recs[0] == "A5" || recs[0] == "A6" || recs[0] == "A7" || recs[0] == "A8" || recs[0] == "A9" || recs[0] == "A10" || recs[0] == "A11" fz[recs[0]] = recs[2][1..-2] end end } if @log.debug? @log.debug("[Blockstack.getBlockstackRecord] fz:") @log.debug(fz) end if fz.key?("A1") && fz.key?("A2") && fz.key?("A3") && fz.key?("A4") && fz.key?("A5") && fz.key?("A6") && fz.key?("A7") && fz.key?("A8") ecc_pubkey_aligned = fz["A1"] ecc_pubkey = ecc_pubkey_aligned[0..63] +"\n"+ ecc_pubkey_aligned[64..ecc_pubkey_aligned.length] rsa_pubkey = nil if fz["A7"] == "2" || fz["A7"] == "3" # sig versions 2 && 3 if !fz.key?("A9") if @log.error? @log.error("[Blockstack.getBlockstackRecord] no 'A9' field, sig ver is >1") @log.error("-> blockstack_id: #{blockstack_id}") end return nil end rsa_pubkey_aligned = fz["A9"] rsa_pubkey = rsa_pubkey_aligned[0..63] +"\n"+ rsa_pubkey_aligned[64..127] +"\n"+ rsa_pubkey_aligned[128..191] +"\n"+ rsa_pubkey_aligned[192..255] +"\n"+ rsa_pubkey_aligned[256..319] +"\n"+ rsa_pubkey_aligned[320..383] +"\n"+ rsa_pubkey_aligned[384..rsa_pubkey_aligned.length] end output = { "ecc_pubkey" => ecc_pubkey, "rsa_pubkey" => rsa_pubkey, "vchain_id" => fz["A2"], "validator_sig" => Base64.decode64(fz["A3"]), "validator_vchain_id" => fz["A4"], "validator_blockstack_id" => fz["A5"], "vchain_role" => fz["A6"], "sig_version" => fz["A7"], "client_sig" => Base64.decode64(fz["A8"]) } if fz["A7"] == "2" || fz["A7"] == "3" # sig versions 2 && 3 output["client_sig_v2"] = Base64.decode64(fz["A8"]) output["validator_sig_v2"] = Base64.decode64(fz["A3"]) if fz["A7"] == "3" # sig version 3 if !fz.key?("A10") || !fz.key?("A11") if @log.error? @log.error("[Blockstack.getBlockstackRecord] no 'A10' or 'A11' fields, sig ver = 3") @log.error("-> blockstack_id: #{blockstack_id}") end return nil end output["client_sig_v3"] = Base64.decode64(fz["A10"]) output["validator_sig_v3"] = Base64.decode64(fz["A11"]) end end if @log.debug? @log.debug("[Blockstack.getBlockstackRecord] output:") @log.debug(output) end @@recs_cache[blockstack_id] = output @@ecc_keys_cache[blockstack_id] = ecc_pubkey @@rsa_keys_cache[blockstack_id] = rsa_pubkey return output else if @log.error? @log.error("[Blockstack.getBlockstackRecord] no 'A*' field") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("--> blockstack_id: #{blockstack_id}") end end return nil end
getPublicKeyECC(blockstack_id, force_refresh=false)
click to toggle source
# File lib/vchain_client/blockstack_client.rb, line 380 def getPublicKeyECC(blockstack_id, force_refresh=false) if @log.debug? @log.debug("[Blockstack.getPublicKeyECC] input:") @log.debug("-> blockstack_id: #{blockstack_id}") end if !force_refresh if @@ecc_keys_cache.key?(blockstack_id) if @log.debug? @log.debug("[Blockstack.getPublicKeyECC] '#{blockstack_id}' is in a cache") end return @@ecc_keys_cache[blockstack_id] end end if @log.debug? @log.debug("[Blockstack.getPublicKeyECC] '#{blockstack_id}' is not in a cache yet") end begin record = self.getBlockstackRecord(blockstack_id, force_refresh); if record != nil if record.key?("ecc_pubkey") @@ecc_keys_cache[blockstack_id] = record["ecc_pubkey"] return record["ecc_pubkey"] else if @log.error? @log.error("[Blockstack.getPublicKeyECC] record '#{blockstack_id}' doesn't have 'ecc_pubkey' field") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("--> blockstack_id: #{blockstack_id}") end end else if @log.error? @log.error("[Blockstack.getPublicKeyECC] failed to retrieve '#{blockstack_id}' record") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("--> blockstack_id: #{blockstack_id}") end end rescue => e if @log.error? @log.error("[Blockstack.getPublicKeyECC] getBlockstackRecord raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("--> blockstack_id: #{blockstack_id}") end raise e end return nil end
getPublicKeyRSA(blockstack_id, force_refresh=false)
click to toggle source
# File lib/vchain_client/blockstack_client.rb, line 444 def getPublicKeyRSA(blockstack_id, force_refresh=false) if @log.debug? @log.debug("[Blockstack.getPublicKeyRSA] input:") @log.debug("-> blockstack_id: #{blockstack_id}") end if !force_refresh if @@rsa_keys_cache.key?(blockstack_id) if @log.debug? @log.debug("[Blockstack.getPublicKeyRSA] '#{blockstack_id}' is in a cache") end return @@rsa_keys_cache[blockstack_id] end end if @log.debug? @log.debug("[Blockstack.getPublicKeyRSA] '#{blockstack_id}' is not in a cache yet") end begin record = self.getBlockstackRecord(blockstack_id, force_refresh); if record != nil if record.key?("rsa_pubkey") @@rsa_keys_cache[blockstack_id] = record["rsa_pubkey"] return record["rsa_pubkey"] else if @log.error? @log.error("[Blockstack.getPublicKeyRSA] record '#{blockstack_id}' doesn't have 'rsa_pubkey' field") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("--> blockstack_id: #{blockstack_id}") end end else if @log.error? @log.error("[Blockstack.getPublicKeyRSA] failed to retrieve '#{blockstack_id}' record") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("--> blockstack_id: #{blockstack_id}") end end rescue => e if @log.error? @log.error("[Blockstack.getPublicKeyRSA] getBlockstackRecord raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> blockstack_id: #{blockstack_id}") @log.error("--> blockstack_id: #{blockstack_id}") end raise e end return nil end