slosilo 1.1.0 → 2.2.2
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 +5 -5
- data/.dockerignore +2 -0
- data/.github/CODEOWNERS +10 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +21 -0
- data/.gitleaks.toml +221 -0
- data/CHANGELOG.md +16 -0
- data/CONTRIBUTING.md +16 -0
- data/Jenkinsfile +58 -0
- data/LICENSE +2 -2
- data/README.md +27 -16
- data/SECURITY.md +42 -0
- data/lib/slosilo.rb +1 -0
- data/lib/slosilo/adapters/sequel_adapter.rb +13 -4
- data/lib/slosilo/attr_encrypted.rb +29 -6
- data/lib/slosilo/errors.rb +3 -0
- data/lib/slosilo/jwt.rb +122 -0
- data/lib/slosilo/key.rb +86 -3
- data/lib/slosilo/keystore.rb +13 -2
- data/lib/slosilo/symmetric.rb +30 -9
- data/lib/slosilo/version.rb +1 -1
- data/lib/tasks/slosilo.rake +5 -0
- data/publish-rubygem.sh +11 -0
- data/slosilo.gemspec +11 -2
- data/spec/encrypted_attributes_spec.rb +114 -0
- data/spec/file_adapter_spec.rb +1 -1
- data/spec/jwt_spec.rb +102 -0
- data/spec/key_spec.rb +63 -4
- data/spec/sequel_adapter_spec.rb +1 -1
- data/spec/slosilo_spec.rb +32 -0
- data/spec/spec_helper.rb +5 -2
- data/spec/symmetric_spec.rb +39 -17
- data/test.sh +27 -0
- metadata +64 -23
data/spec/slosilo_spec.rb
CHANGED
@@ -88,5 +88,37 @@ describe Slosilo do
|
|
88
88
|
expect(subject.token_signer(token)).not_to be
|
89
89
|
end
|
90
90
|
end
|
91
|
+
|
92
|
+
context "with JWT token" do
|
93
|
+
before do
|
94
|
+
expect(key).to receive(:validate_jwt) do |jwt|
|
95
|
+
expect(jwt.header).to eq 'kid' => key.fingerprint
|
96
|
+
expect(jwt.claims).to eq({})
|
97
|
+
expect(jwt.signature).to eq 'sig'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "accepts pre-parsed JSON serialization" do
|
102
|
+
expect(Slosilo.token_signer(
|
103
|
+
'protected' => 'eyJraWQiOiIxMDdiZGI4NTAxYzQxOWZhZDJmZGIyMGI0NjdkNGQwYTYyYTE2YTk4YzM1ZjJkYTBlYjNiMWZmOTI5Nzk1YWQ5In0=',
|
104
|
+
'payload' => 'e30=',
|
105
|
+
'signature' => 'c2ln'
|
106
|
+
)).to eq 'test'
|
107
|
+
end
|
108
|
+
|
109
|
+
it "accepts pre-parsed JWT token" do
|
110
|
+
expect(Slosilo.token_signer(Slosilo::JWT(
|
111
|
+
'protected' => 'eyJraWQiOiIxMDdiZGI4NTAxYzQxOWZhZDJmZGIyMGI0NjdkNGQwYTYyYTE2YTk4YzM1ZjJkYTBlYjNiMWZmOTI5Nzk1YWQ5In0=',
|
112
|
+
'payload' => 'e30=',
|
113
|
+
'signature' => 'c2ln'
|
114
|
+
))).to eq 'test'
|
115
|
+
end
|
116
|
+
|
117
|
+
it "accepts compact serialization" do
|
118
|
+
expect(Slosilo.token_signer(
|
119
|
+
'eyJraWQiOiIxMDdiZGI4NTAxYzQxOWZhZDJmZGIyMGI0NjdkNGQwYTYyYTE2YTk4YzM1ZjJkYTBlYjNiMWZmOTI5Nzk1YWQ5In0=.e30=.c2ln'
|
120
|
+
)).to eq 'test'
|
121
|
+
end
|
122
|
+
end
|
91
123
|
end
|
92
124
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
require "simplecov"
|
2
|
+
require "simplecov-cobertura"
|
3
|
+
|
4
|
+
SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
|
2
5
|
SimpleCov.start
|
3
6
|
|
4
7
|
require 'slosilo'
|
@@ -41,7 +44,7 @@ Dg1ikwi8GUF4HPZe9DyhXgDhg19wM/qcpjX8bSypsUWHWP+FanhjdWU=
|
|
41
44
|
-----END RSA PRIVATE KEY-----
|
42
45
|
""" }
|
43
46
|
let (:key) { Slosilo::Key.new rsa.to_der }
|
44
|
-
let (:key_fingerprint) { "
|
47
|
+
let (:key_fingerprint) { "107bdb8501c419fad2fdb20b467d4d0a62a16a98c35f2da0eb3b1ff929795ad9" }
|
45
48
|
|
46
49
|
let (:another_rsa) do
|
47
50
|
OpenSSL::PKey::RSA.new """
|
@@ -74,7 +77,7 @@ ooQ2FuL0K6ukQfHPjuMswqi41lmVH8gIVqVC+QnImUCrGxH9WXWy
|
|
74
77
|
-----END RSA PRIVATE KEY-----
|
75
78
|
"""
|
76
79
|
end
|
77
|
-
|
80
|
+
|
78
81
|
def self.mock_own_key
|
79
82
|
before { allow(Slosilo).to receive(:[]).with(:own).and_return key }
|
80
83
|
end
|
data/spec/symmetric_spec.rb
CHANGED
@@ -3,34 +3,56 @@ require 'spec_helper'
|
|
3
3
|
describe Slosilo::Symmetric do
|
4
4
|
# TODO transform it to class methods only?
|
5
5
|
let(:plaintext) { "quick brown fox jumped over the lazy dog" }
|
6
|
+
let(:auth_data) { "some record id" }
|
6
7
|
let(:key) { "^\xBAIv\xDB1\x0Fi\x04\x11\xFD\x14\xA7\xCD\xDFf\x93\xFE\x93}\v\x01\x11\x98\x14\xE0;\xC1\xE2 v\xA5".force_encoding("ASCII-8BIT") }
|
7
|
-
let(:iv) { "\
|
8
|
-
let(:ciphertext) { "\
|
8
|
+
let(:iv) { "\xD9\xABn\x01b\xFA\xBD\xC2\xE5\xEA\x01\xAC".force_encoding("ASCII-8BIT") }
|
9
|
+
let(:ciphertext) { "G^W1\x9C\xD4\xCC\x87\xD3\xFF\x86[\x0E3\xC0\xC8^\xD9\xABn\x01b\xFA\xBD\xC2\xE5\xEA\x01\xAC\x9E\xB9:\xF7\xD4ebeq\xDC \xC0sG\xA4\xAE,\xB8A|\x97\xBC\xFD\x85\xE1\xB93\x95>\xBD\n\x05\xFB\x15\x1F\x06#3M9".force_encoding('ASCII-8BIT') }
|
10
|
+
|
9
11
|
describe '#encrypt' do
|
10
|
-
it "encrypts with AES-256-
|
12
|
+
it "encrypts with AES-256-GCM" do
|
11
13
|
allow(subject).to receive_messages random_iv: iv
|
12
|
-
expect(subject.encrypt(plaintext, key: key)).to eq(ciphertext)
|
14
|
+
expect(subject.encrypt(plaintext, key: key, aad: auth_data)).to eq(ciphertext)
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
16
18
|
describe '#decrypt' do
|
17
|
-
it "decrypts with AES-256-
|
18
|
-
expect(subject.decrypt(ciphertext, key: key)).to eq(plaintext)
|
19
|
+
it "decrypts with AES-256-GCM" do
|
20
|
+
expect(subject.decrypt(ciphertext, key: key, aad: auth_data)).to eq(plaintext)
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
context "when the ciphertext has been messed with" do
|
25
|
+
let(:ciphertext) { "pwnd!" } # maybe we should do something more realistic like add some padding?
|
26
|
+
it "raises an exception" do
|
27
|
+
expect{ subject.decrypt(ciphertext, key: key, aad: auth_data)}.to raise_exception /Invalid version/
|
28
|
+
end
|
29
|
+
context "by adding a trailing 0" do
|
30
|
+
let(:new_ciphertext){ ciphertext + '\0' }
|
31
|
+
it "raises an exception" do
|
32
|
+
expect{ subject.decrypt(new_ciphertext, key: key, aad: auth_data) }.to raise_exception /Invalid version/
|
33
|
+
end
|
34
|
+
end
|
19
35
|
end
|
20
|
-
|
21
|
-
context "when
|
22
|
-
let(:
|
23
|
-
let(:
|
24
|
-
|
25
|
-
|
36
|
+
|
37
|
+
context "when no auth_data is given" do
|
38
|
+
let(:auth_data){""}
|
39
|
+
let(:ciphertext){ "Gm\xDAT\xE8I\x9F\xB7\xDC\xBB\x84\xD3Q#\x1F\xF4\x8C\aV\x93\x8F_\xC7\xBC87\xC9U\xF1\xAF\x8A\xD62\x1C5H\x86\x17\x19=B~Y*\xBC\x9D\eJeTx\x1F\x02l\t\t\xD3e\xA4\x11\x13y*\x95\x9F\xCD\xC4@\x9C"}
|
40
|
+
|
41
|
+
it "decrypts the message" do
|
42
|
+
expect(subject.decrypt(ciphertext, key: key, aad: auth_data)).to eq(plaintext)
|
43
|
+
end
|
44
|
+
|
45
|
+
context "and the ciphertext has been messed with" do
|
46
|
+
it "raises an exception" do
|
47
|
+
expect{ subject.decrypt(ciphertext + "\0\0\0", key: key, aad: auth_data)}.to raise_exception OpenSSL::Cipher::CipherError
|
48
|
+
end
|
26
49
|
end
|
27
50
|
end
|
28
51
|
|
29
|
-
context "when the
|
30
|
-
let(:
|
31
|
-
|
32
|
-
|
33
|
-
expect(subject.decrypt(ciphertext, key: key)).to eq("zGptmL3vd4obi1vqSiWHt/Ias2k+6qDtuq9vdow8jNA=")
|
52
|
+
context "when the auth data doesn't match" do
|
53
|
+
let(:auth_data){ "asdf" }
|
54
|
+
it "raises an exception" do
|
55
|
+
expect{ subject.decrypt(ciphertext, key: key, aad: auth_data)}.to raise_exception OpenSSL::Cipher::CipherError
|
34
56
|
end
|
35
57
|
end
|
36
58
|
end
|
data/test.sh
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/bin/bash -xe
|
2
|
+
|
3
|
+
iid=slosilo-test-$(date +%s)
|
4
|
+
|
5
|
+
docker build -t $iid -f - . << EOF
|
6
|
+
FROM ruby
|
7
|
+
WORKDIR /app
|
8
|
+
COPY Gemfile slosilo.gemspec ./
|
9
|
+
RUN bundle
|
10
|
+
COPY . ./
|
11
|
+
RUN bundle
|
12
|
+
EOF
|
13
|
+
|
14
|
+
cidfile=$(mktemp -u)
|
15
|
+
docker run --cidfile $cidfile -v /app/spec/reports $iid bundle exec rake jenkins || :
|
16
|
+
|
17
|
+
cid=$(cat $cidfile)
|
18
|
+
|
19
|
+
docker cp $cid:/app/spec/reports spec/
|
20
|
+
docker cp $cid:/app/coverage spec
|
21
|
+
|
22
|
+
docker rm $cid
|
23
|
+
|
24
|
+
# untag, will use cache next time if available but no junk will be left
|
25
|
+
docker rmi $iid
|
26
|
+
|
27
|
+
rm $cidfile
|
metadata
CHANGED
@@ -1,111 +1,139 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slosilo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rafał Rzepecki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-26 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
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
40
|
version: '3.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: ci_reporter_rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
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
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
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov-cobertura
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: io-grab
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
|
-
- - ~>
|
87
|
+
- - "~>"
|
74
88
|
- !ruby/object:Gem::Version
|
75
89
|
version: 0.0.1
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- - ~>
|
94
|
+
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: 0.0.1
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: sequel
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- -
|
101
|
+
- - ">="
|
88
102
|
- !ruby/object:Gem::Version
|
89
103
|
version: '0'
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
|
-
- -
|
108
|
+
- - ">="
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: sqlite3
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- -
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: activesupport
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
102
130
|
- !ruby/object:Gem::Version
|
103
131
|
version: '0'
|
104
132
|
type: :development
|
105
133
|
prerelease: false
|
106
134
|
version_requirements: !ruby/object:Gem::Requirement
|
107
135
|
requirements:
|
108
|
-
- -
|
136
|
+
- - ">="
|
109
137
|
- !ruby/object:Gem::Version
|
110
138
|
version: '0'
|
111
139
|
description: This gem provides an easy way of storing and retrieving encryption keys
|
@@ -116,12 +144,20 @@ executables: []
|
|
116
144
|
extensions: []
|
117
145
|
extra_rdoc_files: []
|
118
146
|
files:
|
119
|
-
- .
|
120
|
-
- .
|
147
|
+
- ".dockerignore"
|
148
|
+
- ".github/CODEOWNERS"
|
149
|
+
- ".github/PULL_REQUEST_TEMPLATE.md"
|
150
|
+
- ".gitignore"
|
151
|
+
- ".gitleaks.toml"
|
152
|
+
- ".kateproject"
|
153
|
+
- CHANGELOG.md
|
154
|
+
- CONTRIBUTING.md
|
121
155
|
- Gemfile
|
156
|
+
- Jenkinsfile
|
122
157
|
- LICENSE
|
123
158
|
- README.md
|
124
159
|
- Rakefile
|
160
|
+
- SECURITY.md
|
125
161
|
- lib/slosilo.rb
|
126
162
|
- lib/slosilo/adapters/abstract_adapter.rb
|
127
163
|
- lib/slosilo/adapters/file_adapter.rb
|
@@ -131,14 +167,18 @@ files:
|
|
131
167
|
- lib/slosilo/adapters/sequel_adapter/migration.rb
|
132
168
|
- lib/slosilo/attr_encrypted.rb
|
133
169
|
- lib/slosilo/errors.rb
|
170
|
+
- lib/slosilo/jwt.rb
|
134
171
|
- lib/slosilo/key.rb
|
135
172
|
- lib/slosilo/keystore.rb
|
136
173
|
- lib/slosilo/random.rb
|
137
174
|
- lib/slosilo/symmetric.rb
|
138
175
|
- lib/slosilo/version.rb
|
139
176
|
- lib/tasks/slosilo.rake
|
177
|
+
- publish-rubygem.sh
|
140
178
|
- slosilo.gemspec
|
179
|
+
- spec/encrypted_attributes_spec.rb
|
141
180
|
- spec/file_adapter_spec.rb
|
181
|
+
- spec/jwt_spec.rb
|
142
182
|
- spec/key_spec.rb
|
143
183
|
- spec/keystore_spec.rb
|
144
184
|
- spec/random_spec.rb
|
@@ -146,6 +186,7 @@ files:
|
|
146
186
|
- spec/slosilo_spec.rb
|
147
187
|
- spec/spec_helper.rb
|
148
188
|
- spec/symmetric_spec.rb
|
189
|
+
- test.sh
|
149
190
|
homepage: ''
|
150
191
|
licenses:
|
151
192
|
- MIT
|
@@ -156,22 +197,23 @@ require_paths:
|
|
156
197
|
- lib
|
157
198
|
required_ruby_version: !ruby/object:Gem::Requirement
|
158
199
|
requirements:
|
159
|
-
- -
|
200
|
+
- - ">="
|
160
201
|
- !ruby/object:Gem::Version
|
161
202
|
version: 1.9.3
|
162
203
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
204
|
requirements:
|
164
|
-
- -
|
205
|
+
- - ">="
|
165
206
|
- !ruby/object:Gem::Version
|
166
207
|
version: '0'
|
167
208
|
requirements: []
|
168
|
-
|
169
|
-
rubygems_version: 2.2.2
|
209
|
+
rubygems_version: 3.1.2
|
170
210
|
signing_key:
|
171
211
|
specification_version: 4
|
172
212
|
summary: Store SSL keys in a database
|
173
213
|
test_files:
|
214
|
+
- spec/encrypted_attributes_spec.rb
|
174
215
|
- spec/file_adapter_spec.rb
|
216
|
+
- spec/jwt_spec.rb
|
175
217
|
- spec/key_spec.rb
|
176
218
|
- spec/keystore_spec.rb
|
177
219
|
- spec/random_spec.rb
|
@@ -179,4 +221,3 @@ test_files:
|
|
179
221
|
- spec/slosilo_spec.rb
|
180
222
|
- spec/spec_helper.rb
|
181
223
|
- spec/symmetric_spec.rb
|
182
|
-
has_rdoc:
|