vault-tree 0.3.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/CHANGE_LOG.md +27 -0
- data/README.md +15 -73
- data/features/contracts/asymmetric_vault.feature +69 -2
- data/features/contracts/block_chain_key_transfer.feature +59 -0
- data/features/contracts/one_two_three.feature +109 -1
- data/features/contracts/readme.md +5 -6
- data/features/contracts_and_vaults.md +19 -24
- data/features/decision_tree.md +1 -1
- data/features/exceptions.feature +54 -43
- data/features/install_and_usage.md +38 -33
- data/features/keywords/assembled_shamir_key.feature +17 -17
- data/features/keywords/dh_key.feature +5 -5
- data/features/keywords/external_input.feature +35 -0
- data/features/keywords/external_key.feature +24 -0
- data/features/keywords/key.feature +3 -3
- data/features/keywords/random_number.feature +3 -3
- data/features/keywords/shamir_key_shares.feature +29 -0
- data/features/keywords/shamir_share.feature +40 -0
- data/features/keywords/split_key.feature +10 -9
- data/features/keywords/unlocked.feature +3 -3
- data/features/readme.md +1 -1
- data/features/steps/asymmetric_vault.steps.rb +14 -21
- data/features/steps/block_chain_key_transfer.steps.rb +17 -22
- data/features/steps/core.steps.rb +60 -71
- data/features/steps/exceptions.steps.rb +27 -64
- data/features/steps/external_input.steps.rb +17 -0
- data/features/steps/one_two_three.steps.rb +21 -27
- data/features/steps/secret_sharing.steps.rb +36 -19
- data/lib/vault-tree.rb +1 -1
- data/lib/vault-tree/contract/content_ciphertext.rb +33 -0
- data/lib/vault-tree/contract/content_plaintext.rb +33 -0
- data/lib/vault-tree/contract/contract.rb +15 -72
- data/lib/vault-tree/contract/contract_header.rb +11 -0
- data/lib/vault-tree/contract/vault.rb +24 -74
- data/lib/vault-tree/contract/vault_key.rb +21 -0
- data/lib/vault-tree/contract/vault_list.rb +56 -0
- data/lib/vault-tree/exceptions/empty_vault.rb +18 -3
- data/lib/vault-tree/exceptions/failed_lock_attempt.rb +18 -0
- data/lib/vault-tree/exceptions/failed_unlock_attempt.rb +23 -1
- data/lib/vault-tree/exceptions/invalid_external_input.rb +16 -0
- data/lib/vault-tree/exceptions/{missing_passphrase.rb → invalid_shamir_split.rb} +2 -1
- data/lib/vault-tree/exceptions/library_exception.rb +64 -0
- data/lib/vault-tree/exceptions/missing_partner_decryption_key.rb +11 -1
- data/lib/vault-tree/exceptions/unsupported_keyword.rb +17 -1
- data/lib/vault-tree/exceptions/vault_does_not_exist.rb +8 -1
- data/lib/vault-tree/keywords/assembled_shamir_key.rb +1 -1
- data/lib/vault-tree/keywords/contents.rb +1 -1
- data/lib/vault-tree/keywords/dh_key.rb +2 -2
- data/lib/vault-tree/keywords/external_input.rb +58 -0
- data/lib/vault-tree/keywords/external_key.rb +20 -0
- data/lib/vault-tree/keywords/key.rb +7 -1
- data/lib/vault-tree/keywords/keyword_interpreter.rb +5 -3
- data/lib/vault-tree/keywords/public_encryption_key.rb +1 -5
- data/lib/vault-tree/keywords/shamir_key_shares.rb +18 -0
- data/lib/vault-tree/keywords/shamir_share.rb +18 -0
- data/lib/vault-tree/keywords/split_key.rb +1 -1
- data/lib/vault-tree/lock_smith.rb +7 -8
- data/lib/vault-tree/lock_smith/{generated_shamir_key.rb → shamir_key_shares.rb} +22 -21
- data/lib/vault-tree/lock_smith/{split_key.rb → split_key_crypto.rb} +0 -0
- data/lib/vault-tree/version.rb +1 -1
- data/spec/assembled_shamir_key_spec.rb +0 -1
- data/spec/custom_exception_spec.rb +81 -0
- data/spec/lock_smith_spec.rb +0 -48
- data/spec/secret_sharing_spec.rb +0 -1
- data/spec/shamir_key_shares_spec.rb +27 -0
- data/vault-tree.gemspec +1 -1
- metadata +33 -139
- data/Gemfile.lock +0 -53
- data/VagrantFile +0 -30
- data/features/keywords/external_data.feature +0 -11
- data/features/keywords/generated_shamir_key.feature +0 -55
- data/features/keywords/master_passphrase.feature +0 -68
- data/features/manipulating_contracts.md +0 -84
- data/features/support/contract_fixtures/asymmetric_vault.0.1.0.json +0 -69
- data/features/support/contract_fixtures/blank_simple_test_contract.json +0 -14
- data/features/support/contract_fixtures/block_chain_key_transfer.0.1.0.json +0 -59
- data/features/support/contract_fixtures/broken_contract.json +0 -55
- data/features/support/contract_fixtures/one_two_three.0.7.0.json +0 -108
- data/features/support/contract_fixtures/simple_test_contract.json +0 -14
- data/features/support/contract_fixtures/template.json +0 -33
- data/lib/vault-tree/contract/close_validator.rb +0 -28
- data/lib/vault-tree/contract/doorman.rb +0 -113
- data/lib/vault-tree/contract/open_validator.rb +0 -20
- data/lib/vault-tree/exceptions/exception_template.erb +0 -0
- data/lib/vault-tree/exceptions/fill_attempt_master_password.rb +0 -6
- data/lib/vault-tree/exceptions/missing_external_data.rb +0 -6
- data/lib/vault-tree/exceptions/vault_tree_exception.rb +0 -25
- data/lib/vault-tree/keywords/external_data.rb +0 -32
- data/lib/vault-tree/keywords/generated_shamir_key.rb +0 -57
- data/lib/vault-tree/keywords/master_passphrase.rb +0 -9
- data/spec/generated_shamir_key_spec.rb +0 -52
- data/support/cookbooks/ark/.gitignore +0 -12
- data/support/cookbooks/ark/.kitchen.yml +0 -34
- data/support/cookbooks/ark/.travis.yml +0 -6
- data/support/cookbooks/ark/Berksfile +0 -9
- data/support/cookbooks/ark/CHANGELOG.md +0 -87
- data/support/cookbooks/ark/CONTRIBUTING.md +0 -257
- data/support/cookbooks/ark/README.md +0 -301
- data/support/cookbooks/ark/Rakefile +0 -36
- data/support/cookbooks/ark/TESTING.md +0 -25
- data/support/cookbooks/ark/Toftfile +0 -15
- data/support/cookbooks/ark/attributes/default.rb +0 -6
- data/support/cookbooks/ark/chefignore +0 -96
- 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 +0 -94
- data/support/cookbooks/ark/libraries/default.rb +0 -167
- data/support/cookbooks/ark/metadata.rb +0 -13
- data/support/cookbooks/ark/providers/default.rb +0 -370
- data/support/cookbooks/ark/recipes/default.rb +0 -31
- data/support/cookbooks/ark/recipes/test.rb +0 -138
- data/support/cookbooks/ark/resources/default.rb +0 -54
- data/support/cookbooks/ark/templates/default/add_to_path.sh.erb +0 -1
- data/support/cookbooks/ark/test/support/Gemfile +0 -4
- data/support/cookbooks/build-essential/README.md +0 -24
- data/support/cookbooks/build-essential/metadata.rb +0 -10
- data/support/cookbooks/build-essential/recipes/default.rb +0 -45
- data/support/cookbooks/chruby/.gitignore +0 -15
- data/support/cookbooks/chruby/.kitchen.yml +0 -26
- data/support/cookbooks/chruby/.ruby_version +0 -1
- data/support/cookbooks/chruby/Berksfile +0 -3
- data/support/cookbooks/chruby/Gemfile +0 -7
- data/support/cookbooks/chruby/LICENSE +0 -14
- data/support/cookbooks/chruby/README.md +0 -92
- data/support/cookbooks/chruby/Rakefile +0 -7
- data/support/cookbooks/chruby/Thorfile +0 -6
- data/support/cookbooks/chruby/Vagrantfile +0 -86
- data/support/cookbooks/chruby/attributes/default.rb +0 -10
- data/support/cookbooks/chruby/chefignore +0 -96
- data/support/cookbooks/chruby/metadata.rb +0 -11
- data/support/cookbooks/chruby/recipes/default.rb +0 -43
- data/support/cookbooks/chruby/recipes/system.rb +0 -25
- data/support/cookbooks/chruby/templates/default/chruby.sh.erb +0 -22
- data/support/cookbooks/chruby/test/integration/default/bash/embedded_test.sh +0 -1
- data/support/cookbooks/git/.gitignore +0 -14
- data/support/cookbooks/git/.kitchen.yml +0 -46
- data/support/cookbooks/git/Berksfile +0 -8
- data/support/cookbooks/git/CHANGELOG.md +0 -87
- data/support/cookbooks/git/CONTRIBUTING +0 -29
- data/support/cookbooks/git/Gemfile +0 -3
- data/support/cookbooks/git/LICENSE +0 -201
- data/support/cookbooks/git/README.md +0 -115
- data/support/cookbooks/git/TESTING.md +0 -25
- data/support/cookbooks/git/attributes/default.rb +0 -40
- data/support/cookbooks/git/metadata.rb +0 -35
- data/support/cookbooks/git/recipes/default.rb +0 -53
- data/support/cookbooks/git/recipes/server.rb +0 -58
- data/support/cookbooks/git/recipes/source.rb +0 -49
- data/support/cookbooks/git/recipes/windows.rb +0 -37
- data/support/cookbooks/git/templates/default/git-xinetd.d.erb +0 -10
- data/support/cookbooks/git/templates/default/sv-git-daemon-log-run.erb +0 -2
- data/support/cookbooks/git/templates/default/sv-git-daemon-run.erb +0 -3
- data/support/cookbooks/install_ruby/README.md +0 -3
- data/support/cookbooks/install_ruby/metadata.rb +0 -10
- data/support/cookbooks/install_ruby/recipes/default.rb +0 -14
- data/support/cookbooks/ruby_build/.gitignore +0 -6
- data/support/cookbooks/ruby_build/.kitchen.yml +0 -31
- data/support/cookbooks/ruby_build/.travis.yml +0 -4
- data/support/cookbooks/ruby_build/Berksfile +0 -10
- data/support/cookbooks/ruby_build/CHANGELOG.md +0 -72
- data/support/cookbooks/ruby_build/Gemfile +0 -14
- data/support/cookbooks/ruby_build/README.md +0 -338
- data/support/cookbooks/ruby_build/Rakefile +0 -21
- data/support/cookbooks/ruby_build/attributes/default.rb +0 -67
- data/support/cookbooks/ruby_build/chefignore +0 -53
- data/support/cookbooks/ruby_build/libraries/ruby_build_recipe_helpers.rb +0 -40
- data/support/cookbooks/ruby_build/metadata.rb +0 -18
- data/support/cookbooks/ruby_build/providers/ruby.rb +0 -88
- data/support/cookbooks/ruby_build/recipes/default.rb +0 -69
- data/support/cookbooks/ruby_build/resources/ruby.rb +0 -33
- data/support/cookbooks/ruby_build/test/cookbooks/alltherubies/metadata.rb +0 -10
- data/support/cookbooks/ruby_build/test/cookbooks/alltherubies/recipes/default.rb +0 -59
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/_verify_tests.bash +0 -33
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_1.8.7.bats +0 -29
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_1.9.2.bats +0 -18
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_1.9.3.bats +0 -18
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_2.0.0.bats +0 -18
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_jruby.bats +0 -20
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_rbx.bats +0 -18
- data/support/cookbooks/ruby_build/test/integration/alltherubies/bats/verify_ree.bats +0 -19
- data/support/cookbooks/ruby_build/test/integration/installation/bats/installation.bats +0 -6
- data/support/scripts/libsodium_ubuntu.sh +0 -80
- data/support/tasks/.gitkeep +0 -0
- data/support/tasks/libsodium_install.rb +0 -57
@@ -4,9 +4,7 @@ Now that we've explored the ideas of a **Contract**, **Contract Enforcement**, a
|
|
4
4
|
|
5
5
|
#### Vaults
|
6
6
|
|
7
|
-
Vault Tree Contracts are made by assembling simple structures called **Vaults**.
|
8
|
-
|
9
|
-
A vault is like a digital lock box that stores a single unambiguous piece of information. This piece of information is needed to continue the execution of a contract beyond a certain event.
|
7
|
+
Vault Tree Contracts are made by assembling simple structures called **Vaults**. A vault is like a digital lock box that stores a single unambiguous piece of information.
|
10
8
|
|
11
9
|
The light bulb should turn on when you realize that vaults can hold not only valuable external information, but the **keys to other vaults**.
|
12
10
|
|
@@ -21,6 +19,10 @@ benefit of being a **Distributed Cryptographic Contract**. This means:
|
|
21
19
|
* Each Vault encrypts a piece of secret information. This can be external
|
22
20
|
information such as a _URL_ or a _Bitcoin Wallet Address_. More often, a vault will contain the unlocking key to another vault in the contract.
|
23
21
|
* The way in which the contract author **chooses to structure** the releationship between vaults, will determine how the contract is **Enforced**.
|
22
|
+
* It is the responsibility of the contract author to arrange vaults so that there are no contract [moral hazards] or [perverse incentives].
|
23
|
+
|
24
|
+
[moral hazards]: http://en.wikipedia.org/wiki/Moral_hazard
|
25
|
+
[perverse incentives]: http://en.wikipedia.org/wiki/Perverse_incentive
|
24
26
|
|
25
27
|
#### Complete Contracts
|
26
28
|
|
@@ -50,34 +52,29 @@ arranged to enforce the terms of the contract.
|
|
50
52
|
Let's take a look at an example vault:
|
51
53
|
|
52
54
|
```javascript
|
53
|
-
"
|
55
|
+
"bob_random_key": {
|
54
56
|
"fill_with": "RANDOM_NUMBER",
|
55
|
-
"lock_with": "KEY['
|
56
|
-
"unlock_with": "KEY['
|
57
|
-
"contents": "
|
57
|
+
"lock_with": "KEY['bob_first_vault_key']",
|
58
|
+
"unlock_with": "KEY['alice_third_vault_key']",
|
59
|
+
"contents": "dc92c330e5f911e3ac100800200c9a6648ab522cf91739ade ... "
|
58
60
|
}
|
59
61
|
```
|
60
62
|
|
61
|
-
It's important to keep in mind that, **every** vault follows this format. This
|
63
|
+
It's important to keep in mind that, **every** vault follows this format. This
|
64
|
+
convention for representing a vault should be sufficient to build any type of
|
65
|
+
simple or sophisticated contract.
|
62
66
|
|
63
67
|
#### Vault Id
|
64
68
|
|
65
|
-
The **Vault Id** can be thought of as both the name and the **
|
69
|
+
The **Vault Id** can be thought of as both the name and the **unique** identifier of the vault.
|
66
70
|
|
67
71
|
In this case we have:
|
68
72
|
|
69
73
|
```
|
70
|
-
"
|
74
|
+
"bob_random_key"
|
71
75
|
```
|
72
76
|
|
73
|
-
Try to give meaningful names that give insight into the locked contents held within the vault.
|
74
|
-
|
75
|
-
A vault owner is the contract party that is responsibily for filling and locking the vault. In this simple case we have **bob**, but in an employment contract for example, we may have vault owners named **employer** and **employee**.
|
76
|
-
|
77
|
-
It is the responsibility of the contract author to assign vault owners in such a way that there are no contract [moral hazards] or [perverse incentives].
|
78
|
-
|
79
|
-
[moral hazards]: http://en.wikipedia.org/wiki/Moral_hazard
|
80
|
-
[perverse incentives]: http://en.wikipedia.org/wiki/Perverse_incentive
|
77
|
+
Try to give meaningful names that give insight into the locked contents held within the vault.
|
81
78
|
|
82
79
|
#### Fill With
|
83
80
|
|
@@ -103,25 +100,23 @@ The **unlock_with** field naturally identifies the source of the vault's **Unloc
|
|
103
100
|
|
104
101
|
It may not be obvious, but the reference to the Unlocking key does not necessarily need to be the same as the reference to the **Locking Key**. Here are some examples of where this could be the case:
|
105
102
|
|
106
|
-
* The same key is used to lock and unlock the vault, but copies of this key are
|
107
|
-
* held in two separate vaults. Take a look at the **Block Chain Key Transfer**
|
108
|
-
* contract to see a good example of this.
|
103
|
+
* The same key is used to lock and unlock the vault, but copies of this key are held in two separate vaults. Take a look at the **Block Chain Key Transfer** contract to see a good example of this.
|
109
104
|
* Vault Tree supports the notion of an **Asymmetric Vault** through the _DSL Keyword_
|
110
105
|
|
111
106
|
```
|
112
107
|
DH_KEY
|
113
108
|
```
|
114
109
|
|
115
|
-
An Asymmetric Vault is locked and unlocked with the help of a [Public-Private](http://en.wikipedia.org/wiki/Public-key_cryptography) keypair. Vault Tree's underlying cryptographic library makes this possible by implementing a cutting edge variant of the [ECDH] key exchange protocol.
|
110
|
+
An Asymmetric Vault is locked and unlocked with the help of a [Public-Private](http://en.wikipedia.org/wiki/Public-key_cryptography) keypair. Vault Tree's underlying cryptographic library makes this possible by implementing a cutting edge variant of the [ECDH] key exchange protocol.
|
116
111
|
|
117
112
|
[ECDH]: http://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman
|
118
113
|
|
119
114
|
#### Contents
|
120
115
|
|
121
|
-
As you would expect, this field references the encrypted contents of the vault. In the example above you can see the
|
116
|
+
As you would expect, this field references the encrypted contents of the vault. In the example above you can see the _Hex_ encoded ciphertext:
|
122
117
|
|
123
118
|
```
|
124
|
-
"contents": "
|
119
|
+
"contents": "dc92c330e5f911e3ac100800200c9a6648ab522cf91739ade ... "
|
125
120
|
```
|
126
121
|
Here are some items to keep in mind:
|
127
122
|
|
data/features/decision_tree.md
CHANGED
@@ -7,7 +7,7 @@ Contracts can be modeled as a [Decision Tree]. Intuitively this means that:
|
|
7
7
|
* **Events** are represented as nodes in the graph, **Outcomes** are events that correspond to [Leaf Nodes].
|
8
8
|
* Once a contract has been **Negotiated**, contract execution proceeds down the graph beginning at the [Root Node].
|
9
9
|
* Edges in the graph correspond to real world conditions that must be met before making a valid trasition between two events.
|
10
|
-
* **Well Written** contracts
|
10
|
+
* **Well Written** contracts correspond to well structured graphs.
|
11
11
|
|
12
12
|
[Directed Graph]: http://en.wikipedia.org/wiki/Directed_graph
|
13
13
|
[Tree]: http://en.wikipedia.org/wiki/Tree_%28graph_theory%29
|
data/features/exceptions.feature
CHANGED
@@ -1,28 +1,23 @@
|
|
1
1
|
Feature: Vault Tree Exceptions
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
Then an EmptyVault exception is raised
|
3
|
+
The library trys to anticipate common usage errors. A
|
4
|
+
custom error with a helpful message should be raised if there
|
5
|
+
is a problem with you contract.
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
Then a FillAttemptMasterPassword exception is raised
|
7
|
+
If you do run across an unexpected ruby runtime error, please
|
8
|
+
file a Github issue. I want to make the experience of executing
|
9
|
+
and debugging your own contracts as painless as possible.
|
12
10
|
|
13
|
-
|
14
|
-
Given the broken contract
|
15
|
-
When I attempt fill a vault with External Data that does not exists
|
16
|
-
Then a MissingExternalData exception is raised
|
11
|
+
Thanks!
|
17
12
|
|
18
|
-
Scenario:
|
13
|
+
Scenario: Unsupported Keyword
|
19
14
|
Given this broken contract:
|
20
15
|
"""javascript
|
21
16
|
{
|
22
17
|
"header": {},
|
23
18
|
"vaults": {
|
24
|
-
"
|
25
|
-
"fill_with": "
|
19
|
+
"unsupported_keyword":{
|
20
|
+
"fill_with": "UNSUPPORTED_KEYWORD",
|
26
21
|
"lock_with": "UNLOCKED",
|
27
22
|
"unlock_with": "UNLOCKED",
|
28
23
|
"contents": ""
|
@@ -30,63 +25,79 @@ Scenario: Missing External Data On Lock
|
|
30
25
|
}
|
31
26
|
}
|
32
27
|
"""
|
33
|
-
When I attempt
|
34
|
-
Then
|
28
|
+
When I attempt fill a vault with an unsupported Keyword
|
29
|
+
Then an UnsupportedKeyword exception is raised
|
35
30
|
|
36
|
-
Scenario:
|
31
|
+
Scenario: Vault Does Not Exists on Retrieval
|
37
32
|
Given this broken contract:
|
38
33
|
"""javascript
|
39
34
|
{
|
40
35
|
"header": {},
|
41
36
|
"vaults": {
|
42
|
-
|
43
|
-
|
37
|
+
|
38
|
+
"empty_vault":{
|
44
39
|
"fill_with": "RANDOM_NUMBER",
|
45
|
-
"lock_with": "
|
46
|
-
"unlock_with": "
|
40
|
+
"lock_with": "UNLOCKED",
|
41
|
+
"unlock_with": "UNLOCKED",
|
47
42
|
"contents": ""
|
48
43
|
}
|
49
44
|
}
|
50
45
|
}
|
51
46
|
"""
|
52
|
-
When I lock the data away
|
53
|
-
And I attempt to unlock a vault with External Data that does not exists
|
54
|
-
Then a MissingExternalData exception is raised
|
55
|
-
|
56
|
-
Scenario: Unsupported Keyword
|
57
|
-
Given the broken contract
|
58
|
-
When I attempt fill a vault with an unsupported Keyword
|
59
|
-
Then an UnsupportedKeyword exception is raised
|
60
|
-
|
61
|
-
Scenario: Vault Does Not Exists on Retrieval
|
62
|
-
Given the broken contract
|
63
47
|
When I attempt to open a vault that does not exists
|
64
48
|
Then a VaultDoesNotExist exception is raised
|
65
49
|
|
66
50
|
Scenario: Vault Does Not Exists on Closing
|
67
|
-
Given
|
51
|
+
Given this broken contract:
|
52
|
+
"""javascript
|
53
|
+
{
|
54
|
+
"header": {},
|
55
|
+
"vaults": {
|
56
|
+
|
57
|
+
"empty_vault":{
|
58
|
+
"fill_with": "RANDOM_NUMBER",
|
59
|
+
"lock_with": "UNLOCKED",
|
60
|
+
"unlock_with": "UNLOCKED",
|
61
|
+
"contents": ""
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
"""
|
68
66
|
When I attempt to close a vault that does not exists
|
69
67
|
Then a VaultDoesNotExist exception is raised
|
70
68
|
|
71
|
-
Scenario: Missing Partner Decryption Key
|
72
|
-
Given the broken contract
|
73
|
-
When I attempt to fill with an encryption key without first establishing the decryption key
|
74
|
-
Then a MissingPartnerDecryptionKey exception is raised
|
75
|
-
|
76
69
|
Scenario: Failed Symmetric Unlock Attempt
|
77
70
|
Given this broken contract:
|
78
71
|
"""javascript
|
79
72
|
{
|
80
73
|
"header": {},
|
81
74
|
"vaults": {
|
82
|
-
"
|
75
|
+
"some_random_vault":{
|
83
76
|
"fill_with": "RANDOM_NUMBER",
|
84
|
-
"lock_with": "
|
85
|
-
"unlock_with": "
|
77
|
+
"lock_with": "EXTERNAL_INPUT['right_secret']",
|
78
|
+
"unlock_with": "EXTERNAL_INPUT['wrong_secret']",
|
86
79
|
"contents": ""
|
87
80
|
}
|
88
81
|
}
|
89
82
|
}
|
90
83
|
"""
|
91
|
-
When I lock a vault with External
|
84
|
+
When I lock a vault with External Input and attempt to unlock with the wrong External Input
|
92
85
|
Then a FailedUnlockAttempt exception is raised
|
86
|
+
|
87
|
+
Scenario: Missing External Input On Lock
|
88
|
+
Given this broken contract:
|
89
|
+
"""javascript
|
90
|
+
{
|
91
|
+
"header": {},
|
92
|
+
"vaults": {
|
93
|
+
"missing_external_input_vault":{
|
94
|
+
"fill_with": "EXTERNAL_INPUT['empty_value']",
|
95
|
+
"lock_with": "UNLOCKED",
|
96
|
+
"unlock_with": "UNLOCKED",
|
97
|
+
"contents": ""
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
101
|
+
"""
|
102
|
+
When I attempt lock a vault with External Input that does not exists
|
103
|
+
Then an InvalidExternalInput exception is raised
|
@@ -1,57 +1,62 @@
|
|
1
|
-
|
1
|
+
### Install
|
2
2
|
|
3
|
-
[
|
3
|
+
As a prerequisite, get [libsodium] version (>= 0.4.3) on you machine. This is the underlying cryptographic library that Vault Tree depends on.
|
4
4
|
|
5
|
-
|
5
|
+
[libsodium]: https://github.com/jedisct1/libsodium
|
6
6
|
|
7
|
-
|
7
|
+
* If you are on _OSX_ there is a [brew] package available. So just:
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
```
|
10
|
+
brew install libsodium
|
11
|
+
```
|
11
12
|
|
12
|
-
[
|
13
|
+
[brew]: http://brew.sh/
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
* If you're on a Debian based system, there is no _apt-get_ package that I know of, but there
|
16
|
+
are some helpful install scripts on the web.
|
17
|
+
|
18
|
+
Now that you have libsodium, if you're a Ruby developer you know the drill from here:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
gem install vault-tree
|
17
22
|
```
|
18
23
|
|
19
|
-
|
24
|
+
and then
|
20
25
|
|
21
|
-
```
|
22
|
-
|
26
|
+
```ruby
|
27
|
+
require 'vault-tree'
|
23
28
|
```
|
29
|
+
somewhere before you use it.
|
30
|
+
|
31
|
+
### Usage
|
24
32
|
|
25
|
-
|
33
|
+
Executing contracts in your Ruby application is is simple.
|
26
34
|
|
27
|
-
|
35
|
+
Instantiate a new contract object with its corresponding JSON:
|
28
36
|
|
29
|
-
```
|
30
|
-
|
37
|
+
```ruby
|
38
|
+
@contract = VaultTree::Contract.new(contract_json)
|
31
39
|
```
|
32
40
|
|
33
|
-
|
41
|
+
From here you have two methods available:
|
34
42
|
|
43
|
+
```ruby
|
44
|
+
@contract.close_vault('vault_id', external_input = {})
|
35
45
|
```
|
36
|
-
/vagrant
|
37
|
-
```
|
38
|
-
and run
|
39
46
|
|
47
|
+
```ruby
|
48
|
+
@contract.open_vault('vault_id', external_input = {})
|
40
49
|
```
|
41
|
-
bundle
|
42
|
-
rake
|
43
|
-
```
|
44
|
-
|
45
|
-
This will pull down the latest version of the code from [Ruby Gems] and then run all the core contracts and put you in a good spot to start exploring the library.
|
46
50
|
|
47
|
-
|
51
|
+
### Testing
|
48
52
|
|
49
|
-
|
50
|
-
[main repo]: https://github.com/VaultTree/vault-tree
|
51
|
-
[Ruby Gems]: http://rubygems.org
|
53
|
+
A great way to get going is to simply run the tests:
|
52
54
|
|
53
|
-
|
55
|
+
* clone the repo
|
56
|
+
* bundle your dependencies
|
57
|
+
* run `rake`
|
54
58
|
|
55
|
-
|
59
|
+
You should see a full suite of green tests that will give you plenty of living
|
60
|
+
examples of to use Vault Tree in your own application.
|
56
61
|
|
57
|
-
[
|
62
|
+
[Documentation]: https://www.relishapp.com/vault-tree/vault-tree/docs
|
@@ -7,51 +7,51 @@ Scenario: Lock with Generated Key. Unlock with Assembled Shamir Key
|
|
7
7
|
"header": {},
|
8
8
|
"vaults": {
|
9
9
|
"s_1":{
|
10
|
-
"fill_with": "
|
10
|
+
"fill_with": "SHAMIR_SHARE['share_collection','1']",
|
11
11
|
"lock_with": "UNLOCKED",
|
12
12
|
"unlock_with": "UNLOCKED",
|
13
13
|
"contents": ""
|
14
14
|
},
|
15
|
-
|
16
15
|
"s_2":{
|
17
|
-
"fill_with": "
|
16
|
+
"fill_with": "SHAMIR_SHARE['share_collection','2']",
|
18
17
|
"lock_with": "UNLOCKED",
|
19
18
|
"unlock_with": "UNLOCKED",
|
20
19
|
"contents": ""
|
21
20
|
},
|
22
|
-
|
23
21
|
"s_3":{
|
24
|
-
"fill_with": "
|
22
|
+
"fill_with": "SHAMIR_SHARE['share_collection','3']",
|
25
23
|
"lock_with": "UNLOCKED",
|
26
24
|
"unlock_with": "UNLOCKED",
|
27
25
|
"contents": ""
|
28
26
|
},
|
29
|
-
|
30
27
|
"s_4":{
|
31
|
-
"fill_with": "
|
28
|
+
"fill_with": "SHAMIR_SHARE['share_collection','4']",
|
32
29
|
"lock_with": "UNLOCKED",
|
33
30
|
"unlock_with": "UNLOCKED",
|
34
31
|
"contents": ""
|
35
32
|
},
|
36
|
-
|
37
33
|
"s_5":{
|
38
|
-
"fill_with": "
|
34
|
+
"fill_with": "SHAMIR_SHARE['share_collection','5']",
|
35
|
+
"lock_with": "UNLOCKED",
|
36
|
+
"unlock_with": "UNLOCKED",
|
37
|
+
"contents": ""
|
38
|
+
},
|
39
|
+
"share_collection":{
|
40
|
+
"fill_with": "SHAMIR_KEY_SHARES['5','3']",
|
39
41
|
"lock_with": "UNLOCKED",
|
40
42
|
"unlock_with": "UNLOCKED",
|
41
43
|
"contents": ""
|
42
44
|
},
|
43
|
-
|
44
45
|
"message":{
|
45
|
-
"fill_with": "
|
46
|
-
"lock_with": "
|
46
|
+
"fill_with": "EXTERNAL_INPUT['msg']",
|
47
|
+
"lock_with": "ASSEMBLED_SHAMIR_KEY['s_1','s_2','s_3','s_4','s_5']",
|
47
48
|
"unlock_with": "ASSEMBLED_SHAMIR_KEY['s_1','s_2','s_3','s_4','s_5']",
|
48
49
|
"contents": ""
|
49
50
|
}
|
50
51
|
}
|
51
52
|
}
|
52
53
|
"""
|
53
|
-
|
54
|
-
|
55
|
-
Then
|
56
|
-
|
57
|
-
Then I successfully gather the locked shares and unlock the message
|
54
|
+
When I lock away the shamir key share collection
|
55
|
+
And I close the key shares in their respective vaults
|
56
|
+
Then I can lock away a message with the key assembled from the shares
|
57
|
+
And if all the shares are available I can unlock the message
|
@@ -18,15 +18,15 @@ Scenario: Asymmetric Vault
|
|
18
18
|
"header": {},
|
19
19
|
"vaults": {
|
20
20
|
"asymmetric_message":{
|
21
|
-
"fill_with": "
|
21
|
+
"fill_with": "EXTERNAL_INPUT['asymmetric_message']",
|
22
22
|
"lock_with": "DH_KEY['another_public_key','my_decryption_key']",
|
23
23
|
"unlock_with": "DH_KEY['my_public_key','another_decryption_key']",
|
24
24
|
"contents": ""
|
25
25
|
},
|
26
26
|
"my_decryption_key":{
|
27
27
|
"fill_with": "DECRYPTION_KEY",
|
28
|
-
"lock_with": "
|
29
|
-
"unlock_with": "
|
28
|
+
"lock_with": "UNLOCKED",
|
29
|
+
"unlock_with": "UNLOCKED",
|
30
30
|
"contents": ""
|
31
31
|
},
|
32
32
|
"my_public_key":{
|
@@ -37,8 +37,8 @@ Scenario: Asymmetric Vault
|
|
37
37
|
},
|
38
38
|
"another_decryption_key":{
|
39
39
|
"fill_with": "DECRYPTION_KEY",
|
40
|
-
"lock_with": "
|
41
|
-
"unlock_with": "
|
40
|
+
"lock_with": "UNLOCKED",
|
41
|
+
"unlock_with": "UNLOCKED",
|
42
42
|
"contents": ""
|
43
43
|
},
|
44
44
|
"another_public_key":{
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Feature: External Inputs
|
2
|
+
|
3
|
+
The Vault Tree interpreter does not interact directly with outside networks. Its
|
4
|
+
repsonsibility is limited to opening and closing vaults under the assumption
|
5
|
+
that all necessary external inputs will be explicitly passed in.
|
6
|
+
|
7
|
+
Use the EXTERNAL_INPUT Keyword when you want to fill a vault with a string from
|
8
|
+
the outside environment.
|
9
|
+
|
10
|
+
Although you can lock and unlock vaults directly with an EXTERNAL_INPUT string
|
11
|
+
if it happens to be properly formated, it is recommended that you do not do this.
|
12
|
+
|
13
|
+
Instead, lock and unlock vaults with external strings using the EXTERNAL_KEY phrase.
|
14
|
+
EXTERNAL_KEY ensures your password is run through a secure hash before it is used to
|
15
|
+
lock contents. Hashing guarentees a properly padded vault key and keeps the locked vault
|
16
|
+
more secure if you have a weak password.
|
17
|
+
|
18
|
+
Scenario: Close And Open Using with a Key
|
19
|
+
Given the blank contract:
|
20
|
+
"""javascript
|
21
|
+
{
|
22
|
+
"header": {},
|
23
|
+
"vaults": {
|
24
|
+
"message":{
|
25
|
+
"description": "Simple Congratulations Message",
|
26
|
+
"fill_with": "EXTERNAL_INPUT['msg']",
|
27
|
+
"lock_with": "EXTERNAL_INPUT['secret']",
|
28
|
+
"unlock_with": "EXTERNAL_INPUT['secret']",
|
29
|
+
"contents": ""
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
"""
|
34
|
+
When I lock the external input in a vault using a symmetric vault key
|
35
|
+
Then I can recover the input message using the same key
|