attr_secure 0.2.0 → 0.3.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 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