trustworthy 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/lib/trustworthy/cli/add_key.rb +8 -6
- data/lib/trustworthy/cli/command.rb +0 -2
- data/lib/trustworthy/cli/decrypt.rb +7 -14
- data/lib/trustworthy/cli/encrypt.rb +7 -15
- data/lib/trustworthy/cli/init.rb +11 -10
- data/lib/trustworthy/cli.rb +5 -7
- data/lib/trustworthy/prompt.rb +96 -0
- data/lib/trustworthy/settings.rb +8 -0
- data/lib/trustworthy/version.rb +1 -1
- data/lib/trustworthy.rb +4 -1
- data/spec/trustworthy/cli/decrypt_spec.rb +0 -2
- data/spec/trustworthy/cli/encrypt_spec.rb +0 -2
- data/spec/trustworthy/cli/init_spec.rb +1 -22
- data/spec/trustworthy/prompt_spec.rb +158 -0
- data/spec/trustworthy/settings_spec.rb +42 -0
- metadata +5 -5
- data/lib/trustworthy/cli/helpers.rb +0 -64
- data/spec/trustworthy/cli/command_spec.rb +0 -114
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bb4a8a2dc975dae29a9fdc798baa2f38fc3368b
|
4
|
+
data.tar.gz: 87d2308517917931f4b5ebfe6e51d9b992d3e387
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99ccfc9b7e5df3ac5277a0e9a75b92963b8c5a98f9264eb5693a63bd0ec69ec7772099382b5d446aa2cc7a4476ff7e2d50fe1070ef598535fa2dd394e60ea6b3
|
7
|
+
data.tar.gz: e0afdedd53d39762b7c2c577224831e50315b1ffaff7e8971169fc9ce71bd1d0875a7b696e562be0588f1829c474a63d7654d8ec3d8694b8693f2663b4c8c0cb
|
@@ -9,13 +9,15 @@ module Trustworthy
|
|
9
9
|
|
10
10
|
def run(args)
|
11
11
|
options = parse_options('add-key', args)
|
12
|
-
info 'Adding a new key to master key'
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
$terminal.say('Adding a new key to master key')
|
14
|
+
|
15
|
+
prompt = Trustworthy::Prompt.new(options[:config_file], $terminal)
|
16
|
+
master_key = prompt.unlock_master_key
|
17
|
+
key = master_key.create_key
|
18
|
+
username = prompt.add_user_key(key)
|
19
|
+
|
20
|
+
$terminal.say("Added #{username}")
|
19
21
|
end
|
20
22
|
end
|
21
23
|
end
|
@@ -22,26 +22,19 @@ module Trustworthy
|
|
22
22
|
def run(args)
|
23
23
|
options = parse_options(args)
|
24
24
|
|
25
|
-
unless options.has_key?(:input_file)
|
26
|
-
error 'Must provide an input file'
|
27
|
-
print_help
|
28
|
-
return
|
29
|
-
end
|
30
|
-
|
31
|
-
unless options.has_key?(:output_file)
|
32
|
-
error 'Must provide an output file'
|
25
|
+
unless options.has_key?(:input_file) && options.has_key?(:output_file)
|
33
26
|
print_help
|
34
27
|
return
|
35
28
|
end
|
36
29
|
|
30
|
+
prompt = Trustworthy::Prompt.new(options[:config_file], $terminal)
|
37
31
|
File.open(options[:input_file], 'rb') do |input_file|
|
38
32
|
ciphertext = input_file.read
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
33
|
+
|
34
|
+
master_key = prompt.unlock_master_key
|
35
|
+
plaintext = master_key.decrypt(ciphertext)
|
36
|
+
File.open(options[:output_file], 'wb+') do |output_file|
|
37
|
+
output_file.write(plaintext)
|
45
38
|
end
|
46
39
|
end
|
47
40
|
|
@@ -22,30 +22,22 @@ module Trustworthy
|
|
22
22
|
def run(args)
|
23
23
|
options = parse_options(args)
|
24
24
|
|
25
|
-
unless options.has_key?(:input_file)
|
26
|
-
error 'Must provide an input file'
|
27
|
-
print_help
|
28
|
-
return
|
29
|
-
end
|
30
|
-
|
31
|
-
unless options.has_key?(:output_file)
|
32
|
-
error 'Must provide an output file'
|
25
|
+
unless options.has_key?(:input_file) && options.has_key?(:output_file)
|
33
26
|
print_help
|
34
27
|
return
|
35
28
|
end
|
36
29
|
|
30
|
+
prompt = Trustworthy::Prompt.new(options[:config_file], $terminal)
|
37
31
|
File.open(options[:input_file], 'rb') do |input_file|
|
38
32
|
plaintext = input_file.read
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
output_file.write(ciphertext)
|
44
|
-
end
|
33
|
+
master_key = prompt.unlock_master_key
|
34
|
+
ciphertext = master_key.encrypt(plaintext)
|
35
|
+
File.open(options[:output_file], 'wb+') do |output_file|
|
36
|
+
output_file.write(ciphertext)
|
45
37
|
end
|
46
38
|
end
|
47
39
|
|
48
|
-
|
40
|
+
$terminal.say("Encrypted #{options[:input_file]} to #{options[:output_file]}")
|
49
41
|
end
|
50
42
|
end
|
51
43
|
end
|
data/lib/trustworthy/cli/init.rb
CHANGED
@@ -23,27 +23,28 @@ module Trustworthy
|
|
23
23
|
options = parse_options(args)
|
24
24
|
|
25
25
|
if options[:keys] < 2
|
26
|
-
error "Must generate at least two keys"
|
27
26
|
print_help
|
28
27
|
return
|
29
28
|
end
|
30
29
|
|
31
30
|
Trustworthy::Settings.open(options[:config_file]) do |settings|
|
32
31
|
unless settings.empty?
|
33
|
-
|
32
|
+
$terminal.say("Config #{options[:config_file]} already exists")
|
34
33
|
return
|
35
34
|
end
|
35
|
+
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
master_key = Trustworthy::MasterKey.create
|
40
|
-
options[:keys].times do
|
41
|
-
username = add_key(settings, master_key)
|
42
|
-
info "Key #{username} added"
|
43
|
-
end
|
37
|
+
$terminal.say("Creating a new master key with #{options[:keys]} keys")
|
44
38
|
|
45
|
-
|
39
|
+
master_key = Trustworthy::MasterKey.create
|
40
|
+
prompt = Trustworthy::Prompt.new(options[:config_file], $terminal)
|
41
|
+
options[:keys].times do
|
42
|
+
key = master_key.create_key
|
43
|
+
username = prompt.add_user_key(key)
|
44
|
+
$terminal.say("Key #{username} added")
|
46
45
|
end
|
46
|
+
|
47
|
+
$terminal.say("Created #{options[:config_file]}")
|
47
48
|
end
|
48
49
|
end
|
49
50
|
end
|
data/lib/trustworthy/cli.rb
CHANGED
@@ -1,19 +1,17 @@
|
|
1
1
|
require 'highline/import'
|
2
2
|
require 'optparse'
|
3
3
|
|
4
|
-
require 'trustworthy/cli/helpers'
|
5
4
|
require 'trustworthy/cli/command'
|
6
5
|
require 'trustworthy/cli/add_key'
|
7
6
|
require 'trustworthy/cli/init'
|
8
7
|
require 'trustworthy/cli/decrypt'
|
9
8
|
require 'trustworthy/cli/encrypt'
|
9
|
+
require 'trustworthy/prompt'
|
10
10
|
|
11
11
|
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
12
12
|
|
13
13
|
module Trustworthy
|
14
14
|
class CLI
|
15
|
-
include Trustworthy::CLI::Helpers
|
16
|
-
|
17
15
|
Commands = {
|
18
16
|
'add-key' => Trustworthy::CLI::AddKey,
|
19
17
|
'init' => Trustworthy::CLI::Init,
|
@@ -36,12 +34,12 @@ module Trustworthy
|
|
36
34
|
end
|
37
35
|
|
38
36
|
def _print_help
|
39
|
-
say
|
40
|
-
say
|
37
|
+
$terminal.say("#{Trustworthy::CLI.banner}\n\n")
|
38
|
+
$terminal.say('Commands:')
|
41
39
|
Commands.each do |name, klass|
|
42
|
-
say
|
40
|
+
$terminal.say(' %-8s %s' % [name, klass.description])
|
43
41
|
end
|
44
|
-
say
|
42
|
+
$terminal.say("\nSee 'trustworthy <command> --help' for more information on a specific command")
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Trustworthy
|
2
|
+
class Prompt
|
3
|
+
def initialize(config_file, terminal = HighLine.new)
|
4
|
+
@config_file = config_file
|
5
|
+
@terminal = terminal
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_user_key(key)
|
9
|
+
Trustworthy::Settings.open(@config_file) do |settings|
|
10
|
+
username = nil
|
11
|
+
loop do
|
12
|
+
username = _ask('Username: ')
|
13
|
+
if settings.has_key?(username)
|
14
|
+
_error("Key #{username} is already in use")
|
15
|
+
else
|
16
|
+
break
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
loop do
|
21
|
+
password = _ask_password('Password: ')
|
22
|
+
password_confirm = _ask_password('Password (again): ')
|
23
|
+
if password == password_confirm
|
24
|
+
settings.add_key(key, username, password)
|
25
|
+
break
|
26
|
+
else
|
27
|
+
_error('Passwords do not match.')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
username
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def unlock_master_key
|
36
|
+
usernames_in_use = []
|
37
|
+
Trustworthy::Settings.open(@config_file) do |settings|
|
38
|
+
raise 'must have two keys to unlock master key' unless settings.recoverable?
|
39
|
+
|
40
|
+
username1, key1 = _unlock_key(settings, usernames_in_use)
|
41
|
+
usernames_in_use << username1
|
42
|
+
|
43
|
+
username2, key2 = _unlock_key(settings, usernames_in_use)
|
44
|
+
|
45
|
+
master_key = Trustworthy::MasterKey.create_from_keys(key1, key2)
|
46
|
+
_say('Reconstructed master key')
|
47
|
+
|
48
|
+
master_key
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def _unlock_key(settings, usernames_in_use)
|
53
|
+
username = nil
|
54
|
+
loop do
|
55
|
+
username = _ask('Username: ')
|
56
|
+
if usernames_in_use.include?(username)
|
57
|
+
_error("Key #{username} is already in use")
|
58
|
+
elsif settings.find_key(username).nil?
|
59
|
+
_error("Key #{username} does not exist")
|
60
|
+
else
|
61
|
+
break
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
key = nil
|
66
|
+
begin
|
67
|
+
password = _ask_password('Password: ')
|
68
|
+
key = settings.unlock_key(username, password)
|
69
|
+
rescue ArgumentError
|
70
|
+
_error("Password incorrect for #{username}")
|
71
|
+
retry
|
72
|
+
end
|
73
|
+
|
74
|
+
_say("Unlocked #{username}")
|
75
|
+
|
76
|
+
[username, key]
|
77
|
+
end
|
78
|
+
|
79
|
+
def _ask(question)
|
80
|
+
@terminal.ask(question).to_s
|
81
|
+
end
|
82
|
+
|
83
|
+
def _ask_password(question)
|
84
|
+
@terminal.ask(question) { |q| q.echo = false }.to_s
|
85
|
+
end
|
86
|
+
|
87
|
+
def _say(message)
|
88
|
+
@terminal.say(message)
|
89
|
+
end
|
90
|
+
|
91
|
+
def _error(message)
|
92
|
+
colored_message = @terminal.color(message, :error)
|
93
|
+
_say(colored_message)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/trustworthy/settings.rb
CHANGED
@@ -33,6 +33,14 @@ module Trustworthy
|
|
33
33
|
@store[username]
|
34
34
|
end
|
35
35
|
|
36
|
+
def has_key?(username)
|
37
|
+
@store.root?(username)
|
38
|
+
end
|
39
|
+
|
40
|
+
def recoverable?
|
41
|
+
@store.roots.count >= 2
|
42
|
+
end
|
43
|
+
|
36
44
|
def unlock_key(username, password)
|
37
45
|
key = find_key(username)
|
38
46
|
salt = key['salt']
|
data/lib/trustworthy/version.rb
CHANGED
data/lib/trustworthy.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
require 'aead'
|
2
2
|
require 'bigdecimal'
|
3
|
+
require 'highline'
|
3
4
|
require 'hkdf'
|
4
5
|
require 'scrypt'
|
5
6
|
require 'securerandom'
|
7
|
+
require 'yaml/store'
|
8
|
+
|
6
9
|
require 'trustworthy/key'
|
7
10
|
require 'trustworthy/master_key'
|
11
|
+
require 'trustworthy/prompt'
|
8
12
|
require 'trustworthy/random'
|
9
13
|
require 'trustworthy/settings'
|
10
14
|
require 'trustworthy/version'
|
11
|
-
require 'yaml/store'
|
12
15
|
|
13
16
|
module Trustworthy
|
14
17
|
CipherAlgorithm = 'AES-256-CBC-HMAC-SHA-256'
|
@@ -40,7 +40,6 @@ describe Trustworthy::CLI::Decrypt do
|
|
40
40
|
'password2'
|
41
41
|
) do
|
42
42
|
decrypt = Trustworthy::CLI::Encrypt.new
|
43
|
-
decrypt.should_receive(:error).with('Must provide an input file')
|
44
43
|
decrypt.should_receive(:print_help)
|
45
44
|
decrypt.run([])
|
46
45
|
end
|
@@ -54,7 +53,6 @@ describe Trustworthy::CLI::Decrypt do
|
|
54
53
|
'password2'
|
55
54
|
) do
|
56
55
|
decrypt = Trustworthy::CLI::Encrypt.new
|
57
|
-
decrypt.should_receive(:error).with('Must provide an output file')
|
58
56
|
decrypt.should_receive(:print_help)
|
59
57
|
decrypt.run(['-i', 'input.txt'])
|
60
58
|
end
|
@@ -41,7 +41,6 @@ describe Trustworthy::CLI::Encrypt do
|
|
41
41
|
'password2'
|
42
42
|
) do
|
43
43
|
encrypt = Trustworthy::CLI::Encrypt.new
|
44
|
-
encrypt.should_receive(:error).with('Must provide an input file')
|
45
44
|
encrypt.should_receive(:print_help)
|
46
45
|
encrypt.run([])
|
47
46
|
end
|
@@ -55,7 +54,6 @@ describe Trustworthy::CLI::Encrypt do
|
|
55
54
|
'password2'
|
56
55
|
) do
|
57
56
|
encrypt = Trustworthy::CLI::Encrypt.new
|
58
|
-
encrypt.should_receive(:error).with('Must provide an output file')
|
59
57
|
encrypt.should_receive(:print_help)
|
60
58
|
encrypt.run(['-i', 'input.txt'])
|
61
59
|
end
|
@@ -15,7 +15,7 @@ describe Trustworthy::CLI::Init do
|
|
15
15
|
describe 'run' do
|
16
16
|
it 'should not allow any previous keys to exist' do
|
17
17
|
create_config(TestValues::SettingsFile)
|
18
|
-
$terminal.should_receive(:say).with(
|
18
|
+
$terminal.should_receive(:say).with('Config trustworthy.yml already exists')
|
19
19
|
Trustworthy::CLI::Init.new.run([])
|
20
20
|
end
|
21
21
|
|
@@ -37,26 +37,6 @@ describe Trustworthy::CLI::Init do
|
|
37
37
|
subkeys.should have_key('user2')
|
38
38
|
end
|
39
39
|
|
40
|
-
it 'should confirm passwords' do
|
41
|
-
HighLine::Simulate.with(
|
42
|
-
'user1',
|
43
|
-
'password1',
|
44
|
-
'password2',
|
45
|
-
'password1',
|
46
|
-
'password1',
|
47
|
-
'user2',
|
48
|
-
'password2',
|
49
|
-
'password2'
|
50
|
-
) do
|
51
|
-
Trustworthy::CLI::Init.new.run([])
|
52
|
-
end
|
53
|
-
|
54
|
-
contents = File.read(TestValues::SettingsFile)
|
55
|
-
subkeys = YAML.load(contents)
|
56
|
-
subkeys.should have_key('user1')
|
57
|
-
subkeys.should have_key('user2')
|
58
|
-
end
|
59
|
-
|
60
40
|
it 'should write to a specified file' do
|
61
41
|
filename = 'test.yml'
|
62
42
|
within_construct do |construct|
|
@@ -103,7 +83,6 @@ describe Trustworthy::CLI::Init do
|
|
103
83
|
|
104
84
|
it 'should require two subkeys minimum' do
|
105
85
|
init = Trustworthy::CLI::Init.new
|
106
|
-
init.should_receive(:error).with('Must generate at least two keys')
|
107
86
|
init.should_receive(:print_help)
|
108
87
|
init.run(['-k', '1'])
|
109
88
|
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Trustworthy::Prompt do
|
4
|
+
let(:test_key) { Trustworthy::Key.new(BigDecimal.new('1'), BigDecimal.new('2')) }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
$terminal.stub(:say)
|
8
|
+
end
|
9
|
+
|
10
|
+
around(:each) do |example|
|
11
|
+
within_construct do |construct|
|
12
|
+
construct.file(TestValues::SettingsFile)
|
13
|
+
create_config(TestValues::SettingsFile)
|
14
|
+
example.run
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'add_user_key' do
|
19
|
+
it 'should prompt for two user keys' do
|
20
|
+
HighLine::Simulate.with(
|
21
|
+
'user3',
|
22
|
+
'password',
|
23
|
+
'password'
|
24
|
+
) do
|
25
|
+
prompt = Trustworthy::Prompt.new(TestValues::SettingsFile, $terminal)
|
26
|
+
username = prompt.add_user_key(test_key)
|
27
|
+
username.should == 'user3'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should confirm passwords' do
|
32
|
+
HighLine::Simulate.with(
|
33
|
+
'user3',
|
34
|
+
'password1',
|
35
|
+
'password2',
|
36
|
+
'password1',
|
37
|
+
'password1'
|
38
|
+
) do
|
39
|
+
prompt = Trustworthy::Prompt.new(TestValues::SettingsFile, $terminal)
|
40
|
+
username = prompt.add_user_key(test_key)
|
41
|
+
username.should == 'user3'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should require a unique username' do
|
46
|
+
create_config(TestValues::SettingsFile)
|
47
|
+
|
48
|
+
HighLine::Simulate.with(
|
49
|
+
'user1',
|
50
|
+
'user3',
|
51
|
+
'password',
|
52
|
+
'password'
|
53
|
+
) do
|
54
|
+
prompt = Trustworthy::Prompt.new(TestValues::SettingsFile, $terminal)
|
55
|
+
prompt.should_receive(:_error).with('Key user1 is already in use')
|
56
|
+
username = prompt.add_user_key(test_key)
|
57
|
+
username.should == 'user3'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'unlock_master_key' do
|
63
|
+
it 'should prompt for two user keys' do
|
64
|
+
HighLine::Simulate.with(
|
65
|
+
'user1',
|
66
|
+
'password1',
|
67
|
+
'user2',
|
68
|
+
'password2'
|
69
|
+
) do
|
70
|
+
prompt = Trustworthy::Prompt.new(TestValues::SettingsFile, $terminal)
|
71
|
+
master_key = prompt.unlock_master_key
|
72
|
+
master_key.should == TestValues::MasterKey
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should raise an error if not recoverable' do
|
77
|
+
File.open(TestValues::SettingsFile, 'w') do |file|
|
78
|
+
file.write(YAML.dump({}))
|
79
|
+
end
|
80
|
+
|
81
|
+
expect do
|
82
|
+
prompt = Trustworthy::Prompt.new(TestValues::SettingsFile, $terminal)
|
83
|
+
master_key = prompt.unlock_master_key
|
84
|
+
master_key.should == TestValues::MasterKey
|
85
|
+
end.to raise_error('must have two keys to unlock master key')
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should require two distinct keys to unlock' do
|
89
|
+
HighLine::Simulate.with(
|
90
|
+
'user1',
|
91
|
+
'password1',
|
92
|
+
'user1',
|
93
|
+
'user2',
|
94
|
+
'password2'
|
95
|
+
) do
|
96
|
+
prompt = Trustworthy::Prompt.new(TestValues::SettingsFile, $terminal)
|
97
|
+
prompt.should_receive(:_error).with('Key user1 is already in use')
|
98
|
+
prompt.unlock_master_key
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should required an existing user for the first key' do
|
103
|
+
HighLine::Simulate.with(
|
104
|
+
'missing',
|
105
|
+
'user1',
|
106
|
+
'password1',
|
107
|
+
'user2',
|
108
|
+
'password2'
|
109
|
+
) do
|
110
|
+
prompt = Trustworthy::Prompt.new(TestValues::SettingsFile, $terminal)
|
111
|
+
prompt.should_receive(:_error).with('Key missing does not exist')
|
112
|
+
prompt.unlock_master_key
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should required an existing user for the second key' do
|
117
|
+
HighLine::Simulate.with(
|
118
|
+
'user1',
|
119
|
+
'password1',
|
120
|
+
'missing',
|
121
|
+
'user2',
|
122
|
+
'password2'
|
123
|
+
) do
|
124
|
+
prompt = Trustworthy::Prompt.new(TestValues::SettingsFile, $terminal)
|
125
|
+
prompt.should_receive(:_error).with('Key missing does not exist')
|
126
|
+
prompt.unlock_master_key
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should prompt for the correct password for the first key' do
|
131
|
+
HighLine::Simulate.with(
|
132
|
+
'user1',
|
133
|
+
'bad_password',
|
134
|
+
'password1',
|
135
|
+
'user2',
|
136
|
+
'password2'
|
137
|
+
) do
|
138
|
+
prompt = Trustworthy::Prompt.new(TestValues::SettingsFile, $terminal)
|
139
|
+
prompt.should_receive(:_error).with('Password incorrect for user1')
|
140
|
+
prompt.unlock_master_key
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should prompt for the correct password for the second key' do
|
145
|
+
HighLine::Simulate.with(
|
146
|
+
'user1',
|
147
|
+
'password1',
|
148
|
+
'user2',
|
149
|
+
'bad_password',
|
150
|
+
'password2'
|
151
|
+
) do
|
152
|
+
prompt = Trustworthy::Prompt.new(TestValues::SettingsFile, $terminal)
|
153
|
+
prompt.should_receive(:_error).with('Password incorrect for user2')
|
154
|
+
prompt.unlock_master_key
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -63,6 +63,48 @@ describe Trustworthy::Settings do
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
describe 'has_key?' do
|
67
|
+
it 'should be true if the key exists' do
|
68
|
+
Trustworthy::Settings.open(TestValues::SettingsFile) do |settings|
|
69
|
+
key = Trustworthy::Key.new(BigDecimal.new('2'), BigDecimal.new('3'))
|
70
|
+
settings.add_key(key, 'user', 'password1')
|
71
|
+
settings.should have_key('user')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should be false if the key does exists' do
|
76
|
+
Trustworthy::Settings.open(TestValues::SettingsFile) do |settings|
|
77
|
+
settings.should_not have_key('missing')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'recoverable?' do
|
83
|
+
it 'should not be recoverable with no user keys' do
|
84
|
+
Trustworthy::Settings.open(TestValues::SettingsFile) do |settings|
|
85
|
+
settings.should_not be_recoverable
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should not be recoverable with one user key' do
|
90
|
+
Trustworthy::Settings.open(TestValues::SettingsFile) do |settings|
|
91
|
+
key = Trustworthy::Key.new(BigDecimal.new('2'), BigDecimal.new('3'))
|
92
|
+
settings.add_key(key, 'user', 'password')
|
93
|
+
settings.should_not be_recoverable
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should be recoverable with two or more user keys' do
|
98
|
+
Trustworthy::Settings.open(TestValues::SettingsFile) do |settings|
|
99
|
+
key1 = Trustworthy::Key.new(BigDecimal.new('2'), BigDecimal.new('3'))
|
100
|
+
key2 = Trustworthy::Key.new(BigDecimal.new('3'), BigDecimal.new('4'))
|
101
|
+
settings.add_key(key1, 'user1', 'password')
|
102
|
+
settings.add_key(key2, 'user2', 'password')
|
103
|
+
settings.should be_recoverable
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
66
108
|
describe 'unlock_key' do
|
67
109
|
it 'should decrypt the key with the password' do
|
68
110
|
Trustworthy::Settings.open(TestValues::SettingsFile) do |settings|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trustworthy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Downey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-03-
|
11
|
+
date: 2013-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aead
|
@@ -122,23 +122,23 @@ files:
|
|
122
122
|
- lib/trustworthy/cli/command.rb
|
123
123
|
- lib/trustworthy/cli/decrypt.rb
|
124
124
|
- lib/trustworthy/cli/encrypt.rb
|
125
|
-
- lib/trustworthy/cli/helpers.rb
|
126
125
|
- lib/trustworthy/cli/init.rb
|
127
126
|
- lib/trustworthy/cli.rb
|
128
127
|
- lib/trustworthy/key.rb
|
129
128
|
- lib/trustworthy/master_key.rb
|
129
|
+
- lib/trustworthy/prompt.rb
|
130
130
|
- lib/trustworthy/random.rb
|
131
131
|
- lib/trustworthy/settings.rb
|
132
132
|
- lib/trustworthy/version.rb
|
133
133
|
- lib/trustworthy.rb
|
134
134
|
- spec/spec_helper.rb
|
135
135
|
- spec/trustworthy/cli/add_key_spec.rb
|
136
|
-
- spec/trustworthy/cli/command_spec.rb
|
137
136
|
- spec/trustworthy/cli/decrypt_spec.rb
|
138
137
|
- spec/trustworthy/cli/encrypt_spec.rb
|
139
138
|
- spec/trustworthy/cli/init_spec.rb
|
140
139
|
- spec/trustworthy/key_spec.rb
|
141
140
|
- spec/trustworthy/master_key_spec.rb
|
141
|
+
- spec/trustworthy/prompt_spec.rb
|
142
142
|
- spec/trustworthy/random_spec.rb
|
143
143
|
- spec/trustworthy/settings_spec.rb
|
144
144
|
- bin/trustworthy
|
@@ -170,11 +170,11 @@ summary: Encrypt and decrypt files with multiple key holders
|
|
170
170
|
test_files:
|
171
171
|
- spec/spec_helper.rb
|
172
172
|
- spec/trustworthy/cli/add_key_spec.rb
|
173
|
-
- spec/trustworthy/cli/command_spec.rb
|
174
173
|
- spec/trustworthy/cli/decrypt_spec.rb
|
175
174
|
- spec/trustworthy/cli/encrypt_spec.rb
|
176
175
|
- spec/trustworthy/cli/init_spec.rb
|
177
176
|
- spec/trustworthy/key_spec.rb
|
178
177
|
- spec/trustworthy/master_key_spec.rb
|
178
|
+
- spec/trustworthy/prompt_spec.rb
|
179
179
|
- spec/trustworthy/random_spec.rb
|
180
180
|
- spec/trustworthy/settings_spec.rb
|
@@ -1,64 +0,0 @@
|
|
1
|
-
module Trustworthy
|
2
|
-
class CLI
|
3
|
-
module Helpers
|
4
|
-
def add_key(settings, master_key)
|
5
|
-
key = master_key.create_key
|
6
|
-
username = ask('Username: ')
|
7
|
-
|
8
|
-
loop do
|
9
|
-
password = ask_password('Password: ')
|
10
|
-
password_confirm = ask_password('Password (again): ')
|
11
|
-
if password == password_confirm
|
12
|
-
settings.add_key(key, username, password)
|
13
|
-
break
|
14
|
-
else
|
15
|
-
error 'Passwords do not match.'
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
username
|
20
|
-
end
|
21
|
-
|
22
|
-
def unlock_master_key(settings)
|
23
|
-
usernames_in_use = []
|
24
|
-
|
25
|
-
username1, key1 = _unlock_key(settings, usernames_in_use)
|
26
|
-
usernames_in_use << username1
|
27
|
-
|
28
|
-
username2, key2 = _unlock_key(settings, usernames_in_use)
|
29
|
-
|
30
|
-
master_key = Trustworthy::MasterKey.create_from_keys(key1, key2)
|
31
|
-
info "Reconstructed master key"
|
32
|
-
|
33
|
-
master_key
|
34
|
-
end
|
35
|
-
|
36
|
-
def _unlock_key(settings, usernames_in_use)
|
37
|
-
username = nil
|
38
|
-
loop do
|
39
|
-
username = ask('Username: ')
|
40
|
-
if usernames_in_use.include?(username)
|
41
|
-
error "Key #{username} is already in use"
|
42
|
-
elsif settings.find_key(username).nil?
|
43
|
-
error "Key #{username} does not exist"
|
44
|
-
else
|
45
|
-
break
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
key = nil
|
50
|
-
begin
|
51
|
-
password = ask_password('Password: ')
|
52
|
-
key = settings.unlock_key(username, password)
|
53
|
-
rescue ArgumentError
|
54
|
-
error "Password incorrect for #{username}"
|
55
|
-
retry
|
56
|
-
end
|
57
|
-
|
58
|
-
info "Unlocked #{username}"
|
59
|
-
|
60
|
-
[username, key]
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,114 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Trustworthy::CLI::Command do
|
4
|
-
def test_command
|
5
|
-
return @klass if @klass
|
6
|
-
@klass = Class.new
|
7
|
-
@klass.send(:include, Trustworthy::CLI::Command)
|
8
|
-
@klass
|
9
|
-
end
|
10
|
-
|
11
|
-
before(:each) do
|
12
|
-
$terminal.stub(:say)
|
13
|
-
end
|
14
|
-
|
15
|
-
around(:each) do |example|
|
16
|
-
within_construct do |construct|
|
17
|
-
construct.file(TestValues::SettingsFile)
|
18
|
-
create_config(TestValues::SettingsFile)
|
19
|
-
example.run
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe 'unlock_master_key' do
|
24
|
-
it 'should require two distinct keys to unlock' do
|
25
|
-
command = test_command.new
|
26
|
-
command.should_receive(:error).with('Key user1 is already in use')
|
27
|
-
|
28
|
-
HighLine::Simulate.with(
|
29
|
-
'user1',
|
30
|
-
'password1',
|
31
|
-
'user1',
|
32
|
-
'user2',
|
33
|
-
'password2'
|
34
|
-
) do
|
35
|
-
Trustworthy::Settings.open(TestValues::SettingsFile) do |settings|
|
36
|
-
master_key = command.unlock_master_key(settings)
|
37
|
-
master_key.should == TestValues::MasterKey
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'should required an existing user for the first key' do
|
43
|
-
command = test_command.new
|
44
|
-
command.should_receive(:error).with('Key missing does not exist')
|
45
|
-
|
46
|
-
HighLine::Simulate.with(
|
47
|
-
'missing',
|
48
|
-
'user1',
|
49
|
-
'password1',
|
50
|
-
'user2',
|
51
|
-
'password2'
|
52
|
-
) do
|
53
|
-
Trustworthy::Settings.open(TestValues::SettingsFile) do |settings|
|
54
|
-
master_key = command.unlock_master_key(settings)
|
55
|
-
master_key.should == TestValues::MasterKey
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'should required an existing user for the second key' do
|
61
|
-
command = test_command.new
|
62
|
-
command.should_receive(:error).with('Key missing does not exist')
|
63
|
-
|
64
|
-
HighLine::Simulate.with(
|
65
|
-
'user1',
|
66
|
-
'password1',
|
67
|
-
'missing',
|
68
|
-
'user2',
|
69
|
-
'password2'
|
70
|
-
) do
|
71
|
-
Trustworthy::Settings.open(TestValues::SettingsFile) do |settings|
|
72
|
-
master_key = command.unlock_master_key(settings)
|
73
|
-
master_key.should == TestValues::MasterKey
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'should prompt for the correct password for the first key' do
|
79
|
-
command = test_command.new
|
80
|
-
command.should_receive(:error).with('Password incorrect for user1')
|
81
|
-
|
82
|
-
HighLine::Simulate.with(
|
83
|
-
'user1',
|
84
|
-
'bad_password',
|
85
|
-
'password1',
|
86
|
-
'user2',
|
87
|
-
'password2'
|
88
|
-
) do
|
89
|
-
Trustworthy::Settings.open(TestValues::SettingsFile) do |settings|
|
90
|
-
master_key = command.unlock_master_key(settings)
|
91
|
-
master_key.should == TestValues::MasterKey
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'should prompt for the correct password for the second key' do
|
97
|
-
command = test_command.new
|
98
|
-
command.should_receive(:error).with('Password incorrect for user2')
|
99
|
-
|
100
|
-
HighLine::Simulate.with(
|
101
|
-
'user1',
|
102
|
-
'password1',
|
103
|
-
'user2',
|
104
|
-
'bad_password',
|
105
|
-
'password2'
|
106
|
-
) do
|
107
|
-
Trustworthy::Settings.open(TestValues::SettingsFile) do |settings|
|
108
|
-
master_key = command.unlock_master_key(settings)
|
109
|
-
master_key.should == TestValues::MasterKey
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|