Class: Keybox::Storage::Container
- Defined in:
- lib/keybox/storage/container.rb
Overview
The container of the Keybox records. The Container itself is a Keybox::Storage::Record with a few extra methods.
A instance of a Container is created with a passphrase and a path to a file. The passphrase can be anything that has a to_s method.
container = Keybox::Storage::Container.new("i love ruby", "/tmp/database.yml")
This will load from the given file with the given passphrase if the file exists, or it will initialize the container to accept records.
The records are held decrypted in memory, so keep that in mind if that is a concern.
Add Records
record = Keybox::Storage::Record.new
record.field1 = "data"
record.field2 = "some more data"
container << record
Delete Records
container.delete(record)
There is no ‘update’ record, just delete it and add it.
Find a record accepts a string and will look in all the records it contains for anything that matches it. It coerces strings into Regexp
so any regex can be used here too.
container.find("data")
Report if the container or any of its records have been modified:
container.modified?
Save the container to its default location:
container.save
Or to some other location
container.save("/some/other/path.yml")
Direct access to the decrypted records is also available through the records
accessor.
container.records #=> Array of Keybox::Storage::Record
Constant Summary collapse
- ITERATIONS =
2048
- MINIMUM_PHRASE_LENGTH =
4
Constants inherited from Record
Instance Attribute Summary collapse
-
#records ⇒ Object
readonly
Returns the value of attribute records.
Attributes inherited from Record
#creation_time, #data_members, #last_access_time, #modification_time, #uuid
Instance Method Summary collapse
-
#<<(obj) ⇒ Object
Add a record to the system.
-
#calculated_key(passphrase = @passphrase) ⇒ Object
calculate the encryption key from the initial passphrase.
-
#calculated_key_digest(passphrase) ⇒ Object
calculate the key digest of the encryption key.
-
#delete(obj) ⇒ Object
Delete a record from the system, we force a modified flag here since the underlying Record wasn’t ‘assigned to’ we have to force modification notification.
-
#find(search_string, restricted_to = nil) ⇒ Object
Search all the records in the database finding any that match the search string passed in.
-
#find_by_url(url) ⇒ Object
Search only records that have a
url
field. -
#initialize(passphrase, path) ⇒ Container
constructor
A new instance of Container.
-
#length ⇒ Object
The number of Records in the Container.
-
#load_from_file ⇒ Object
load from file, if this is successful then replace the existing member fields on this instance with the data from the file.
-
#modified? ⇒ Boolean
See if we are modified, or if any of the records are modified.
-
#passphrase=(new_passphrase) ⇒ Object
Change the master password of the container.
-
#save(path = @path) ⇒ Object
save the current container to a file.
-
#size ⇒ Object
The number of Records in the Container.
Methods inherited from Record
#==, #data_member_names, #eql?, #method_missing, #modified=, #to_yaml_properties
Constructor Details
#initialize(passphrase, path) ⇒ Container
Returns a new instance of Container.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/keybox/storage/container.rb', line 73 def initialize(passphrase,path) super() @path = path @passphrase = passphrase @records = [] if not load_from_file then strength_check(@passphrase) self.version = Keybox::VERSION self.key_calc_iterations = ITERATIONS self.key_digest_salt = Keybox::RandomDevice.random_bytes(32) self.key_digest_algorithm = Keybox::Digest::DEFAULT_ALGORITHM self.key_digest = calculated_key_digest(passphrase) self.records_init_vector = Keybox::RandomDevice.random_bytes(16) self.records_cipher_algorithm = Keybox::Cipher::DEFAULT_ALGORITHM self.records_encrypted_data = "" self.records_digest_salt = Keybox::RandomDevice.random_bytes(32) self.records_digest_algorithm = Keybox::Digest::DEFAULT_ALGORITHM self.records_digest = "" end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Keybox::Storage::Record
Instance Attribute Details
#records ⇒ Object (readonly)
Returns the value of attribute records.
69 70 71 |
# File 'lib/keybox/storage/container.rb', line 69 def records @records end |
Instance Method Details
#<<(obj) ⇒ Object
Add a record to the system
170 171 172 173 174 175 |
# File 'lib/keybox/storage/container.rb', line 170 def <<(obj) if obj.respond_to?("needs_container_passphrase?") and obj.needs_container_passphrase? then obj.container_passphrase = @passphrase end @records << obj end |
#calculated_key(passphrase = @passphrase) ⇒ Object
calculate the encryption key from the initial passphrase
152 153 154 155 156 157 158 |
# File 'lib/keybox/storage/container.rb', line 152 def calculated_key(passphrase = @passphrase) key = self.key_digest_salt + passphrase self.key_calc_iterations.times do key = Keybox::Digest::CLASSES[self.key_digest_algorithm].digest(key) end return key end |
#calculated_key_digest(passphrase) ⇒ Object
calculate the key digest of the encryption key
163 164 165 |
# File 'lib/keybox/storage/container.rb', line 163 def calculated_key_digest(passphrase) Keybox::Digest::CLASSES[self.key_digest_algorithm].hexdigest(calculated_key(passphrase)) end |
#delete(obj) ⇒ Object
Delete a record from the system, we force a modified flag here since the underlying Record wasn’t ‘assigned to’ we have to force modification notification.
196 197 198 199 |
# File 'lib/keybox/storage/container.rb', line 196 def delete(obj) @records.delete(obj) @modified = true end |
#find(search_string, restricted_to = nil) ⇒ Object
Search all the records in the database finding any that match the search string passed in. The Search string is converted to a Regexp before beginning.
A list of restricted fields can also be passed in and the regexp will only be matched against those fields
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/keybox/storage/container.rb', line 216 def find(search_string,restricted_to = nil) case search_string when Regexp regex = Regexp.new(search_string.source,search_string. | Regexp::IGNORECASE) else regex = Regexp.new(search_string.to_s,Regexp::IGNORECASE) end matches = [] @records.each do |record| restricted_to = restricted_to || ( record.data_member_names - %w(password) ) record.data_members.each_pair do |k,v| if regex.match(v) and restricted_to.include?(k.to_s) then matches << record break end end end return matches end |
#find_by_url(url) ⇒ Object
Search only records that have a url
field
204 205 206 |
# File 'lib/keybox/storage/container.rb', line 204 def find_by_url(url) find(url,%w(url)) end |
#length ⇒ Object
The number of Records in the Container
180 181 182 |
# File 'lib/keybox/storage/container.rb', line 180 def length @records.size end |
#load_from_file ⇒ Object
load from file, if this is successful then replace the existing member fields on this instance with the data from the file
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/keybox/storage/container.rb', line 116 def load_from_file return false unless File.exists?(@path) return false unless tmp = YAML.load_file(@path) @creation_time = tmp.creation_time @modification_time = tmp.modification_time @last_access_time = tmp.last_access_time @data_members = tmp.data_members @uuid = tmp.uuid validate_passphrase decrypt_records validate_decryption load_records @modified = false true end |
#modified? ⇒ Boolean
See if we are modified, or if any of the records are modified
240 241 242 243 244 245 246 |
# File 'lib/keybox/storage/container.rb', line 240 def modified? return true if super @records.each do |record| return true if record.modified? end return false end |
#passphrase=(new_passphrase) ⇒ Object
Change the master password of the container
102 103 104 105 106 107 108 109 |
# File 'lib/keybox/storage/container.rb', line 102 def passphrase=(new_passphrase) strength_check(new_passphrase) @passphrase = new_passphrase self.key_digest_salt = Keybox::RandomDevice.random_bytes(32) self.key_digest = calculated_key_digest(new_passphrase) self.records_init_vector = Keybox::RandomDevice.random_bytes(16) self.records_digest_salt = Keybox::RandomDevice.random_bytes(32) end |
#save(path = @path) ⇒ Object
save the current container to a file
135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/keybox/storage/container.rb', line 135 def save(path = @path) calculate_records_digest encrypt_records File.open(path,"w") do |f| f.write(self.to_yaml) end # mark everything as not modified @records.each do |record| record.modified = false end @modified = false end |
#size ⇒ Object
The number of Records in the Container
187 188 189 |
# File 'lib/keybox/storage/container.rb', line 187 def size @records.size end |