class VChainClient::Crypto
Public Class Methods
new(config)
click to toggle source
# File lib/vchain_client/crypto.rb, line 16 def initialize(config) @config = config @log = Log4r::Logger["vchain_client"] end
Public Instance Methods
checkTreeSignature(tree_root_hash, blockchain_txid, blockchain_block_hash, blockchain_timestamp, blockstack_client_id, sig_version, signature, pubkey)
click to toggle source
# File lib/vchain_client/crypto.rb, line 747 def checkTreeSignature(tree_root_hash, blockchain_txid, blockchain_block_hash, blockchain_timestamp, blockstack_client_id, sig_version, signature, pubkey) what_to_check = tree_root_hash what_to_check += blockchain_txid what_to_check += blockchain_block_hash what_to_check += blockchain_timestamp.to_s what_to_check += blockstack_client_id what_to_check += sig_version if @log.debug? @log.debug("[Crypto.checkTreeSignature] input:") @log.debug("-> tree_root_hash: #{tree_root_hash}") @log.debug("-> blockchain_txid: #{blockchain_txid}") @log.debug("-> blockchain_block_hash: #{blockchain_block_hash}") @log.debug("-> blockchain_timestamp: #{blockchain_timestamp}") @log.debug("-> blockstack_client_id: #{blockstack_client_id}") @log.debug("-> sig_version: #{sig_version}") @log.debug("-> signature: "+ Base64.encode64(signature)) @log.debug("-> pubkey: #{pubkey}") end begin return self.verifySignature(what_to_check, signature, pubkey) rescue => e if @log.error? @log.error("[Crypto.checkTreeSignature] verifySignature raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> tree_root_hash: #{tree_root_hash}") @log.error("-> blockchain_txid: #{blockchain_txid}") @log.error("-> blockchain_block_hash: #{blockchain_block_hash}") @log.error("-> blockchain_timestamp: #{blockchain_timestamp}") @log.error("-> blockstack_client_id: #{blockstack_client_id}") @log.error("-> sig_version: #{sig_version}") @log.error("-> signature: "+ Base64.encode64(signature)) @log.error("-> pubkey: #{pubkey}") @log.error("--> what_to_check: #{what_to_check}") @log.error("--> signature: "+ Base64.encode64(signature)) @log.error("--> pubkey: #{pubkey}") end raise e end end
checkVerificationSignature(field_hash, data_hash, doc_hash, credentials_hash, verification_type, weight, timestamp, blockstack_client_id, pubkey, signature, version)
click to toggle source
# File lib/vchain_client/crypto.rb, line 793 def checkVerificationSignature(field_hash, data_hash, doc_hash, credentials_hash, verification_type, weight, timestamp, blockstack_client_id, pubkey, signature, version) if @log.debug? @log.debug("[Crypto.checkVerificationSignature] input:") @log.debug("-> field_hash: #{field_hash}") @log.debug("-> data_hash: #{data_hash}") @log.debug("-> doc_hash: #{doc_hash}") @log.debug("-> credentials_hash: #{credentials_hash}") @log.debug("-> type: #{verification_type}") @log.debug("-> weight: "+ weight.to_s) @log.debug("-> timestamp: "+ timestamp.to_s) @log.debug("-> blockstack_client_id: #{blockstack_client_id}") @log.debug("-> signature: "+ Base64.encode64(signature)) @log.debug("-> pubkey: #{pubkey}") end what_to_check = field_hash what_to_check += data_hash what_to_check += doc_hash what_to_check += credentials_hash what_to_check += verification_type what_to_check += weight.to_s what_to_check += timestamp.to_s what_to_check += blockstack_client_id what_to_check += version begin return self.verifySignature(what_to_check, signature, pubkey) rescue => e if @log.error? @log.error("[Crypto.checkVerificationSignature] verifySignature raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> field_hash: #{field_hash}") @log.error("-> data_hash: #{data_hash}") @log.error("-> doc_hash: #{doc_hash}") @log.error("-> credentials_hash: #{credentials_hash}") @log.error("-> verification_type: #{verification_type}") @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> weight: "+ weight.to_s) @log.error("-> blockstack_client_id: #{blockstack_client_id}") @log.error("-> signature: "+ Base64.encode64(signature)) @log.error("-> pubkey: #{pubkey}") end raise e end end
decodeCypher(encoded_payload, key, iv)
click to toggle source
# File lib/vchain_client/crypto.rb, line 152 def decodeCypher(encoded_payload, key, iv) cifd = OpenSSL::Cipher.new('AES-256-CTR') cifd.decrypt cifd.key = key cifd.iv = iv decoded = '' decoded << cifd.update(encoded_payload) decoded << cifd.final return decoded end
decodeRSA(encoded_data)
click to toggle source
# File lib/vchain_client/crypto.rb, line 68 def decodeRSA(encoded_data) priv_key_path = @config["rsa_private_key_location"] if @log.debug? @log.debug("[Crypto.decodeRSA] input:") @log.debug("-> key path: #{priv_key_path}") @log.debug("-> input:") @log.debug(encoded_data) end if @@rsa_private_key == nil begin @@rsa_private_key = File.read(priv_key_path) rescue => e if @log.error? @log.error("[Crypto.decodeRSA] File.read raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("--> priv_key_path: #{priv_key_path}") @log.error("-> input:") @log.error(encoded_data) end raise e end if @log.debug? @log.debug("[Crypto.decodeRSA] priv key is loaded") end end if @@rsa_private_key == nil if @log.error? @log.error("[Crypto.decodeRSA] failed to load private key") @log.error("--> priv_key_path: #{priv_key_path}") @log.error("-> input:") @log.error(encoded_data) end return nil end if @@ec_rsa_private == nil begin @@ec_rsa_private = OpenSSL::PKey::RSA.new(@@rsa_private_key) rescue => e if @log.error? @log.error("[Crypto.decodeRSA] OpenSSL::PKey::EC.new raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("--> priv_key_path: #{priv_key_path}") @log.error("-> input:") @log.error(encoded_data) end raise e end if @log.debug? @log.debug("[Crypto.decodeRSA] key initialized") end end if @@ec_rsa_private == nil if @log.error? @log.error("[Crypto.decodeRSA] failed init EC key") @log.error("--> priv_key_path: #{priv_key_path}") @log.error("-> input:") @log.error(encoded_data) end return nil end return @@ec_rsa_private.private_decrypt(encoded_data, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING) end
encodeCypher(document)
click to toggle source
# File lib/vchain_client/crypto.rb, line 168 def encodeCypher(document) cif = OpenSSL::Cipher.new('AES-256-CTR') cif.encrypt cif.key = key = cif.random_key cif.iv = iv = cif.random_iv out = { "payload" => (cif.update(document) + cif.final), "key" => key, "iv" => iv } return out end
encodeRSA(payload)
click to toggle source
# File lib/vchain_client/crypto.rb, line 62 def encodeRSA(payload) vchain_public_key = self.getVChainPublicKeyRSA() return vchain_public_key.public_encrypt(payload, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING) end
getVChainPublicKeyRSA()
click to toggle source
# File lib/vchain_client/crypto.rb, line 22 def getVChainPublicKeyRSA() if @@vchain_rsa_public_key != nil return @@vchain_rsa_public_key end blockstackClient = VChainClient::BlockstackClient.new(@config) vchain_public_key_body = nil begin vchain_public_key_body = blockstackClient.getPublicKeyRSA("vchain_core_01.id") rescue => e if @log.error? @log.error("[check] failed to retrieve vchain public RSA key from Blockstack") @log.error("#{e.class}, #{e.message}") end raise e end if vchain_public_key_body == nil if @log.error? @log.error("[check] failed to retrieve vchain public RSA key from Blockstack") end return false end vchain_public_key_str = "-----BEGIN PUBLIC KEY-----\n" vchain_public_key_str += vchain_public_key_body vchain_public_key_str += "\n-----END PUBLIC KEY-----" @@vchain_rsa_public_key = OpenSSL::PKey::RSA.new(vchain_public_key_str) return @@vchain_rsa_public_key end
signBatchRequest(batch, timestamp)
click to toggle source
# File lib/vchain_client/crypto.rb, line 185 def signBatchRequest(batch, timestamp) OpenSSL::PKey::EC.send(:alias_method, :private?, :private_key?) priv_key_path = @config["ecc_private_key_location"] if @log.debug? @log.debug("[Crypto.signBatchRequest] input:") @log.debug("-> timestamp: "+ timestamp.to_s) @log.debug("-> key path: #{priv_key_path}") @log.debug("-> input:") @log.debug(batch) end if @@ecc_private_key == nil begin @@ecc_private_key = File.read(priv_key_path) rescue => e if @log.error? @log.error("[Crypto.signBatchRequest] File.read raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> timestamp: "+ timestamp.to_s) @log.error("--> priv_key_path: #{priv_key_path}") @log.error("-> input:") @log.error(batch) end raise e end if @log.debug? @log.debug("[Crypto.signBatchRequest] priv key is loaded") end end if @@ecc_private_key == nil if @log.error? @log.error("[Crypto.signBatchRequest] failed to load private key") @log.error("-> timestamp: "+ timestamp.to_s) @log.error("--> priv_key_path: #{priv_key_path}") @log.error("-> input:") @log.error(batch) end return nil end if @@ec_ecc_private == nil begin @@ec_ecc_private = OpenSSL::PKey::EC.new(@@ecc_private_key) rescue => e if @log.error? @log.error("[Crypto.signBatchRequest] OpenSSL::PKey::EC.new raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> timestamp: "+ timestamp.to_s) @log.error("--> priv_key_path: #{priv_key_path}") @log.error("-> input:") @log.error(batch) end raise e end if @log.debug? @log.debug("[Crypto.signBatchRequest] key initialized") end end if @@ec_ecc_private == nil if @log.error? @log.error("[Crypto.signBatchRequest] failed init EC key") @log.error("-> timestamp: "+ timestamp.to_s) @log.error("--> priv_key_path: #{priv_key_path}") @log.error("-> input:") @log.error(batch) end return nil end digest = OpenSSL::Digest::SHA256.new whole_sign = "" batch.each { |batch_element| whole_sign += batch_element["data"].to_json whole_sign += batch_element["point_type"] whole_sign += batch_element["weight"].to_s whole_sign += timestamp.to_s } if @log.debug? @log.debug("[Crypto.signBatchRequest] whole_to_sign: "+ whole_sign) end whole_signature = nil begin whole_signature = @@ec_ecc_private.sign(digest, whole_sign) rescue => e if @log.error? @log.error("[Crypto.signBatchRequest] ec.sign raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> timestamp: "+ timestamp.to_s) @log.error("--> priv_key_path: #{priv_key_path}") @log.error("--> whole_sign: #{whole_sign}") @log.error("-> input:") @log.error(batch) end raise e end if whole_signature == nil if @log.error? @log.error("[Crypto.signBatchRequest] failed to sign") @log.error("-> timestamp: "+ timestamp.to_s) @log.error("--> priv_key_path: #{priv_key_path}") @log.error("--> whole_sign: #{whole_sign}") @log.error("-> input:") @log.error(batch) end return nil end if @log.debug? @log.debug("[Crypto.signBatchRequest] whole_signature raw: "+ Base64.encode64(whole_signature)) end return Base64.encode64(whole_signature).gsub(/\n/, "") end
signDataPoint(point_type, data, doc_hash, credentials_hash, weight, timestamp)
click to toggle source
# File lib/vchain_client/crypto.rb, line 536 def signDataPoint(point_type, data, doc_hash, credentials_hash, weight, timestamp) OpenSSL::PKey::EC.send(:alias_method, :private?, :private_key?) this_client_id = @config["blockstack"]["client_id"] priv_key_path = @config["ecc_private_key_location"] if @log.debug? @log.debug("[Crypto.signDataPoint] input:") @log.debug("-> this_client_id: #{this_client_id}") @log.debug("-> doc_hash: #{doc_hash}") @log.debug("-> credentials_hash: #{credentials_hash}") @log.debug("-> weight: "+ weight.to_s) @log.debug("-> timestamp: "+ timestamp.to_s) @log.debug("-> point_type: #{point_type}") @log.debug("-> key path: #{priv_key_path}") @log.debug("-> data:") @log.debug(data) end if @@ecc_private_key == nil begin @@ecc_private_key = File.read(priv_key_path) rescue => e if @log.error? @log.error("[Crypto.signDataPoint] File.read raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> this_client_id: #{this_client_id}") @log.error("-> doc_hash: #{doc_hash}") @log.error("-> credentials_hash: #{credentials_hash}") @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> point_type: #{point_type}") @log.error("-> key path: #{priv_key_path}") @log.error("-> data:") @log.error(data) end raise e end if @log.debug? @log.debug("[Crypto.signDataPoint] priv key loaded") end end if @@ecc_private_key == nil if @log.error? @log.error("[Crypto.signDataPoint] failed to load private key") @log.error("-> this_client_id: #{this_client_id}") @log.error("-> doc_hash: #{doc_hash}") @log.error("-> credentials_hash: #{credentials_hash}") @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> point_type: #{point_type}") @log.error("-> key path: #{priv_key_path}") @log.error("-> data:") @log.error(data) end return nil end if @@ec_ecc_private == nil begin @@ec_ecc_private = OpenSSL::PKey::EC.new(@@ecc_private_key) rescue => e if @log.error? @log.error("[Crypto.signDataPoint] OpenSSL::PKey::EC.new raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> this_client_id: #{this_client_id}") @log.error("-> doc_hash: #{doc_hash}") @log.error("-> credentials_hash: #{credentials_hash}") @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> point_type: #{point_type}") @log.error("-> key path: #{priv_key_path}") @log.error("-> data:") @log.error(data) @log.error("--> priv_key_path: #{priv_key_path}") end raise e end if @log.debug? @log.debug("[Crypto.signDataPoint] key created") end end if @@ec_ecc_private == nil if @log.error? @log.error("[Crypto.signDataPoint] failed init EC key") @log.error("-> this_client_id: #{this_client_id}") @log.error("-> doc_hash: #{doc_hash}") @log.error("-> credentials_hash: #{credentials_hash}") @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> point_type: #{point_type}") @log.error("-> key path: #{priv_key_path}") @log.error("-> data:") @log.error(data) @log.error("--> priv_key_path: #{priv_key_path}") end return nil end digest = OpenSSL::Digest::SHA256.new output = {} data.each{ |rec| field = rec[0] value = rec[1] if @log.debug? @log.debug("[Crypto.signDataPoint] field: #{field}, value: #{value}") end if field != 'client_id' field_hash = Digest::SHA512.hexdigest(field) value_hash = Digest::SHA512.hexdigest(value) what_to_sign = field_hash what_to_sign += value_hash what_to_sign += Digest::SHA512.hexdigest(doc_hash) what_to_sign += Digest::SHA512.hexdigest(credentials_hash) what_to_sign += point_type what_to_sign += weight.to_s what_to_sign += timestamp.to_s what_to_sign += this_client_id what_to_sign += VChainClient::Client::DATA_POINT_VERSION if @log.debug? @log.debug("[Crypto.signDataPoint] field_hash: #{field_hash}") @log.debug("[Crypto.signDataPoint] value_hash: #{value_hash}") end signature = nil begin signature = @@ec_ecc_private.sign(digest, what_to_sign) rescue => e if @log.error? @log.error("[Crypto.signDataPoint] ec.sign raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> this_client_id: #{this_client_id}") @log.error("-> doc_hash: #{doc_hash}") @log.error("-> credentials_hash: #{credentials_hash}") @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> point_type: #{point_type}") @log.error("-> key path: #{priv_key_path}") @log.error("-> data:") @log.error(data) @log.error("--> priv_key_path: #{priv_key_path}") @log.error("--> what_to_sign: #{what_to_sign}") end raise e end if signature == nil if @log.error? @log.error("[Crypto.signDataPoint] failed to sign") @log.error("-> this_client_id: #{this_client_id}") @log.error("-> doc_hash: #{doc_hash}") @log.error("-> credentials_hash: #{credentials_hash}") @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> point_type: #{point_type}") @log.error("-> key path: #{priv_key_path}") @log.error("-> data:") @log.error(data) @log.error("--> priv_key_path: #{priv_key_path}") @log.error("--> what_to_sign: #{what_to_sign}") end return nil end if @log.debug? @log.debug("[Crypto.signDataPoint] signature raw: "+ Base64.encode64(signature)) end output[field] = Base64.encode64(signature).gsub(/\n/, "") end } if @log.debug? @log.debug("[Crypto.signDataPoint] output:") @log.debug(output) end return output end
signRequest(document, point_type, weight, timestamp)
click to toggle source
# File lib/vchain_client/crypto.rb, line 327 def signRequest(document, point_type, weight, timestamp) OpenSSL::PKey::EC.send(:alias_method, :private?, :private_key?) priv_key_path = @config["ecc_private_key_location"] if @log.debug? @log.debug("[Crypto.signRequest] input:") @log.debug("-> point_type: "+ point_type) @log.debug("-> weight: "+ weight.to_s) @log.debug("-> timestamp: "+ timestamp.to_s) @log.debug("-> key path: #{priv_key_path}") @log.debug("-> input:") @log.debug(document) end if @@ecc_private_key == nil begin @@ecc_private_key = File.read(priv_key_path) rescue => e if @log.error? @log.error("[Crypto.signRequest] File.read raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> point_type: "+ point_type) @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> input:") @log.error(document) @log.error("--> priv_key_path: #{priv_key_path}") end raise e end if @log.debug? @log.debug("[Crypto.signRequest] priv key is loaded") end end if @@ecc_private_key == nil if @log.error? @log.error("[Crypto.signRequest] failed to load private key") @log.error("-> point_type: "+ point_type) @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> input:") @log.error(document) @log.error("--> priv_key_path: #{priv_key_path}") end return nil end if @@ec_ecc_private == nil begin @@ec_ecc_private = OpenSSL::PKey::EC.new(@@ecc_private_key) rescue => e if @log.error? @log.error("[Crypto.signRequest] OpenSSL::PKey::EC.new raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> point_type: "+ point_type) @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> input:") @log.error(document) @log.error("--> priv_key_path: #{priv_key_path}") end raise e end if @log.debug? @log.debug("[Crypto.signRequest] key initialized") end end if @@ec_ecc_private == nil if @log.error? @log.error("[Crypto.signRequest] failed init EC key") @log.error("-> point_type: "+ point_type) @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> input:") @log.error(document) @log.error("--> priv_key_path: #{priv_key_path}") end return nil end digest = OpenSSL::Digest::SHA256.new whole_sign = document.to_json + point_type + weight.to_s + timestamp.to_s if @log.debug? @log.debug("[Crypto.signRequest] whole_to_sign: "+ whole_sign) end whole_signature = nil begin whole_signature = @@ec_ecc_private.sign(digest, whole_sign) rescue => e if @log.error? @log.error("[Crypto.signRequest] ec.sign raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> point_type: "+ point_type) @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> input:") @log.error(document) @log.error("--> priv_key_path: #{priv_key_path}") @log.error("--> whole_sign: #{whole_sign}") end raise e end if whole_signature == nil if @log.error? @log.error("[Crypto.signRequest] failed to sign") @log.error("-> point_type: "+ point_type) @log.error("-> weight: "+ weight.to_s) @log.error("-> timestamp: "+ timestamp.to_s) @log.error("-> input:") @log.error(document) @log.error("--> priv_key_path: #{priv_key_path}") @log.error("--> whole_sign: #{whole_sign}") end return nil end if @log.debug? @log.debug("[Crypto.signRequest] whole_signature raw: "+ Base64.encode64(whole_signature)) end return Base64.encode64(whole_signature).gsub(/\n/, "") end
verifySignature(what_to_check, signature, public_key)
click to toggle source
# File lib/vchain_client/crypto.rb, line 477 def verifySignature(what_to_check, signature, public_key) pub_key = "-----BEGIN PUBLIC KEY-----\n" pub_key += public_key pub_key += "\n-----END PUBLIC KEY-----" ec = nil begin ec = OpenSSL::PKey::EC.new(pub_key) rescue => e if @log.error? @log.error("[Crypto.verifySignature] OpenSSL::PKey::EC.new raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> what_to_check: #{what_to_check}") @log.error("-> signature: "+ Base64.encode64(signature)) @log.error("-> public_key: "+ pub_key) @log.error(document) @log.error("--> pub_key: #{pub_key}") end raise e end if ec == nil if @log.error? @log.error("[Crypto.verifySignature] failed init EC key") @log.error("-> what_to_check: #{what_to_check}") @log.error("-> signature: "+ Base64.encode64(signature)) @log.error("-> public_key: "+ pub_key) @log.error("--> pub_key: #{pub_key}") end return false end digest = OpenSSL::Digest::SHA256.new begin return ec.verify(digest, signature, what_to_check) rescue => e if @log.error? @log.error("[Crypto.verifySignature] ec.verify raised exception:") @log.error("#{e.class}, #{e.message}") @log.error("-> what_to_check: #{what_to_check}") @log.error("-> signature: "+ Base64.encode64(signature)) @log.error("-> public_key: "+ pub_key) @log.error(document) @log.error("--> signature: "+ Base64.encode64(signature)) @log.error("--> what_to_check: #{what_to_check}") end raise e end end