Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 74 lines (63 sloc) 2.336 kb
679acfb @fxn message_verifier.rb needs active_support/base64
fxn authored
1 require 'active_support/base64'
b7afaa0 @fxn message_verifier.rb needs active_support/core_ext/object/blank
fxn authored
2 require 'active_support/core_ext/object/blank'
679acfb @fxn message_verifier.rb needs active_support/base64
fxn authored
3
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
4 module ActiveSupport
b99fb66 @suchasurge more style changes
suchasurge authored
5 # +MessageVerifier+ makes it easy to generate and verify messages which are signed
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
6 # to prevent tampering.
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -exec ...
spastorino authored
7 #
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
8 # This is useful for cases like remember-me tokens and auto-unsubscribe links where the
9 # session store isn't suitable or available.
10 #
11 # Remember Me:
f9b1aa7 @NZKoz Don't need _message as it's in the class name already
NZKoz authored
12 # cookies[:remember_me] = @verifier.generate([@user.id, 2.weeks.from_now])
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -exec ...
spastorino authored
13 #
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
14 # In the authentication filter:
15 #
f9b1aa7 @NZKoz Don't need _message as it's in the class name already
NZKoz authored
16 # id, time = @verifier.verify(cookies[:remember_me])
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
17 # if time < Time.now
18 # self.current_user = User.find(id)
19 # end
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -exec ...
spastorino authored
20 #
2d30d4c @wvanbergen Add some documentation for the new serializer property of MessageVerifie...
wvanbergen authored
21 # By default it uses Marshal to serialize the message. If you want to use another
22 # serialization method, you can set the serializer attribute to something that responds
23 # to dump and load, e.g.:
24 #
25 # @verifier.serializer = YAML
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
26 class MessageVerifier
27 class InvalidSignature < StandardError; end
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -exec ...
spastorino authored
28
41fea03 @wvanbergen Use an options hash to specify digest/cipher algorithm and a serializer ...
wvanbergen authored
29 def initialize(secret, options = {})
30 unless options.is_a?(Hash)
31 ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :digest => 'algorithm' to sepcify the digest algorithm."
32 options = { :digest => options }
33 end
34
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
35 @secret = secret
41fea03 @wvanbergen Use an options hash to specify digest/cipher algorithm and a serializer ...
wvanbergen authored
36 @digest = options[:digest] || 'SHA1'
37 @serializer = options[:serializer] || Marshal
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
38 end
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -exec ...
spastorino authored
39
f9b1aa7 @NZKoz Don't need _message as it's in the class name already
NZKoz authored
40 def verify(signed_message)
9212138 @packagethief MessageVerifier#verify raises InvalidSignature if the signature is blank
packagethief authored
41 raise InvalidSignature if signed_message.blank?
42
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
43 data, digest = signed_message.split("--")
69aa5e8 @lifo Ensure MessageVerifier raises appropriate exception on tampered data
lifo authored
44 if data.present? && digest.present? && secure_compare(digest, generate_digest(data))
41fea03 @wvanbergen Use an options hash to specify digest/cipher algorithm and a serializer ...
wvanbergen authored
45 @serializer.load(ActiveSupport::Base64.decode64(data))
5e6dab8 @codahale Fix timing attack vulnerability in ActiveSupport::MessageVerifier.
codahale authored
46 else
47 raise InvalidSignature
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
48 end
49 end
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -exec ...
spastorino authored
50
f9b1aa7 @NZKoz Don't need _message as it's in the class name already
NZKoz authored
51 def generate(value)
41fea03 @wvanbergen Use an options hash to specify digest/cipher algorithm and a serializer ...
wvanbergen authored
52 data = ActiveSupport::Base64.encode64s(@serializer.dump(value))
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
53 "#{data}--#{generate_digest(data)}"
54 end
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -exec ...
spastorino authored
55
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
56 private
f959758 @tenderlove making secure_compare faster
tenderlove authored
57 # constant-time comparison algorithm to prevent timing attacks
58 def secure_compare(a, b)
59 return false unless a.bytesize == b.bytesize
a8a336c @wycats Revert "ruby 1.9 friendly secure_compare" because it breaks CI and Sam R...
wycats authored
60
16bae77 @wycats Revert "Improve performance of MessageVerifier while keeping it constant...
wycats authored
61 l = a.unpack "C#{a.bytesize}"
f959758 @tenderlove making secure_compare faster
tenderlove authored
62
16bae77 @wycats Revert "Improve performance of MessageVerifier while keeping it constant...
wycats authored
63 res = 0
64 b.each_byte { |byte| res |= byte ^ l.shift }
65 res == 0
5e6dab8 @codahale Fix timing attack vulnerability in ActiveSupport::MessageVerifier.
codahale authored
66 end
67
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
68 def generate_digest(data)
51d155e @jeremy Lazy-require OpenSSL
jeremy authored
69 require 'openssl' unless defined?(OpenSSL)
0a692e4 @jeremy Use OpenSSL::Digest.const(...).new instead of OpenSSL::Digest::Digest.ne...
jeremy authored
70 OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@digest).new, @secret, data)
d460c9a @NZKoz Add ActiveSupport::MessageVerifier to aid users who need to store tamper...
NZKoz authored
71 end
72 end
51d155e @jeremy Lazy-require OpenSSL
jeremy authored
73 end
Something went wrong with that request. Please try again.