Class: Aspera::Keychain::EncryptedHash
- Inherits:
-
Object
- Object
- Aspera::Keychain::EncryptedHash
- Defined in:
- lib/aspera/keychain/encrypted_hash.rb
Overview
Manage secrets in a simple Hash
Instance Method Summary collapse
- #delete(label:) ⇒ Object
- #get(label:, exception: true) ⇒ Object
-
#initialize(path, current_password) ⇒ EncryptedHash
constructor
A new instance of EncryptedHash.
- #list ⇒ Object
-
#password=(new_password) ⇒ Object
set the password and cipher.
-
#save ⇒ Object
save current data to file with format.
-
#set(options) ⇒ Object
set a secret.
Constructor Details
#initialize(path, current_password) ⇒ EncryptedHash
Returns a new instance of EncryptedHash.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/aspera/keychain/encrypted_hash.rb', line 20 def initialize(path, current_password) Aspera.assert_type(path, String){'path to vault file'} @path = path @all_secrets = {} @cipher_name = DEFAULT_CIPHER_NAME vault_encrypted_data = nil if File.exist?(@path) vault_file = File.read(@path) if vault_file.start_with?('---') vault_info = YAML.parse(vault_file).to_ruby Aspera.assert(vault_info.keys.sort == FILE_KEYS){'Invalid vault file'} @cipher_name = vault_info['cipher'] vault_encrypted_data = vault_info['data'] else # legacy vault file @cipher_name = LEGACY_CIPHER_NAME vault_encrypted_data = File.read(@path, mode: 'rb') end end # setting password also creates the cipher self.password = current_password if !vault_encrypted_data.nil? @all_secrets = YAML.load_stream(@cipher.decrypt(vault_encrypted_data)).first end end |
Instance Method Details
#delete(label:) ⇒ Object
93 94 95 96 |
# File 'lib/aspera/keychain/encrypted_hash.rb', line 93 def delete(label:) @all_secrets.delete(label) save end |
#get(label:, exception: true) ⇒ Object
98 99 100 101 102 103 |
# File 'lib/aspera/keychain/encrypted_hash.rb', line 98 def get(label:, exception: true) Aspera.assert(@all_secrets.key?(label)){"Label not found: #{label}"} if exception result = @all_secrets[label].clone result[:label] = label if result.is_a?(Hash) return result end |
#list ⇒ Object
82 83 84 85 86 87 88 89 90 91 |
# File 'lib/aspera/keychain/encrypted_hash.rb', line 82 def list result = [] @all_secrets.each do |label, values| normal = values.symbolize_keys normal[:label] = label CONTENT_KEYS.each{|k|normal[k] = '' unless normal.key?(k)} result.push(normal) end return result end |
#password=(new_password) ⇒ Object
set the password and cipher
47 48 49 50 51 52 53 54 |
# File 'lib/aspera/keychain/encrypted_hash.rb', line 47 def password=(new_password) # number of bits in second position key_bytes = DEFAULT_CIPHER_NAME.split('-')[1].to_i / Environment::BITS_PER_BYTE # derive key from passphrase, add trailing zeros key = "#{new_password}#{"\x0" * key_bytes}"[0..(key_bytes - 1)] Log.log.trace1{"secret=[#{key}],#{key.length}"} @cipher = SymmetricEncryption.cipher = SymmetricEncryption::Cipher.new(cipher_name: DEFAULT_CIPHER_NAME, key: key, encoding: :none) end |
#save ⇒ Object
save current data to file with format
57 58 59 60 61 62 63 64 65 |
# File 'lib/aspera/keychain/encrypted_hash.rb', line 57 def save vault_info = { 'version' => '1.0.0', 'type' => FILE_TYPE, 'cipher' => @cipher_name, 'data' => @cipher.encrypt(YAML.dump(@all_secrets)) } File.write(@path, YAML.dump(vault_info)) end |
#set(options) ⇒ Object
set a secret
69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/aspera/keychain/encrypted_hash.rb', line 69 def set() Aspera.assert_type(, Hash){'options'} unsupported = .keys - CONTENT_KEYS Aspera.assert(unsupported.empty?){"unsupported options: #{unsupported}"} .each_pair do |k, v| Aspera.assert_type(v, String){k.to_s} end label = .delete(:label) raise "secret #{label} already exist, delete first" if @all_secrets.key?(label) @all_secrets[label] = .symbolize_keys save end |