attr_encryptor 1.0.2 → 2.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 15fa84f14870e8333f343f5ce8d2e56b71e7c576
4
+ data.tar.gz: de53d4a0d42aa01b867d29834a056224d4173caf
5
+ SHA512:
6
+ metadata.gz: 78abb59d5e439b54eb77f7eb4b786669457039a7dcc7724014caed61f941b664e0b2a2fb77f6e22f431c5d70b7fe1b4c38cb0580166725fe166092e4c5da8da5
7
+ data.tar.gz: ace36c9f963ab74233525b8a2e6ea9a3f41d3db9ec626b298305f30ddddcd94ac51f948fd1582c36a3c693275b4b936e7e916067c26bebd61478827c0031a6b8
@@ -0,0 +1 @@
1
+ attr_encrypted
@@ -0,0 +1 @@
1
+ 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ ruby '2.0.0'
2
+ source 'https://rubygems.org'
3
+
4
+
5
+ gem 'encryptor2'
6
+
7
+ group :development do
8
+ gem 'pry'
9
+ gem 'activerecord'
10
+ gem 'datamapper'
11
+ gem 'mocha'
12
+ gem 'sequel'
13
+ gem 'dm-sqlite-adapter'
14
+ gem 'sqlite3'
15
+ end
@@ -0,0 +1,108 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activemodel (4.0.0)
5
+ activesupport (= 4.0.0)
6
+ builder (~> 3.1.0)
7
+ activerecord (4.0.0)
8
+ activemodel (= 4.0.0)
9
+ activerecord-deprecated_finders (~> 1.0.2)
10
+ activesupport (= 4.0.0)
11
+ arel (~> 4.0.0)
12
+ activerecord-deprecated_finders (1.0.3)
13
+ activesupport (4.0.0)
14
+ i18n (~> 0.6, >= 0.6.4)
15
+ minitest (~> 4.2)
16
+ multi_json (~> 1.3)
17
+ thread_safe (~> 0.1)
18
+ tzinfo (~> 0.3.37)
19
+ addressable (2.3.5)
20
+ arel (4.0.0)
21
+ atomic (1.1.10)
22
+ bcrypt-ruby (3.1.1)
23
+ builder (3.1.4)
24
+ coderay (1.0.9)
25
+ data_objects (0.10.13)
26
+ addressable (~> 2.1)
27
+ datamapper (1.2.0)
28
+ dm-aggregates (~> 1.2.0)
29
+ dm-constraints (~> 1.2.0)
30
+ dm-core (~> 1.2.0)
31
+ dm-migrations (~> 1.2.0)
32
+ dm-serializer (~> 1.2.0)
33
+ dm-timestamps (~> 1.2.0)
34
+ dm-transactions (~> 1.2.0)
35
+ dm-types (~> 1.2.0)
36
+ dm-validations (~> 1.2.0)
37
+ dm-aggregates (1.2.0)
38
+ dm-core (~> 1.2.0)
39
+ dm-constraints (1.2.0)
40
+ dm-core (~> 1.2.0)
41
+ dm-core (1.2.1)
42
+ addressable (~> 2.3)
43
+ dm-do-adapter (1.2.0)
44
+ data_objects (~> 0.10.6)
45
+ dm-core (~> 1.2.0)
46
+ dm-migrations (1.2.0)
47
+ dm-core (~> 1.2.0)
48
+ dm-serializer (1.2.2)
49
+ dm-core (~> 1.2.0)
50
+ fastercsv (~> 1.5)
51
+ json (~> 1.6)
52
+ json_pure (~> 1.6)
53
+ multi_json (~> 1.0)
54
+ dm-sqlite-adapter (1.2.0)
55
+ dm-do-adapter (~> 1.2.0)
56
+ do_sqlite3 (~> 0.10.6)
57
+ dm-timestamps (1.2.0)
58
+ dm-core (~> 1.2.0)
59
+ dm-transactions (1.2.0)
60
+ dm-core (~> 1.2.0)
61
+ dm-types (1.2.2)
62
+ bcrypt-ruby (~> 3.0)
63
+ dm-core (~> 1.2.0)
64
+ fastercsv (~> 1.5)
65
+ json (~> 1.6)
66
+ multi_json (~> 1.0)
67
+ stringex (~> 1.4)
68
+ uuidtools (~> 2.1)
69
+ dm-validations (1.2.0)
70
+ dm-core (~> 1.2.0)
71
+ do_sqlite3 (0.10.13)
72
+ data_objects (= 0.10.13)
73
+ encryptor2 (1.0.0)
74
+ fastercsv (1.5.5)
75
+ i18n (0.6.4)
76
+ json (1.8.0)
77
+ json_pure (1.8.0)
78
+ metaclass (0.0.1)
79
+ method_source (0.8.1)
80
+ minitest (4.7.5)
81
+ mocha (0.14.0)
82
+ metaclass (~> 0.0.1)
83
+ multi_json (1.7.7)
84
+ pry (0.9.12.2)
85
+ coderay (~> 1.0.5)
86
+ method_source (~> 0.8)
87
+ slop (~> 3.4)
88
+ sequel (4.0.0)
89
+ slop (3.4.5)
90
+ sqlite3 (1.3.7)
91
+ stringex (1.5.1)
92
+ thread_safe (0.1.0)
93
+ atomic
94
+ tzinfo (0.3.37)
95
+ uuidtools (2.1.4)
96
+
97
+ PLATFORMS
98
+ ruby
99
+
100
+ DEPENDENCIES
101
+ activerecord
102
+ datamapper
103
+ dm-sqlite-adapter
104
+ encryptor2
105
+ mocha
106
+ pry
107
+ sequel
108
+ sqlite3
data/README.md CHANGED
@@ -15,7 +15,7 @@ It works with ANY class, however, you get a few extra features when you're using
15
15
 
16
16
  Encrypting attributes has never been easier:
17
17
 
18
- ### You database
18
+ ### Your database
19
19
 
20
20
  add a `encrypted_ssn`, `encrypted_ssn_salt`, `encrypted_ssn_iv`. All of
21
21
  them will be populated automatically
@@ -23,6 +23,7 @@ them will be populated automatically
23
23
  create_table :google_apps_admins do |t|
24
24
  t.string :username
25
25
  t.string :encrypted_password
26
+ t.string :encrypted_password_salt
26
27
  t.string :encrypted_password_iv
27
28
  t.string :domain
28
29
  t.timestamps
@@ -243,6 +244,14 @@ encrypted string. I've had this problem myself using MySQL. You can simply pass
243
244
 
244
245
  The default encoding is `m*` (base64). You can change this by setting `:encode => 'some encoding'`. See the `Array#pack` method at http://www.ruby-doc.org/core/classes/Array.html#M002245 for more encoding options.
245
246
 
247
+ ### String Encoding/Charset
248
+
249
+ If you are trying to store UTF-8 (or other non-english charsets) strings in your encrypted parameters, you may get the decrypted string back as a US-ASCII or ASCII-8BIT string.
250
+
251
+ To fix this, add the `:charset => 'UTF-8'` option to your encrypted attribute definitions.
252
+ This option defaults to whatever your `Encoding.default_internal` is set to. `:charset => :default` will force it to use the default value.
253
+
254
+ This option only applies to encrypted strings and will be ignored when encrypting marshalled objects.
246
255
 
247
256
  ### Marshaling
248
257
 
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rake'
2
2
  require 'rake/testtask'
3
- require 'rake/rdoctask'
3
+ require 'rdoc/task'
4
4
 
5
5
  desc 'Default: run unit tests.'
6
6
  task :default => :test
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
16
16
 
17
17
  s.author = 'Daniel Palacio'
18
18
  s.email = 'danpal@gmail.com'
19
- s.homepage = 'http://github.com/danpal/attr_encrypted'
19
+ s.homepage = 'http://github.com/danpal/attr_encryptor'
20
20
 
21
21
  s.has_rdoc = false
22
22
  s.rdoc_options = ['--line-numbers', '--inline-source', '--main', 'README.rdoc']
@@ -69,6 +69,8 @@ module AttrEncryptor
69
69
  # :unless => Attributes are only encrypted if this option evaluates to false. If you pass a symbol representing an instance
70
70
  # method then the result of the method will be evaluated. Any objects that respond to <tt>:call</tt> are evaluated as well.
71
71
  # Defaults to false.
72
+ # :charset => Forces the decrypted string to be interpreted as the specified encoding. Does not change the underlying bits.
73
+ # Use :default to use Ruby's default encoding.
72
74
  #
73
75
  # You can specify your own default options
74
76
  #
@@ -111,10 +113,12 @@ module AttrEncryptor
111
113
  :load_method => 'load',
112
114
  :encryptor => Encryptor,
113
115
  :encrypt_method => 'encrypt',
114
- :decrypt_method => 'decrypt'
116
+ :decrypt_method => 'decrypt',
117
+ :charset => :default
115
118
  }.merge!(attr_encrypted_options).merge!(attributes.last.is_a?(Hash) ? attributes.pop : {})
116
119
 
117
120
  options[:encode] = options[:default_encoding] if options[:encode] == true
121
+ options[:charset] = Encoding.default_internal if options[:charset] == :default
118
122
 
119
123
  attributes.each do |attribute|
120
124
  encrypted_attribute_name = (options[:attribute] ? options[:attribute] : [options[:prefix], attribute, options[:suffix]].join).to_sym
@@ -122,27 +126,27 @@ module AttrEncryptor
122
126
  instance_methods_as_symbols = instance_methods.collect { |method| method.to_sym }
123
127
  attr_reader encrypted_attribute_name unless instance_methods_as_symbols.include?(encrypted_attribute_name)
124
128
  attr_writer encrypted_attribute_name unless instance_methods_as_symbols.include?(:"#{encrypted_attribute_name}=")
125
-
129
+
126
130
  attr_reader (encrypted_attribute_name.to_s + "_iv").to_sym unless instance_methods_as_symbols.include?((encrypted_attribute_name.to_s + "_iv").to_sym )
127
131
  attr_writer (encrypted_attribute_name.to_s + "_iv").to_sym unless instance_methods_as_symbols.include?((encrypted_attribute_name.to_s + "_iv").to_sym )
128
-
132
+
129
133
  attr_reader (encrypted_attribute_name.to_s + "_salt").to_sym unless instance_methods_as_symbols.include?((encrypted_attribute_name.to_s + "_salt").to_sym )
130
134
  attr_writer (encrypted_attribute_name.to_s + "_salt").to_sym unless instance_methods_as_symbols.include?((encrypted_attribute_name.to_s + "_salt").to_sym )
131
135
 
132
136
 
133
137
 
134
138
  define_method(attribute) do
135
-
139
+
136
140
  load_iv_for_attribute(attribute,encrypted_attribute_name, options[:algorithm])
137
- load_salt_for_attribute(attribute,encrypted_attribute_name)
141
+ load_salt_for_attribute(attribute,encrypted_attribute_name)
138
142
 
139
143
  instance_variable_get("@#{attribute}") || instance_variable_set("@#{attribute}", decrypt(attribute, send(encrypted_attribute_name)))
140
144
  end
141
145
 
142
146
  define_method("#{attribute}=") do |value|
143
147
  load_iv_for_attribute(attribute, encrypted_attribute_name, options[:algorithm])
144
- load_salt_for_attribute(attribute, encrypted_attribute_name)
145
-
148
+ load_salt_for_attribute(attribute, encrypted_attribute_name)
149
+
146
150
  #this add's the iv and salt on the options for this instance
147
151
  send("#{encrypted_attribute_name}=", encrypt(attribute, value))
148
152
  instance_variable_set("@#{attribute}", value)
@@ -195,10 +199,16 @@ module AttrEncryptor
195
199
  encrypted_value = encrypted_value.unpack(options[:encode]).first if options[:encode]
196
200
  value = options[:encryptor].send(options[:decrypt_method], options.merge!(:value => encrypted_value))
197
201
  value = options[:marshaler].send(options[:load_method], value) if options[:marshal]
198
- value
202
+ return_value = value
199
203
  else
200
- encrypted_value
204
+ return_value = encrypted_value
201
205
  end
206
+
207
+ if RUBY_VERSION > '1.9' && options[:charset].present? && return_value.present? && return_value.is_a?(String)
208
+ return_value.force_encoding(options[:charset])
209
+ end
210
+
211
+ return_value
202
212
  end
203
213
 
204
214
  # Encrypts a value for the attribute specified
@@ -292,10 +302,7 @@ module AttrEncryptor
292
302
  def encrypt(attribute, value)
293
303
  self.class.encrypt(attribute, value, evaluated_attr_encrypted_options_for(attribute))
294
304
  end
295
-
296
- def foo
297
305
 
298
- end
299
306
  protected
300
307
 
301
308
  # Returns attr_encrypted options evaluated in the current object's scope for the attribute specified
@@ -319,7 +326,7 @@ module AttrEncryptor
319
326
  def load_iv_for_attribute (attribute, encrypted_attribute_name, algorithm)
320
327
  iv = send("#{encrypted_attribute_name.to_s + "_iv"}")
321
328
  if(iv == nil)
322
- begin
329
+ begin
323
330
  algorithm = algorithm || "aes-256-cbc"
324
331
  algo = OpenSSL::Cipher::Cipher.new(algorithm)
325
332
  iv = [algo.random_iv].pack("m")
@@ -331,10 +338,10 @@ module AttrEncryptor
331
338
  end
332
339
 
333
340
  def load_salt_for_attribute(attribute, encrypted_attribute_name)
334
- salt = send("#{encrypted_attribute_name.to_s + "_salt"}") || send("#{encrypted_attribute_name.to_s + "_salt"}=", Time.now.to_i.to_s)
341
+ salt = send("#{encrypted_attribute_name.to_s + "_salt"}") || send("#{encrypted_attribute_name.to_s + "_salt"}=", Digest::SHA256.hexdigest((Time.now.to_i * rand(1000)).to_s)[0..15])
335
342
  self.class.encrypted_attributes[attribute.to_sym] = self.class.encrypted_attributes[attribute.to_sym].merge(:salt => salt)
336
343
  end
337
-
344
+
338
345
 
339
346
  end
340
347
  end
@@ -4,19 +4,26 @@ if defined?(ActiveRecord::Base)
4
4
  module ActiveRecord
5
5
  def self.extended(base) # :nodoc:
6
6
  base.class_eval do
7
+ class << self
8
+ alias_method_chain :attr_encrypted, :defined_attributes
9
+ alias_method_chain :attr_encryptor, :defined_attributes
10
+ end
11
+
7
12
  attr_encrypted_options[:encode] = true
8
13
  end
9
14
  end
10
15
 
11
16
  protected
12
17
 
13
- # Ensures the attribute methods for db fields have been defined before calling the original
14
- # <tt>attr_encrypted</tt> method
15
- def attr_encrypted(*attrs)
16
- define_attribute_methods rescue nil
17
- super
18
- attrs.reject { |attr| attr.is_a?(Hash) }.each { |attr| alias_method "#{attr}_before_type_cast", attr }
19
- end
18
+ # Ensures the attribute methods for db fields have been defined before calling the original
19
+ # <tt>attr_encrypted</tt> method
20
+ def attr_encrypted_with_defined_attributes(*attrs)
21
+ define_attribute_methods rescue nil
22
+ attr_encrypted_without_defined_attributes *attrs
23
+ attrs.reject { |attr| attr.is_a?(Hash) }.each { |attr| alias_method "#{attr}_before_type_cast", attr }
24
+ end
25
+
26
+ alias attr_encryptor_with_defined_attributes attr_encrypted_with_defined_attributes
20
27
  end
21
28
  end
22
29
  end
@@ -1,9 +1,9 @@
1
1
  module AttrEncryptor
2
2
  # Contains information about this gem's version
3
3
  module Version
4
- MAJOR = 1
4
+ MAJOR = 2
5
5
  MINOR = 0
6
- PATCH = 2
6
+ PATCH = 0
7
7
 
8
8
  # Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and <tt>PATCH</tt> with <tt>'.'</tt>
9
9
  #
@@ -30,8 +30,8 @@ create_tables
30
30
  ActiveRecord::MissingAttributeError = ActiveModel::MissingAttributeError unless defined?(ActiveRecord::MissingAttributeError)
31
31
 
32
32
  class Person < ActiveRecord::Base
33
- attr_encrypted :email, :key => "secret"
34
- attr_encrypted :credentials, :key => Proc.new { |user| Encryptor.encrypt(:value => user.salt, :key => 'secret_key') }, :marshal => true
33
+ attr_encrypted :email, :key => SECRET_KEY
34
+ attr_encrypted :credentials, :key => Proc.new { |user| Encryptor.encrypt(:value => user.salt, :key => SECRET_KEY) }, :marshal => true
35
35
 
36
36
 
37
37
  after_initialize :initialize_salt_and_credentials
@@ -39,7 +39,7 @@ class Person < ActiveRecord::Base
39
39
  protected
40
40
 
41
41
  def initialize_salt_and_credentials
42
- self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(5)).to_s)
42
+ self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(1000)).to_s)[0..15]
43
43
  self.credentials ||= { :username => 'example', :password => 'test' }
44
44
  end
45
45
  end
@@ -58,43 +58,42 @@ class ActiveRecordTest < Test::Unit::TestCase
58
58
  def setup
59
59
  ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
60
60
  create_tables
61
- Account.create!(:key => "secret", :password => "password")
61
+ Account.create!(:key => SECRET_KEY, :password => "password")
62
62
  end
63
63
 
64
- def _test_should_encrypt_email
64
+ def test_should_encrypt_email
65
65
  @person = Person.create :email => 'test@example.com'
66
66
  assert_not_nil @person.encrypted_email
67
67
  assert_not_equal @person.email, @person.encrypted_email
68
68
  assert_equal @person.email, Person.find(:first).email
69
69
  end
70
70
 
71
- def _test_should_marshal_and_encrypt_credentials
71
+ def test_should_marshal_and_encrypt_credentials
72
72
  @person = Person.create
73
73
  assert_not_nil @person.encrypted_credentials
74
74
  assert_not_equal @person.credentials, @person.encrypted_credentials
75
75
  assert_equal @person.credentials, Person.find(:first).credentials
76
76
  end
77
77
 
78
- def _test_should_encode_by_default
78
+ def test_should_encode_by_default
79
79
  assert Person.attr_encrypted_options[:encode]
80
80
  end
81
81
 
82
- def _test_should_validate_presence_of_email
82
+ def test_should_validate_presence_of_email
83
83
  @person = PersonWithValidation.new
84
84
  assert !@person.valid?
85
85
  assert !@person.errors[:email].empty? || @person.errors.on(:email)
86
86
  end
87
87
 
88
- def _test_should_encrypt_decrypt_with_iv
88
+ def test_should_encrypt_decrypt_with_iv
89
89
  @person = Person.create :email => 'test@example.com'
90
90
  @person2 = Person.find(@person.id)
91
91
  assert_not_nil @person2.encrypted_email_iv
92
92
  assert_equal 'test@example.com', @person2.email
93
93
  end
94
-
94
+
95
95
  def _test_should_create_an_account_regardless_of_arguments_order
96
- Account.create!(:key => "secret", :password => "password")
97
- Account.create!(:password => "password" , :key => "secret")
96
+ Account.create!(:key => SECRET_KEY, :password => "password")
97
+ Account.create!(:password => "password" , :key => SECRET_KEY)
98
98
  end
99
-
100
99
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  require File.expand_path('../test_helper', __FILE__)
2
3
 
3
4
  class SillyEncryptor
@@ -11,22 +12,26 @@ class SillyEncryptor
11
12
  end
12
13
 
13
14
  class User
14
- self.attr_encrypted_options[:key] = Proc.new { |user| user.class.to_s } # default key
15
+ self.attr_encrypted_options[:key] = Proc.new { |user| SECRET_KEY } # default key
15
16
 
16
- attr_encrypted :email, :without_encoding, :key => 'secret key'
17
+ attr_encrypted :email, :without_encoding, :key => SECRET_KEY
17
18
  attr_encrypted :password, :prefix => 'crypted_', :suffix => '_test'
18
- attr_encrypted :ssn, :key => :salt, :attribute => 'ssn_encrypted'
19
+ attr_encrypted :ssn, :key => :secret_key, :attribute => 'ssn_encrypted'
19
20
  attr_encrypted :credit_card, :encryptor => SillyEncryptor, :encrypt_method => :silly_encrypt, :decrypt_method => :silly_decrypt, :some_arg => 'test'
20
- attr_encrypted :with_encoding, :key => 'secret key', :encode => true
21
- attr_encrypted :with_custom_encoding, :key => 'secret key', :encode => 'm'
22
- attr_encrypted :with_marshaling, :key => 'secret key', :marshal => true
23
- attr_encrypted :with_true_if, :key => 'secret key', :if => true
24
- attr_encrypted :with_false_if, :key => 'secret key', :if => false
25
- attr_encrypted :with_true_unless, :key => 'secret key', :unless => true
26
- attr_encrypted :with_false_unless, :key => 'secret key', :unless => false
27
- attr_encrypted :with_if_changed, :key => 'secret key', :if => :should_encrypt
21
+ attr_encrypted :with_encoding, :key => SECRET_KEY, :encode => true
22
+ attr_encrypted :with_custom_encoding, :key => SECRET_KEY, :encode => 'm'
23
+ attr_encrypted :with_marshaling, :key => SECRET_KEY, :marshal => true
24
+ attr_encrypted :with_true_if, :key => SECRET_KEY, :if => true
25
+ attr_encrypted :with_false_if, :key => SECRET_KEY, :if => false
26
+ attr_encrypted :with_true_unless, :key => SECRET_KEY, :unless => true
27
+ attr_encrypted :with_false_unless, :key => SECRET_KEY, :unless => false
28
+ attr_encrypted :with_if_changed, :key => SECRET_KEY, :if => :should_encrypt
28
29
 
29
- attr_encryptor :aliased, :key => 'secret_key'
30
+ attr_encrypted :utf8, :key => SECRET_KEY, :charset => 'UTF-8'
31
+ attr_encrypted :default_enc, :key => SECRET_KEY
32
+ attr_encrypted :us_ascii, :key => SECRET_KEY, :charset => 'US-ASCII'
33
+
34
+ attr_encryptor :aliased, :key => SECRET_KEY
30
35
 
31
36
  attr_accessor :salt
32
37
  attr_accessor :should_encrypt
@@ -35,6 +40,10 @@ class User
35
40
  self.salt = Time.now.to_i.to_s
36
41
  self.should_encrypt = true
37
42
  end
43
+
44
+ def secret_key
45
+ SECRET_KEY
46
+ end
38
47
  end
39
48
 
40
49
  class Admin < User
@@ -158,7 +167,8 @@ class AttrEncryptorTest < Test::Unit::TestCase
158
167
  assert_nil @user.ssn_encrypted
159
168
  @user.ssn = 'testing'
160
169
  assert_not_nil @user.ssn_encrypted
161
- assert_equal Encryptor.encrypt(:value => 'testing', :key => @user.salt, :iv => @user.ssn_encrypted_iv.unpack("m").first, :salt => Time.now.to_i.to_s), @user.ssn_encrypted
170
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.ssn_encrypted_iv.unpack("m").first, :salt => @user.ssn_encrypted_salt )
171
+ assert_equal encrypted, @user.ssn_encrypted
162
172
  end
163
173
 
164
174
  def test_should_evaluate_a_key_passed_as_a_proc
@@ -166,7 +176,8 @@ class AttrEncryptorTest < Test::Unit::TestCase
166
176
  assert_nil @user.crypted_password_test
167
177
  @user.password = 'testing'
168
178
  assert_not_nil @user.crypted_password_test
169
- assert_equal Encryptor.encrypt(:value => 'testing', :key => 'User', :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => Time.now.to_i.to_s), @user.crypted_password_test
179
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt)
180
+ assert_equal encrypted, @user.crypted_password_test
170
181
  end
171
182
 
172
183
  def test_should_use_options_found_in_the_attr_encrypted_options_attribute
@@ -174,8 +185,9 @@ class AttrEncryptorTest < Test::Unit::TestCase
174
185
  assert_nil @user.crypted_password_test
175
186
  @user.password = 'testing'
176
187
  assert_not_nil @user.crypted_password_test
177
- assert_equal Encryptor.encrypt(:value => 'testing', :key => 'User', :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => Time.now.to_i.to_s), @user.crypted_password_test
178
- end
188
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt)
189
+ assert_equal encrypted, @user.crypted_password_test
190
+ end
179
191
 
180
192
  def test_should_inherit_encrypted_attributes
181
193
  assert_equal [User.encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, Admin.encrypted_attributes.keys.collect { |key| key.to_s }.sort
@@ -216,7 +228,8 @@ class AttrEncryptorTest < Test::Unit::TestCase
216
228
  assert_nil @user.encrypted_with_true_if
217
229
  @user.with_true_if = 'testing'
218
230
  assert_not_nil @user.encrypted_with_true_if
219
- assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key', :iv => @user.encrypted_with_true_if_iv.unpack("m").first, :salt => Time.now.to_i.to_s), @user.encrypted_with_true_if
231
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_true_if_iv.unpack("m").first, :salt => @user.encrypted_with_true_if_salt)
232
+ assert_equal encrypted, @user.encrypted_with_true_if
220
233
  end
221
234
 
222
235
  def test_should_not_encrypt_with_false_if
@@ -232,7 +245,8 @@ class AttrEncryptorTest < Test::Unit::TestCase
232
245
  assert_nil @user.encrypted_with_false_unless
233
246
  @user.with_false_unless = 'testing'
234
247
  assert_not_nil @user.encrypted_with_false_unless
235
- assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key', :iv => @user.encrypted_with_false_unless_iv.unpack("m").first, :salt => Time.now.to_i.to_s,), @user.encrypted_with_false_unless
248
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_false_unless_iv.unpack("m").first, :salt => @user.encrypted_with_false_unless_salt)
249
+ assert_equal encrypted, @user.encrypted_with_false_unless
236
250
  end
237
251
 
238
252
  def test_should_not_encrypt_with_true_unless
@@ -252,7 +266,7 @@ class AttrEncryptorTest < Test::Unit::TestCase
252
266
  @user.with_if_changed = "encrypt_stuff"
253
267
  @user.stubs(:instance_variable_get).returns(nil)
254
268
  @user.stubs(:instance_variable_set).raises("BadStuff")
255
- assert_raise RuntimeError do
269
+ assert_raise RuntimeError do
256
270
  @user.with_if_changed
257
271
  end
258
272
 
@@ -269,6 +283,29 @@ class AttrEncryptorTest < Test::Unit::TestCase
269
283
  assert_equal '3', User.decrypt_email(string_encrypted_email)
270
284
  end
271
285
 
286
+ def test_should_force_utf8_charset_on_decrypted_string
287
+ utf8_str = 'thïs should bé UTF-8'.force_encoding('UTF-8')
288
+ encrypted_utf8 = User.encrypt_utf8(utf8_str)
289
+ decrypted_utf8 = User.decrypt_utf8(encrypted_utf8)
290
+ assert_equal decrypted_utf8.encoding, Encoding::UTF_8
291
+ end
292
+
293
+ def test_should_force_default_encoding_on_decrypted_string
294
+ Encoding.default_internal = 'ASCII-8BIT' #Provide a default.
295
+ default_str = 'this is a default encoding'
296
+ encrypted_def = User.encrypt_default_enc(default_str)
297
+ decrypted_def = User.decrypt_default_enc(encrypted_def)
298
+ assert_equal decrypted_def.encoding, Encoding.default_internal
299
+ Encoding.default_internal = nil
300
+ end
301
+
302
+ def test_should_force_ascii_charset_on_decrypted_string
303
+ ascii_str = 'this should be US-ASCII'.force_encoding('US-ASCII')
304
+ encrypted_ascii = User.encrypt_us_ascii(ascii_str)
305
+ decrypted_ascii = User.decrypt_us_ascii(encrypted_ascii)
306
+ assert_equal decrypted_ascii.encoding, Encoding::US_ASCII
307
+ end
308
+
272
309
  def test_should_create_query_accessor
273
310
  @user = User.new
274
311
  assert !@user.email?
@@ -13,9 +13,9 @@ class Client
13
13
  property :encrypted_credentials, Text
14
14
  property :encrypted_credentials_iv, Text
15
15
  property :encrypted_credentials_salt, Text
16
-
17
- attr_encrypted :email, :key => 'a secret key'
18
- attr_encrypted :credentials, :key => 'some private key', :marshal => true
16
+
17
+ attr_encrypted :email, :key => SECRET_KEY
18
+ attr_encrypted :credentials, :key => SECRET_KEY, :marshal => true
19
19
 
20
20
  def initialize(attrs = {})
21
21
  super attrs
@@ -13,9 +13,9 @@ DB.create_table :humans do
13
13
  column :encrypted_credentials_salt, String
14
14
  end
15
15
 
16
- class Human < Sequel::Model(:humans)
17
- attr_encrypted :email, :key => 'a secret key'
18
- attr_encrypted :credentials, :key => 'some private key', :marshal => true
16
+ class Human < Sequel::Model(:humans)
17
+ attr_encrypted :email, :key => SECRET_KEY
18
+ attr_encrypted :credentials, :key => SECRET_KEY, :marshal => true
19
19
 
20
20
  def after_initialize(attrs = {})
21
21
  self.credentials ||= { :username => 'example', :password => 'test' }
@@ -29,7 +29,6 @@ class SequelTest < Test::Unit::TestCase
29
29
  end
30
30
 
31
31
  def test_should_encrypt_email
32
- require 'ruby-debug'
33
32
  @human = Human.new :email => 'test@example.com'
34
33
  assert @human.save
35
34
  assert_not_nil @human.encrypted_email
@@ -39,7 +38,7 @@ class SequelTest < Test::Unit::TestCase
39
38
 
40
39
  def test_should_marshal_and_encrypt_credentials
41
40
 
42
- @human = Human.new
41
+ @human = Human.new :credentials => { :username => 'example', :password => 'test' }
43
42
  assert @human.save
44
43
  assert_not_nil @human.encrypted_credentials
45
44
  assert_not_equal @human.credentials, @human.encrypted_credentials
@@ -5,10 +5,12 @@ gem 'activerecord', ENV['ACTIVE_RECORD_VERSION'] if ENV['ACTIVE_RECORD_VERSION']
5
5
  require 'active_record'
6
6
  require 'data_mapper'
7
7
  require 'sequel'
8
- require 'mocha'
8
+ require 'mocha/setup'
9
9
 
10
10
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
11
  $:.unshift(File.dirname(__FILE__))
12
12
  require 'attr_encryptor'
13
13
 
14
14
  puts "\nTesting with ActiveRecord #{ActiveRecord::VERSION::STRING rescue ENV['ACTIVE_RECORD_VERSION']}"
15
+
16
+ SECRET_KEY = 4.times.map { Digest::SHA256.hexdigest((Time.now.to_i * rand(5)).to_s) }.join
metadata CHANGED
@@ -1,93 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attr_encryptor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
5
- prerelease:
4
+ version: 2.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Daniel Palacio
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-01-07 00:00:00.000000000Z
11
+ date: 2013-07-17 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: encryptor2
16
- requirement: &70193477683240 !ruby/object:Gem::Requirement
17
- none: false
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: 1.0.0
22
20
  type: :runtime
23
21
  prerelease: false
24
- version_requirements: *70193477683240
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0
25
27
  - !ruby/object:Gem::Dependency
26
28
  name: activerecord
27
- requirement: &70193477682720 !ruby/object:Gem::Requirement
28
- none: false
29
+ requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
- - - ! '>='
31
+ - - '>='
31
32
  - !ruby/object:Gem::Version
32
33
  version: 2.0.0
33
34
  type: :development
34
35
  prerelease: false
35
- version_requirements: *70193477682720
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 2.0.0
36
41
  - !ruby/object:Gem::Dependency
37
42
  name: datamapper
38
- requirement: &70193477682340 !ruby/object:Gem::Requirement
39
- none: false
43
+ requirement: !ruby/object:Gem::Requirement
40
44
  requirements:
41
- - - ! '>='
45
+ - - '>='
42
46
  - !ruby/object:Gem::Version
43
47
  version: '0'
44
48
  type: :development
45
49
  prerelease: false
46
- version_requirements: *70193477682340
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
47
55
  - !ruby/object:Gem::Dependency
48
56
  name: mocha
49
- requirement: &70193477702100 !ruby/object:Gem::Requirement
50
- none: false
57
+ requirement: !ruby/object:Gem::Requirement
51
58
  requirements:
52
- - - ! '>='
59
+ - - '>='
53
60
  - !ruby/object:Gem::Version
54
61
  version: '0'
55
62
  type: :development
56
63
  prerelease: false
57
- version_requirements: *70193477702100
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: sequel
60
- requirement: &70193477701680 !ruby/object:Gem::Requirement
61
- none: false
71
+ requirement: !ruby/object:Gem::Requirement
62
72
  requirements:
63
- - - ! '>='
73
+ - - '>='
64
74
  - !ruby/object:Gem::Version
65
75
  version: '0'
66
76
  type: :development
67
77
  prerelease: false
68
- version_requirements: *70193477701680
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: dm-sqlite-adapter
71
- requirement: &70193477701260 !ruby/object:Gem::Requirement
72
- none: false
85
+ requirement: !ruby/object:Gem::Requirement
73
86
  requirements:
74
- - - ! '>='
87
+ - - '>='
75
88
  - !ruby/object:Gem::Version
76
89
  version: '0'
77
90
  type: :development
78
91
  prerelease: false
79
- version_requirements: *70193477701260
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
80
97
  - !ruby/object:Gem::Dependency
81
98
  name: sqlite3
82
- requirement: &70193477700840 !ruby/object:Gem::Requirement
83
- none: false
99
+ requirement: !ruby/object:Gem::Requirement
84
100
  requirements:
85
- - - ! '>='
101
+ - - '>='
86
102
  - !ruby/object:Gem::Version
87
103
  version: '0'
88
104
  type: :development
89
105
  prerelease: false
90
- version_requirements: *70193477700840
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
91
111
  description: Generates attr_accessors that encrypt and decrypt attributes transparently
92
112
  email: danpal@gmail.com
93
113
  executables: []
@@ -95,7 +115,10 @@ extensions: []
95
115
  extra_rdoc_files: []
96
116
  files:
97
117
  - .gitignore
98
- - .rvmrc
118
+ - .ruby-gemset
119
+ - .ruby-version
120
+ - Gemfile
121
+ - Gemfile.lock
99
122
  - MIT-LICENSE
100
123
  - README.md
101
124
  - Rakefile
@@ -111,8 +134,9 @@ files:
111
134
  - test/debug_order.rb
112
135
  - test/sequel_test.rb
113
136
  - test/test_helper.rb
114
- homepage: http://github.com/danpal/attr_encrypted
137
+ homepage: http://github.com/danpal/attr_encryptor
115
138
  licenses: []
139
+ metadata: {}
116
140
  post_install_message:
117
141
  rdoc_options:
118
142
  - --line-numbers
@@ -122,22 +146,20 @@ rdoc_options:
122
146
  require_paths:
123
147
  - lib
124
148
  required_ruby_version: !ruby/object:Gem::Requirement
125
- none: false
126
149
  requirements:
127
- - - ! '>='
150
+ - - '>='
128
151
  - !ruby/object:Gem::Version
129
152
  version: '0'
130
153
  required_rubygems_version: !ruby/object:Gem::Requirement
131
- none: false
132
154
  requirements:
133
- - - ! '>='
155
+ - - '>='
134
156
  - !ruby/object:Gem::Version
135
157
  version: '0'
136
158
  requirements: []
137
159
  rubyforge_project:
138
- rubygems_version: 1.8.6
160
+ rubygems_version: 2.0.3
139
161
  signing_key:
140
- specification_version: 3
162
+ specification_version: 4
141
163
  summary: Encrypt and decrypt attributes
142
164
  test_files:
143
165
  - test/active_record_test.rb
@@ -146,4 +168,3 @@ test_files:
146
168
  - test/debug_order.rb
147
169
  - test/sequel_test.rb
148
170
  - test/test_helper.rb
149
- has_rdoc: false
data/.rvmrc DELETED
@@ -1,47 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
- # development environment upon cd'ing into the directory
5
-
6
- # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
- environment_id="ruby-1.9.2-p290@attr_encrypted"
8
-
9
- #
10
- # Uncomment following line if you want options to be set only for given project.
11
- #
12
- # PROJECT_JRUBY_OPTS=( --1.9 )
13
-
14
- #
15
- # First we attempt to load the desired environment directly from the environment
16
- # file. This is very fast and efficient compared to running through the entire
17
- # CLI and selector. If you want feedback on which environment was used then
18
- # insert the word 'use' after --create as this triggers verbose mode.
19
- #
20
- if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
21
- && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
22
- then
23
- \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
24
-
25
- if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
26
- then
27
- . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
28
- fi
29
- else
30
- # If the environment file has not yet been created, use the RVM CLI to select.
31
- if ! rvm --create "$environment_id"
32
- then
33
- echo "Failed to create RVM environment '${environment_id}'."
34
- exit 1
35
- fi
36
- fi
37
-
38
- #
39
- # If you use an RVM gemset file to install a list of gems (*.gems), you can have
40
- # it be automatically loaded. Uncomment the following and adjust the filename if
41
- # necessary.
42
- #
43
- # filename=".gems"
44
- # if [[ -s "$filename" ]] ; then
45
- # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
46
- # fi
47
-