cirandas.net

ref: master

vendor/ezcrypto/lib/active_crypto.rb


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
require "ezcrypto.rb"
module ActiveCrypto # :nodoc:

    def self.append_features(base)  #:nodoc:
      super
      base.extend(ClassMethods)
    end

=begin rdoc

Usage is very simple. You will generally only need the two class methods listed here in your ActiveRecord class model.

== License

ActiveCrypto and EzCrypto are released under the MIT license.


== Support

To contact the author, send mail to pelleb@gmail.com

Also see my blogs at:
http://stakeventures.com and
http://neubia.com

This project was based on code used in my project StakeItOut, where you can securely share web services with your partners.
https://stakeitout.com

(C) 2005 Pelle Braendgaard

=end
    module ClassMethods
      @@session_keys={}

=begin rdoc
Turn encryption on for this record. List all encrypted attributes

  class Document < ActiveRecord::Base
		encrypt :title,:body
	end

Options are:
  <tt>key</tt> - to specify an external KeyHolder, which holds the key used for encrypting and decrypting
  <tt>base64</tt> - set to true in order to base64 encode the encrypted attributes.  defaults to false

  class Document < ActiveRecord::Base
  	belongs_to :user
  	encrypt :title,:body,:key=>:user, :base64 => true
  end

=end
      def encrypt(*attributes)
      	include ActiveCrypto::Encrypted
      	before_save :encrypt_attributes
      	after_save :decrypt_attributes
        options=attributes.last.is_a?(Hash) ? attributes.pop : {}
        keyholder
        if options and options[:key]
  				module_eval <<-"end;"
  					def session_key
  						(send :#{options[:key]} ).send :session_key
  					end
  					@@external_key=true
  				end;
        end

        base64_encode = (options and options[:base64])
        module_eval <<-"end;"
          def self.ezcrypto_base64?
            #{base64_encode.to_s}
          end
        end;

        self.encrypted_attributes=attributes
      end

=begin rdoc
Creates support in this class for holding a key. Adds the following methods:

* enter_password(password,salt="onetwothree")
* set_session_key(key)
* session_key

Use it as follows:

  class User < ActiveRecord::Base
  	has_many :documents
  	keyholder
  end

=end
      def keyholder()
      	include ActiveCrypto::AssociationKeyHolder
      	after_create :save_session_key
      end

=begin rdoc
Clears the session_key array. Generally this is handled automatically as a filter in ActionController. Only use these if you need to
do something out of the ordinary.
=end
      def clear_session_keys() #:nodoc:
        @@session_keys.clear
      end

=begin rdoc
Sets the session_keys array. Only use these if you need to
do something out of the ordinary, as it is handled
=end
      def session_keys=(keys) #:nodoc:
        @@session_keys=keys
      end

      def session_keys() #:nodoc:
        @@session_keys
      end

    end

=begin rdoc
This module handles all standard key management features.
=end
    module KeyHolder

=begin rdoc
Creates a key for object based on given password and an optional salt.
=end
      def enter_password(password,salt="onetwothree")
        set_session_key(EzCrypto::Key.with_password(password, salt))
      end

=begin rdoc
Decodes the Base64 encoded key and uses it as it's session key
=end
      def set_encoded_key(enc)
        set_session_key(EzCrypto::Key.decode(enc))
      end
=begin rdoc
Sets a session key for the object. This should be a EzCrypto::Key instance.
=end
      def set_session_key(key)
        @session_key=key
        self.decrypt_attributes if self.class.include? Encrypted
      end

=begin rdoc
Returns the session_key
=end
      def session_key
        @session_key
      end

    end

    module AssociationKeyHolder
      include ActiveCrypto::KeyHolder


      def save_session_key
        ActiveRecord::Base.session_keys[session_key_id]=@session_key if @session_key
      end
=begin rdoc
Sets a session key for the object. This should be a EzCrypto::Key instance.
=end
      def set_session_key(key)
        if self.new_record?
          @session_key=key
        else
          ActiveRecord::Base.session_keys[session_key_id]=key
        end
        decrypt_attributes if self.class.include? Encrypted #if respond_to?(:decrypt_attributes)

      end

=begin rdoc
Returns the session_key
=end
      def session_key
        if self.new_record?
          @session_key
        else
          ActiveRecord::Base.session_keys[session_key_id]
        end
      end



      def session_key_id
        "#{self.class.to_s}:#{id}"
      end

    end

    module Encrypted    #:nodoc:
      def self.append_features(base)  #:nodoc:
        super
        base.extend ClassAccessors
      end

      module ClassAccessors
        def encrypted_attributes
          @encrypted_attributes||=[]
        end

        def encrypted_attributes=(attrs)
          @encrypted_attributes=attrs
        end

      end

      protected

      def encrypt_attributes
        if !is_encrypted?
          self.class.encrypted_attributes.each do |key|
            value=read_attribute(key)
            write_attribute(key,_encrypt(value)) if value
          end
          @is_encrypted=true
        end
        true
      end

      def decrypt_attributes
        if is_encrypted?
          self.class.encrypted_attributes.each do |key|
            value=read_attribute(key)
            write_attribute(key,_decrypt(value)) if value
          end
          @is_encrypted=false
        end
        true
      end

      def after_find
        @is_encrypted=true
        decrypt_attributes unless session_key.nil?
      end

      private
      def is_encrypted?
        @is_encrypted
      end

      def _decrypt(data)
        if session_key.nil?
          raise MissingKeyError
        else
          if data
            self.class.ezcrypto_base64? ? session_key.decrypt64(data) : session_key.decrypt(data)
          else
            nil
          end
        end
      end

      def _encrypt(data)
        if session_key.nil?
          raise MissingKeyError
        else
          if data
            self.class.ezcrypto_base64? ? session_key.encrypt64(data) : session_key.encrypt(data)
          else
            nil
          end
        end
      end

    end


module ActionController # :nodoc:
=begin rdoc
This includes some basic support in the ActionController for handling session keys. It creates two filters one before the action and one after.
These do the following:

If the users session already has a 'session_keys' value it loads it into the ActiveRecord::Base.session_keys class field. If not it
clears any existing session_keys.

Leaving the action it stores any session_keys in the corresponding session variable.

These filters are automatically enabled. You do not have to do anything.

To manually clear the session keys call clear_session_keys. This should be done for example as part of a session log off action.
=end
    def self.append_features(base) #:nodoc:
      super
      base.send :prepend_before_filter, :load_session_keys
      base.send :prepend_after_filter, :save_session_keys
    end

=begin rdoc
Clears the session keys. Call this when a user logs of.
=end
    def clear_session_keys
      ActiveRecord::Base.clear_session_keys
    end


    private
    def load_session_keys
      if session['session_keys']
        ActiveRecord::Base.session_keys=session['session_keys']
      else
        ActiveRecord::Base.clear_session_keys
      end
    end

    def save_session_keys
      if ActiveRecord::Base.session_keys.size>0
        session['session_keys']=ActiveRecord::Base.session_keys
      else
        session['session_keys']=nil
      end
    end


end

class MissingKeyError < RuntimeError
end
end
ActiveRecord::Base.send :include, ActiveCrypto
ActionController::Base.send :include, ActiveCrypto::ActionController