class OnePass::OpVault
Handle all the 1Password OpVault
operations
Constants
- DESIGNATION_TYPES
- FIELD_TYPES
Public Class Methods
new(vault_path)
click to toggle source
# File lib/OnePass/op_vault.rb, line 26 def initialize(vault_path) check_and_set_vault vault_path check_and_set_profile File.join(@vault_path, 'default', 'profile.js') @items = {} @item_index = {} end
Public Instance Methods
check_and_set_profile(profile_path)
click to toggle source
# File lib/OnePass/op_vault.rb, line 40 def check_and_set_profile(profile_path) unless File.exist? profile_path raise ArgumentError.new, 'Vault profile does not exist' end profile = File.read profile_path unless profile.start_with?('var profile=') && profile.end_with?(';') raise 'Vault profile format incorrect' end @profile = JSON.parse profile[12..-2] rescue raise 'Unable to parse vault profile' end
check_and_set_vault(vault_path)
click to toggle source
# File lib/OnePass/op_vault.rb, line 33 def check_and_set_vault(vault_path) @vault_path = File.expand_path(vault_path) unless File.exist? @vault_path raise ArgumentError.new, 'Vault file does not exist' end end
check_hmac(data, hmac_key, desired_hmac)
click to toggle source
# File lib/OnePass/op_vault.rb, line 75 def check_hmac(data, hmac_key, desired_hmac) digest = OpenSSL::Digest::SHA256.new computed_hmac = OpenSSL::HMAC.digest digest, hmac_key, data raise ArgumentError.new, 'Invalid HMAC' if computed_hmac != desired_hmac end
decrypt_data(key, iv, data)
click to toggle source
# File lib/OnePass/op_vault.rb, line 98 def decrypt_data(key, iv, data) cipher = OpenSSL::Cipher::AES256.new(:CBC).decrypt cipher.key = key cipher.iv = iv cipher.padding = 0 cipher.update(data) + cipher.final end
decrypt_keys(encrypted_key, derived_key, derived_mac_key)
click to toggle source
# File lib/OnePass/op_vault.rb, line 137 def decrypt_keys(encrypted_key, derived_key, derived_mac_key) key_base = decrypt_opdata encrypted_key, derived_key, derived_mac_key keys = OpenSSL::Digest::SHA512.new.digest key_base # => key, hmac [keys[0..31], keys[32..63]] end
decrypt_opdata(cipher_text, cipher_key, cipher_mac_key)
click to toggle source
# File lib/OnePass/op_vault.rb, line 106 def decrypt_opdata(cipher_text, cipher_key, cipher_mac_key) key_data = cipher_text[0..-33] mac_data = cipher_text[-32..-1] check_hmac key_data, cipher_mac_key, mac_data plaintext = decrypt_data cipher_key, key_data[16..31], key_data[32..-1] plaintext_size = key_data[8..15].unpack('Q')[0] plaintext[-plaintext_size..-1] end
derive_keys(master_password, salt, iterations)
click to toggle source
# File lib/OnePass/op_vault.rb, line 117 def derive_keys(master_password, salt, iterations) digest = OpenSSL::Digest::SHA512.new derived_key = OpenSSL::PKCS5.pbkdf2_hmac( master_password, salt, iterations, digest.digest_length, digest ) # => key, hmac [derived_key[0..31], derived_key[32..63]] end
find(search)
click to toggle source
# File lib/OnePass/op_vault.rb, line 94 def find(search) @items.values_at *@item_index.values_at(*@item_index.keys.grep(search)) end
item_detail(item)
click to toggle source
# File lib/OnePass/op_vault.rb, line 163 def item_detail(item) data = Base64.decode64(item['d']) item_key, item_mac_key = item_keys item detail = decrypt_opdata data, item_key, item_mac_key { 'uuid' => item['uuid'] }.merge JSON.parse detail end
item_keys(item)
click to toggle source
# File lib/OnePass/op_vault.rb, line 145 def item_keys(item) item_key = Base64.decode64 item['k'] key_data = item_key[0..-33] key_hmac = item_key[-32..-1] check_hmac key_data, @master_mac_key, key_hmac plaintext = decrypt_data @master_key, key_data[0..15], key_data[16..-1] # => key, hmac [plaintext[0..31], plaintext[32..63]] end
item_overview(item)
click to toggle source
# File lib/OnePass/op_vault.rb, line 157 def item_overview(item) data = Base64.decode64(item['o']) overview = decrypt_opdata data, @overview_key, @overview_mac_key { 'uuid' => item['uuid'] }.merge JSON.parse overview end
load_items()
click to toggle source
# File lib/OnePass/op_vault.rb, line 81 def load_items file_glob = File.join(@vault_path, 'default', 'band_*.js') Dir.glob(file_glob) do |file| band = JSON.parse File.read(file)[3..-3] @items.merge! band end @items.each_pair do |uuid, item| overview = item_overview item @item_index[overview['title']] = uuid end end
lock()
click to toggle source
# File lib/OnePass/op_vault.rb, line 71 def lock @master_key = @master_mac_key = nil end
master_keys(derived_key, derived_mac_key)
click to toggle source
# File lib/OnePass/op_vault.rb, line 127 def master_keys(derived_key, derived_mac_key) encrypted = Base64.decode64(@profile['masterKey']) decrypt_keys encrypted, derived_key, derived_mac_key end
overview_keys(derived_key, derived_mac_key)
click to toggle source
# File lib/OnePass/op_vault.rb, line 132 def overview_keys(derived_key, derived_mac_key) encrypted = Base64.decode64(@profile['overviewKey']) decrypt_keys encrypted, derived_key, derived_mac_key end
unlock(master_password = nil) { || ... }
click to toggle source
# File lib/OnePass/op_vault.rb, line 55 def unlock(master_password = nil) master_password = yield if block_given? salt = Base64.decode64(@profile['salt']) iterations = @profile['iterations'] key, mac_key = derive_keys master_password, salt, iterations @master_key, @master_mac_key = master_keys key, mac_key @overview_key, @overview_mac_key = overview_keys key, mac_key rescue raise 'Incorrect password' end
unlocked?()
click to toggle source
# File lib/OnePass/op_vault.rb, line 67 def unlocked? !!@master_key && !!@overview_key end