chintala-strongbox 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.textile +182 -0
- data/Rakefile +39 -0
- data/init.rb +1 -0
- data/lib/strongbox.rb +97 -0
- data/lib/strongbox/lock.rb +152 -0
- data/rails/init.rb +1 -0
- data/strongbox.gemspec +23 -0
- data/test/database.yml +4 -0
- data/test/fixtures/encrypted +0 -0
- data/test/fixtures/keypair.pem +24 -0
- data/test/method_key_test.rb +77 -0
- data/test/missing_attributes_test.rb +77 -0
- data/test/proc_key_test.rb +57 -0
- data/test/strongbox_multiply_test.rb +52 -0
- data/test/strongbox_test.rb +252 -0
- data/test/test_helper.rb +86 -0
- data/test/validations_test.rb +101 -0
- metadata +125 -0
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'../init.rb')
|
data/strongbox.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
lib = File.expand_path('../lib/', __FILE__)
|
2
|
+
$:.unshift lib unless $:.include?(lib)
|
3
|
+
require 'strongbox'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "chintala-strongbox"
|
7
|
+
s.version = Strongbox::VERSION
|
8
|
+
s.summary = "Secures ActiveRecord fields with public key encryption."
|
9
|
+
s.authors = ["Spike Ilacqua"]
|
10
|
+
s.email = "spike@stuff-things.net"
|
11
|
+
s.description = <<-EOF
|
12
|
+
Strongbox provides Public Key Encryption for ActiveRecord. By using a
|
13
|
+
public key sensitive information can be encrypted and stored automatically.
|
14
|
+
Once stored a password is required to access the information. dependencies
|
15
|
+
are specified in standard Ruby syntax.
|
16
|
+
EOF
|
17
|
+
s.homepage = "http://stuff-things.net/strongbox"
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = `git ls-files -- test/*`.split("\n")
|
20
|
+
s.add_runtime_dependency 'activerecord'
|
21
|
+
s.add_development_dependency 'thoughtbot-shoulda'
|
22
|
+
s.add_development_dependency 'sqlite3'
|
23
|
+
end
|
data/test/database.yml
ADDED
Binary file
|
@@ -0,0 +1,24 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
Proc-Type: 4,ENCRYPTED
|
3
|
+
DEK-Info: DES-EDE3-CBC,317921A00FB0882F
|
4
|
+
|
5
|
+
f+GWBkcLJLsBUElOEKhqrtYgT1X4nixaZHD5x0VhmW2FrREz4vcqXrxwLTaRQJK/
|
6
|
+
vHFJ/7IVmEHScwEognSfw/wX2HMIHczoQT3ugsa29Nt7t1VLGy9jvN1+1f+g90xe
|
7
|
+
02jC7CYEKUJ3agZPox49i0/UN9OCIgdtKfecdDHYWyziob8yYTsUdDGyAXlPv0Kx
|
8
|
+
0MPSCRDtEh4UJ2PIFyw2HowkYeNss6uIte9rxJGINI11D9vmXR0pH0XyCwHQn+2T
|
9
|
+
ScHWg8BJ1rkBKydbKQ4vnfhGMjG+bZyrJXrJSoazXroseuhHu8QRUONm5Kl/zW1f
|
10
|
+
GP1CjIfTCQQZECYIa2tXTFdL9y2ZOCn8xit57SwEpmJMvZC58PkQX5+/aHPcOXhl
|
11
|
+
YrF+6FEfNpdBz9PUmv4Af2kTa88xZqm1Q3GtTOk7wsJpfeTMhU71KjA1pL9xNPrT
|
12
|
+
DnKhtfLGvcgo8Z9BGOiLFe9uQvhhprX7isc1XdysbMigsVIWLvZp9RxRp/zAn7fy
|
13
|
+
y56C6mc3tUwcq89RcxAn+bC75gwZO/hyVrnkhManOMfHTEiZXVybU9Ril3SZ+ry6
|
14
|
+
8AxMid0ZWbbtCHdDc5rHfXsGeFhJZxBbg/WtMxBPGHNByqs8sWUM9Z8YoK8WMYxV
|
15
|
+
GvC9RB4m0jgA4S3MEOMmKOXDuJxa7IgTgApVmLPl+sDOHGK3xAItYJJawJqOZQ1f
|
16
|
+
r+x/8g19CuehuflCxDo+D4/RJMqkOEq+0FGUqI8lHv6vR6+YpkGdrQQXUohBy67f
|
17
|
+
3Qym1ztZ8ygsttgJwnhwAfMh8FdIrVJc7NZ8pDiBZbg=
|
18
|
+
-----END RSA PRIVATE KEY-----
|
19
|
+
-----BEGIN PUBLIC KEY-----
|
20
|
+
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9F1ipsLL+V68bGSJFqFLQKgXq
|
21
|
+
Glyyplx0s9KxgLbmbDICXpV7DceKaIBUkPZDx2DrlvjZmG+rG5ehdWNI7q/hupao
|
22
|
+
NF0WzEiOp+30gISeyl81Z/NAmhcwcOnZpbS9nl4JLaWrN7iGC1geNBNDo+lVbsm1
|
23
|
+
O2+Tlt8rjHsNjzgIzQIDAQAB
|
24
|
+
-----END PUBLIC KEY-----
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class MethodKeyTest < Test::Unit::TestCase
|
4
|
+
context 'With an attribute containing a string for the key pair' do
|
5
|
+
setup do
|
6
|
+
@password = 'boost facile'
|
7
|
+
rebuild_model :key_pair => :key_pair_attribute
|
8
|
+
Dummy.class_eval do
|
9
|
+
attr_accessor :key_pair_attribute
|
10
|
+
end
|
11
|
+
|
12
|
+
@dummy = Dummy.new
|
13
|
+
@dummy.key_pair_attribute = File.read(File.join(FIXTURES_DIR,'keypair.pem'))
|
14
|
+
@dummy.secret = 'Shhhh'
|
15
|
+
end
|
16
|
+
|
17
|
+
should_encypted_and_decrypt
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'With a methods returning the key pair' do
|
21
|
+
setup do
|
22
|
+
@password = 'boost facile'
|
23
|
+
rebuild_model :key_pair => :key_pair_method
|
24
|
+
Dummy.class_eval do
|
25
|
+
def key_pair_method
|
26
|
+
File.read(File.join(FIXTURES_DIR,'keypair.pem'))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
@dummy = Dummy.new
|
31
|
+
@dummy.secret = 'Shhhh'
|
32
|
+
end
|
33
|
+
|
34
|
+
should_encypted_and_decrypt
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'With attributes containing strings for the keys' do
|
38
|
+
setup do
|
39
|
+
@password = 'boost facile'
|
40
|
+
rsa_key = OpenSSL::PKey::RSA.new(2048)
|
41
|
+
cipher = OpenSSL::Cipher::Cipher.new('des3')
|
42
|
+
rebuild_model :public_key => :public_key_attribute,
|
43
|
+
:private_key => :private_key_attribute
|
44
|
+
Dummy.class_eval do
|
45
|
+
attr_accessor :public_key_attribute, :private_key_attribute
|
46
|
+
end
|
47
|
+
@dummy = Dummy.new
|
48
|
+
@dummy.public_key_attribute = rsa_key.public_key.to_pem
|
49
|
+
@dummy.private_key_attribute = rsa_key.to_pem(cipher,@password)
|
50
|
+
@dummy.secret = 'Shhhh'
|
51
|
+
end
|
52
|
+
|
53
|
+
should_encypted_and_decrypt
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'With methods returning the keys' do
|
57
|
+
setup do
|
58
|
+
@password = 'boost facile'
|
59
|
+
rebuild_model :public_key => :public_key_method,
|
60
|
+
:private_key => :private_key_method
|
61
|
+
Dummy.class_eval do
|
62
|
+
def public_key_method
|
63
|
+
File.read(File.join(FIXTURES_DIR,'keypair.pem'))
|
64
|
+
end
|
65
|
+
|
66
|
+
def private_key_method
|
67
|
+
File.read(File.join(FIXTURES_DIR,'keypair.pem'))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
@dummy = Dummy.new
|
72
|
+
@dummy.secret = 'Shhhh'
|
73
|
+
end
|
74
|
+
|
75
|
+
should_encypted_and_decrypt
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class MissingAttribuesTest < Test::Unit::TestCase
|
4
|
+
context 'A Class with a secured field without a matching database column' do
|
5
|
+
setup do
|
6
|
+
ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
|
7
|
+
table.string :in_the_clear
|
8
|
+
end
|
9
|
+
rebuild_class {}
|
10
|
+
end
|
11
|
+
|
12
|
+
should 'raise' do
|
13
|
+
assert_raise(Strongbox::StrongboxError) do
|
14
|
+
Dummy.class_eval do
|
15
|
+
encrypt_with_public_key :secret, :key_pair =>
|
16
|
+
File.join(FIXTURES_DIR,'keypair.pem')
|
17
|
+
end
|
18
|
+
@dummy = Dummy.new
|
19
|
+
@dummy.secret = 'Shhhh'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
teardown do
|
24
|
+
rebuild_model
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'A Class with a secured field missing symmetric database columns' do
|
29
|
+
setup do
|
30
|
+
ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
|
31
|
+
table.string :in_the_clear
|
32
|
+
table.string :secret
|
33
|
+
end
|
34
|
+
rebuild_class {}
|
35
|
+
end
|
36
|
+
|
37
|
+
should 'raise' do
|
38
|
+
assert_raise(Strongbox::StrongboxError) do
|
39
|
+
Dummy.class_eval do
|
40
|
+
encrypt_with_public_key :secret, :key_pair =>
|
41
|
+
File.join(FIXTURES_DIR,'keypair.pem')
|
42
|
+
end
|
43
|
+
@dummy = Dummy.new
|
44
|
+
@dummy.secret = 'Shhhh'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
teardown do
|
49
|
+
rebuild_model
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'A Class with a secured field without a matching database column told not to check columns' do
|
54
|
+
setup do
|
55
|
+
ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
|
56
|
+
table.string :in_the_clear
|
57
|
+
end
|
58
|
+
rebuild_class {}
|
59
|
+
end
|
60
|
+
|
61
|
+
should 'not raise' do
|
62
|
+
assert_nothing_raised do
|
63
|
+
Dummy.class_eval do
|
64
|
+
encrypt_with_public_key(:secret,
|
65
|
+
:key_pair => File.join(FIXTURES_DIR,'keypair.pem'),
|
66
|
+
:ensure_required_columns => false)
|
67
|
+
end
|
68
|
+
@dummy = Dummy.new
|
69
|
+
@dummy.secret = 'Shhhh'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
teardown do
|
74
|
+
rebuild_model
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class ProcKeyTest < Test::Unit::TestCase
|
4
|
+
context 'With a Proc returning a string for a key pair' do
|
5
|
+
setup do
|
6
|
+
@password = 'boost facile'
|
7
|
+
rebuild_model :key_pair => Proc.new {
|
8
|
+
File.read(File.join(FIXTURES_DIR,'keypair.pem'))
|
9
|
+
}
|
10
|
+
@dummy = Dummy.new
|
11
|
+
@dummy.secret = 'Shhhh'
|
12
|
+
end
|
13
|
+
|
14
|
+
should_encypted_and_decrypt
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'With a Proc returning a key object' do
|
18
|
+
setup do
|
19
|
+
@password = 'boost facile'
|
20
|
+
@private_key = OpenSSL::PKey::RSA.new(2048)
|
21
|
+
rebuild_model :key_pair => Proc.new { @private_key }
|
22
|
+
@dummy = Dummy.new
|
23
|
+
@dummy.secret = 'Shhhh'
|
24
|
+
end
|
25
|
+
|
26
|
+
should_encypted_and_decrypt
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'With Procs returning public and private key strings' do
|
30
|
+
setup do
|
31
|
+
@password = 'boost facile'
|
32
|
+
@key_pair = File.read(File.join(FIXTURES_DIR,'keypair.pem'))
|
33
|
+
|
34
|
+
rebuild_model :public_key => Proc.new { @key_pair },
|
35
|
+
:private_key => Proc.new { @key_pair }
|
36
|
+
@dummy = Dummy.new
|
37
|
+
@dummy.secret = 'Shhhh'
|
38
|
+
end
|
39
|
+
|
40
|
+
should_encypted_and_decrypt
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'With Procs returning public and private key objects' do
|
44
|
+
setup do
|
45
|
+
@password = 'boost facile'
|
46
|
+
@private_key = OpenSSL::PKey::RSA.new(2048)
|
47
|
+
@public_key = @private_key.public_key
|
48
|
+
|
49
|
+
rebuild_model :public_key => Proc.new { @public_key },
|
50
|
+
:private_key => Proc.new { @private_key }
|
51
|
+
@dummy = Dummy.new
|
52
|
+
@dummy.secret = 'Shhhh'
|
53
|
+
end
|
54
|
+
|
55
|
+
should_encypted_and_decrypt
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'test/test_helper'
|
3
|
+
|
4
|
+
class StrongboxMultiPlyTest < Test::Unit::TestCase
|
5
|
+
context 'A Class with two secured fields' do
|
6
|
+
setup do
|
7
|
+
@password = 'boost facile'
|
8
|
+
key_pair = File.join(FIXTURES_DIR,'keypair.pem')
|
9
|
+
Dummy.class_eval do
|
10
|
+
encrypt_with_public_key :secret, :segreto, :key_pair => key_pair
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'that is valid' do
|
15
|
+
setup do
|
16
|
+
@dummy = Dummy.new
|
17
|
+
@dummy.secret = 'I have a secret...'
|
18
|
+
end
|
19
|
+
|
20
|
+
should 'return "*encrypted*" when the record is locked' do
|
21
|
+
assert_equal '*encrypted*', @dummy.secret.decrypt
|
22
|
+
end
|
23
|
+
|
24
|
+
should 'return the secrets when unlocked' do
|
25
|
+
assert_equal 'I have a secret...', @dummy.secret.decrypt(@password)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'Using strings for keys' do
|
32
|
+
setup do
|
33
|
+
@password = 'boost facile'
|
34
|
+
key_pair = File.read(File.join(FIXTURES_DIR,'keypair.pem'))
|
35
|
+
public_key = OpenSSL::PKey::RSA.new(key_pair,"")
|
36
|
+
private_key = OpenSSL::PKey::RSA.new(key_pair,@password)
|
37
|
+
Dummy.class_eval do
|
38
|
+
encrypt_with_public_key :secret, :public_key => public_key, :private_key => private_key
|
39
|
+
end
|
40
|
+
@dummy = Dummy.new
|
41
|
+
@dummy.secret = 'Shhhh'
|
42
|
+
end
|
43
|
+
|
44
|
+
should 'return "*encrypted*" when locked' do
|
45
|
+
assert_equal '*encrypted*', @dummy.secret.decrypt
|
46
|
+
end
|
47
|
+
|
48
|
+
should 'return secret when unlocked' do
|
49
|
+
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,252 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'test/test_helper'
|
3
|
+
|
4
|
+
class StrongboxTest < Test::Unit::TestCase
|
5
|
+
context 'A Class with a secured field' do
|
6
|
+
setup do
|
7
|
+
@password = 'boost facile'
|
8
|
+
rebuild_model :key_pair => File.join(FIXTURES_DIR,'keypair.pem')
|
9
|
+
end
|
10
|
+
|
11
|
+
should 'not error when trying to also create a secure field' do
|
12
|
+
assert_nothing_raised do
|
13
|
+
Dummy.class_eval do
|
14
|
+
encrypt_with_public_key :secret
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'that is valid' do
|
20
|
+
setup do
|
21
|
+
@dummy = Dummy.new
|
22
|
+
@dummy.secret = 'Shhhh'
|
23
|
+
@dummy.in_the_clear = 'Hey you guys!'
|
24
|
+
end
|
25
|
+
|
26
|
+
should 'not change unencrypted fields' do
|
27
|
+
assert_equal 'Hey you guys!', @dummy.in_the_clear
|
28
|
+
end
|
29
|
+
|
30
|
+
should 'return "*encrypted*" when locked' do
|
31
|
+
assert_equal '*encrypted*', @dummy.secret.decrypt
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'return secret when unlocked' do
|
35
|
+
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
|
36
|
+
end
|
37
|
+
|
38
|
+
should 'generate and store symmetric encryption key and IV' do
|
39
|
+
assert_not_nil @dummy.attributes['secret_key']
|
40
|
+
assert_not_nil @dummy.attributes['secret_iv']
|
41
|
+
end
|
42
|
+
|
43
|
+
should 'raise on bad password' do
|
44
|
+
assert_raises(OpenSSL::PKey::RSAError) do
|
45
|
+
@dummy.secret.decrypt('letmein')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
should 'impliment to_json' do
|
50
|
+
assert_nothing_raised do
|
51
|
+
@dummy.secret.to_json
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'updating unencrypted fields' do
|
56
|
+
setup do
|
57
|
+
@dummy.in_the_clear = 'I see you...'
|
58
|
+
@dummy.save
|
59
|
+
end
|
60
|
+
|
61
|
+
should 'not effect the secret' do
|
62
|
+
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'updating the secret' do
|
67
|
+
setup do
|
68
|
+
@dummy.secret = @new_secret = 'Don\'t tell'
|
69
|
+
@dummy.save
|
70
|
+
end
|
71
|
+
|
72
|
+
should 'update the secret' do
|
73
|
+
assert_equal @new_secret, @dummy.secret.decrypt(@password)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'with symmetric encryption disabled' do
|
78
|
+
setup do
|
79
|
+
rebuild_class(:key_pair => File.join(FIXTURES_DIR,'keypair.pem'),
|
80
|
+
:symmetric => :never)
|
81
|
+
@dummy = Dummy.new
|
82
|
+
@dummy.secret = 'Shhhh'
|
83
|
+
end
|
84
|
+
|
85
|
+
should 'return "*encrypted*" when locked' do
|
86
|
+
assert_equal '*encrypted*', @dummy.secret.decrypt
|
87
|
+
end
|
88
|
+
|
89
|
+
should 'return secret when unlocked' do
|
90
|
+
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
|
91
|
+
end
|
92
|
+
|
93
|
+
should 'allow decryption of other strings encrypted with the same key' do
|
94
|
+
encrypted_text = File.read(File.join(FIXTURES_DIR,'encrypted'))
|
95
|
+
assert_equal 'Setec Astronomy', @dummy.secret.decrypt(@password, encrypted_text)
|
96
|
+
end
|
97
|
+
|
98
|
+
should 'not generate and store symmetric encryption key and IV' do
|
99
|
+
assert_nil @dummy.attributes['secret_key']
|
100
|
+
assert_nil @dummy.attributes['secret_iv']
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'with Base64 encoding enabled' do
|
106
|
+
setup do
|
107
|
+
rebuild_class(:key_pair => File.join(FIXTURES_DIR,'keypair.pem'),
|
108
|
+
:base64 => true)
|
109
|
+
@dummy = Dummy.new
|
110
|
+
@dummy.secret = 'Shhhh'
|
111
|
+
end
|
112
|
+
|
113
|
+
should 'Base64 encode the ciphertext' do
|
114
|
+
# Base64 encoded text is limited to the charaters A–Z, a–z, and 0–9,
|
115
|
+
# and is padded with 0 to 2 equal-signs
|
116
|
+
assert_match /^[0-9A-Za-z+\/]+={0,2}$/, @dummy.attributes['secret']
|
117
|
+
assert_match /^[0-9A-Za-z+\/]+={0,2}$/, @dummy.attributes['secret_key']
|
118
|
+
assert_match /^[0-9A-Za-z+\/]+={0,2}$/, @dummy.attributes['secret_iv']
|
119
|
+
end
|
120
|
+
|
121
|
+
should 'encrypt the data' do
|
122
|
+
assert_not_equal @dummy.attributes['secret'], 'Shhhh'
|
123
|
+
assert_equal '*encrypted*', @dummy.secret.decrypt
|
124
|
+
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'using blowfish cipher instead of AES' do
|
130
|
+
setup do
|
131
|
+
rebuild_class(:key_pair => File.join(FIXTURES_DIR,'keypair.pem'),
|
132
|
+
:symmetric_cipher => 'bf-cbc')
|
133
|
+
@dummy = Dummy.new
|
134
|
+
@dummy.secret = 'Shhhh'
|
135
|
+
end
|
136
|
+
|
137
|
+
should 'encrypt the data' do
|
138
|
+
assert_not_equal @dummy.attributes['secret'], 'Shhhh'
|
139
|
+
assert_equal '*encrypted*', @dummy.secret.decrypt
|
140
|
+
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'when a public key is not provided' do
|
146
|
+
setup do
|
147
|
+
rebuild_class
|
148
|
+
@dummy = Dummy.new
|
149
|
+
end
|
150
|
+
|
151
|
+
should 'raise on encrypt' do
|
152
|
+
assert_raises(Strongbox::StrongboxError) do
|
153
|
+
@dummy.secret = 'Shhhh'
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'when a private key is not provided' do
|
159
|
+
setup do
|
160
|
+
@password = 'boost facile'
|
161
|
+
rebuild_class(:public_key => File.join(FIXTURES_DIR,'keypair.pem'))
|
162
|
+
@dummy = Dummy.new(:secret => 'Shhhh')
|
163
|
+
end
|
164
|
+
|
165
|
+
should 'raise on decrypt with a password' do
|
166
|
+
assert_raises(Strongbox::StrongboxError) do
|
167
|
+
@dummy.secret.decrypt(@password)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
should 'return "*encrypted*" when still locked' do
|
172
|
+
assert_equal '*encrypted*', @dummy.secret.decrypt
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "when an unencrypted public key is used" do
|
177
|
+
setup do
|
178
|
+
rebuild_class(:public_key => generate_key_pair.public_key)
|
179
|
+
@dummy = Dummy.new(:secret => 'Shhhh')
|
180
|
+
end
|
181
|
+
|
182
|
+
should "encrypt the data" do
|
183
|
+
assert_not_equal @dummy.attributes['secret'], 'Shhhh'
|
184
|
+
assert_equal '*encrypted*', @dummy.secret.decrypt
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "when an unencrypted key pair is used" do
|
189
|
+
setup do
|
190
|
+
rebuild_class(:key_pair => generate_key_pair)
|
191
|
+
@dummy = Dummy.new(:secret => 'Shhhh')
|
192
|
+
end
|
193
|
+
|
194
|
+
should "encrypt the data" do
|
195
|
+
assert_not_equal @dummy.attributes['secret'], 'Shhhh'
|
196
|
+
assert_equal "Shhhh", @dummy.secret.decrypt('')
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
context 'A Class with two secured fields' do
|
201
|
+
setup do
|
202
|
+
@password = 'boost facile'
|
203
|
+
key_pair = File.join(FIXTURES_DIR,'keypair.pem')
|
204
|
+
Dummy.class_eval do
|
205
|
+
encrypt_with_public_key :secret, :key_pair => key_pair
|
206
|
+
encrypt_with_public_key :segreto, :key_pair => key_pair,
|
207
|
+
:symmetric => :never
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context 'that is valid' do
|
212
|
+
setup do
|
213
|
+
@dummy = Dummy.new
|
214
|
+
@dummy.secret = 'I have a secret...'
|
215
|
+
@dummy.segreto = 'Ho un segreto...'
|
216
|
+
end
|
217
|
+
|
218
|
+
should 'return "*encrypted*" when the record is locked' do
|
219
|
+
assert_equal '*encrypted*', @dummy.secret.decrypt
|
220
|
+
assert_equal '*encrypted*', @dummy.segreto.decrypt
|
221
|
+
end
|
222
|
+
|
223
|
+
should 'return the secrets when unlocked' do
|
224
|
+
assert_equal 'I have a secret...', @dummy.secret.decrypt(@password)
|
225
|
+
assert_equal 'Ho un segreto...', @dummy.segreto.decrypt(@password)
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context 'Using strings for keys' do
|
232
|
+
setup do
|
233
|
+
@password = 'boost facile'
|
234
|
+
key_pair = File.read(File.join(FIXTURES_DIR,'keypair.pem'))
|
235
|
+
public_key = OpenSSL::PKey::RSA.new(key_pair,"")
|
236
|
+
private_key = OpenSSL::PKey::RSA.new(key_pair,@password)
|
237
|
+
Dummy.class_eval do
|
238
|
+
encrypt_with_public_key :secret, :public_key => public_key, :private_key => private_key
|
239
|
+
end
|
240
|
+
@dummy = Dummy.new
|
241
|
+
@dummy.secret = 'Shhhh'
|
242
|
+
end
|
243
|
+
|
244
|
+
should 'return "*encrypted*" when locked' do
|
245
|
+
assert_equal '*encrypted*', @dummy.secret.decrypt
|
246
|
+
end
|
247
|
+
|
248
|
+
should 'return secret when unlocked' do
|
249
|
+
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|