encrypted_cookie 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0352358d7b487ba0caebdc794eb34832213b01a8
4
+ data.tar.gz: 017a9b0e14be94789516403de3e3a13c511b4445
5
+ SHA512:
6
+ metadata.gz: c011384dc4191e17eec7e598b6b89b5e4c327202b9b78decb8d26dcf2f8fceb0416c8c3182b744bd17819f188f09c56dc5add8a64542d2792e9e4b8d7103935f
7
+ data.tar.gz: 59f8667546f117c5786e8ed9230f8757bf91cc4f012a5975440c3dce5fb18054eeda0d08ade721190a6392e95f9c8f64f7640fe5e386851a184bf220b356cdb0
@@ -1,6 +1,6 @@
1
1
  ## Encrypted session cookies for Rack (and therefore Sinatra)
2
2
 
3
- The `encrypted_cookie` gem provides 128-bit-AES-encrypted, tamper-proof cookies
3
+ The `encrypted_cookie` gem provides 256-bit-AES-encrypted, tamper-proof cookies
4
4
  for Rack through the class `Rack::Session::EncryptedCookie`.
5
5
 
6
6
  ## How to use encrypted\_cookie
@@ -20,16 +20,37 @@ Sinatra example:
20
20
  "session: " + session.inspect
21
21
  end
22
22
 
23
- _*_ Your `:secret` must be at least 16 bytes long and should be really random.
23
+ _*_ Your `:secret` must be at least 32 bytes long and should be really random.
24
+ Don't use a password or passphrase, generate something random (see below).
24
25
 
25
26
  ## Encryption and integrity protection
26
27
 
27
- The cookie encryption method is 128-bit AES (with salt). Additionally, the
28
- cookies are integrity protected with Rack's built-in HMAC support, which means
29
- that if a user tampers with their cookie in any way, their session will
30
- immediately be reset to `{}` (empty hash).
28
+ The cookie is encrypted with 256-bit AES in CBC mode (with random IV). The
29
+ encrypted cookie is then signed with a HMAC, to prevent tampering and chosen
30
+ ciphertext attacks. Any attempt at tampering with the cookie will reset the
31
+ user to `{}` (empty hash).
31
32
 
32
33
  ## Generating a good secret
33
34
 
34
- require 'openssl'
35
- puts OpenSSL::Random.random_bytes(16).inspect
35
+ Run this in a terminal and paste the output into your script:
36
+
37
+ $ ruby -rsecurerandom -e "puts SecureRandom.hex(32)"
38
+
39
+ ## Developing
40
+
41
+ To get the specs running:
42
+
43
+ ```bash
44
+ $ cd path-to-clone
45
+ $ gem install bundler # if not already installed
46
+ $ bundle install
47
+ $ bundle exec rspec
48
+ ```
49
+
50
+ # Thanks
51
+
52
+ - [@namelessjon](https://github.com/namelessjon) - Jon - For the massive crypto improvements!
53
+ - [@mkristian](https://github.com/mkristian) - Christian Meier
54
+ - [@danp](https://github.com/danp) - Dan Peterson
55
+ - [@stmllr](https://github.com/stmllr) - Steffen Müller
56
+ - [@andrhamm](https://github.com/andrhamm) - Andrew Hammond
data/Rakefile CHANGED
@@ -8,5 +8,6 @@ Echoe.new('encrypted_cookie', '0.0.4') do |p|
8
8
  p.author = "Christian von Kleist"
9
9
  p.email = "cvonkleist at-a-place-called gmail.com"
10
10
  p.ignore_pattern = ["tmp/*", "script/*"]
11
- p.development_dependencies = []
11
+ p.runtime_dependencies = ["rack >=1.1 <3"]
12
+ p.development_dependencies = ["rack-test ~>0.6.2", "sinatra ~>1.3.4", "rspec ~>2.14.1"]
12
13
  end
@@ -1,32 +1,41 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  Gem::Specification.new do |s|
4
- s.name = %q{encrypted_cookie}
5
- s.version = "0.0.4"
4
+ s.name = "encrypted_cookie"
5
+ s.version = "0.0.5"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Christian von Kleist"]
9
- s.cert_chain = ["/home/cvk/.gemcert/gem-public_cert.pem"]
10
- s.date = %q{2011-03-03}
11
- s.description = %q{Encrypted session cookies for Rack}
12
- s.email = %q{cvonkleist at-a-place-called gmail.com}
9
+ s.date = "2017-11-27"
10
+ s.description = "Encrypted session cookies for Rack"
11
+ s.email = "cvonkleist at-a-place-called gmail.com"
13
12
  s.extra_rdoc_files = ["README.markdown", "lib/encrypted_cookie.rb"]
14
- s.files = ["Manifest", "README.markdown", "Rakefile", "encrypted_cookie.gemspec", "lib/encrypted_cookie.rb", "spec/encrypted_cookie_spec.rb"]
15
- s.homepage = %q{http://github.com/cvonkleist/encrypted_cookie}
13
+ s.files = ["Manifest", "README.markdown", "Rakefile", "encrypted_cookie.gemspec", "lib/encrypted_cookie.rb", "lib/encrypted_cookie/encryptor.rb", "spec/encrypted_cookie_spec.rb"]
14
+ s.homepage = "http://github.com/cvonkleist/encrypted_cookie"
16
15
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Encrypted_cookie", "--main", "README.markdown"]
17
16
  s.require_paths = ["lib"]
18
- s.rubyforge_project = %q{encrypted_cookie}
19
- s.rubygems_version = %q{1.3.7}
20
- s.signing_key = %q{/home/cvk/.gemcert/gem-private_key.pem}
21
- s.summary = %q{Encrypted session cookies for Rack}
17
+ s.rubyforge_project = "encrypted_cookie"
18
+ s.rubygems_version = "2.0.3"
19
+ s.summary = "Encrypted session cookies for Rack"
22
20
 
23
21
  if s.respond_to? :specification_version then
24
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
- s.specification_version = 3
22
+ s.specification_version = 4
26
23
 
27
24
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
25
+ s.add_runtime_dependency(%q<rack>, ["< 3", ">= 1.1"])
26
+ s.add_development_dependency(%q<rack-test>, ["~> 0.6.2"])
27
+ s.add_development_dependency(%q<sinatra>, ["~> 1.3.4"])
28
+ s.add_development_dependency(%q<rspec>, ["~> 2.14.1"])
28
29
  else
30
+ s.add_dependency(%q<rack>, ["< 3", ">= 1.1"])
31
+ s.add_dependency(%q<rack-test>, ["~> 0.6.2"])
32
+ s.add_dependency(%q<sinatra>, ["~> 1.3.4"])
33
+ s.add_dependency(%q<rspec>, ["~> 2.14.1"])
29
34
  end
30
35
  else
36
+ s.add_dependency(%q<rack>, ["< 3", ">= 1.1"])
37
+ s.add_dependency(%q<rack-test>, ["~> 0.6.2"])
38
+ s.add_dependency(%q<sinatra>, ["~> 1.3.4"])
39
+ s.add_dependency(%q<rspec>, ["~> 2.14.1"])
31
40
  end
32
41
  end
@@ -1,15 +1,15 @@
1
- require 'openssl'
2
1
  require 'rack/request'
3
2
  require 'rack/response'
3
+ require 'encrypted_cookie/encryptor'
4
4
 
5
5
  module Rack
6
6
 
7
7
  module Session
8
8
 
9
- # Rack::Session::EncryptedCookie provides AES-128-encrypted, tamper-proof
9
+ # Rack::Session::EncryptedCookie provides AES-256-encrypted, tamper-proof
10
10
  # cookie-based session management.
11
11
  #
12
- # The session is Marshal'd, HMAC'd, and encrypted.
12
+ # The session is Marshal'd, encrypted and HMAC'd.
13
13
  #
14
14
  # Example:
15
15
  #
@@ -19,11 +19,22 @@ module Rack
19
19
  # :domain => 'foo.com',
20
20
  # :path => '/',
21
21
  # :expire_after => 2592000
22
+ # :time_to_live => 600
22
23
  #
23
24
  # All parameters are optional except :secret.
24
-
25
+ #
26
+ # The default for the session time-to-live is 30 minutes. You can set
27
+ # the timeout on per session base by adding the expiration time in the
28
+ # session:
29
+ # session[Rack::Session::EncryptedCookie::EXPIRES] = Time.now + 120
30
+ #
31
+ # Note that you shouldn't trust the expire_after parameter in the cookie
32
+ # for session expiry as that can be altered by the recipient. Instead,
33
+ # use time_to_live which is server side check.
25
34
  class EncryptedCookie
26
35
 
36
+ EXPIRES = '_encrypted_cookie_expires_'
37
+
27
38
  def initialize(app, options={})
28
39
  @app = app
29
40
  @key = options[:key] || "rack.session"
@@ -31,7 +42,9 @@ module Rack
31
42
  fail "Error! A secret is required to use encrypted cookies. Do something like this:\n\nuse Rack::Session::EncryptedCookie, :secret => YOUR_VERY_LONG_VERY_RANDOM_SECRET_KEY_HERE" unless @secret
32
43
  @default_options = {:domain => nil,
33
44
  :path => "/",
45
+ :time_to_live => 1800,
34
46
  :expire_after => nil}.merge(options)
47
+ @encryptor = Encryptor.new(@secret)
35
48
  end
36
49
 
37
50
  def call(env)
@@ -42,40 +55,45 @@ module Rack
42
55
 
43
56
  private
44
57
 
58
+ def remove_expiration(session_data)
59
+ expires = session_data.delete(EXPIRES)
60
+ if expires and expires < Time.now
61
+ session_data.clear
62
+ end
63
+ end
64
+
45
65
  def load_session(env)
46
66
  request = Rack::Request.new(env)
67
+ env["rack.session.options"] = @default_options.dup
68
+
47
69
  session_data = request.cookies[@key]
70
+ session_data = @encryptor.decrypt(session_data)
71
+ session_data = Marshal.load(session_data)
72
+ remove_expiration(session_data)
48
73
 
49
- if session_data
50
- if session_data = decrypt(session_data)
51
- session_data, digest = session_data.split("--")
52
- session_data = nil unless digest == generate_hmac(session_data)
53
- end
54
- end
74
+ env["rack.session"] = session_data
75
+ rescue
76
+ env["rack.session"] = Hash.new
77
+ end
55
78
 
56
- begin
57
- session_data = session_data.unpack("m*").first
58
- session_data = Marshal.load(session_data)
59
- env["rack.session"] = session_data
60
- rescue
61
- env["rack.session"] = Hash.new
79
+ def add_expiration(session_data, options)
80
+ if options[:time_to_live] && !session_data.key?(EXPIRES)
81
+ expires = Time.now + options[:time_to_live]
82
+ session_data.merge!({EXPIRES => expires})
62
83
  end
63
-
64
- env["rack.session.options"] = @default_options.dup
65
84
  end
66
85
 
67
86
  def commit_session(env, status, headers, body)
68
- session_data = Marshal.dump(env["rack.session"])
69
- session_data = [session_data].pack("m*")
87
+ options = env["rack.session.options"]
70
88
 
71
- session_data = "#{session_data}--#{generate_hmac(session_data)}"
72
-
73
- session_data = encrypt(session_data)
89
+ session_data = env["rack.session"]
90
+ add_expiration(session_data, options)
91
+ session_data = Marshal.dump(session_data)
92
+ session_data = @encryptor.encrypt(session_data)
74
93
 
75
94
  if session_data.size > (4096 - @key.size)
76
95
  env["rack.errors"].puts("Warning! Rack::Session::Cookie data size exceeds 4K. Content dropped.")
77
96
  else
78
- options = env["rack.session.options"]
79
97
  cookie = Hash.new
80
98
  cookie[:value] = session_data
81
99
  cookie[:expires] = Time.now + options[:expire_after] unless options[:expire_after].nil?
@@ -84,38 +102,6 @@ module Rack
84
102
 
85
103
  [status, headers, body]
86
104
  end
87
-
88
- def generate_hmac(data)
89
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, @secret, data)
90
- end
91
-
92
- def encrypt(str)
93
- aes = OpenSSL::Cipher::Cipher.new('aes-128-cbc').encrypt
94
- aes.key = @secret
95
- iv = OpenSSL::Random.random_bytes(aes.iv_len)
96
- aes.iv = iv
97
- [iv + (aes.update(str) << aes.final)].pack('m0')
98
- end
99
-
100
- # decrypts string. returns nil if an error occurs
101
- #
102
- # returns nil if openssl raises an error during decryption (likely
103
- # someone is tampering with the session data, or the sinatra user was
104
- # previously using Cookie and has just switched to EncryptedCookie), and
105
- # will also return nil if the text to decrypt is too short to possibly be
106
- # good aes data.
107
- def decrypt(str)
108
- str = str.unpack('m0').first
109
- aes = OpenSSL::Cipher::Cipher.new('aes-128-cbc').decrypt
110
- aes.key = @secret
111
- iv = str[0, aes.iv_len]
112
- aes.iv = iv
113
- crypted_text = str[aes.iv_len..-1]
114
- return nil if crypted_text.nil? || iv.nil?
115
- aes.update(crypted_text) << aes.final
116
- rescue
117
- nil
118
- end
119
105
  end
120
106
  end
121
107
  end
@@ -0,0 +1,123 @@
1
+ require 'openssl'
2
+ require 'rack/utils'
3
+ module Rack
4
+ module Session
5
+ class EncryptedCookie
6
+ # Encrypts messages with authentication
7
+ #
8
+ # The use of authentication is essential to avoid Chosen Ciphertext
9
+ # Attacks. By using this in an encrypt then MAC form, we avoid some
10
+ # attacks such as e.g. being used as a CBC padding oracle to decrypt
11
+ # the ciphertext.
12
+ class Encryptor
13
+ # Create the encryptor
14
+ #
15
+ # Pass in the secret, which should be at least 32-bytes worth of
16
+ # entropy, e.g. a string generated by `SecureRandom.hex(32)`.
17
+ # This also allows specification of the algorithm for the cipher
18
+ # and MAC. But don't change that unless you're very sure.
19
+ def initialize(secret, cipher = 'aes-256-cbc', hmac = 'SHA256')
20
+ @cipher = cipher
21
+ @hmac = hmac
22
+
23
+ # use the HMAC to derive two independent keys for the encryption and
24
+ # authentication of ciphertexts It is bad practice to use the same key
25
+ # for encryption and authentication. This also allows us to use all
26
+ # of the entropy in a long key (e.g. 64 hex bytes) when straight
27
+ # assignement would could result in assigning a key with a much
28
+ # reduced key space. Also, the personalisation strings further help
29
+ # reduce the possibility of key reuse by ensuring it should be unique
30
+ # to this gem, even with shared secrets.
31
+ @encryption_key = hmac("EncryptedCookie Encryption", secret)
32
+ @authentication_key = hmac("EncryptedCookie Authentication", secret)
33
+ end
34
+
35
+ # Encrypts message
36
+ #
37
+ # Returns the base64 encoded ciphertext plus IV. In addtion, the
38
+ # message is prepended with a MAC code to prevent chosen ciphertext
39
+ # attacks.
40
+ def encrypt(message)
41
+ # encrypt the message
42
+ encrypted = encrypt_message(message)
43
+
44
+ [authenticate_message(encrypted) + encrypted].pack('m0')
45
+ end
46
+
47
+ # decrypts base64 encoded ciphertext
48
+ #
49
+ # First, it checks the message tag and returns nil if that fails to verify.
50
+ # Otherwise, the data is passed on to the AES function for decryption.
51
+ def decrypt(ciphertext)
52
+ ciphertext = ciphertext.unpack('m').first
53
+ tag = ciphertext[0, hmac_length]
54
+ ciphertext = ciphertext[hmac_length..-1]
55
+
56
+ # make sure we actually had enough data for the tag too.
57
+ if tag && ciphertext && verify_message(tag, ciphertext)
58
+ decrypt_ciphertext(ciphertext)
59
+ else
60
+ nil
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ # HMAC digest of the message using the given secret
67
+ def hmac(secret, message)
68
+ OpenSSL::HMAC.digest(@hmac, secret, message)
69
+ end
70
+
71
+ def hmac_length
72
+ OpenSSL::Digest.new(@hmac).size
73
+ end
74
+
75
+ # returns the message authentication tag
76
+ #
77
+ # This is computed as HMAC(authentication_key, message)
78
+ def authenticate_message(message)
79
+ hmac(@authentication_key, message)
80
+ end
81
+
82
+ # verifies the message
83
+ #
84
+ # This does its best to be constant time, by use of the rack secure compare
85
+ # function.
86
+ def verify_message(tag, message)
87
+ own_tag = authenticate_message(message)
88
+ Rack::Utils.secure_compare(tag, own_tag)
89
+ end
90
+
91
+ # Encrypt
92
+ #
93
+ # Encrypts the given message with a random IV, then returns the ciphertext
94
+ # with the IV prepended.
95
+ def encrypt_message(message)
96
+ aes = OpenSSL::Cipher.new(@cipher).encrypt
97
+ aes.key = @encryption_key
98
+ iv = aes.random_iv
99
+ aes.iv = iv
100
+ iv + (aes.update(message) << aes.final)
101
+ end
102
+
103
+ # Decrypt
104
+ #
105
+ # Pulls the IV off the front of the message and decrypts. Catches
106
+ # OpenSSL errors and returns nil. But this should never happen, as the
107
+ # verify method should catch all corrupted ciphertexts.
108
+ def decrypt_ciphertext(ciphertext)
109
+ aes = OpenSSL::Cipher.new(@cipher).decrypt
110
+ aes.key = @encryption_key
111
+ iv = ciphertext[0, aes.iv_len]
112
+ aes.iv = iv
113
+ crypted_text = ciphertext[aes.iv_len..-1]
114
+ return nil if crypted_text.nil? || iv.nil?
115
+ aes.update(crypted_text) << aes.final
116
+ rescue
117
+ nil
118
+ end
119
+
120
+ end
121
+ end
122
+ end
123
+ end
@@ -1,20 +1,36 @@
1
1
  require 'rack/test'
2
- require 'sinatra'
2
+ require 'sinatra/base'
3
3
  require 'rspec'
4
4
  require 'cgi'
5
- require File.dirname(__FILE__) + '/../lib/encrypted_cookie'
5
+ require './lib/encrypted_cookie'
6
6
 
7
7
  include Rack::Session
8
8
 
9
+
10
+ module Helper
11
+ def unpack_cookie
12
+ data = last_response.headers['Set-Cookie'][/rack.session=(.*?);/, 1]
13
+ data = data.split('--').first
14
+ str = CGI.unescape(data).unpack('m').first
15
+ end
16
+ end
17
+
18
+
9
19
  RSpec.configure do |conf|
10
20
  conf.include Rack::Test::Methods
21
+ conf.include Helper
11
22
  end
12
23
 
13
24
  class EncryptedApp < Sinatra::Application
14
- use Rack::Session::EncryptedCookie, :secret => 'foo' * 10
25
+ disable :show_exceptions
26
+ use Rack::Session::EncryptedCookie, :secret => 'foo' * 10, :time_to_live => 0.1
15
27
  get '/' do
16
28
  "session: " + session.inspect
17
29
  end
30
+ get '/timeout/:value' do
31
+ session[Rack::Session::EncryptedCookie::EXPIRES] = Time.now + params[:value].to_i
32
+ "timeout set"
33
+ end
18
34
  get '/set/:key/:value' do
19
35
  session[params[:key]] = params[:value]
20
36
  "all set"
@@ -23,8 +39,10 @@ end
23
39
 
24
40
  # this app has cookie integrity protection, but not encryption
25
41
  class UnencryptedApp < Sinatra::Application
42
+ disable :show_exceptions
26
43
  use Rack::Session::Cookie, :secret => 'foo' * 10
27
44
  get '/' do
45
+ session[:foo] = 'bar'
28
46
  "session: " + session.inspect
29
47
  end
30
48
  end
@@ -32,7 +50,7 @@ end
32
50
  describe EncryptedCookie do
33
51
  it 'should fail if no secret is specified' do
34
52
  lambda { EncryptedCookie.new(nil) }.should raise_error(/A secret is required/)
35
- lambda { EncryptedCookie.new(nil, :secret => 'foo') }.should_not raise_error(/A secret is required/)
53
+ lambda { EncryptedCookie.new(nil, :secret => 'foo') }.should_not raise_error
36
54
  end
37
55
  end
38
56
 
@@ -51,18 +69,6 @@ describe EncryptedApp do
51
69
  get '/'
52
70
  last_response.body.should == 'session: {"foo"=>"bar"}'
53
71
  last_response.headers['Set-Cookie'].should_not include("BAh7AA")
54
-
55
- data = last_response.headers['Set-Cookie'][/rack.session=(.*?);/, 1]
56
- str = CGI.unescape(data).unpack('m0').first
57
- aes = OpenSSL::Cipher::Cipher.new('aes-128-cbc').decrypt
58
- aes.key = 'foo' * 10
59
- aes.iv = str[0, aes.iv_len]
60
- crypted_text = str[aes.iv_len..-1]
61
-
62
- plaintext = (aes.update(crypted_text) << aes.final)
63
- base64_marshal_data, hmac = plaintext.split('--')
64
- session_hash = Marshal.load(base64_marshal_data.unpack('m0').first)
65
- session_hash.should == {"foo" => "bar"}
66
72
  end
67
73
  it "should make encrypted session data that can't be decrypted with the wrong key" do
68
74
  get '/set/foo/bar'
@@ -71,12 +77,11 @@ describe EncryptedApp do
71
77
  last_response.body.should == 'session: {"foo"=>"bar"}'
72
78
  last_response.headers['Set-Cookie'].should_not include("BAh7AA")
73
79
 
74
- data = last_response.headers['Set-Cookie'][/rack.session=(.*?);/, 1]
75
- str = CGI.unescape(data).unpack('m0').first
76
- aes = OpenSSL::Cipher::Cipher.new('aes-128-cbc').decrypt
80
+ data = unpack_cookie
81
+ aes = OpenSSL::Cipher.new('aes-128-cbc').decrypt
77
82
  aes.key = 'bar' * 10
78
- iv = str[0, aes.iv_len]
79
- crypted_text = str[aes.iv_len..-1]
83
+ iv = data[0, aes.iv_len]
84
+ crypted_text = data[aes.iv_len..-1]
80
85
 
81
86
  lambda { plaintext = (aes.update(crypted_text) << aes.final) }.should raise_error("bad decrypt")
82
87
  end
@@ -98,6 +103,25 @@ describe EncryptedApp do
98
103
  get '/'
99
104
  last_response.body.should == 'session: {}'
100
105
  end
106
+ it "should reset the session on timeout" do
107
+ get '/set/foo/bar'
108
+ last_response.body.should == 'all set'
109
+ get '/'
110
+ last_response.body.should == 'session: {"foo"=>"bar"}'
111
+ sleep 0.08
112
+ get '/'
113
+ last_response.body.should == 'session: {"foo"=>"bar"}'
114
+ sleep 0.08
115
+ get '/'
116
+ last_response.body.should == 'session: {"foo"=>"bar"}'
117
+ sleep 0.1
118
+ get '/'
119
+ last_response.body.should == 'session: {}'
120
+ get '/timeout/0'
121
+ last_response.body.should == 'timeout set'
122
+ get '/'
123
+ last_response.body.should == 'session: {}'
124
+ end
101
125
  end
102
126
 
103
127
  describe UnencryptedApp do
@@ -106,7 +130,7 @@ describe UnencryptedApp do
106
130
  end
107
131
  it "should include unencrypted marshal'd data" do
108
132
  get '/'
109
- last_response.body.should == 'session: {}'
110
- last_response.headers['Set-Cookie'].should include("BAh7AA")
133
+ cookie = Marshal.load(unpack_cookie)
134
+ cookie['foo'].should == 'bar'
111
135
  end
112
136
  end
metadata CHANGED
@@ -1,100 +1,119 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: encrypted_cookie
3
- version: !ruby/object:Gem::Version
4
- hash: 23
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 0
9
- - 4
10
- version: 0.0.4
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Christian von Kleist
14
8
  autorequire:
15
9
  bindir: bin
16
- cert_chain:
17
- - |
18
- -----BEGIN CERTIFICATE-----
19
- MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDApjdm9u
20
- a2xlaXN0MRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj
21
- b20wHhcNMTEwMzAxMTkzMjA0WhcNMTIwMjI5MTkzMjA0WjBBMRMwEQYDVQQDDApj
22
- dm9ua2xlaXN0MRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
23
- FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9y1uDfBvTfKE4
24
- tPGA5hbAav7pUtP8HRdBDLZOOks0+j0b1E4fUNglG4kdEBNpLk/ngVkPweUj8i5h
25
- oNVNRN2oxRw/4bSikOeNS3mpIqc/muDa2aMaO3ALtC9TrOIAZMx6+bbHZa4MeHwv
26
- AGAkrW8xV8FsHdD/yj3uAsEXFp6OdvCvVRQn2dRDF1nnPH62qeVPYrg+A+C/63Hn
27
- +8xd428nMeO6oOdKJpjJc7sBifW6dZbxZWU+x4eoQjIWpCMVGx4mB2LhRxA8I2AZ
28
- YEB4bdWLiQNLDW8BW18BALJRwSYGma6bQWeYp3BP+bYcg2Twqsj9l/byA/ad1arU
29
- 7toOPs9DAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
30
- BBSLpCugjo/9vnQB4ne51IOzvAEqEzANBgkqhkiG9w0BAQUFAAOCAQEAjNr9nF4C
31
- zVmcdovmY5ctUVhxi+iWZ6sApuEanzmZ4WL2ldAMam3vUWz9it66wN+uQuBt3HHW
32
- OAFBTKpFnrxwD24ZAxnetn6bphctGW/he8GyLInBdUkhq5W/Oz+Ca6WkMy/Ofm2v
33
- kN0NjJDThfqNTimd/YnyuXo0MSq6jJdv4x5g+Cd1GqIE9nJktDr+C3Bn2Kl0RU8k
34
- 0dJtwaemYW21gKzLDNJaREmmaEzceqCZawE52p4Ay2tMIGrZDE4lcq1TnGbM0YIN
35
- tg88OxjT6gj/ANHONv3pFs0TZs/LOTlpUoIstpNKnVxkz4Xut3XUsqfCzHUOBnoC
36
- DnOM3kD7rptG2g==
37
- -----END CERTIFICATE-----
38
-
39
- date: 2011-03-03 00:00:00 -05:00
40
- default_executable:
41
- dependencies: []
42
-
10
+ cert_chain: []
11
+ date: 2017-11-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "<"
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: '1.1'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "<"
28
+ - !ruby/object:Gem::Version
29
+ version: '3'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '1.1'
33
+ - !ruby/object:Gem::Dependency
34
+ name: rack-test
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.6.2
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.6.2
47
+ - !ruby/object:Gem::Dependency
48
+ name: sinatra
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 1.3.4
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 1.3.4
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 2.14.1
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 2.14.1
43
75
  description: Encrypted session cookies for Rack
44
76
  email: cvonkleist at-a-place-called gmail.com
45
77
  executables: []
46
-
47
78
  extensions: []
48
-
49
- extra_rdoc_files:
79
+ extra_rdoc_files:
50
80
  - README.markdown
51
81
  - lib/encrypted_cookie.rb
52
- files:
82
+ files:
53
83
  - Manifest
54
84
  - README.markdown
55
85
  - Rakefile
56
86
  - encrypted_cookie.gemspec
57
87
  - lib/encrypted_cookie.rb
88
+ - lib/encrypted_cookie/encryptor.rb
58
89
  - spec/encrypted_cookie_spec.rb
59
- has_rdoc: true
60
90
  homepage: http://github.com/cvonkleist/encrypted_cookie
61
91
  licenses: []
62
-
92
+ metadata: {}
63
93
  post_install_message:
64
- rdoc_options:
65
- - --line-numbers
66
- - --inline-source
67
- - --title
94
+ rdoc_options:
95
+ - "--line-numbers"
96
+ - "--inline-source"
97
+ - "--title"
68
98
  - Encrypted_cookie
69
- - --main
99
+ - "--main"
70
100
  - README.markdown
71
- require_paths:
101
+ require_paths:
72
102
  - lib
73
- required_ruby_version: !ruby/object:Gem::Requirement
74
- none: false
75
- requirements:
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
76
105
  - - ">="
77
- - !ruby/object:Gem::Version
78
- hash: 3
79
- segments:
80
- - 0
81
- version: "0"
82
- required_rubygems_version: !ruby/object:Gem::Requirement
83
- none: false
84
- requirements:
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
85
110
  - - ">="
86
- - !ruby/object:Gem::Version
87
- hash: 11
88
- segments:
89
- - 1
90
- - 2
91
- version: "1.2"
111
+ - !ruby/object:Gem::Version
112
+ version: '1.2'
92
113
  requirements: []
93
-
94
114
  rubyforge_project: encrypted_cookie
95
- rubygems_version: 1.3.7
115
+ rubygems_version: 2.4.5.1
96
116
  signing_key:
97
- specification_version: 3
117
+ specification_version: 4
98
118
  summary: Encrypted session cookies for Rack
99
119
  test_files: []
100
-
data.tar.gz.sig DELETED
Binary file
metadata.gz.sig DELETED
Binary file