mack-encryption 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,313 @@
1
+ require "ezcrypto.rb"
2
+ module ActiveCrypto # :nodoc:
3
+
4
+ def self.append_features(base) #:nodoc:
5
+ super
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ =begin rdoc
10
+
11
+ Usage is very simple. You will generally only need the two class methods listed here in your ActiveRecord class model.
12
+
13
+ == License
14
+
15
+ ActiveCrypto and EzCrypto are released under the MIT license.
16
+
17
+
18
+ == Support
19
+
20
+ To contact the author, send mail to pelleb@gmail.com
21
+
22
+ Also see my blogs at:
23
+ http://stakeventures.com and
24
+ http://neubia.com
25
+
26
+ This project was based on code used in my project StakeItOut, where you can securely share web services with your partners.
27
+ https://stakeitout.com
28
+
29
+ (C) 2005 Pelle Braendgaard
30
+
31
+ =end
32
+ module ClassMethods
33
+ @@session_keys={}
34
+
35
+ =begin rdoc
36
+ Turn encryption on for this record. List all encrypted attributes
37
+
38
+ class Document < ActiveRecord::Base
39
+ encrypt :title,:body
40
+ end
41
+
42
+ Include optional option :key, to specify an external KeyHolder, which holds the key used for encrypting and decrypting:
43
+
44
+ class Document < ActiveRecord::Base
45
+ belongs_to :user
46
+ encrypt :title,:body,:key=>:user
47
+ end
48
+
49
+ =end
50
+ def encrypt(*attributes)
51
+ include ActiveCrypto::Encrypted
52
+ before_save :encrypt_attributes
53
+ after_save :decrypt_attributes
54
+ options=attributes.last.is_a?(Hash) ? attributes.pop : {}
55
+ keyholder
56
+ if options and options[:key]
57
+ module_eval <<-"end;"
58
+ def session_key
59
+ (send :#{options[:key]} ).send :session_key
60
+ end
61
+ @@external_key=true
62
+ end;
63
+ end
64
+ self.encrypted_attributes=attributes
65
+ end
66
+
67
+ =begin rdoc
68
+ Creates support in this class for holding a key. Adds the following methods:
69
+
70
+ * enter_password(password,salt="onetwothree")
71
+ * set_session_key(key)
72
+ * session_key
73
+
74
+ Use it as follows:
75
+
76
+ class User < ActiveRecord::Base
77
+ has_many :documents
78
+ keyholder
79
+ end
80
+
81
+ =end
82
+ def keyholder()
83
+ include ActiveCrypto::AssociationKeyHolder
84
+ after_create :save_session_key
85
+ end
86
+
87
+ =begin rdoc
88
+ Clears the session_key array. Generally this is handled automatically as a filter in ActionController. Only use these if you need to
89
+ do something out of the ordinary.
90
+ =end
91
+ def clear_session_keys() #:nodoc:
92
+ @@session_keys.clear
93
+ end
94
+
95
+ =begin rdoc
96
+ Sets the session_keys array. Only use these if you need to
97
+ do something out of the ordinary, as it is handled
98
+ =end
99
+ def session_keys=(keys) #:nodoc:
100
+ @@session_keys=keys
101
+ end
102
+
103
+ def session_keys() #:nodoc:
104
+ @@session_keys
105
+ end
106
+
107
+ end
108
+
109
+ =begin rdoc
110
+ This module handles all standard key management features.
111
+ =end
112
+ module KeyHolder
113
+
114
+ =begin rdoc
115
+ Creates a key for object based on given password and an optional salt.
116
+ =end
117
+ def enter_password(password,salt="onetwothree")
118
+ set_session_key(EzCrypto::Key.with_password(password, salt))
119
+ end
120
+
121
+ =begin rdoc
122
+ Decodes the Base64 encoded key and uses it as it's session key
123
+ =end
124
+ def set_encoded_key(enc)
125
+ set_session_key(EzCrypto::Key.decode(enc))
126
+ end
127
+ =begin rdoc
128
+ Sets a session key for the object. This should be a EzCrypto::Key instance.
129
+ =end
130
+ def set_session_key(key)
131
+ @session_key=key
132
+ self.decrypt_attributes if self.class.include? Encrypted
133
+ end
134
+
135
+ =begin rdoc
136
+ Returns the session_key
137
+ =end
138
+ def session_key
139
+ @session_key
140
+ end
141
+
142
+ end
143
+
144
+ module AssociationKeyHolder
145
+ include ActiveCrypto::KeyHolder
146
+
147
+
148
+ def save_session_key
149
+ ActiveRecord::Base.session_keys[session_key_id]=@session_key if @session_key
150
+ end
151
+ =begin rdoc
152
+ Sets a session key for the object. This should be a EzCrypto::Key instance.
153
+ =end
154
+ def set_session_key(key)
155
+ if self.new_record?
156
+ @session_key=key
157
+ else
158
+ ActiveRecord::Base.session_keys[session_key_id]=key
159
+ end
160
+ decrypt_attributes if self.class.include? Encrypted #if respond_to?(:decrypt_attributes)
161
+
162
+ end
163
+
164
+ =begin rdoc
165
+ Returns the session_key
166
+ =end
167
+ def session_key
168
+ if self.new_record?
169
+ @session_key
170
+ else
171
+ ActiveRecord::Base.session_keys[session_key_id]
172
+ end
173
+ end
174
+
175
+
176
+
177
+ def session_key_id
178
+ "#{self.class.to_s}:#{id}"
179
+ end
180
+
181
+ end
182
+
183
+ module Encrypted #:nodoc:
184
+ def self.append_features(base) #:nodoc:
185
+ super
186
+ base.extend ClassAccessors
187
+ end
188
+
189
+ module ClassAccessors
190
+ def encrypted_attributes
191
+ @encrypted_attributes||=[]
192
+ end
193
+
194
+ def encrypted_attributes=(attrs)
195
+ @encrypted_attributes=attrs
196
+ end
197
+
198
+ end
199
+
200
+ protected
201
+
202
+ def encrypt_attributes
203
+ if !is_encrypted?
204
+ self.class.encrypted_attributes.each do |key|
205
+ value=read_attribute(key)
206
+ write_attribute(key,_encrypt(value)) if value
207
+ end
208
+ @is_encrypted=true
209
+ end
210
+ true
211
+ end
212
+
213
+ def decrypt_attributes
214
+ if is_encrypted?
215
+ self.class.encrypted_attributes.each do |key|
216
+ value=read_attribute(key)
217
+ write_attribute(key,_decrypt(value)) if value
218
+ end
219
+ @is_encrypted=false
220
+ end
221
+ true
222
+ end
223
+
224
+ def after_find
225
+ @is_encrypted=true
226
+ decrypt_attributes unless session_key.nil?
227
+ end
228
+
229
+ private
230
+ def is_encrypted?
231
+ @is_encrypted
232
+ end
233
+
234
+ def _decrypt(data)
235
+ if session_key.nil?
236
+ raise MissingKeyError
237
+ else
238
+ if data
239
+ session_key.decrypt(data)
240
+ else
241
+ nil
242
+ end
243
+ end
244
+ end
245
+
246
+ def _encrypt(data)
247
+ if session_key.nil?
248
+ raise MissingKeyError
249
+ else
250
+ if data
251
+ session_key.encrypt(data)
252
+ else
253
+ nil
254
+ end
255
+ end
256
+ end
257
+
258
+ end
259
+
260
+
261
+ module ActionController # :nodoc:
262
+ =begin rdoc
263
+ This includes some basic support in the ActionController for handling session keys. It creates two filters one before the action and one after.
264
+ These do the following:
265
+
266
+ If the users session already has a 'session_keys' value it loads it into the ActiveRecord::Base.session_keys class field. If not it
267
+ clears any existing session_keys.
268
+
269
+ Leaving the action it stores any session_keys in the corresponding session variable.
270
+
271
+ These filters are automatically enabled. You do not have to do anything.
272
+
273
+ To manually clear the session keys call clear_session_keys. This should be done for example as part of a session log off action.
274
+ =end
275
+ def self.append_features(base) #:nodoc:
276
+ super
277
+ base.send :prepend_before_filter, :load_session_keys
278
+ base.send :prepend_after_filter, :save_session_keys
279
+ end
280
+
281
+ =begin rdoc
282
+ Clears the session keys. Call this when a user logs of.
283
+ =end
284
+ def clear_session_keys
285
+ ActiveRecord::Base.clear_session_keys
286
+ end
287
+
288
+
289
+ private
290
+ def load_session_keys
291
+ if session['session_keys']
292
+ ActiveRecord::Base.session_keys=session['session_keys']
293
+ else
294
+ ActiveRecord::Base.clear_session_keys
295
+ end
296
+ end
297
+
298
+ def save_session_keys
299
+ if ActiveRecord::Base.session_keys.size>0
300
+ session['session_keys']=ActiveRecord::Base.session_keys
301
+ else
302
+ session['session_keys']=nil
303
+ end
304
+ end
305
+
306
+
307
+ end
308
+
309
+ class MissingKeyError < RuntimeError
310
+ end
311
+ end
312
+ ActiveRecord::Base.send :include, ActiveCrypto
313
+ ActionController::Base.send :include, ActiveCrypto::ActionController