slosilo 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +109 -3
- data/lib/slosilo/version.rb +1 -1
- data/slosilo.gemspec +2 -2
- data/spec/file_adapter_spec.rb +10 -10
- data/spec/key_spec.rb +57 -37
- data/spec/keystore_spec.rb +2 -2
- data/spec/random_spec.rb +12 -2
- data/spec/sequel_adapter_spec.rb +26 -30
- data/spec/slosilo_spec.rb +15 -15
- data/spec/spec_helper.rb +1 -19
- data/spec/symmetric_spec.rb +9 -9
- metadata +26 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 19532fb817cc0d993257331452fd6fc36be49da8
|
4
|
+
data.tar.gz: 63c9b867b4e125aff0e5680e21a9a31605629716
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 799000b32ea19b4b5ca3fb63901007e16c659af8ea383f3d469ed4a91a1c23b10529eeffda3167b73e0bf67043258622c997b68fefd110cf5fb96cedc8b3769c
|
7
|
+
data.tar.gz: c017465fd76fd4aa9812924ead3c3342d66d3f87f222cd94c0f08c0eadd2dd66c7088e3bc5333ae6d4a83f165c2329456cc38158b2de5d17e76dd1fe0d098449
|
data/README.md
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
# Slosilo
|
2
2
|
|
3
|
-
Slosilo is a
|
4
|
-
|
3
|
+
Slosilo is providing a ruby interface to some cryptographic primitives:
|
4
|
+
- symmetric encryption,
|
5
|
+
- a mixin for easy encryption of object attributes (WARNING: unauthenticated, see below),
|
6
|
+
- asymmetric encryption and signing,
|
7
|
+
- a keystore in a postgres sequel db -- it allows easy storage and retrieval of keys,
|
8
|
+
- a keystore in files.
|
5
9
|
|
6
10
|
## Installation
|
7
11
|
|
@@ -13,6 +17,105 @@ And then execute:
|
|
13
17
|
|
14
18
|
$ bundle
|
15
19
|
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
### Symmetric encryption
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
sym = Slosilo::Symmetric.new
|
26
|
+
key = sym.random_key
|
27
|
+
ciphertext = sym.encrypt "secret message", key: key
|
28
|
+
```
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
sym = Slosilo::Symmetric.new
|
32
|
+
message = sym.decrypt ciphertext, key: key
|
33
|
+
```
|
34
|
+
|
35
|
+
### Encryption mixin
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
require 'slosilo'
|
39
|
+
|
40
|
+
class Foo
|
41
|
+
attr_accessor :foo
|
42
|
+
attr_encrypted :foo
|
43
|
+
|
44
|
+
def raw_foo
|
45
|
+
@foo
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Slosilo::encryption_key = Slosilo::Symmetric.new.random_key
|
50
|
+
|
51
|
+
obj = Foo.new
|
52
|
+
obj.foo = "bar"
|
53
|
+
obj.raw_foo # => "\xC4\xEF\x87\xD3b\xEA\x12\xDF\xD0\xD4hk\xEDJ\v\x1Cr\xF2#\xA3\x11\xA4*k\xB7\x8F\x8F\xC2\xBD\xBB\xFF\xE3"
|
54
|
+
obj.foo # => "bar"
|
55
|
+
```
|
56
|
+
|
57
|
+
You can safely use it in ie. ActiveRecord::Base or Sequel::Model subclasses.
|
58
|
+
|
59
|
+
#### Warning
|
60
|
+
|
61
|
+
The encrypted data is not authenticated; it's intended to prevent
|
62
|
+
opportunistic access to secrets by a third party which gets hold of a database
|
63
|
+
dump. *IT DOES NOT prevent tampering.* If your threat model includes an attacker
|
64
|
+
which can modify the database, `attr_encrypted` by itself IS NOT SECURE.
|
65
|
+
|
66
|
+
### Asymmetric encryption and signing
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
private_key = Slosilo::Key.new
|
70
|
+
public_key = private_key.public
|
71
|
+
```
|
72
|
+
|
73
|
+
#### Key dumping
|
74
|
+
```ruby
|
75
|
+
k = public_key.to_s # => "-----BEGIN PUBLIC KEY----- ...
|
76
|
+
(Slosilo::Key.new k) == public_key # => true
|
77
|
+
```
|
78
|
+
|
79
|
+
#### Encryption
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
encrypted = public_key.encrypt_message "eagle one sees many clouds"
|
83
|
+
# => "\xA3\x1A\xD2\xFC\xB0 ...
|
84
|
+
|
85
|
+
public_key.decrypt_message encrypted
|
86
|
+
# => OpenSSL::PKey::RSAError: private key needed.
|
87
|
+
|
88
|
+
private_key.decrypt_message encrypted
|
89
|
+
# => "eagle one sees many clouds"
|
90
|
+
```
|
91
|
+
|
92
|
+
#### Signing
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
token = private_key.signed_token "missile launch not authorized"
|
96
|
+
# => {"data"=>"missile launch not authorized", "timestamp"=>"2014-10-13 12:41:25 UTC", "signature"=>"bSImk...DzV3o", "key"=>"455f7ac42d2d483f750b4c380761821d"}
|
97
|
+
|
98
|
+
public_key.token_valid? token # => true
|
99
|
+
|
100
|
+
token["data"] = "missile launch authorized"
|
101
|
+
public_key.token_valid? token # => false
|
102
|
+
```
|
103
|
+
|
104
|
+
### Keystore
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
Slosilo::encryption_key = ENV['SLOSILO_KEY']
|
108
|
+
Slosilo.adapter = Slosilo::Adapters::FileAdapter.new "~/.keys"
|
109
|
+
|
110
|
+
Slosilo[:own] = Slosilo::Key.new
|
111
|
+
Slosilo[:their] = Slosilo::Key.new File.read("foo.pem")
|
112
|
+
|
113
|
+
msg = Slosilo[:their].encrypt_message 'bar'
|
114
|
+
p Slosilo[:own].signed_token msg
|
115
|
+
```
|
116
|
+
|
117
|
+
### Keystore in database
|
118
|
+
|
16
119
|
Add a migration to create the necessary table:
|
17
120
|
|
18
121
|
require 'slosilo/adapters/sequel_adapter/migration'
|
@@ -21,7 +124,10 @@ Remember to migrate your database
|
|
21
124
|
|
22
125
|
$ rake db:migrate
|
23
126
|
|
24
|
-
|
127
|
+
Then
|
128
|
+
```ruby
|
129
|
+
Slosilo.adapter = Slosilo::Adapters::SequelAdapter.new
|
130
|
+
```
|
25
131
|
|
26
132
|
## Contributing
|
27
133
|
|
data/lib/slosilo/version.rb
CHANGED
data/slosilo.gemspec
CHANGED
@@ -18,8 +18,8 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.required_ruby_version = '>= 1.9.3'
|
19
19
|
|
20
20
|
gem.add_development_dependency 'rake'
|
21
|
-
gem.add_development_dependency 'rspec', '~>
|
22
|
-
gem.add_development_dependency '
|
21
|
+
gem.add_development_dependency 'rspec', '~> 3.0'
|
22
|
+
gem.add_development_dependency 'ci_reporter_rspec'
|
23
23
|
gem.add_development_dependency 'simplecov'
|
24
24
|
gem.add_development_dependency 'io-grab', '~> 0.0.1'
|
25
25
|
gem.add_development_dependency 'sequel' # for sequel tests
|
data/spec/file_adapter_spec.rb
CHANGED
@@ -13,7 +13,7 @@ describe Slosilo::Adapters::FileAdapter do
|
|
13
13
|
describe "#get_key" do
|
14
14
|
context "when given key does not exist" do
|
15
15
|
it "returns nil" do
|
16
|
-
subject.get_key(:whatever).
|
16
|
+
expect(subject.get_key(:whatever)).not_to be
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -22,7 +22,7 @@ describe Slosilo::Adapters::FileAdapter do
|
|
22
22
|
context "unacceptable id" do
|
23
23
|
let(:id) { "foo.bar" }
|
24
24
|
it "isn't accepted" do
|
25
|
-
|
25
|
+
expect { subject.put_key id, key }.to raise_error
|
26
26
|
end
|
27
27
|
end
|
28
28
|
context "acceptable id" do
|
@@ -30,11 +30,11 @@ describe Slosilo::Adapters::FileAdapter do
|
|
30
30
|
let(:key_encrypted) { "encrypted key" }
|
31
31
|
let(:fname) { "#{dir}/#{id}.key" }
|
32
32
|
it "creates the key" do
|
33
|
-
Slosilo::EncryptedAttributes.
|
34
|
-
File.
|
35
|
-
File.
|
33
|
+
expect(Slosilo::EncryptedAttributes).to receive(:encrypt).with(key.to_der).and_return key_encrypted
|
34
|
+
expect(File).to receive(:write).with(fname, key_encrypted)
|
35
|
+
expect(File).to receive(:chmod).with(0400, fname)
|
36
36
|
subject.put_key id, key
|
37
|
-
subject.instance_variable_get("@keys")[id].
|
37
|
+
expect(subject.instance_variable_get("@keys")[id]).to eq(key)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -45,7 +45,7 @@ describe Slosilo::Adapters::FileAdapter do
|
|
45
45
|
it "iterates over each key" do
|
46
46
|
results = []
|
47
47
|
adapter.each { |id,k| results << { id => k } }
|
48
|
-
results.
|
48
|
+
expect(results).to eq([ { one: :onek}, {two: :twok } ])
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -60,13 +60,13 @@ describe Slosilo::Adapters::FileAdapter do
|
|
60
60
|
|
61
61
|
describe '#get_key' do
|
62
62
|
it "loads and decrypts the key" do
|
63
|
-
adapter.get_key(id).
|
63
|
+
expect(adapter.get_key(id)).to eq(key)
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
67
|
describe '#get_by_fingerprint' do
|
68
68
|
it "can look up a key by a fingerprint" do
|
69
|
-
adapter.get_by_fingerprint(key_fingerprint).
|
69
|
+
expect(adapter.get_by_fingerprint(key_fingerprint)).to eq([key, id])
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -74,7 +74,7 @@ describe Slosilo::Adapters::FileAdapter do
|
|
74
74
|
it "enumerates the keys" do
|
75
75
|
results = []
|
76
76
|
adapter.each { |id,k| results << { id => k } }
|
77
|
-
results.
|
77
|
+
expect(results).to eq([ { id => key } ])
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
data/spec/key_spec.rb
CHANGED
@@ -4,38 +4,50 @@ describe Slosilo::Key do
|
|
4
4
|
include_context "with example key"
|
5
5
|
|
6
6
|
subject { key }
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
|
8
|
+
describe '#to_der' do
|
9
|
+
subject { super().to_der }
|
10
|
+
it { is_expected.to eq(rsa.to_der) }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#to_s' do
|
14
|
+
subject { super().to_s }
|
15
|
+
it { is_expected.to eq(rsa.public_key.to_pem) }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#fingerprint' do
|
19
|
+
subject { super().fingerprint }
|
20
|
+
it { is_expected.to eq(key_fingerprint) }
|
21
|
+
end
|
22
|
+
it { is_expected.to be_private }
|
11
23
|
|
12
24
|
context "with identical key" do
|
13
25
|
let(:other) { Slosilo::Key.new rsa.to_der }
|
14
26
|
it "is equal" do
|
15
|
-
subject.
|
27
|
+
expect(subject).to eq(other)
|
16
28
|
end
|
17
29
|
|
18
30
|
it "is eql?" do
|
19
|
-
subject.eql?(other).
|
31
|
+
expect(subject.eql?(other)).to be_truthy
|
20
32
|
end
|
21
33
|
|
22
34
|
it "has equal hash" do
|
23
|
-
subject.hash.
|
35
|
+
expect(subject.hash).to eq(other.hash)
|
24
36
|
end
|
25
37
|
end
|
26
38
|
|
27
39
|
context "with a different key" do
|
28
40
|
let(:other) { Slosilo::Key.new another_rsa }
|
29
41
|
it "is not equal" do
|
30
|
-
subject.
|
42
|
+
expect(subject).not_to eq(other)
|
31
43
|
end
|
32
44
|
|
33
45
|
it "is not eql?" do
|
34
|
-
subject.eql?(other).
|
46
|
+
expect(subject.eql?(other)).not_to be_truthy
|
35
47
|
end
|
36
48
|
|
37
49
|
it "has different hash" do
|
38
|
-
subject.hash.
|
50
|
+
expect(subject.hash).not_to eq(other.hash)
|
39
51
|
end
|
40
52
|
end
|
41
53
|
|
@@ -54,14 +66,14 @@ describe Slosilo::Key do
|
|
54
66
|
it "generates a symmetric encryption key and encrypts the plaintext with the public key" do
|
55
67
|
ctxt, skey = subject.encrypt plaintext
|
56
68
|
pskey = rsa.private_decrypt skey
|
57
|
-
Slosilo::Symmetric.new.decrypt(ctxt, key: pskey).
|
69
|
+
expect(Slosilo::Symmetric.new.decrypt(ctxt, key: pskey)).to eq(plaintext)
|
58
70
|
end
|
59
71
|
end
|
60
72
|
|
61
73
|
describe '#encrypt_message' do
|
62
74
|
it "#encrypts a message and then returns the result as a single string" do
|
63
|
-
subject.
|
64
|
-
subject.encrypt_message(plaintext).
|
75
|
+
expect(subject).to receive(:encrypt).with(plaintext).and_return ['fake ciphertext', 'fake key']
|
76
|
+
expect(subject.encrypt_message(plaintext)).to eq('fake keyfake ciphertext')
|
65
77
|
end
|
66
78
|
end
|
67
79
|
|
@@ -69,14 +81,14 @@ describe Slosilo::Key do
|
|
69
81
|
let(:skey) { "\x15\xFF\xD4>\x9C\xF4\x0F\xB6\x04C\x18\xC1\x96\xC3\xE0T\xA3\xF5\xE8\x17\xA6\xE0\x86~rrw\xC3\xDF\x11)$\x9B\r@\x0E\xE4Zv\rw-\xFC\x1C\x84\x17\xBD\xDB\x12u\xCD\r\xFEo\xD5\xC8[\x8FEA\\\xA9\xA2F#\x8BH -\xFA\xF7\xA9\xEBf\x97\xAAT}\x8E*\xC0r\x944p\xD0\x9A\xE7\xBD\a;O\f\xEF\xE4B.y\xFA\xB4e@O\xBB\x15>y\xC9\t=\x01\xE1J\xF3X\xA9\x9E3\x04^H\x1F\xFF\x19C\x93ve)@\xF7\t_\xCF\xDE\xF1\xB7]\x83lL\xB8%A\x93p{\xE9Y\xBAu\xCE\x99T\xDC\xDF\xE7\x0FD%\xB9AXb\x1CW\x94$P\xBB\xE1g\xDEE\t\xC4\x92\x9E\xFEt\xDF\xD0\xEA\x03\xC4\x12\xA9\x02~u\xF4\x92 ;\xA0\xCE.\b+)\x05\xEDo\xA5cF\xF8\x12\xD7F\x97\xE44\xBF\xF1@\xA5\xC5\xA8\xE5\a\xE8ra<\x04\xB5\xA2\f\t\xF7T\x97\e\xF5(^\xAB\xA5%84\x10\xD1\x13e<\xCA/\xBF}%\xF6\xB1%\xB2".force_encoding("ASCII-8BIT") }
|
70
82
|
describe '#decrypt' do
|
71
83
|
it "decrypts the symmetric key and then uses it to decrypt the ciphertext" do
|
72
|
-
subject.decrypt(ciphertext, skey).
|
84
|
+
expect(subject.decrypt(ciphertext, skey)).to eq(plaintext)
|
73
85
|
end
|
74
86
|
end
|
75
87
|
|
76
88
|
describe '#decrypt_message' do
|
77
89
|
it "splits the message into key and rest, then #decrypts it" do
|
78
|
-
subject.
|
79
|
-
subject.decrypt_message(skey + ciphertext).
|
90
|
+
expect(subject).to receive(:decrypt).with(ciphertext, skey).and_return plaintext
|
91
|
+
expect(subject.decrypt_message(skey + ciphertext)).to eq(plaintext)
|
80
92
|
end
|
81
93
|
end
|
82
94
|
|
@@ -85,17 +97,25 @@ describe Slosilo::Key do
|
|
85
97
|
subject { Slosilo::Key.new }
|
86
98
|
let (:rsa) { double "key" }
|
87
99
|
it "generates a new key pair" do
|
88
|
-
OpenSSL::PKey::RSA.
|
89
|
-
subject.key.
|
100
|
+
expect(OpenSSL::PKey::RSA).to receive(:new).with(2048).and_return(rsa)
|
101
|
+
expect(subject.key).to eq(rsa)
|
90
102
|
end
|
91
103
|
end
|
92
104
|
context "when given an armored key" do
|
93
105
|
subject { Slosilo::Key.new rsa.to_der }
|
94
|
-
|
106
|
+
|
107
|
+
describe '#to_der' do
|
108
|
+
subject { super().to_der }
|
109
|
+
it { is_expected.to eq(rsa.to_der) }
|
110
|
+
end
|
95
111
|
end
|
96
112
|
context "when given a key instance" do
|
97
113
|
subject { Slosilo::Key.new rsa }
|
98
|
-
|
114
|
+
|
115
|
+
describe '#to_der' do
|
116
|
+
subject { super().to_der }
|
117
|
+
it { is_expected.to eq(rsa.to_der) }
|
118
|
+
end
|
99
119
|
end
|
100
120
|
context "when given something else" do
|
101
121
|
subject { Slosilo::Key.new "foo" }
|
@@ -108,21 +128,21 @@ describe Slosilo::Key do
|
|
108
128
|
describe "#sign" do
|
109
129
|
context "when given a hash" do
|
110
130
|
it "converts to a sorted array and signs that" do
|
111
|
-
key.
|
131
|
+
expect(key).to receive(:sign_string).with '[["a",3],["b",42]]'
|
112
132
|
key.sign b: 42, a: 3
|
113
133
|
end
|
114
134
|
end
|
115
135
|
context "when given an array" do
|
116
136
|
it "signs a JSON representation instead" do
|
117
|
-
key.
|
137
|
+
expect(key).to receive(:sign_string).with '[2,[42,2]]'
|
118
138
|
key.sign [2, [42, 2]]
|
119
139
|
end
|
120
140
|
end
|
121
141
|
context "when given a string" do
|
122
142
|
let(:expected_signature) { "d[\xA4\x00\x02\xC5\x17\xF5P\x1AD\x91\xF9\xC1\x00P\x0EG\x14,IN\xDE\x17\xE1\xA2a\xCC\xABR\x99'\xB0A\xF5~\x93M/\x95-B\xB1\xB6\x92!\x1E\xEA\x9C\v\xC2O\xA8\x91\x1C\xF9\x11\x92a\xBFxm-\x93\x9C\xBBoM\x92%\xA9\xD06$\xC1\xBC.`\xF8\x03J\x16\xE1\xB0c\xDD\xBF\xB0\xAA\xD7\xD4\xF4\xFC\e*\xAB\x13A%-\xD3\t\xA5R\x18\x01let6\xC8\xE9\"\x7F6O\xC7p\x82\xAB\x04J(IY\xAA]b\xA4'\xD6\x873`\xAB\x13\x95g\x9C\x17\xCAB\xF8\xB9\x85B:^\xC5XY^\x03\xEA\xB6V\x17b2\xCA\xF5\xD6\xD4\xD2\xE3u\x11\xECQ\x0Fb\x14\xE2\x04\xE1<a\xC5\x01eW-\x15\x01X\x81K\x1A\xE5A\vVj\xBF\xFC\xFE#\xD5\x93y\x16\xDC\xB4\x8C\xF0\x02Y\xA8\x87i\x01qC\xA7#\xE8\f\xA5\xF0c\xDEJ\xB0\xDB BJ\x87\xA4\xB0\x92\x80\x03\x95\xEE\xE9\xB8K\xC0\xE3JbE-\xD4\xCBP\\\x13S\"\eZ\xE1\x93\xFDa pinch of salt".force_encoding("ASCII-8BIT") }
|
123
143
|
it "signs it" do
|
124
|
-
key.
|
125
|
-
key.sign("this sentence is not this sentence").
|
144
|
+
allow(key).to receive_messages shake_salt: 'a pinch of salt'
|
145
|
+
expect(key.sign("this sentence is not this sentence")).to eq(expected_signature)
|
126
146
|
end
|
127
147
|
end
|
128
148
|
end
|
@@ -136,44 +156,44 @@ describe Slosilo::Key do
|
|
136
156
|
let(:expected_signature) { Base64::urlsafe_encode64 "\xB0\xCE{\x9FP\xEDV\x9C\xE7b\x8B[\xFAil\x87^\x96\x17Z\x97\x1D\xC2?B\x96\x9C\x8Ep-\xDF_\x8F\xC21\xD9^\xBC\n\x16\x04\x8DJ\xF6\xAF-\xEC\xAD\x03\xF9\xEE:\xDF\xB5\x8F\xF9\xF6\x81m\xAB\x9C\xAB1\x1E\x837\x8C\xFB\xA8P\xA8<\xEA\x1Dx\xCEd\xED\x84f\xA7\xB5t`\x96\xCC\x0F\xA9t\x8B\x9Fo\xBF\x92K\xFA\xFD\xC5?\x8F\xC68t\xBC\x9F\xDE\n$\xCA\xD2\x8F\x96\x0EtX2\x8Cl\x1E\x8Aa\r\x8D\xCAi\x86\x1A\xBD\x1D\xF7\xBC\x8561j\x91YlO\xFA(\x98\x10iq\xCC\xAF\x9BV\xC6\v\xBC\x10Xm\xCD\xFE\xAD=\xAA\x95,\xB4\xF7\xE8W\xB8\x83;\x81\x88\xE6\x01\xBA\xA5F\x91\x17\f\xCE\x80\x8E\v\x83\x9D<\x0E\x83\xF6\x8D\x03\xC0\xE8A\xD7\x90i\x1D\x030VA\x906D\x10\xA0\xDE\x12\xEF\x06M\xD8\x8B\xA9W\xC8\x9DTc\x8AJ\xA4\xC0\xD3!\xFA\x14\x89\xD1p\xB4J7\xA5\x04\xC2l\xDC8<\x04Y\xD8\xA4\xFB[\x89\xB1\xEC\xDA\xB8\xD7\xEA\x03Ja pinch of salt".force_encoding("ASCII-8BIT") }
|
137
157
|
let(:expected_token) { token_to_sign.merge "signature" => expected_signature, "key" => key_fingerprint }
|
138
158
|
before do
|
139
|
-
key.
|
140
|
-
Time.
|
159
|
+
allow(key).to receive_messages shake_salt: salt
|
160
|
+
allow(Time).to receive_messages new: time
|
141
161
|
end
|
142
162
|
subject { key.signed_token data }
|
143
|
-
it {
|
163
|
+
it { is_expected.to eq(expected_token) }
|
144
164
|
end
|
145
165
|
|
146
166
|
describe "#token_valid?" do
|
147
167
|
let(:data) { { "foo" => :bar } }
|
148
168
|
let(:signature) { Base64::urlsafe_encode64 "\xB0\xCE{\x9FP\xEDV\x9C\xE7b\x8B[\xFAil\x87^\x96\x17Z\x97\x1D\xC2?B\x96\x9C\x8Ep-\xDF_\x8F\xC21\xD9^\xBC\n\x16\x04\x8DJ\xF6\xAF-\xEC\xAD\x03\xF9\xEE:\xDF\xB5\x8F\xF9\xF6\x81m\xAB\x9C\xAB1\x1E\x837\x8C\xFB\xA8P\xA8<\xEA\x1Dx\xCEd\xED\x84f\xA7\xB5t`\x96\xCC\x0F\xA9t\x8B\x9Fo\xBF\x92K\xFA\xFD\xC5?\x8F\xC68t\xBC\x9F\xDE\n$\xCA\xD2\x8F\x96\x0EtX2\x8Cl\x1E\x8Aa\r\x8D\xCAi\x86\x1A\xBD\x1D\xF7\xBC\x8561j\x91YlO\xFA(\x98\x10iq\xCC\xAF\x9BV\xC6\v\xBC\x10Xm\xCD\xFE\xAD=\xAA\x95,\xB4\xF7\xE8W\xB8\x83;\x81\x88\xE6\x01\xBA\xA5F\x91\x17\f\xCE\x80\x8E\v\x83\x9D<\x0E\x83\xF6\x8D\x03\xC0\xE8A\xD7\x90i\x1D\x030VA\x906D\x10\xA0\xDE\x12\xEF\x06M\xD8\x8B\xA9W\xC8\x9DTc\x8AJ\xA4\xC0\xD3!\xFA\x14\x89\xD1p\xB4J7\xA5\x04\xC2l\xDC8<\x04Y\xD8\xA4\xFB[\x89\xB1\xEC\xDA\xB8\xD7\xEA\x03Ja pinch of salt".force_encoding("ASCII-8BIT") }
|
149
169
|
let(:token) { { "data" => data, "timestamp" => "2012-01-01 01:01:01 UTC", "signature" => signature } }
|
150
|
-
before { Time.
|
170
|
+
before { allow(Time).to receive_messages now: Time.new(2012,1,1,1,2,1,0) }
|
151
171
|
subject { key.token_valid? token }
|
152
|
-
it {
|
172
|
+
it { is_expected.to be_truthy }
|
153
173
|
|
154
174
|
it "doesn't check signature on the advisory key field" do
|
155
|
-
key.token_valid?(token.merge "key" => key_fingerprint).
|
175
|
+
expect(key.token_valid?(token.merge "key" => key_fingerprint)).to be_truthy
|
156
176
|
end
|
157
177
|
|
158
178
|
it "rejects the token if the key field is present and doesn't match" do
|
159
|
-
key.token_valid?(token.merge "key" => "this is not the key you are looking for").
|
179
|
+
expect(key.token_valid?(token.merge "key" => "this is not the key you are looking for")).not_to be_truthy
|
160
180
|
end
|
161
181
|
|
162
182
|
context "when token is 1 hour old" do
|
163
|
-
before { Time.
|
164
|
-
it {
|
183
|
+
before { allow(Time).to receive_messages now: Time.new(2012,1,1,2,1,1,0) }
|
184
|
+
it { is_expected.to be_falsey }
|
165
185
|
context "when timestamp in the token is changed accordingly" do
|
166
186
|
let(:token) { { "data" => data, "timestamp" => "2012-01-01 02:00:01 UTC", "signature" => signature } }
|
167
|
-
it {
|
187
|
+
it { is_expected.to be_falsey }
|
168
188
|
end
|
169
189
|
end
|
170
190
|
context "when the data is changed" do
|
171
191
|
let(:data) { { "foo" => :baz } }
|
172
|
-
it {
|
192
|
+
it { is_expected.to be_falsey }
|
173
193
|
end
|
174
194
|
context "when RSA decrypt raises an error" do
|
175
|
-
before { OpenSSL::PKey::RSA.
|
176
|
-
it {
|
195
|
+
before { expect_any_instance_of(OpenSSL::PKey::RSA).to receive(:public_decrypt).and_raise(OpenSSL::PKey::RSAError) }
|
196
|
+
it { is_expected.to be_falsey }
|
177
197
|
end
|
178
198
|
end
|
179
199
|
end
|
data/spec/keystore_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe Slosilo::Keystore do
|
|
7
7
|
describe '#put' do
|
8
8
|
it "handles Slosilo::Keys" do
|
9
9
|
subject.put(:test, key)
|
10
|
-
adapter['test'].to_der.
|
10
|
+
expect(adapter['test'].to_der).to eq(rsa.to_der)
|
11
11
|
end
|
12
12
|
|
13
13
|
it "refuses to store a key with a nil id" do
|
@@ -19,7 +19,7 @@ describe Slosilo::Keystore do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it "passes the Slosilo key to the adapter" do
|
22
|
-
adapter.
|
22
|
+
expect(adapter).to receive(:put_key).with "test", key
|
23
23
|
subject.put :test, key
|
24
24
|
end
|
25
25
|
end
|
data/spec/random_spec.rb
CHANGED
@@ -4,6 +4,16 @@ describe Slosilo::Random do
|
|
4
4
|
subject { Slosilo::Random }
|
5
5
|
let(:other_salt) { Slosilo::Random::salt }
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
describe '#salt' do
|
8
|
+
subject { super().salt }
|
9
|
+
describe '#length' do
|
10
|
+
subject { super().length }
|
11
|
+
it { is_expected.to eq(32) }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#salt' do
|
16
|
+
subject { super().salt }
|
17
|
+
it { is_expected.not_to eq(other_salt) }
|
18
|
+
end
|
9
19
|
end
|
data/spec/sequel_adapter_spec.rb
CHANGED
@@ -8,21 +8,21 @@ describe Slosilo::Adapters::SequelAdapter do
|
|
8
8
|
include_context "with example key"
|
9
9
|
|
10
10
|
let(:model) { double "model" }
|
11
|
-
before { subject.
|
11
|
+
before { allow(subject).to receive_messages create_model: model }
|
12
12
|
|
13
13
|
describe "#get_key" do
|
14
14
|
context "when given key does not exist" do
|
15
|
-
before { model.
|
15
|
+
before { allow(model).to receive_messages :[] => nil }
|
16
16
|
it "returns nil" do
|
17
|
-
subject.get_key(:whatever).
|
17
|
+
expect(subject.get_key(:whatever)).not_to be
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
context "when it exists" do
|
22
22
|
let(:id) { "id" }
|
23
|
-
before { model.
|
23
|
+
before { allow(model).to receive(:[]).with(id).and_return (double "key entry", id: id, key: rsa.to_der) }
|
24
24
|
it "returns it" do
|
25
|
-
subject.get_key(id).
|
25
|
+
expect(subject.get_key(id)).to eq(key)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -30,14 +30,14 @@ describe Slosilo::Adapters::SequelAdapter do
|
|
30
30
|
describe "#put_key" do
|
31
31
|
let(:id) { "id" }
|
32
32
|
it "creates the key" do
|
33
|
-
model.
|
34
|
-
model.
|
33
|
+
expect(model).to receive(:create).with id: id, key: key.to_der
|
34
|
+
allow(model).to receive_messages columns: [:id, :key]
|
35
35
|
subject.put_key id, key
|
36
36
|
end
|
37
37
|
|
38
38
|
it "adds the fingerprint if feasible" do
|
39
|
-
model.
|
40
|
-
model.
|
39
|
+
expect(model).to receive(:create).with id: id, key: key.to_der, fingerprint: key.fingerprint
|
40
|
+
allow(model).to receive_messages columns: [:id, :key, :fingerprint]
|
41
41
|
subject.put_key id, key
|
42
42
|
end
|
43
43
|
end
|
@@ -46,25 +46,21 @@ describe Slosilo::Adapters::SequelAdapter do
|
|
46
46
|
describe "#each" do
|
47
47
|
let(:one) { double("one", id: :one, key: :onek) }
|
48
48
|
let(:two) { double("two", id: :two, key: :twok) }
|
49
|
-
before { model.
|
49
|
+
before { allow(model).to receive(:each).and_yield(one).and_yield(two) }
|
50
50
|
|
51
51
|
it "iterates over each key" do
|
52
52
|
results = []
|
53
|
-
Slosilo::Key.
|
53
|
+
allow(Slosilo::Key).to receive(:new) {|x|x}
|
54
54
|
adapter.each { |id,k| results << { id => k } }
|
55
|
-
results.
|
55
|
+
expect(results).to eq([ { one: :onek}, {two: :twok } ])
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
59
|
shared_context "database" do
|
60
60
|
let(:db) { Sequel.sqlite }
|
61
61
|
before do
|
62
|
-
subject.
|
63
|
-
|
64
|
-
Sequel::Model.cache_anonymous_models = false
|
65
|
-
rescue NoMethodError # sequel 4.0 moved the method
|
66
|
-
Sequel.cache_anonymous_models = false
|
67
|
-
end
|
62
|
+
allow(subject).to receive(:create_model).and_call_original
|
63
|
+
Sequel.cache_anonymous_models = false
|
68
64
|
Sequel::Model.db = db
|
69
65
|
end
|
70
66
|
end
|
@@ -91,24 +87,24 @@ describe Slosilo::Adapters::SequelAdapter do
|
|
91
87
|
before { subject.migrate! }
|
92
88
|
|
93
89
|
it "supports look up by id" do
|
94
|
-
subject.get_key("test").
|
90
|
+
expect(subject.get_key("test")).to eq(key)
|
95
91
|
end
|
96
92
|
|
97
93
|
it "supports look up by fingerprint, without a warning" do
|
98
|
-
$stderr.grab do
|
99
|
-
subject.get_by_fingerprint(key.fingerprint).
|
100
|
-
end.
|
94
|
+
expect($stderr.grab do
|
95
|
+
expect(subject.get_by_fingerprint(key.fingerprint)).to eq([key, 'test'])
|
96
|
+
end).to be_empty
|
101
97
|
end
|
102
98
|
end
|
103
99
|
|
104
100
|
it "supports look up by id" do
|
105
|
-
subject.get_key("test").
|
101
|
+
expect(subject.get_key("test")).to eq(key)
|
106
102
|
end
|
107
103
|
|
108
104
|
it "supports look up by fingerprint, but issues a warning" do
|
109
|
-
$stderr.grab do
|
110
|
-
subject.get_by_fingerprint(key.fingerprint).
|
111
|
-
end.
|
105
|
+
expect($stderr.grab do
|
106
|
+
expect(subject.get_by_fingerprint(key.fingerprint)).to eq([key, 'test'])
|
107
|
+
end).not_to be_empty
|
112
108
|
end
|
113
109
|
end
|
114
110
|
|
@@ -129,11 +125,11 @@ describe Slosilo::Adapters::SequelAdapter do
|
|
129
125
|
end
|
130
126
|
|
131
127
|
it "supports look up by id" do
|
132
|
-
subject.get_key("test").
|
128
|
+
expect(subject.get_key("test")).to eq(key)
|
133
129
|
end
|
134
130
|
|
135
131
|
it "supports look up by fingerprint" do
|
136
|
-
subject.get_by_fingerprint(key.fingerprint).
|
132
|
+
expect(subject.get_by_fingerprint(key.fingerprint)).to eq([key, 'test'])
|
137
133
|
end
|
138
134
|
end
|
139
135
|
|
@@ -141,7 +137,7 @@ describe Slosilo::Adapters::SequelAdapter do
|
|
141
137
|
include_context "encryption key"
|
142
138
|
include_context "current schema"
|
143
139
|
|
144
|
-
it {
|
140
|
+
it { is_expected.to be_secure }
|
145
141
|
|
146
142
|
it "saves the keys in encrypted form" do
|
147
143
|
subject.put_key 'test', key
|
@@ -158,7 +154,7 @@ describe Slosilo::Adapters::SequelAdapter do
|
|
158
154
|
|
159
155
|
include_context "current schema"
|
160
156
|
|
161
|
-
it {
|
157
|
+
it { is_expected.not_to be_secure }
|
162
158
|
|
163
159
|
it "refuses to store a private key" do
|
164
160
|
expect { subject.put_key 'test', key }.to raise_error(Slosilo::Error::InsecureKeyStorage)
|
data/spec/slosilo_spec.rb
CHANGED
@@ -7,32 +7,32 @@ describe Slosilo do
|
|
7
7
|
|
8
8
|
describe '[]' do
|
9
9
|
it "returns a Slosilo::Key" do
|
10
|
-
Slosilo[:test].
|
10
|
+
expect(Slosilo[:test]).to be_instance_of Slosilo::Key
|
11
11
|
end
|
12
12
|
|
13
13
|
it "allows looking up by fingerprint" do
|
14
|
-
Slosilo[fingerprint: key_fingerprint].
|
14
|
+
expect(Slosilo[fingerprint: key_fingerprint]).to eq(key)
|
15
15
|
end
|
16
16
|
|
17
17
|
context "when the requested key does not exist" do
|
18
18
|
it "returns nil instead of creating a new key" do
|
19
|
-
Slosilo[:aether].
|
19
|
+
expect(Slosilo[:aether]).not_to be
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
describe '.sign' do
|
25
25
|
let(:own_key) { double "own key" }
|
26
|
-
before { Slosilo.
|
26
|
+
before { allow(Slosilo).to receive(:[]).with(:own).and_return own_key }
|
27
27
|
let (:argument) { double "thing to sign" }
|
28
28
|
it "fetches the own key and signs using that" do
|
29
|
-
own_key.
|
29
|
+
expect(own_key).to receive(:sign).with(argument)
|
30
30
|
Slosilo.sign argument
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
describe '.token_valid?' do
|
35
|
-
before { adapter['test'].
|
35
|
+
before { allow(adapter['test']).to receive_messages token_valid?: false }
|
36
36
|
let(:key2) { double "key 2", token_valid?: false }
|
37
37
|
let(:key3) { double "key 3", token_valid?: false }
|
38
38
|
before do
|
@@ -44,19 +44,19 @@ describe Slosilo do
|
|
44
44
|
subject { Slosilo.token_valid? token }
|
45
45
|
|
46
46
|
context "when no key validates the token" do
|
47
|
-
before { Slosilo::Key.
|
48
|
-
it {
|
47
|
+
before { allow(Slosilo::Key).to receive_messages new: (double "key", token_valid?: false) }
|
48
|
+
it { is_expected.to be_falsey }
|
49
49
|
end
|
50
50
|
|
51
51
|
context "when a key validates the token" do
|
52
52
|
let(:valid_key) { double token_valid?: true }
|
53
53
|
let(:invalid_key) { double token_valid?: true }
|
54
54
|
before do
|
55
|
-
Slosilo::Key.
|
55
|
+
allow(Slosilo::Key).to receive_messages new: invalid_key
|
56
56
|
adapter[:key2] = valid_key
|
57
57
|
end
|
58
58
|
|
59
|
-
it {
|
59
|
+
it { is_expected.to be_truthy }
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -66,18 +66,18 @@ describe Slosilo do
|
|
66
66
|
let(:token) {{ 'data' => 'foo', 'key' => key.fingerprint, 'signature' => 'XXX' }}
|
67
67
|
|
68
68
|
context "and the signature is valid" do
|
69
|
-
before { key.
|
69
|
+
before { allow(key).to receive(:token_valid?).with(token).and_return true }
|
70
70
|
|
71
71
|
it "returns the key id" do
|
72
|
-
subject.token_signer(token).
|
72
|
+
expect(subject.token_signer(token)).to eq('test')
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
76
|
context "and the signature is invalid" do
|
77
|
-
before { key.
|
77
|
+
before { allow(key).to receive(:token_valid?).with(token).and_return false }
|
78
78
|
|
79
79
|
it "returns nil" do
|
80
|
-
subject.token_signer(token).
|
80
|
+
expect(subject.token_signer(token)).not_to be
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
@@ -85,7 +85,7 @@ describe Slosilo do
|
|
85
85
|
context "when token doesn't match a key" do
|
86
86
|
let(:token) {{ 'data' => 'foo', 'key' => "footprint", 'signature' => 'XXX' }}
|
87
87
|
it "returns nil" do
|
88
|
-
subject.token_signer(token).
|
88
|
+
expect(subject.token_signer(token)).not_to be
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
require "simplecov"
|
2
2
|
SimpleCov.start
|
3
3
|
|
4
|
-
RSpec.configure do |c|
|
5
|
-
c.treat_symbols_as_metadata_keys_with_true_values = true
|
6
|
-
end
|
7
|
-
|
8
4
|
require 'slosilo'
|
9
5
|
|
10
6
|
shared_context "with mock adapter" do
|
@@ -80,20 +76,6 @@ ooQ2FuL0K6ukQfHPjuMswqi41lmVH8gIVqVC+QnImUCrGxH9WXWy
|
|
80
76
|
end
|
81
77
|
|
82
78
|
def self.mock_own_key
|
83
|
-
before { Slosilo.
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
class RackEnvironmentInputMatcher
|
88
|
-
def initialize expected
|
89
|
-
@expected = expected
|
79
|
+
before { allow(Slosilo).to receive(:[]).with(:own).and_return key }
|
90
80
|
end
|
91
|
-
|
92
|
-
def == env
|
93
|
-
env['rack.input'].read.should == @expected
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def rack_environment_with_input expected
|
98
|
-
RackEnvironmentInputMatcher.new expected
|
99
81
|
end
|
data/spec/symmetric_spec.rb
CHANGED
@@ -8,21 +8,21 @@ describe Slosilo::Symmetric do
|
|
8
8
|
let(:ciphertext) { "\xA1\xFA#z\x16\x80R\xCC|\x0Fyc\xB7j\x17\xED\x15\xC9r\xC9\xEE\xB9\xBC5\xB7\ni\x0F\f\xC8X\x80 h\a\xF4\xA6\xE3\x15\x9D\xF1-\xE5\bs\xF6\x02Z\x0F\xCD|S\x1A\xAA\x9At\xEFT\x17\xA5lT\x8C\xF3".force_encoding("ASCII-8BIT") }
|
9
9
|
describe '#encrypt' do
|
10
10
|
it "encrypts with AES-256-CBC" do
|
11
|
-
subject.
|
12
|
-
subject.encrypt(plaintext, key: key).
|
11
|
+
allow(subject).to receive_messages random_iv: iv
|
12
|
+
expect(subject.encrypt(plaintext, key: key)).to eq(ciphertext)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
describe '#decrypt' do
|
17
17
|
it "decrypts with AES-256-CBC" do
|
18
|
-
subject.decrypt(ciphertext, key: key).
|
18
|
+
expect(subject.decrypt(ciphertext, key: key)).to eq(plaintext)
|
19
19
|
end
|
20
20
|
|
21
21
|
context "when ciphertext happens to end in a zero" do
|
22
22
|
let(:ciphertext) { "\x7F\xD6\xEAb\xE56\a\xD3\xC5\xF2J\n\x8C\x8Fg\xB7-\\\x8A\fh\x18\xC8\x91\xB9 \x97\xC9\x12\xE6\xA6\xAE\xB1I\x1E\x80\xAB\xD8\xDC\xBD\xB6\xCD\x9A\xA3MH\xA8\xB0\xC7\xDA\x87\xA7c\xD75,\xD2A\xB8\x9E\xE3o\x04\x00" }
|
23
23
|
let(:key) { "4pSuk1rAQyuHA5uUYaj0X0BsiPCFb9Nc8J03XA6V5/Y" }
|
24
24
|
it "works correctly" do
|
25
|
-
subject.decrypt(ciphertext, key: key).
|
25
|
+
expect(subject.decrypt(ciphertext, key: key)).to eq("R6KNTQ4aUivojbaqhgAqj1I4PaF8h/5/YcENy4uNbfk=")
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -30,22 +30,22 @@ describe Slosilo::Symmetric do
|
|
30
30
|
let(:ciphertext) { "\xC0\xDA#\xE9\xE1\xFD\xEDJ\xADs4P\xA9\xD6\x92 \xF7\xF8_M\xF6\x16\xC2i$\x8BT^\b\xA1\xB2L&\xE9\x80\x02[]6i\x9B\xD3\xC3\xED\xA9\xD1\x94\xE8\x15\xFD\xDA\xFEUj\xC5upH*\xBF\x82\x15le" }
|
31
31
|
let(:key) { "4pSuk1rAQyuHA5uUYaj0X0BsiPCFb9Nc8J03XA6V5/Y" }
|
32
32
|
it "works correctly" do
|
33
|
-
subject.decrypt(ciphertext, key: key).
|
33
|
+
expect(subject.decrypt(ciphertext, key: key)).to eq("zGptmL3vd4obi1vqSiWHt/Ias2k+6qDtuq9vdow8jNA=")
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
describe '#random_iv' do
|
39
39
|
it "generates a random iv" do
|
40
|
-
OpenSSL::Cipher.
|
41
|
-
subject.random_iv.
|
40
|
+
expect_any_instance_of(OpenSSL::Cipher).to receive(:random_iv).and_return :iv
|
41
|
+
expect(subject.random_iv).to eq(:iv)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
describe '#random_key' do
|
46
46
|
it "generates a random key" do
|
47
|
-
OpenSSL::Cipher.
|
48
|
-
subject.random_key.
|
47
|
+
expect_any_instance_of(OpenSSL::Cipher).to receive(:random_key).and_return :key
|
48
|
+
expect(subject.random_key).to eq(:key)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
metadata
CHANGED
@@ -1,111 +1,111 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slosilo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rafał Rzepecki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '3.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '3.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: ci_reporter_rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: simplecov
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: io-grab
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ~>
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: 0.0.1
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ~>
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 0.0.1
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: sequel
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - '>='
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - '>='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: sqlite3
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - '>='
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - '>='
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
description: This gem provides an easy way of storing and retrieving encryption keys
|
@@ -116,8 +116,8 @@ executables: []
|
|
116
116
|
extensions: []
|
117
117
|
extra_rdoc_files: []
|
118
118
|
files:
|
119
|
-
-
|
120
|
-
-
|
119
|
+
- .gitignore
|
120
|
+
- .kateproject
|
121
121
|
- Gemfile
|
122
122
|
- LICENSE
|
123
123
|
- README.md
|
@@ -156,12 +156,12 @@ require_paths:
|
|
156
156
|
- lib
|
157
157
|
required_ruby_version: !ruby/object:Gem::Requirement
|
158
158
|
requirements:
|
159
|
-
- -
|
159
|
+
- - '>='
|
160
160
|
- !ruby/object:Gem::Version
|
161
161
|
version: 1.9.3
|
162
162
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
|
-
- -
|
164
|
+
- - '>='
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
167
|
requirements: []
|
@@ -179,3 +179,4 @@ test_files:
|
|
179
179
|
- spec/slosilo_spec.rb
|
180
180
|
- spec/spec_helper.rb
|
181
181
|
- spec/symmetric_spec.rb
|
182
|
+
has_rdoc:
|