trustworthy 0.1.0 → 0.2.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 +7 -0
- data/README.md +51 -19
- data/bin/trustworthy +2 -140
- data/lib/trustworthy/cli/add_key.rb +22 -0
- data/lib/trustworthy/cli/command.rb +63 -0
- data/lib/trustworthy/cli/decrypt.rb +52 -0
- data/lib/trustworthy/cli/encrypt.rb +52 -0
- data/lib/trustworthy/cli/helpers.rb +64 -0
- data/lib/trustworthy/cli/init.rb +50 -0
- data/lib/trustworthy/cli.rb +47 -0
- data/lib/trustworthy/master_key.rb +14 -13
- data/lib/trustworthy/settings.rb +30 -37
- data/lib/trustworthy/version.rb +1 -1
- data/lib/trustworthy.rb +7 -4
- data/spec/spec_helper.rb +19 -7
- data/spec/trustworthy/cli/add_key_spec.rb +37 -0
- data/spec/trustworthy/cli/command_spec.rb +114 -0
- data/spec/trustworthy/cli/decrypt_spec.rb +63 -0
- data/spec/trustworthy/cli/encrypt_spec.rb +64 -0
- data/spec/trustworthy/cli/init_spec.rb +111 -0
- data/spec/trustworthy/master_key_spec.rb +12 -12
- data/spec/trustworthy/settings_spec.rb +54 -59
- metadata +51 -52
- data/lib/trustworthy/crypto.rb +0 -50
- data/spec/trustworthy/crypto_spec.rb +0 -42
data/lib/trustworthy/settings.rb
CHANGED
@@ -1,63 +1,56 @@
|
|
1
1
|
module Trustworthy
|
2
2
|
class Settings
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
new(yaml['keys'], yaml['secrets'])
|
3
|
+
def self.open(filename)
|
4
|
+
store = YAML::Store.new(filename)
|
5
|
+
store.transaction do
|
6
|
+
yield Trustworthy::Settings.new(store)
|
7
|
+
end
|
9
8
|
end
|
10
9
|
|
11
|
-
def initialize(
|
12
|
-
@
|
13
|
-
@secrets = secrets
|
10
|
+
def initialize(store)
|
11
|
+
@store = store
|
14
12
|
end
|
15
13
|
|
16
14
|
def add_key(key, username, password)
|
17
15
|
salt = SCrypt::Engine.generate_salt
|
18
16
|
|
19
|
-
|
17
|
+
cipher = _cipher_from_password(salt, password)
|
18
|
+
nonce = Trustworthy::Cipher.generate_nonce
|
20
19
|
plaintext = "#{key.x.to_s('F')},#{key.y.to_s('F')}"
|
21
|
-
ciphertext =
|
20
|
+
ciphertext = cipher.encrypt(nonce, '', plaintext)
|
22
21
|
|
23
|
-
@
|
22
|
+
@store[username] = {
|
24
23
|
'salt' => salt,
|
25
|
-
'
|
26
|
-
'authentication' => crypto.sign(ciphertext)
|
24
|
+
'encrypted_point' => nonce + ciphertext,
|
27
25
|
}
|
28
26
|
end
|
29
27
|
|
30
|
-
def
|
31
|
-
@
|
28
|
+
def empty?
|
29
|
+
@store.roots.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_key(username)
|
33
|
+
@store[username]
|
32
34
|
end
|
33
35
|
|
34
36
|
def unlock_key(username, password)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
key = find_key(username)
|
38
|
+
salt = key['salt']
|
39
|
+
ciphertext = key['encrypted_point']
|
40
|
+
ciphertext.force_encoding('BINARY') if ciphertext.respond_to?(:force_encoding)
|
41
|
+
nonce = ciphertext.slice(0, Trustworthy::Cipher.nonce_len)
|
42
|
+
ciphertext = ciphertext.slice(Trustworthy::Cipher.nonce_len..-1)
|
43
|
+
|
44
|
+
cipher = _cipher_from_password(salt, password)
|
45
|
+
plaintext = cipher.decrypt(nonce, '', ciphertext)
|
42
46
|
x, y = plaintext.split(',').map { |n| BigDecimal.new(n) }
|
43
47
|
Trustworthy::Key.new(x, y)
|
44
48
|
end
|
45
49
|
|
46
|
-
def
|
47
|
-
File.open(filename, 'w') do |file|
|
48
|
-
data = YAML.dump('keys' => @keys, 'secrets' => @secrets)
|
49
|
-
file.write(data)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def _crypto_from_password(salt, password)
|
50
|
+
def _cipher_from_password(salt, password)
|
54
51
|
cost, salt = salt.rpartition('$')
|
55
|
-
|
56
|
-
|
57
|
-
encryption_key = raw_key.slice(0, 32)
|
58
|
-
authentication_key = raw_key.slice(32, 32)
|
59
|
-
|
60
|
-
Trustworthy::Crypto.new(encryption_key, authentication_key)
|
52
|
+
key = SCrypt::Engine.scrypt(password, salt, cost, 64)
|
53
|
+
Trustworthy::Cipher.new(key)
|
61
54
|
end
|
62
55
|
end
|
63
56
|
end
|
data/lib/trustworthy/version.rb
CHANGED
data/lib/trustworthy.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
|
+
require 'aead'
|
1
2
|
require 'bigdecimal'
|
2
3
|
require 'hkdf'
|
3
|
-
require 'openssl'
|
4
|
-
require 'posix/spawn'
|
5
4
|
require 'scrypt'
|
6
5
|
require 'securerandom'
|
7
|
-
require 'trustworthy/crypto'
|
8
6
|
require 'trustworthy/key'
|
9
7
|
require 'trustworthy/master_key'
|
10
8
|
require 'trustworthy/random'
|
11
9
|
require 'trustworthy/settings'
|
12
10
|
require 'trustworthy/version'
|
13
|
-
require 'yaml'
|
11
|
+
require 'yaml/store'
|
12
|
+
|
13
|
+
module Trustworthy
|
14
|
+
CipherAlgorithm = 'AES-256-CBC-HMAC-SHA-256'
|
15
|
+
Cipher = AEAD::Cipher.new(CipherAlgorithm)
|
16
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,18 +1,30 @@
|
|
1
|
-
require 'fakefs/safe'
|
2
|
-
|
3
1
|
require 'trustworthy'
|
2
|
+
require 'trustworthy/cli'
|
3
|
+
require 'construct'
|
4
|
+
require 'highline/simulate'
|
4
5
|
|
5
6
|
RSpec.configure do |config|
|
6
7
|
config.order = 'random'
|
8
|
+
config.include Construct::Helpers
|
7
9
|
config.before(:each) do
|
8
10
|
Trustworthy::Random.stub(:_source).and_return('/dev/urandom')
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
12
|
-
module
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
module TestValues
|
15
|
+
SettingsFile = 'trustworthy.yml'
|
16
|
+
InitializationVector = ['39164ec082fb8b7336d3c5500af99dcb'].pack('H*')
|
17
|
+
Plaintext = 'the chair is against the wall'
|
18
|
+
Ciphertext = ['39164ec082fb8b7336d3c5500af99dcb6f5eac5d817a65b8ac7c5ed80691db36904e1ce613a1057d807b37127d927a4b0a9a1b951ef576fc9a9edca0ef5b83e2bae850a8b3b79bfeddff892d1941d439'].pack('H*')
|
19
|
+
Salt = '400$8$1b$3e31f076a3226825'
|
20
|
+
MasterKey = Trustworthy::MasterKey.new(BigDecimal.new('1'), BigDecimal.new('5'))
|
21
|
+
EncryptedPoint = ['39164ec082fb8b7336d3c5500af99dcb17d2e60496ed553dfab4b05c568aa9260cb8e53930911c8e718bc97eb88def400e5cac1e4ee3d15060920c25d1346285'].pack('H*')
|
22
|
+
EncryptedFile = ['39164ec082fb8b7336d3c5500af99dcba37f59607382f87a2da14881a9e1eabd23965d46d7c1a651b0c930cd0ee756d9358d67edaaba02a22e902136a2a90953672c2937b0cbaac0167922918578a98c'].pack('H*')
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_config(filename)
|
26
|
+
Trustworthy::Settings.open(filename) do |settings|
|
27
|
+
settings.add_key(TestValues::MasterKey.create_key, 'user1', 'password1')
|
28
|
+
settings.add_key(TestValues::MasterKey.create_key, 'user2', 'password2')
|
17
29
|
end
|
18
30
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Trustworthy::CLI::AddKey do
|
4
|
+
before(:each) do
|
5
|
+
$terminal.stub(:say)
|
6
|
+
end
|
7
|
+
|
8
|
+
around(:each) do |example|
|
9
|
+
within_construct do |construct|
|
10
|
+
construct.file(TestValues::SettingsFile)
|
11
|
+
create_config(TestValues::SettingsFile)
|
12
|
+
example.run
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'run' do
|
17
|
+
it 'should add a new user' do
|
18
|
+
HighLine::Simulate.with(
|
19
|
+
'user1',
|
20
|
+
'password1',
|
21
|
+
'user2',
|
22
|
+
'password2',
|
23
|
+
'user3',
|
24
|
+
'password3',
|
25
|
+
'password3'
|
26
|
+
) do
|
27
|
+
Trustworthy::CLI::AddKey.new.run([])
|
28
|
+
end
|
29
|
+
|
30
|
+
contents = File.read(TestValues::SettingsFile)
|
31
|
+
subkeys = YAML.load(contents)
|
32
|
+
subkeys.should have_key('user1')
|
33
|
+
subkeys.should have_key('user2')
|
34
|
+
subkeys.should have_key('user3')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,114 @@
|
|
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
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Trustworthy::CLI::Decrypt do
|
4
|
+
before(:each) do
|
5
|
+
$terminal.stub(:say)
|
6
|
+
end
|
7
|
+
|
8
|
+
around(:each) do |example|
|
9
|
+
within_construct do |construct|
|
10
|
+
construct.file(TestValues::SettingsFile)
|
11
|
+
construct.file('input.txt', TestValues::EncryptedFile)
|
12
|
+
construct.file('output.txt')
|
13
|
+
create_config(TestValues::SettingsFile)
|
14
|
+
example.run
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'run' do
|
19
|
+
it 'should unlock the master key and decrypt the file' do
|
20
|
+
HighLine::Simulate.with(
|
21
|
+
'user1',
|
22
|
+
'password1',
|
23
|
+
'user2',
|
24
|
+
'password2'
|
25
|
+
) do
|
26
|
+
Trustworthy::CLI::Decrypt.new.run(['-i', 'input.txt', '-o', 'output.txt'])
|
27
|
+
end
|
28
|
+
|
29
|
+
File.open('output.txt', 'rb') do |file|
|
30
|
+
ciphertext = file.read
|
31
|
+
ciphertext.should == TestValues::Plaintext
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should require an input file' do
|
36
|
+
HighLine::Simulate.with(
|
37
|
+
'user1',
|
38
|
+
'password1',
|
39
|
+
'user2',
|
40
|
+
'password2'
|
41
|
+
) do
|
42
|
+
decrypt = Trustworthy::CLI::Encrypt.new
|
43
|
+
decrypt.should_receive(:error).with('Must provide an input file')
|
44
|
+
decrypt.should_receive(:print_help)
|
45
|
+
decrypt.run([])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should require an output file' do
|
50
|
+
HighLine::Simulate.with(
|
51
|
+
'user1',
|
52
|
+
'password1',
|
53
|
+
'user2',
|
54
|
+
'password2'
|
55
|
+
) do
|
56
|
+
decrypt = Trustworthy::CLI::Encrypt.new
|
57
|
+
decrypt.should_receive(:error).with('Must provide an output file')
|
58
|
+
decrypt.should_receive(:print_help)
|
59
|
+
decrypt.run(['-i', 'input.txt'])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Trustworthy::CLI::Encrypt do
|
4
|
+
before(:each) do
|
5
|
+
$terminal.stub(:say)
|
6
|
+
AEAD::Cipher::AES_256_CBC_HMAC_SHA_256.stub(:generate_nonce).and_return(TestValues::InitializationVector)
|
7
|
+
end
|
8
|
+
|
9
|
+
around(:each) do |example|
|
10
|
+
within_construct do |construct|
|
11
|
+
construct.file(TestValues::SettingsFile)
|
12
|
+
construct.file('input.txt', TestValues::Plaintext)
|
13
|
+
construct.file('output.txt')
|
14
|
+
create_config(TestValues::SettingsFile)
|
15
|
+
example.run
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'run' do
|
20
|
+
it 'should unlock the master key and encrypt the file' do
|
21
|
+
HighLine::Simulate.with(
|
22
|
+
'user1',
|
23
|
+
'password1',
|
24
|
+
'user2',
|
25
|
+
'password2'
|
26
|
+
) do
|
27
|
+
Trustworthy::CLI::Encrypt.new.run(['-i', 'input.txt', '-o', 'output.txt'])
|
28
|
+
end
|
29
|
+
|
30
|
+
File.open('output.txt', 'rb') do |file|
|
31
|
+
ciphertext = file.read
|
32
|
+
ciphertext.should == TestValues::EncryptedFile
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should require an input file' do
|
37
|
+
HighLine::Simulate.with(
|
38
|
+
'user1',
|
39
|
+
'password1',
|
40
|
+
'user2',
|
41
|
+
'password2'
|
42
|
+
) do
|
43
|
+
encrypt = Trustworthy::CLI::Encrypt.new
|
44
|
+
encrypt.should_receive(:error).with('Must provide an input file')
|
45
|
+
encrypt.should_receive(:print_help)
|
46
|
+
encrypt.run([])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should require an output file' do
|
51
|
+
HighLine::Simulate.with(
|
52
|
+
'user1',
|
53
|
+
'password1',
|
54
|
+
'user2',
|
55
|
+
'password2'
|
56
|
+
) do
|
57
|
+
encrypt = Trustworthy::CLI::Encrypt.new
|
58
|
+
encrypt.should_receive(:error).with('Must provide an output file')
|
59
|
+
encrypt.should_receive(:print_help)
|
60
|
+
encrypt.run(['-i', 'input.txt'])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Trustworthy::CLI::Init do
|
4
|
+
before(:each) do
|
5
|
+
$terminal.stub(:say)
|
6
|
+
end
|
7
|
+
|
8
|
+
around(:each) do |example|
|
9
|
+
within_construct do |construct|
|
10
|
+
construct.file(TestValues::SettingsFile)
|
11
|
+
example.run
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'run' do
|
16
|
+
it 'should not allow any previous keys to exist' do
|
17
|
+
create_config(TestValues::SettingsFile)
|
18
|
+
$terminal.should_receive(:say).with(/Config trustworthy\.yml already exists/)
|
19
|
+
Trustworthy::CLI::Init.new.run([])
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should write a settings file' do
|
23
|
+
HighLine::Simulate.with(
|
24
|
+
'user1',
|
25
|
+
'password1',
|
26
|
+
'password1',
|
27
|
+
'user2',
|
28
|
+
'password2',
|
29
|
+
'password2'
|
30
|
+
) do
|
31
|
+
Trustworthy::CLI::Init.new.run([])
|
32
|
+
end
|
33
|
+
|
34
|
+
contents = File.read(TestValues::SettingsFile)
|
35
|
+
subkeys = YAML.load(contents)
|
36
|
+
subkeys.should have_key('user1')
|
37
|
+
subkeys.should have_key('user2')
|
38
|
+
end
|
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
|
+
it 'should write to a specified file' do
|
61
|
+
filename = 'test.yml'
|
62
|
+
within_construct do |construct|
|
63
|
+
construct.file(filename)
|
64
|
+
HighLine::Simulate.with(
|
65
|
+
'user1',
|
66
|
+
'password1',
|
67
|
+
'password1',
|
68
|
+
'user2',
|
69
|
+
'password2',
|
70
|
+
'password2'
|
71
|
+
) do
|
72
|
+
Trustworthy::CLI::Init.new.run(['-c', filename])
|
73
|
+
end
|
74
|
+
|
75
|
+
contents = File.read(filename)
|
76
|
+
subkeys = YAML.load(contents)
|
77
|
+
subkeys.should have_key('user1')
|
78
|
+
subkeys.should have_key('user2')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should generate the specified number of keys' do
|
83
|
+
HighLine::Simulate.with(
|
84
|
+
'user1',
|
85
|
+
'password1',
|
86
|
+
'password1',
|
87
|
+
'user2',
|
88
|
+
'password2',
|
89
|
+
'password2',
|
90
|
+
'user3',
|
91
|
+
'password3',
|
92
|
+
'password3'
|
93
|
+
) do
|
94
|
+
Trustworthy::CLI::Init.new.run(['-k', '3'])
|
95
|
+
end
|
96
|
+
|
97
|
+
contents = File.read(TestValues::SettingsFile)
|
98
|
+
subkeys = YAML.load(contents)
|
99
|
+
subkeys.should have_key('user1')
|
100
|
+
subkeys.should have_key('user2')
|
101
|
+
subkeys.should have_key('user3')
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should require two subkeys minimum' do
|
105
|
+
init = Trustworthy::CLI::Init.new
|
106
|
+
init.should_receive(:error).with('Must generate at least two keys')
|
107
|
+
init.should_receive(:print_help)
|
108
|
+
init.run(['-k', '1'])
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -6,11 +6,11 @@ describe Trustworthy::MasterKey do
|
|
6
6
|
key1 = master_key.create_key
|
7
7
|
key2 = master_key.create_key
|
8
8
|
|
9
|
-
ciphertext = master_key.encrypt(
|
9
|
+
ciphertext = master_key.encrypt(TestValues::Plaintext)
|
10
10
|
|
11
11
|
new_master_key = Trustworthy::MasterKey.create_from_keys(key1, key2)
|
12
12
|
plaintext = new_master_key.decrypt(ciphertext)
|
13
|
-
plaintext.should ==
|
13
|
+
plaintext.should == TestValues::Plaintext
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'should function with any 2 of n keys' do
|
@@ -18,14 +18,14 @@ describe Trustworthy::MasterKey do
|
|
18
18
|
key1 = master_key1.create_key
|
19
19
|
key2 = master_key1.create_key
|
20
20
|
|
21
|
-
ciphertext = master_key1.encrypt(
|
21
|
+
ciphertext = master_key1.encrypt(TestValues::Plaintext)
|
22
22
|
|
23
23
|
master_key2 = Trustworthy::MasterKey.create_from_keys(key1, key2)
|
24
24
|
key3 = master_key2.create_key
|
25
25
|
|
26
26
|
master_key3 = Trustworthy::MasterKey.create_from_keys(key1, key3)
|
27
27
|
plaintext = master_key3.decrypt(ciphertext)
|
28
|
-
plaintext.should ==
|
28
|
+
plaintext.should == TestValues::Plaintext
|
29
29
|
end
|
30
30
|
|
31
31
|
describe 'self.create' do
|
@@ -63,25 +63,25 @@ describe Trustworthy::MasterKey do
|
|
63
63
|
|
64
64
|
describe 'encrypt' do
|
65
65
|
it 'should encrypt and sign the data using the intercept' do
|
66
|
-
|
66
|
+
AEAD::Cipher::AES_256_CBC_HMAC_SHA_256.stub(:generate_nonce).and_return(TestValues::InitializationVector)
|
67
67
|
master_key = Trustworthy::MasterKey.new(BigDecimal.new('6'), BigDecimal.new('24'))
|
68
|
-
ciphertext = master_key.encrypt(
|
69
|
-
ciphertext.should ==
|
68
|
+
ciphertext = master_key.encrypt(TestValues::Plaintext)
|
69
|
+
ciphertext.should == TestValues::Ciphertext
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
73
|
describe 'decrypt' do
|
74
74
|
it 'should decrypt and verify the data using the intercept' do
|
75
75
|
master_key = Trustworthy::MasterKey.new(BigDecimal.new('6'), BigDecimal.new('24'))
|
76
|
-
|
77
|
-
plaintext
|
78
|
-
plaintext.should == 'foobar'
|
76
|
+
plaintext = master_key.decrypt(TestValues::Ciphertext)
|
77
|
+
plaintext.should == TestValues::Plaintext
|
79
78
|
end
|
80
79
|
|
81
80
|
it 'should raise an invalid signature error if signatures do not match' do
|
82
81
|
master_key = Trustworthy::MasterKey.new(BigDecimal.new('6'), BigDecimal.new('24'))
|
83
|
-
ciphertext =
|
84
|
-
expect { master_key.decrypt(ciphertext) }.to raise_error('
|
82
|
+
ciphertext = TestValues::Ciphertext.next
|
83
|
+
expect { master_key.decrypt(ciphertext) }.to raise_error(ArgumentError, 'ciphertext failed authentication step')
|
85
84
|
end
|
86
85
|
end
|
87
86
|
end
|
87
|
+
|