vault-tree 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +26 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +43 -0
- data/LICENSE.txt +22 -0
- data/README.md +118 -0
- data/Rakefile +17 -0
- data/VagrantFile +30 -0
- data/features/core.feature +44 -0
- data/features/exceptions.feature +41 -0
- data/features/steps/core.steps.rb +168 -0
- data/features/steps/exceptions.steps.rb +103 -0
- data/features/support/env.rb +1 -0
- data/features/world.rb +3 -0
- data/lib/vault-tree.rb +7 -0
- data/lib/vault-tree/config/dependencies.rb +4 -0
- data/lib/vault-tree/config/lib.rb +2 -0
- data/lib/vault-tree/config/path_helpers.rb +49 -0
- data/lib/vault-tree/config/string.rb +25 -0
- data/lib/vault-tree/contract/close_validator.rb +35 -0
- data/lib/vault-tree/contract/contract.rb +85 -0
- data/lib/vault-tree/contract/contract_presenter.rb +27 -0
- data/lib/vault-tree/contract/doorman.rb +112 -0
- data/lib/vault-tree/contract/null_vault.rb +16 -0
- data/lib/vault-tree/contract/open_validator.rb +20 -0
- data/lib/vault-tree/contract/vault.rb +96 -0
- data/lib/vault-tree/exceptions/empty_vault.rb +8 -0
- data/lib/vault-tree/exceptions/fill_attempt_master_password.rb +6 -0
- data/lib/vault-tree/exceptions/invalid_signature.rb +0 -0
- data/lib/vault-tree/exceptions/malformed_json.rb +0 -0
- data/lib/vault-tree/exceptions/missing_external_data.rb +6 -0
- data/lib/vault-tree/exceptions/missing_partner_decryption_key.rb +6 -0
- data/lib/vault-tree/exceptions/missing_passphrase.rb +6 -0
- data/lib/vault-tree/exceptions/non_unique_vault_id.rb +0 -0
- data/lib/vault-tree/exceptions/unsupported_keyword.rb +6 -0
- data/lib/vault-tree/exceptions/vault_does_not_exist.rb +6 -0
- data/lib/vault-tree/exceptions/vault_tree_exception.rb +6 -0
- data/lib/vault-tree/keywords/decryption_key.rb +14 -0
- data/lib/vault-tree/keywords/external_data.rb +13 -0
- data/lib/vault-tree/keywords/keyword.rb +19 -0
- data/lib/vault-tree/keywords/keyword_interpreter.rb +45 -0
- data/lib/vault-tree/keywords/master_passphrase.rb +9 -0
- data/lib/vault-tree/keywords/public_encryption_key.rb +27 -0
- data/lib/vault-tree/keywords/random_number.rb +9 -0
- data/lib/vault-tree/keywords/shared_key.rb +24 -0
- data/lib/vault-tree/keywords/unlocked.rb +9 -0
- data/lib/vault-tree/keywords/vault_contents.rb +13 -0
- data/lib/vault-tree/lock_smith/asymmetric_cipher.rb +31 -0
- data/lib/vault-tree/lock_smith/crypto_hash.rb +11 -0
- data/lib/vault-tree/lock_smith/digital_signature.rb +32 -0
- data/lib/vault-tree/lock_smith/encryption_key_pair.rb +25 -0
- data/lib/vault-tree/lock_smith/null_vault.rb +4 -0
- data/lib/vault-tree/lock_smith/random_number.rb +11 -0
- data/lib/vault-tree/lock_smith/shared_key_pair.rb +12 -0
- data/lib/vault-tree/lock_smith/signing_key_pair.rb +25 -0
- data/lib/vault-tree/lock_smith/symmetric_cipher.rb +25 -0
- data/lib/vault-tree/util/json.rb +16 -0
- data/lib/vault-tree/version.rb +3 -0
- data/spec/app/locksmith/asymmetric_cipher_spec.rb +25 -0
- data/spec/app/locksmith/signing_key_pair_spec.rb +22 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/fixtures/blank_simple_test_contract.json +14 -0
- data/spec/support/fixtures/broken_contract.json +55 -0
- data/spec/support/fixtures/one_two_three-0.5.0.EXP.json +105 -0
- data/spec/support/fixtures/reference_contract.1.0.0.json +227 -0
- data/spec/support/fixtures/simple_test_contract.json +14 -0
- data/support/cookbooks/ark/.gitignore +12 -0
- data/support/cookbooks/ark/.kitchen.yml +34 -0
- data/support/cookbooks/ark/.travis.yml +6 -0
- data/support/cookbooks/ark/Berksfile +9 -0
- data/support/cookbooks/ark/CHANGELOG.md +87 -0
- data/support/cookbooks/ark/CONTRIBUTING.md +257 -0
- data/support/cookbooks/ark/README.md +301 -0
- data/support/cookbooks/ark/Rakefile +36 -0
- data/support/cookbooks/ark/TESTING.md +25 -0
- data/support/cookbooks/ark/Toftfile +15 -0
- data/support/cookbooks/ark/attributes/default.rb +6 -0
- data/support/cookbooks/ark/chefignore +96 -0
- data/support/cookbooks/ark/files/default/foo.tar.gz +0 -0
- data/support/cookbooks/ark/files/default/foo.tbz +0 -0
- data/support/cookbooks/ark/files/default/foo.tgz +0 -0
- data/support/cookbooks/ark/files/default/foo.zip +0 -0
- data/support/cookbooks/ark/files/default/tests/minitest/default_test.rb +0 -0
- data/support/cookbooks/ark/files/default/tests/minitest/support/helpers.rb +0 -0
- data/support/cookbooks/ark/files/default/tests/minitest/test_test.rb +94 -0
- data/support/cookbooks/ark/libraries/default.rb +167 -0
- data/support/cookbooks/ark/metadata.rb +13 -0
- data/support/cookbooks/ark/providers/default.rb +370 -0
- data/support/cookbooks/ark/recipes/default.rb +31 -0
- data/support/cookbooks/ark/recipes/test.rb +138 -0
- data/support/cookbooks/ark/resources/default.rb +54 -0
- data/support/cookbooks/ark/templates/default/add_to_path.sh.erb +1 -0
- data/support/cookbooks/ark/test/support/Gemfile +4 -0
- data/support/cookbooks/build-essential/README.md +24 -0
- data/support/cookbooks/build-essential/metadata.rb +10 -0
- data/support/cookbooks/build-essential/recipes/default.rb +45 -0
- data/support/cookbooks/chruby/.gitignore +15 -0
- data/support/cookbooks/chruby/.kitchen.yml +26 -0
- data/support/cookbooks/chruby/.ruby_version +1 -0
- data/support/cookbooks/chruby/Berksfile +3 -0
- data/support/cookbooks/chruby/Gemfile +7 -0
- data/support/cookbooks/chruby/LICENSE +14 -0
- data/support/cookbooks/chruby/README.md +92 -0
- data/support/cookbooks/chruby/Rakefile +7 -0
- data/support/cookbooks/chruby/Thorfile +6 -0
- data/support/cookbooks/chruby/Vagrantfile +86 -0
- data/support/cookbooks/chruby/attributes/default.rb +10 -0
- data/support/cookbooks/chruby/chefignore +96 -0
- data/support/cookbooks/chruby/metadata.rb +11 -0
- data/support/cookbooks/chruby/recipes/default.rb +43 -0
- data/support/cookbooks/chruby/recipes/system.rb +25 -0
- data/support/cookbooks/chruby/templates/default/chruby.sh.erb +22 -0
- data/support/cookbooks/chruby/test/integration/default/bash/embedded_test.sh +1 -0
- data/support/cookbooks/git/.gitignore +14 -0
- data/support/cookbooks/git/.kitchen.yml +46 -0
- data/support/cookbooks/git/Berksfile +8 -0
- data/support/cookbooks/git/CHANGELOG.md +87 -0
- data/support/cookbooks/git/CONTRIBUTING +29 -0
- data/support/cookbooks/git/Gemfile +3 -0
- data/support/cookbooks/git/LICENSE +201 -0
- data/support/cookbooks/git/README.md +115 -0
- data/support/cookbooks/git/TESTING.md +25 -0
- data/support/cookbooks/git/attributes/default.rb +40 -0
- data/support/cookbooks/git/metadata.rb +35 -0
- data/support/cookbooks/git/recipes/default.rb +53 -0
- data/support/cookbooks/git/recipes/server.rb +58 -0
- data/support/cookbooks/git/recipes/source.rb +49 -0
- data/support/cookbooks/git/recipes/windows.rb +37 -0
- data/support/cookbooks/git/templates/default/git-xinetd.d.erb +10 -0
- data/support/cookbooks/git/templates/default/sv-git-daemon-log-run.erb +2 -0
- data/support/cookbooks/git/templates/default/sv-git-daemon-run.erb +3 -0
- data/support/cookbooks/install_ruby/README.md +3 -0
- data/support/cookbooks/install_ruby/metadata.rb +10 -0
- data/support/cookbooks/install_ruby/recipes/default.rb +14 -0
- data/support/cookbooks/ruby_build/.gitignore +6 -0
- data/support/cookbooks/ruby_build/.kitchen.yml +31 -0
- data/support/cookbooks/ruby_build/.travis.yml +4 -0
- data/support/cookbooks/ruby_build/Berksfile +10 -0
- data/support/cookbooks/ruby_build/CHANGELOG.md +72 -0
- data/support/cookbooks/ruby_build/Gemfile +14 -0
- data/support/cookbooks/ruby_build/README.md +338 -0
- data/support/cookbooks/ruby_build/Rakefile +21 -0
- data/support/cookbooks/ruby_build/attributes/default.rb +67 -0
- data/support/cookbooks/ruby_build/chefignore +53 -0
- data/support/cookbooks/ruby_build/libraries/ruby_build_recipe_helpers.rb +40 -0
- data/support/cookbooks/ruby_build/metadata.rb +18 -0
- data/support/cookbooks/ruby_build/providers/ruby.rb +88 -0
- data/support/cookbooks/ruby_build/recipes/default.rb +69 -0
- data/support/cookbooks/ruby_build/resources/ruby.rb +33 -0
- data/support/cookbooks/ruby_build/test/cookbooks/alltherubies/metadata.rb +10 -0
- data/support/cookbooks/ruby_build/test/cookbooks/alltherubies/recipes/default.rb +59 -0
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/_verify_tests.bash +33 -0
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_1.8.7.bats +29 -0
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_1.9.2.bats +18 -0
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_1.9.3.bats +18 -0
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_2.0.0.bats +18 -0
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_jruby.bats +20 -0
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_rbx.bats +18 -0
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_ree.bats +19 -0
- data/support/cookbooks/ruby_build/test/integration/installation/bats/installation.bats +6 -0
- data/support/scripts/libsodium_ubuntu.sh +80 -0
- data/support/tasks/.gitkeep +0 -0
- data/support/tasks/libsodium_install.rb +57 -0
- data/vault-tree.gemspec +26 -0
- metadata +305 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Given(/^a valid blank contract$/) do
|
|
2
|
+
contract_path = VaultTree::PathHelpers.reference_contract
|
|
3
|
+
@contract_json = File.read(contract_path)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
When(/^I attempt fill a vault without providing a master passphrase$/) do
|
|
7
|
+
begin
|
|
8
|
+
@contract = VaultTree::Contract.new(@contract_json)
|
|
9
|
+
@contract = @contract.close_vault('alice_contract_secret')
|
|
10
|
+
rescue => e
|
|
11
|
+
@exception = e
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
Then(/^a MissingPassphrase exception is raised$/) do
|
|
16
|
+
@exception.should be_an_instance_of(VaultTree::Exceptions::MissingPassphrase)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
Given(/^the broken contract$/) do
|
|
20
|
+
contract_path = VaultTree::PathHelpers.broken_contract
|
|
21
|
+
@contract_json = File.read(contract_path)
|
|
22
|
+
@contract = VaultTree::Contract.new(@contract_json, master_passphrase: 'TEST_USER', external_data: {})
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
When(/^I attempt fill a vault with External Data that does not exists$/) do
|
|
26
|
+
begin
|
|
27
|
+
@contract = @contract.close_vault('missing_external_data_vault')
|
|
28
|
+
rescue => e
|
|
29
|
+
@exception = e
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
Then(/^a MissingExternalData exception is raised$/) do
|
|
34
|
+
@exception.should be_an_instance_of(VaultTree::Exceptions::MissingExternalData)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
When(/^I attempt fill a vault with my Master Password$/) do
|
|
38
|
+
begin
|
|
39
|
+
@contract = @contract.close_vault('fill_with_master_pass_vault')
|
|
40
|
+
rescue => e
|
|
41
|
+
@exception = e
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
Then(/^a FillAttemptMasterPassword exception is raised$/) do
|
|
46
|
+
@exception.should be_an_instance_of(VaultTree::Exceptions::FillAttemptMasterPassword)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
When(/^I attempt to open an empty vault$/) do
|
|
50
|
+
begin
|
|
51
|
+
@contents = @contract.retrieve_contents('empty_vault')
|
|
52
|
+
rescue => e
|
|
53
|
+
@exception = e
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
Then(/^an EmptyVault exception is raised$/) do
|
|
58
|
+
@exception.should be_an_instance_of(VaultTree::Exceptions::EmptyVault)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
When(/^I attempt to open a vault that does not exists$/) do
|
|
62
|
+
begin
|
|
63
|
+
@contents = @contract.retrieve_contents('non_existant_vault')
|
|
64
|
+
rescue => e
|
|
65
|
+
@exception = e
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
When(/^I attempt to close a vault that does not exists$/) do
|
|
70
|
+
begin
|
|
71
|
+
@contents = @contract.close_vault('non_existant_vault')
|
|
72
|
+
rescue => e
|
|
73
|
+
@exception = e
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
Then(/^a VaultDoesNotExist exception is raised$/) do
|
|
78
|
+
@exception.should be_an_instance_of(VaultTree::Exceptions::VaultDoesNotExist)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
When(/^I attempt fill a vault with an unsupported Keyword$/) do
|
|
82
|
+
begin
|
|
83
|
+
@contract = @contract.close_vault('unsupported_keyword')
|
|
84
|
+
rescue => e
|
|
85
|
+
@exception = e
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
Then(/^an UnsupportedKeyword exception is raised$/) do
|
|
90
|
+
@exception.should be_an_instance_of(VaultTree::Exceptions::UnsupportedKeyword)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
When(/^I attempt to fill with an encryption key without first establishing the decryption key$/) do
|
|
94
|
+
begin
|
|
95
|
+
@contract = @contract.close_vault('orphaned_public_key')
|
|
96
|
+
rescue => e
|
|
97
|
+
@exception = e
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
Then(/^a MissingPartnerDecryptionKey exception is raised$/) do
|
|
102
|
+
@exception.should be_an_instance_of(VaultTree::Exceptions::MissingPartnerDecryptionKey)
|
|
103
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require_relative '../../lib/vault-tree'
|
data/features/world.rb
ADDED
data/lib/vault-tree.rb
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# require_relative - Ruby > 1.9 method
|
|
2
|
+
# require_rel - 'gem require_all' helper method to require all relative
|
|
3
|
+
|
|
4
|
+
require_relative 'vault-tree/config/dependencies'
|
|
5
|
+
require_relative 'vault-tree/config/path_helpers'
|
|
6
|
+
require_relative 'vault-tree/config/string'
|
|
7
|
+
require_relative 'vault-tree/config/lib'
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module VaultTree
|
|
2
|
+
module PathHelpers
|
|
3
|
+
extend self
|
|
4
|
+
|
|
5
|
+
def current_dir
|
|
6
|
+
File.dirname(__FILE__)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def walk_to_root
|
|
10
|
+
'../../../'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def project_dir
|
|
14
|
+
File.expand_path(project_dir_rel)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def project_dir_rel
|
|
18
|
+
File.join(current_dir,walk_to_root)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def app_dir
|
|
22
|
+
lib_dir
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def lib_dir
|
|
26
|
+
"#{project_dir}/lib"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def fixtures_dir
|
|
30
|
+
"#{project_dir}/spec/support/fixtures"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def reference_contract
|
|
34
|
+
"#{fixtures_dir}/reference_contract.1.0.0.json"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def broken_contract
|
|
38
|
+
"#{fixtures_dir}/broken_contract.json"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def blank_simple_test_contract
|
|
42
|
+
"#{fixtures_dir}/blank_simple_test_contract.json"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def simple_test_contract
|
|
46
|
+
"#{fixtures_dir}/simple_test_contract.json"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class String
|
|
2
|
+
def compress
|
|
3
|
+
gsub("\n", '').squeeze(' ').strip
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def extract_ancestor_id
|
|
7
|
+
self.gsub(/(CONTENTS\[\')|(\'\])/,'').strip
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def checksum
|
|
11
|
+
Digest::SHA1.hexdigest(self)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def non_empty?
|
|
15
|
+
! self.empty?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def camelize
|
|
19
|
+
self.split("_").each {|s| s.capitalize! }.join("")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def has_ancestor?
|
|
23
|
+
self.include? 'CONTENTS'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module VaultTree
|
|
2
|
+
class CloseValidator
|
|
3
|
+
attr_reader :vault
|
|
4
|
+
|
|
5
|
+
def initialize(vault)
|
|
6
|
+
@vault = vault
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def validate!
|
|
10
|
+
confirm_valid_fill_keyword
|
|
11
|
+
validate_external_data
|
|
12
|
+
true
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def confirm_valid_fill_keyword
|
|
18
|
+
raise Exceptions::FillAttemptMasterPassword if vault.fill_with == 'MASTER_PASSPHRASE'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def validate_external_data
|
|
22
|
+
if external_data_required? && external_data_missing?
|
|
23
|
+
raise Exceptions::MissingExternalData
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def external_data_required?
|
|
28
|
+
vault.fill_with == 'EXTERNAL_DATA'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def external_data_missing?
|
|
32
|
+
vault.contract.external_data(vault.id).nil?
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module VaultTree
|
|
2
|
+
class Contract
|
|
3
|
+
attr_reader :json
|
|
4
|
+
|
|
5
|
+
def initialize(json, params = {})
|
|
6
|
+
@json = json
|
|
7
|
+
@master_passphrase = params[:master_passphrase]
|
|
8
|
+
@external_data = params[:external_data]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def close_vault(id)
|
|
12
|
+
validate_vault(id)
|
|
13
|
+
update_vaults vault(id).close
|
|
14
|
+
self
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def retrieve_contents(id)
|
|
18
|
+
validate_vault(id)
|
|
19
|
+
vault(id).retrieve_contents
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def vault_closed?(id)
|
|
23
|
+
non_empty_contents?(id)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def header
|
|
27
|
+
contract["header"]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def vaults
|
|
31
|
+
contract["vaults"]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def vault(id)
|
|
35
|
+
id.nil? ? NullVault.new : Vault.new(id, vaults[id], self)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def update_vaults(vault)
|
|
39
|
+
@contract["vaults"][vault.id] = vault.properties unless vault.kind_of?(NullVault)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def as_json
|
|
43
|
+
ContractPresenter.new(self).as_json
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def master_passphrase
|
|
47
|
+
validate_passphrase
|
|
48
|
+
@master_passphrase
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def external_data(id)
|
|
52
|
+
@external_data[id]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def passphrase_present?
|
|
58
|
+
!! @master_passphrase
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def valid_id?(id)
|
|
62
|
+
id.nil? || vaults.include?(id)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def non_empty_contents?(id)
|
|
66
|
+
! empty_contents?(id)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def empty_contents?(id)
|
|
70
|
+
vaults[id]['contents'].nil? || vaults[id]['contents'].empty?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def contract
|
|
74
|
+
@contract ||= Support::JSON.decode(json)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def validate_vault(id)
|
|
78
|
+
raise Exceptions::VaultDoesNotExist unless valid_id?(id)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def validate_passphrase
|
|
82
|
+
raise Exceptions::MissingPassphrase unless passphrase_present?
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module VaultTree
|
|
2
|
+
class ContractPresenter
|
|
3
|
+
attr_reader :contract
|
|
4
|
+
|
|
5
|
+
def initialize(contract)
|
|
6
|
+
@contract = contract
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def as_json
|
|
10
|
+
JSON.pretty_generate(contract_hash)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def contract_hash
|
|
16
|
+
{header: contract_header, vaults: contract_vaults}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def contract_header
|
|
20
|
+
contract.header
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def contract_vaults
|
|
24
|
+
contract.vaults
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module VaultTree
|
|
2
|
+
class Vault
|
|
3
|
+
class Doorman
|
|
4
|
+
attr_reader :vault
|
|
5
|
+
|
|
6
|
+
def initialize(vault)
|
|
7
|
+
@vault = vault
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def locked_contents
|
|
11
|
+
CloseValidator.new(vault).validate!
|
|
12
|
+
already_locked? ? contents : ciphertext_contents
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def unlocked_contents
|
|
16
|
+
OpenValidator.new(vault).validate!
|
|
17
|
+
plaintext_contents
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def ciphertext_contents
|
|
23
|
+
shared_locking_key? ? asymmetric_ciphertext : symmetric_ciphertext
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def plaintext_contents
|
|
27
|
+
shared_unlocking_key? ? asymmetric_plaintext : symmetric_plaintext
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def asymmetric_ciphertext
|
|
31
|
+
asymmetric_cipher.encrypt(public_key: locking_public_key, secret_key: locking_secret_key, plain_text: filler)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def asymmetric_plaintext
|
|
35
|
+
asymmetric_cipher.decrypt(public_key: unlocking_public_key, secret_key: unlocking_secret_key, cipher_text: contents)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def symmetric_ciphertext
|
|
39
|
+
symmetric_cipher.encrypt(key: locking_key, plain_text: filler)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def symmetric_plaintext
|
|
43
|
+
symmetric_cipher.decrypt(key: unlocking_key, cipher_text: contents)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def locking_key
|
|
47
|
+
vault.locking_key
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def unlocking_key
|
|
51
|
+
vault.unlocking_key
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def locking_public_key
|
|
55
|
+
locking_key_pair.public_key
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def locking_secret_key
|
|
59
|
+
locking_key_pair.secret_key
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def unlocking_public_key
|
|
63
|
+
unlocking_key_pair.public_key
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def unlocking_secret_key
|
|
67
|
+
unlocking_key_pair.secret_key
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def locking_key_pair
|
|
71
|
+
vault.locking_key if shared_locking_key?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def unlocking_key_pair
|
|
75
|
+
vault.unlocking_key if shared_unlocking_key?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def empty?
|
|
79
|
+
vault.empty?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def already_locked?
|
|
83
|
+
! empty?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def filler
|
|
87
|
+
vault.filler
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def contents
|
|
91
|
+
vault.contents
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def shared_locking_key?
|
|
95
|
+
vault.lock_with =~ /SHARED_KEY/
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def shared_unlocking_key?
|
|
99
|
+
vault.unlock_with =~ /SHARED_KEY/
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def asymmetric_cipher
|
|
103
|
+
LockSmith::AsymmetricCipher.new
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def symmetric_cipher
|
|
107
|
+
LockSmith::SymmetricCipher.new
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|