attr_secure 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3e6810f8e6b2500a0fd71a8d2cd2755bbab0759f
4
- data.tar.gz: b9d9017ec05194584f60af544a3564ba1f26cfc1
3
+ metadata.gz: 823b15116fee5d14b97ae231f81b48e7cb1b304e
4
+ data.tar.gz: 49b2aefa2a76a6eb4e6cd466320cba879ac88d20
5
5
  SHA512:
6
- metadata.gz: df04a6247b167ff02122d97de4498cf2c89d2b3277799382985bab5e5a97f920a7b4847fb5ff789513da857a56252b5137145f548affed24fa7afcf1516d011f
7
- data.tar.gz: 05418d708166a33ee050a171cdbe422373f54c1130e4f17334c12d5d93dc3fba9291a4052151136617e99457d6cefb5ebc4faddde5ec0b10c92ac0d483b1e49b
6
+ metadata.gz: 19037e5da221dc532f23f733380f1bf0d10f18fb1b18d1877aa648d32b42262ae42622a9491173be0630979bec41d601a13e9861b778d38b933bcd69f3f7213c
7
+ data.tar.gz: fd893bd6f3858c51e74c74057fbec4a88c99d588b849d1d42228a2996ad516669e29991f3ba6179bc7eef5cca3eb5800e1b3b083b80955552027444d7b32ab87
data/README.md CHANGED
@@ -42,22 +42,26 @@ To make an model attribute secure, first you need a secure key:
42
42
 
43
43
  dd if=/dev/urandom bs=32 count=1 2>/dev/null | openssl base64
44
44
 
45
- There's a number of ways of setting a key for a given attribute. The easiest is to default the key via the environment.
45
+ There's a number of ways of setting a key for a given attribute. The easiest is to default the key via the environment.
46
46
  Setting the environment variable `ATTR_SECURE_SECRET` to a secret value will secure all attributes with the same key.
47
47
 
48
48
  Alternatively, if you want to use different keys for different attributes you can do this too:
49
49
 
50
50
  attr_secure :my_attribute, :secret => "EKq88AMFeRLqEx5knUcoJ4LOnrv52d7hfAFgEKMoDKzqNei4m7kbu"
51
-
51
+
52
52
  If you would like your key dependent on something else, a lambda is OK too:
53
53
 
54
54
  attr_secure :my_attribute, :secret => lambda {|record| record.user.secret }
55
-
55
+
56
56
  Remember kids, it's not a good idea to hard-code secrets.
57
57
 
58
58
  Note: You will want to set your table columns for encrypted values to :text or
59
59
  similar. Encrypted values are long.
60
60
 
61
+ ## Key rotation
62
+
63
+ You can pass a comma delimited list of keys as your secret. attr_secure will decrypt with each key in turn until it hits a verified value. Encryption always happens with the newest (leftmost) key.
64
+
61
65
  ## Contributing
62
66
 
63
67
  1. Fork it
data/attr_secure.gemspec CHANGED
@@ -24,5 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "sequel"
25
25
  spec.add_development_dependency "sqlite3"
26
26
 
27
- spec.add_dependency 'fernet'
27
+ spec.add_dependency 'fernet', '1.6'
28
28
  end
@@ -3,7 +3,9 @@ module AttrSecure
3
3
  module ActiveRecord
4
4
 
5
5
  def self.valid?(object)
6
- object.respond_to?(:<) && defined?(ActiveRecord) && object < ::ActiveRecord::Base
6
+ object.respond_to?(:<) && object < ::ActiveRecord::Base
7
+ rescue NameError
8
+ false
7
9
  end
8
10
 
9
11
  def self.write_attribute(object, attribute, value)
@@ -3,7 +3,9 @@ module AttrSecure
3
3
  module Sequel
4
4
 
5
5
  def self.valid?(object)
6
- object.respond_to?(:<) && defined?(Sequel) && object < ::Sequel::Model
6
+ object.respond_to?(:<) && object < ::Sequel::Model
7
+ rescue NameError
8
+ false
7
9
  end
8
10
 
9
11
  def self.write_attribute(object, attribute, value)
@@ -9,19 +9,30 @@ module AttrSecure
9
9
  attr_reader :secret
10
10
 
11
11
  def initialize(secret)
12
- @secret = secret
12
+ @secret = secret.split(",")
13
+ end
14
+
15
+ def secret=(val)
16
+ @secret = secret.split(",")
13
17
  end
14
18
 
15
19
  def encrypt(value)
16
- Fernet.generate(secret) do |generator|
20
+ Fernet.generate([secret].flatten.first) do |generator|
17
21
  generator.data = { value: value }
18
22
  end
19
23
  end
20
24
 
21
25
  def decrypt(value)
22
26
  return nil if value.nil?
23
- verifier = Fernet.verifier(secret, value)
24
- verifier.data['value'] if verifier.valid?
27
+ [secret].flatten.each do |_secret|
28
+ begin
29
+ verifier = Fernet.verifier(_secret, value)
30
+ return verifier.data['value'] if verifier.valid?
31
+ rescue
32
+ end
33
+ raise OpenSSL::Cipher::CipherError
34
+ end
25
35
  end
36
+
26
37
  end
27
38
  end
@@ -1,3 +1,3 @@
1
1
  module AttrSecure
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -16,6 +16,11 @@ describe AttrSecure::Adapters::ActiveRecord do
16
16
  it "should not be valid" do
17
17
  expect(described_class.valid?(String)).to be_false
18
18
  end
19
+
20
+ it "should not be valid if activerecord is not loaded" do
21
+ hide_const('ActiveRecord')
22
+ expect(described_class.valid?(described)).to be_false
23
+ end
19
24
  end
20
25
 
21
26
  describe "write attribute" do
@@ -16,6 +16,11 @@ describe AttrSecure::Adapters::Sequel do
16
16
  it "should not be valid" do
17
17
  expect(described_class.valid?(String)).to be_false
18
18
  end
19
+
20
+ it "should not be valid if sequel is not loaded" do
21
+ hide_const('Sequel')
22
+ expect(described_class.valid?(described)).to be_false
23
+ end
19
24
  end
20
25
 
21
26
  describe "write attribute" do
@@ -6,8 +6,8 @@ describe AttrSecure do
6
6
  let(:described) { Class.new }
7
7
  let(:secure_mock) { double(AttrSecure::Secure) }
8
8
  let(:secret_mock) { double(AttrSecure::Secret) }
9
- let(:crypter) { mock(:secure_crypter) }
10
- let(:adapter) { mock(:adapter) }
9
+ let(:crypter) { double(:secure_crypter) }
10
+ let(:adapter) { double(:adapter) }
11
11
 
12
12
  before do
13
13
  described.extend(AttrSecure)
data/spec/secure_spec.rb CHANGED
@@ -1,22 +1,46 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe AttrSecure::Secure do
4
- subject { described_class.new(secret) }
5
- let(:secret) { 'fWSvpC6Eh1/FFE1TUgXpcEzMmmGc9IZSqoexzEslzKI=' }
6
-
7
- describe 'encrypt' do
8
- it "should encrypt a string" do
9
- expect(subject.encrypt('encrypted')).to be_a(String)
10
- expect(subject.encrypt('encrypted')).to_not be_empty
11
- expect(subject.encrypt('encrypted')).to_not eq(subject.encrypt('encrypted'))
4
+ context "with a simple key" do
5
+
6
+ subject { described_class.new(secret) }
7
+ let(:secret) { 'fWSvpC6Eh1/FFE1TUgXpcEzMmmGc9IZSqoexzEslzKI=' }
8
+
9
+ describe '#encrypt' do
10
+ it "should encrypt a string" do
11
+ expect(subject.encrypt('encrypted')).to be_a(String)
12
+ expect(subject.encrypt('encrypted')).to_not be_empty
13
+ expect(subject.encrypt('encrypted')).to_not eq(subject.encrypt('encrypted'))
14
+ end
12
15
  end
13
- end
14
16
 
15
- describe 'decrypt' do
16
- let(:encrypted_value) { subject.encrypt('decrypted') }
17
+ describe '#decrypt' do
18
+ let(:encrypted_value) { subject.encrypt('decrypted') }
17
19
 
18
- it "should decrypt a string" do
19
- expect(subject.decrypt(encrypted_value)).to eq('decrypted')
20
+ it "should decrypt a string" do
21
+ expect(subject.decrypt(encrypted_value)).to eq('decrypted')
22
+ end
20
23
  end
21
24
  end
25
+
26
+ # context "with an array of keys" do
27
+ # subject { described_class.new(secret) }
28
+ # let(:secret) { 'fWSvpC6Eh1/FFE1TUgXpcEzMmmGc9IZSqoexzEslzKI=,d9ssNmUYn7UpMoSc0eM2glVUG2DPYwXveLTDU7j8pBY=' }
29
+
30
+ # describe '#encrypt' do
31
+ # it "should encrypt a string" do
32
+ # expect(subject.encrypt('encrypted')).to be_a(String)
33
+ # expect(subject.encrypt('encrypted')).to_not be_empty
34
+ # expect(subject.encrypt('encrypted')).to_not eq(subject.encrypt('encrypted'))
35
+ # end
36
+ # end
37
+
38
+ # describe '#decrypt' do
39
+ # let(:encrypted_value) { subject.encrypt('decrypted') }
40
+
41
+ # it "should decrypt a string" do
42
+ # expect(subject.decrypt(encrypted_value)).to eq('decrypted')
43
+ # end
44
+ # end
45
+ # end
22
46
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attr_secure
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neil Middleton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-07 00:00:00.000000000 Z
11
+ date: 2013-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -84,16 +84,16 @@ dependencies:
84
84
  name: fernet
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '1.6'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '1.6'
97
97
  description: Securely stores activerecord model attributes
98
98
  email:
99
99
  - neil@neilmiddleton.com
@@ -144,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
144
  version: '0'
145
145
  requirements: []
146
146
  rubyforge_project:
147
- rubygems_version: 2.0.2
147
+ rubygems_version: 2.0.7
148
148
  signing_key:
149
149
  specification_version: 4
150
150
  summary: Securely stores activerecord model attributes