encrypted_cookie 0.0.2 → 0.0.3
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.
- data.tar.gz.sig +3 -2
- data/Manifest +1 -1
- data/README.markdown +35 -0
- data/Rakefile +1 -1
- data/encrypted_cookie.gemspec +3 -3
- data/lib/encrypted_cookie.rb +38 -6
- data/pkg/encrypted_cookie-0.0.2.gem +0 -0
- data/spec/encrypted_cookie_spec.rb +10 -1
- metadata +5 -5
- metadata.gz.sig +1 -1
- data/test/demo.rb +0 -15
data.tar.gz.sig
CHANGED
@@ -1,2 +1,3 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
~��4r=�<'��t�;=�p*��=���
|
2
|
+
>�T(R�����z�
|
3
|
+
�@��ϱ�w����)2~�<�Z�x<���+\��S~I���k}|"���c�"��@v�40�������D4�Ƭ9k���*�����(��$���B�ֻ4�����{�ߺ#�ͦ]�4�T^h����D4�Y�0����
|
data/Manifest
CHANGED
data/README.markdown
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
## Encrypted session cookies for Rack (and therefore Sinatra)
|
2
|
+
|
3
|
+
The `encrypted_cookie` gem provides 128-bit-AES-encrypted, tamper-proof cookies
|
4
|
+
for Rack through the class `Rack::Session::EncryptedCookie`.
|
5
|
+
|
6
|
+
## How to use encrypted\_cookie
|
7
|
+
|
8
|
+
$ gem install encrypted_cookie
|
9
|
+
|
10
|
+
Sinatra example:
|
11
|
+
|
12
|
+
require 'sinatra'
|
13
|
+
require 'encrypted_cookie'
|
14
|
+
|
15
|
+
use Rack::Session::EncryptedCookie,
|
16
|
+
:secret => TYPE_YOUR_LONG_RANDOM_STRING_HERE*
|
17
|
+
|
18
|
+
get '/' do
|
19
|
+
session[:foo] = 'bar'
|
20
|
+
"session: " + session.inspect
|
21
|
+
end
|
22
|
+
|
23
|
+
_*_ Your `:secret` must be at least 16 bytes long and should be really random.
|
24
|
+
|
25
|
+
## Encryption and integrity protection
|
26
|
+
|
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).
|
31
|
+
|
32
|
+
## Generating a good secret
|
33
|
+
|
34
|
+
require 'openssl'
|
35
|
+
puts OpenSSL::Random.random_bytes(16).inspect
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('encrypted_cookie', '0.0.
|
5
|
+
Echoe.new('encrypted_cookie', '0.0.3') do |p|
|
6
6
|
p.description = "Encrypted session cookies for Rack"
|
7
7
|
p.url = "http://github.com/cvonkleist/encrypted_cookie"
|
8
8
|
p.author = "Christian von Kleist"
|
data/encrypted_cookie.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{encrypted_cookie}
|
5
|
-
s.version = "0.0.
|
5
|
+
s.version = "0.0.3"
|
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
9
|
s.cert_chain = ["/home/cvk/.gemcert/gem-public_cert.pem"]
|
10
|
-
s.date = %q{2011-03-
|
10
|
+
s.date = %q{2011-03-03}
|
11
11
|
s.description = %q{Encrypted session cookies for Rack}
|
12
12
|
s.email = %q{cvonkleist at-a-place-called gmail.com}
|
13
13
|
s.extra_rdoc_files = ["README.markdown", "lib/encrypted_cookie.rb"]
|
14
|
-
s.files = ["Manifest", "README.markdown", "Rakefile", "encrypted_cookie.gemspec", "lib/encrypted_cookie.rb", "
|
14
|
+
s.files = ["Manifest", "README.markdown", "Rakefile", "encrypted_cookie.gemspec", "lib/encrypted_cookie.rb", "pkg/encrypted_cookie-0.0.2.gem", "spec/encrypted_cookie_spec.rb"]
|
15
15
|
s.homepage = %q{http://github.com/cvonkleist/encrypted_cookie}
|
16
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Encrypted_cookie", "--main", "README.markdown"]
|
17
17
|
s.require_paths = ["lib"]
|
data/lib/encrypted_cookie.rb
CHANGED
@@ -1,9 +1,29 @@
|
|
1
1
|
require 'openssl'
|
2
|
-
require 'rack/
|
2
|
+
require 'rack/request'
|
3
|
+
require 'rack/response'
|
3
4
|
|
4
5
|
module Rack
|
6
|
+
|
5
7
|
module Session
|
6
|
-
|
8
|
+
|
9
|
+
# Rack::Session::EncryptedCookie provides AES-128-encrypted, tamper-proof
|
10
|
+
# cookie-based session management.
|
11
|
+
#
|
12
|
+
# The session is Marshal'd, HMAC'd, and encrypted.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
#
|
16
|
+
# use Rack::Session::EncryptedCookie,
|
17
|
+
# :secret => 'change_me',
|
18
|
+
# :key => 'rack.session',
|
19
|
+
# :domain => 'foo.com',
|
20
|
+
# :path => '/',
|
21
|
+
# :expire_after => 2592000
|
22
|
+
#
|
23
|
+
# All parameters are optional except :secret.
|
24
|
+
|
25
|
+
class EncryptedCookie
|
26
|
+
|
7
27
|
def initialize(app, options={})
|
8
28
|
@app = app
|
9
29
|
@key = options[:key] || "rack.session"
|
@@ -14,14 +34,24 @@ module Rack
|
|
14
34
|
:expire_after => nil}.merge(options)
|
15
35
|
end
|
16
36
|
|
37
|
+
def call(env)
|
38
|
+
load_session(env)
|
39
|
+
status, headers, body = @app.call(env)
|
40
|
+
commit_session(env, status, headers, body)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
17
45
|
def load_session(env)
|
18
46
|
request = Rack::Request.new(env)
|
19
47
|
session_data = request.cookies[@key]
|
20
48
|
|
21
49
|
if session_data
|
22
|
-
|
23
|
-
|
24
|
-
|
50
|
+
#begin
|
51
|
+
session_data = decrypt(session_data)
|
52
|
+
session_data, digest = session_data.split("--")
|
53
|
+
session_data = nil unless digest == generate_hmac(session_data)
|
54
|
+
#rescue OpenSSL::Cipher::Cipher
|
25
55
|
end
|
26
56
|
|
27
57
|
begin
|
@@ -56,7 +86,9 @@ module Rack
|
|
56
86
|
[status, headers, body]
|
57
87
|
end
|
58
88
|
|
59
|
-
|
89
|
+
def generate_hmac(data)
|
90
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, @secret, data)
|
91
|
+
end
|
60
92
|
|
61
93
|
def encrypt(str)
|
62
94
|
aes = OpenSSL::Cipher::Cipher.new('aes-128-cbc').encrypt
|
Binary file
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'rack/test'
|
2
2
|
require 'sinatra'
|
3
3
|
require 'rspec'
|
4
|
-
require 'ruby-debug'
|
5
4
|
require 'cgi'
|
6
5
|
require File.dirname(__FILE__) + '/../lib/encrypted_cookie'
|
7
6
|
|
@@ -81,6 +80,16 @@ describe EncryptedApp do
|
|
81
80
|
|
82
81
|
lambda { plaintext = (aes.update(crypted_text) << aes.final) }.should raise_error("bad decrypt")
|
83
82
|
end
|
83
|
+
it "should reset the session if someone messes with the crypted data" do
|
84
|
+
get '/set/foo/bar'
|
85
|
+
last_response.body.should == 'all set'
|
86
|
+
get '/'
|
87
|
+
last_response.body.should == 'session: {"foo"=>"bar"}'
|
88
|
+
|
89
|
+
rack_mock_session.cookie_jar.instance_variable_get(:@cookies).first.instance_variable_set(:@name_and_value, 'rack.session=lkjsdlfkjsd')
|
90
|
+
get '/'
|
91
|
+
last_response.body.should == 'session: {}'
|
92
|
+
end
|
84
93
|
end
|
85
94
|
|
86
95
|
describe UnencryptedApp do
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: encrypted_cookie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Christian von Kleist
|
@@ -36,7 +36,7 @@ cert_chain:
|
|
36
36
|
DnOM3kD7rptG2g==
|
37
37
|
-----END CERTIFICATE-----
|
38
38
|
|
39
|
-
date: 2011-03-
|
39
|
+
date: 2011-03-03 00:00:00 -05:00
|
40
40
|
default_executable:
|
41
41
|
dependencies: []
|
42
42
|
|
@@ -55,8 +55,8 @@ files:
|
|
55
55
|
- Rakefile
|
56
56
|
- encrypted_cookie.gemspec
|
57
57
|
- lib/encrypted_cookie.rb
|
58
|
+
- pkg/encrypted_cookie-0.0.2.gem
|
58
59
|
- spec/encrypted_cookie_spec.rb
|
59
|
-
- test/demo.rb
|
60
60
|
has_rdoc: true
|
61
61
|
homepage: http://github.com/cvonkleist/encrypted_cookie
|
62
62
|
licenses: []
|
metadata.gz.sig
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
Ve��rH�����A-�*�F�%�[��$�yy���7ڻ
|
data/test/demo.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'sinatra'
|
2
|
-
require '../lib/encrypted_cookie'
|
3
|
-
|
4
|
-
use Rack::Session::EncryptedCookie,
|
5
|
-
:key => 'rack.session',
|
6
|
-
:secret => 'ASDFASDFASDJFsakdfji2j3oij2o3ij4l12kj3'
|
7
|
-
|
8
|
-
get '/' do
|
9
|
-
"session = " + session.inspect
|
10
|
-
end
|
11
|
-
|
12
|
-
get '/set/:data' do
|
13
|
-
session[:data] = params[:data]
|
14
|
-
redirect '/'
|
15
|
-
end
|