fernet 1.0 → 1.1

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/fernet.gemspec CHANGED
@@ -4,8 +4,8 @@ require File.expand_path('../lib/fernet/version', __FILE__)
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Harold Giménez"]
6
6
  gem.email = ["harold.gimenez@gmail.com"]
7
- gem.description = %q{Delicious HMAC Digest(if) authentication}
8
- gem.summary = %q{Easily generate and verify HMAC based authentication tokens}
7
+ gem.description = %q{Delicious HMAC Digest(if) authentication and encryption}
8
+ gem.summary = %q{Easily generate and verify AES encrypted HMAC based authentication tokens}
9
9
  gem.homepage = ""
10
10
 
11
11
  gem.files = `git ls-files`.split($\)
@@ -15,5 +15,7 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Fernet::VERSION
17
17
 
18
+ gem.add_dependency "yajl-ruby"
19
+
18
20
  gem.add_development_dependency "rspec"
19
21
  end
data/lib/fernet.rb CHANGED
@@ -3,6 +3,10 @@ require 'fernet/generator'
3
3
  require 'fernet/verifier'
4
4
  require 'fernet/secret'
5
5
 
6
+ if RUBY_VERSION == '1.8.7'
7
+ require 'shim/base64'
8
+ end
9
+
6
10
  module Fernet
7
11
  def self.generate(secret, encrypt = true, &block)
8
12
  Generator.new(secret, encrypt).generate(&block)
@@ -1,5 +1,5 @@
1
1
  require 'base64'
2
- require 'json'
2
+ require 'yajl'
3
3
  require 'openssl'
4
4
  require 'date'
5
5
 
@@ -16,13 +16,13 @@ module Fernet
16
16
 
17
17
  def generate
18
18
  yield self if block_given?
19
- data.merge!(issued_at: DateTime.now)
19
+ data.merge!(:issued_at => DateTime.now)
20
20
 
21
21
  if encrypt?
22
22
  iv = encrypt_data!
23
23
  @payload = "#{base64(data)}|#{base64(iv)}"
24
24
  else
25
- @payload = base64(JSON.dump(data))
25
+ @payload = base64(Yajl::Encoder.encode(data))
26
26
  end
27
27
 
28
28
  mac = OpenSSL::HMAC.hexdigest('sha256', payload, signing_key)
@@ -47,7 +47,7 @@ module Fernet
47
47
  iv = cipher.random_iv
48
48
  cipher.iv = iv
49
49
  cipher.key = encryption_key
50
- @data = cipher.update(JSON.dump(data)) + cipher.final
50
+ @data = cipher.update(Yajl::Encoder.encode(data)) + cipher.final
51
51
  iv
52
52
  end
53
53
 
data/lib/fernet/secret.rb CHANGED
@@ -6,12 +6,12 @@ module Fernet
6
6
  end
7
7
 
8
8
  def encryption_key
9
- @secret.byteslice(@secret.bytesize/2, @secret.bytesize)
9
+ @secret.slice(@secret.size/2, @secret.size)
10
10
  end
11
11
 
12
12
  def signing_key
13
13
  if @encrypt
14
- @secret.byteslice(0, @secret.bytesize/2)
14
+ @secret.slice(0, @secret.size/2)
15
15
  else
16
16
  @secret
17
17
  end
@@ -1,16 +1,18 @@
1
1
  require 'base64'
2
- require 'json'
2
+ require 'yajl'
3
3
  require 'openssl'
4
4
  require 'date'
5
5
 
6
6
  module Fernet
7
7
  class Verifier
8
8
  attr_reader :token, :data
9
- attr_writer :seconds_valid
9
+ attr_accessor :ttl, :enforce_ttl
10
10
 
11
11
  def initialize(secret, decrypt)
12
- @secret = Secret.new(secret, decrypt)
13
- @decrypt = decrypt
12
+ @secret = Secret.new(secret, decrypt)
13
+ @decrypt = decrypt
14
+ @ttl = 60
15
+ @enforce_ttl = true
14
16
  end
15
17
 
16
18
  def verify_token(token)
@@ -27,7 +29,7 @@ module Fernet
27
29
  end
28
30
 
29
31
  def inspect
30
- "#<Fernet::Verifier @secret=[masked] @token=#{@token} @data=#{@data.inspect} @seconds_valid=#{@seconds_valid}>"
32
+ "#<Fernet::Verifier @secret=[masked] @token=#{@token} @data=#{@data.inspect} @ttl=#{@ttl}>"
31
33
  end
32
34
  alias to_s inspect
33
35
 
@@ -38,18 +40,22 @@ module Fernet
38
40
  parts = @token.split('|')
39
41
  if decrypt?
40
42
  encrypted_data, iv, @received_signature = *parts
41
- @data = JSON.parse(decrypt!(encrypted_data, Base64.urlsafe_decode64(iv)))
43
+ @data = Yajl::Parser.parse(decrypt!(encrypted_data, Base64.urlsafe_decode64(iv)))
42
44
  signing_blob = "#{encrypted_data}|#{iv}"
43
45
  else
44
46
  encoded_data, @received_signature = *parts
45
47
  signing_blob = encoded_data
46
- @data = JSON.parse(Base64.urlsafe_decode64(encoded_data))
48
+ @data = Yajl::Parser.parse(Base64.urlsafe_decode64(encoded_data))
47
49
  end
48
50
  @regenerated_mac = OpenSSL::HMAC.hexdigest('sha256', signing_blob, signing_key)
49
51
  end
50
52
 
51
53
  def token_recent_enough?
52
- DateTime.parse(data['issued_at']) > (DateTime.now - 60)
54
+ if enforce_ttl?
55
+ DateTime.parse(data['issued_at']) > (now - ttl)
56
+ else
57
+ true
58
+ end
53
59
  end
54
60
 
55
61
  def signatures_match?
@@ -80,5 +86,12 @@ module Fernet
80
86
  @decrypt
81
87
  end
82
88
 
89
+ def enforce_ttl?
90
+ @enforce_ttl
91
+ end
92
+
93
+ def now
94
+ DateTime.now
95
+ end
83
96
  end
84
97
  end
@@ -1,3 +1,3 @@
1
1
  module Fernet
2
- VERSION = "1.0"
2
+ VERSION = "1.1"
3
3
  end
@@ -0,0 +1,21 @@
1
+ Base64.class_eval do
2
+ def strict_encode64(bin)
3
+ encode64(bin).tr("\n",'')
4
+ end
5
+
6
+ def strict_decode64(str)
7
+ unless str.include?("\n")
8
+ decode64(str)
9
+ else
10
+ raise(ArgumentError,"invalid base64")
11
+ end
12
+ end
13
+
14
+ def urlsafe_encode64(bin)
15
+ strict_encode64(bin).tr("+/", "-_")
16
+ end
17
+
18
+ def urlsafe_decode64(str)
19
+ strict_decode64(str.tr("-_", "+/"))
20
+ end
21
+ end
data/spec/fernet_spec.rb CHANGED
@@ -3,11 +3,11 @@ require 'fernet'
3
3
 
4
4
  describe Fernet do
5
5
  let(:token_data) do
6
- { email: 'harold@heroku.com', id: '123', arbitrary: 'data' }
6
+ { :email => 'harold@heroku.com', :id => '123', :arbitrary => 'data' }
7
7
  end
8
8
 
9
- let(:secret) { 'JrdICDH6x3M7duQeM8dJEMK4Y5TkBIsYDw1lPy35RiY=' }
10
- let(:bad_secret) { 'jrdICDH6x3M7duQeM8dJEMK4Y5TkBIsYDw1lPy35RiY=' }
9
+ let(:secret) { 'JrdICDH6x3M7duQeM8dJEMK4Y5TkBIsYDw1lPy35RiY=' }
10
+ let(:bad_secret) { 'badICDH6x3M7duQeM8dJEMK4Y5TkBIsYDw1lPy35RiY=' }
11
11
 
12
12
  it 'can verify tokens it generates' do
13
13
  token = Fernet.generate(secret) do |generator|
@@ -45,7 +45,7 @@ describe Fernet do
45
45
  end
46
46
 
47
47
  Fernet.verify(bad_secret, token) do |verifier|
48
- verifier.seconds_valid = 0
48
+ verifier.ttl = 0
49
49
  end.should be_false
50
50
  end
51
51
 
@@ -57,6 +57,20 @@ describe Fernet do
57
57
  Fernet.verify(secret, token).should be_true
58
58
  end
59
59
 
60
+ it 'can TTL enforcement' do
61
+ token = Fernet.generate(secret) do |generator|
62
+ generator.data = token_data
63
+ end
64
+
65
+ Fernet.verify(secret, token) do |verifier|
66
+ def verifier.now
67
+ Time.now + 99999999999
68
+ end
69
+ verifier.enforce_ttl = false
70
+ true
71
+ end.should be_true
72
+ end
73
+
60
74
  it 'generates without custom data' do
61
75
  token = Fernet.generate(secret)
62
76
 
@@ -88,5 +102,4 @@ describe Fernet do
88
102
  verifier.data['password'].should == 'password1'
89
103
  end
90
104
  end
91
-
92
105
  end
metadata CHANGED
@@ -1,34 +1,59 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: fernet
3
- version: !ruby/object:Gem::Version
4
- version: '1.0'
3
+ version: !ruby/object:Gem::Version
4
+ hash: 13
5
5
  prerelease:
6
+ segments:
7
+ - 1
8
+ - 1
9
+ version: "1.1"
6
10
  platform: ruby
7
- authors:
8
- - Harold Giménez
11
+ authors:
12
+ - "Harold Gim\xC3\xA9nez"
9
13
  autorequire:
10
14
  bindir: bin
11
15
  cert_chain: []
12
- date: 2012-08-14 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
16
+
17
+ date: 2012-08-15 00:00:00 Z
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: yajl-ruby
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
15
34
  name: rspec
16
- requirement: &70135148211780 !ruby/object:Gem::Requirement
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
17
37
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ hash: 3
42
+ segments:
43
+ - 0
44
+ version: "0"
22
45
  type: :development
23
- prerelease: false
24
- version_requirements: *70135148211780
25
- description: Delicious HMAC Digest(if) authentication
26
- email:
46
+ version_requirements: *id002
47
+ description: Delicious HMAC Digest(if) authentication and encryption
48
+ email:
27
49
  - harold.gimenez@gmail.com
28
50
  executables: []
51
+
29
52
  extensions: []
53
+
30
54
  extra_rdoc_files: []
31
- files:
55
+
56
+ files:
32
57
  - .gitignore
33
58
  - .rspec
34
59
  - Gemfile
@@ -41,32 +66,42 @@ files:
41
66
  - lib/fernet/secret.rb
42
67
  - lib/fernet/verifier.rb
43
68
  - lib/fernet/version.rb
69
+ - lib/shim/base64.rb
44
70
  - spec/fernet_spec.rb
45
71
  - spec/spec_helper.rb
46
- homepage: ''
72
+ homepage: ""
47
73
  licenses: []
74
+
48
75
  post_install_message:
49
76
  rdoc_options: []
50
- require_paths:
77
+
78
+ require_paths:
51
79
  - lib
52
- required_ruby_version: !ruby/object:Gem::Requirement
80
+ required_ruby_version: !ruby/object:Gem::Requirement
53
81
  none: false
54
- requirements:
55
- - - ! '>='
56
- - !ruby/object:Gem::Version
57
- version: '0'
58
- required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
90
  none: false
60
- requirements:
61
- - - ! '>='
62
- - !ruby/object:Gem::Version
63
- version: '0'
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 3
95
+ segments:
96
+ - 0
97
+ version: "0"
64
98
  requirements: []
99
+
65
100
  rubyforge_project:
66
101
  rubygems_version: 1.8.10
67
102
  signing_key:
68
103
  specification_version: 3
69
- summary: Easily generate and verify HMAC based authentication tokens
70
- test_files:
104
+ summary: Easily generate and verify AES encrypted HMAC based authentication tokens
105
+ test_files:
71
106
  - spec/fernet_spec.rb
72
107
  - spec/spec_helper.rb