legacy-fernet 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fernet.gemspec
4
+ gemspec
@@ -0,0 +1,29 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ legacy-fernet (1.6.1)
5
+ multi_json
6
+ oj
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ diff-lcs (1.1.3)
12
+ multi_json (1.7.9)
13
+ oj (2.1.4)
14
+ rspec (2.11.0)
15
+ rspec-core (~> 2.11.0)
16
+ rspec-expectations (~> 2.11.0)
17
+ rspec-mocks (~> 2.11.0)
18
+ rspec-core (2.11.1)
19
+ rspec-expectations (2.11.3)
20
+ diff-lcs (~> 1.1.3)
21
+ rspec-mocks (2.11.3)
22
+
23
+ PLATFORMS
24
+ java
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ legacy-fernet!
29
+ rspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Harold Giménez
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,108 @@
1
+ # Fernet
2
+
3
+ [![Build Status](https://secure.travis-ci.org/hgmnz/fernet.png)](http://travis-ci.org/hgmnz/fernet)
4
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/hgmnz/fernet)
5
+
6
+ Fernet allows you to easily generate and verify **HMAC based authentication
7
+ tokens** for issuing API requests between remote servers. It also **encrypts**
8
+ data by default, so it can be used to transmit secure messages over the wire.
9
+
10
+ ![Fernet](http://f.cl.ly/items/2d0P3d26271O3p2v253u/photo.JPG)
11
+
12
+ Fernet is usually served as a *digestif* after a meal but may also be served
13
+ with coffee and espresso or mixed into coffee and espresso drinks.
14
+
15
+ Fernet about it!
16
+
17
+ ## Installation
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ gem 'fernet'
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install fernet
30
+
31
+ ## Usage
32
+
33
+ Both server and client must share a secret.
34
+
35
+ You want to encode some data in the token as well, for example, an email
36
+ address can be used to verify it on the other end.
37
+
38
+ ```ruby
39
+ token = Fernet.generate(secret) do |generator|
40
+ generator.data = { email: 'harold@heroku.com' }
41
+ end
42
+ ```
43
+ On the server side, the receiver can use this token to verify whether it's
44
+ legit:
45
+
46
+ ```ruby
47
+ verified = Fernet.verify(secret, token) do |verifier|
48
+ verifier.data['email'] == 'harold@heroku.com'
49
+ end
50
+ ```
51
+
52
+ The `verified` variable will be true if:
53
+
54
+ * The email encoded in the token data is `harold@heroku.com`
55
+ * The token was generated in the last 60 seconds
56
+ * The secret used to generate the token matches
57
+
58
+ Otherwise, `verified` will be false, and you should deny the request with an
59
+ HTTP 401, for example.
60
+
61
+ The `Fernet.verify` method can be awkward if extracting the plain text data is
62
+ required. For this case, a `verifier` can be requested that makes that
63
+ use case more pleasent:
64
+
65
+ ```ruby
66
+ verifier = Fernet.verifier(secret, token)
67
+ if verifier.valid? # signature valid, TTL verified
68
+ operate_on(verifier.data) # the original, decrypted data
69
+ end
70
+ ```
71
+
72
+ The specs
73
+ ([spec/fernet_spec.rb](https://github.com/hgmnz/fernet/blob/master/spec/fernet_spec.rb))
74
+ have more usage examples.
75
+
76
+ ### Global configuration
77
+
78
+ It's possible to configure fernet via the `Configuration` class. Put this in an initializer:
79
+
80
+ ```ruby
81
+ # default values shown here
82
+ Fernet::Configuration.run do |config|
83
+ config.enforce_ttl = true
84
+ config.ttl = 60
85
+ config.encrypt = true
86
+ end
87
+ ```
88
+
89
+ ### Generating a secret
90
+
91
+ Generating appropriate secrets is beyond the scope of `Fernet`, but you should
92
+ generate it using `/dev/random` in a *nix. To generate a base64-encoded 256 bit
93
+ (32 byte) random sequence, try:
94
+
95
+ dd if=/dev/urandom bs=32 count=1 2>/dev/null | openssl base64
96
+
97
+ ### Attribution
98
+
99
+ This library was largely made possible by [Mr. Tom
100
+ Maher](http://twitter.com/#tmaher), who clearly articulated the mechanics
101
+ behind this process, and further found ways to make it
102
+ [more](https://github.com/hgmnz/fernet/commit/2bf0b4a66b49ef3fc92ef50708a2c8b401950fc2)
103
+ [secure](https://github.com/hgmnz/fernet/commit/051161d0afb0b41480734d84bc824bdbc7f9c563).
104
+
105
+ ## License
106
+
107
+ Fernet is copyright (c) Harold Giménez and is released under the terms of the
108
+ MIT License found in the LICENSE file.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/fernet/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Harold Giménez"]
6
+ gem.email = ["harold.gimenez@gmail.com"]
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
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "legacy-fernet"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Legacy::Fernet::VERSION
17
+
18
+ gem.add_dependency "oj"
19
+ gem.add_dependency "multi_json"
20
+
21
+ gem.add_development_dependency "rspec"
22
+ end
@@ -0,0 +1,27 @@
1
+ require 'fernet/version'
2
+ require 'fernet/generator'
3
+ require 'fernet/verifier'
4
+ require 'fernet/secret'
5
+ require 'fernet/configuration'
6
+
7
+ if RUBY_VERSION == '1.8.7'
8
+ require 'shim/base64'
9
+ end
10
+
11
+ Legacy::Fernet::Configuration.run
12
+
13
+ module Legacy::Fernet
14
+ def self.generate(secret, encrypt = Configuration.encrypt, &block)
15
+ Generator.new(secret, encrypt).generate(&block)
16
+ end
17
+
18
+ def self.verify(secret, token, encrypt = Configuration.encrypt, &block)
19
+ Verifier.new(secret, encrypt).verify_token(token, &block)
20
+ end
21
+
22
+ def self.verifier(secret, token, encrypt = Configuration.encrypt)
23
+ Verifier.new(secret, encrypt).tap do |v|
24
+ v.verify_token(token)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,39 @@
1
+ require 'singleton'
2
+ module Legacy::Fernet
3
+ class Configuration
4
+ include Singleton
5
+
6
+ # Whether to enforce a message TTL
7
+ # (true or false)
8
+ attr_accessor :enforce_ttl
9
+
10
+ # How long messages are considered valid to the verifier
11
+ # (an integer in seconds)
12
+ attr_accessor :ttl
13
+
14
+ # Whether to encrypt the payload
15
+ # (true or false)
16
+ attr_accessor :encrypt
17
+
18
+ def self.run
19
+ self.instance.enforce_ttl = true
20
+ self.instance.ttl = 60
21
+ self.instance.encrypt = true
22
+ yield self.instance if block_given?
23
+ end
24
+
25
+ class << self
26
+ def method_missing(method)
27
+ if self.instance.respond_to?(method)
28
+ self.instance.send(method)
29
+ else
30
+ super
31
+ end
32
+ end
33
+
34
+ def respond_to?(method)
35
+ self.instance.respond_to?(method) || super
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,71 @@
1
+ require 'base64'
2
+ require 'multi_json'
3
+ require 'openssl'
4
+ require 'date'
5
+
6
+ module Legacy::Fernet
7
+ class Generator
8
+ attr_accessor :data, :payload
9
+
10
+ def initialize(secret, encrypt)
11
+ @secret = Secret.new(secret, encrypt)
12
+ @encrypt = encrypt
13
+ @payload = ''
14
+ @data = {}
15
+ end
16
+
17
+ def generate
18
+ yield self if block_given?
19
+ data.merge!(:issued_at => DateTime.now)
20
+
21
+ if encrypt?
22
+ iv = encrypt_data!
23
+ @payload = "#{base64(data)}|#{base64(iv)}"
24
+ else
25
+ @payload = base64(MultiJson.dump(data))
26
+ end
27
+
28
+ mac = OpenSSL::HMAC.hexdigest('sha256', payload, signing_key)
29
+ "#{payload}|#{mac}"
30
+ end
31
+
32
+ def inspect
33
+ "#<Legacy::Fernet::Generator @secret=[masked] @data=#{@data.inspect}>"
34
+ end
35
+ alias to_s inspect
36
+
37
+ def data
38
+ @data ||= {}
39
+ end
40
+
41
+ private
42
+ attr_reader :secret
43
+
44
+ def encrypt_data!
45
+ cipher = OpenSSL::Cipher.new('AES-128-CBC')
46
+ cipher.encrypt
47
+ iv = cipher.random_iv
48
+ cipher.iv = iv
49
+ cipher.key = encryption_key
50
+ @data = cipher.update(MultiJson.dump(data)) + cipher.final
51
+ iv
52
+ end
53
+
54
+ def base64(chars)
55
+ Base64.urlsafe_encode64(chars)
56
+ end
57
+
58
+ def encryption_key
59
+ @secret.encryption_key
60
+ end
61
+
62
+ def signing_key
63
+ @secret.signing_key
64
+ end
65
+
66
+ def encrypt?
67
+ @encrypt
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,20 @@
1
+ module Legacy::Fernet
2
+ class Secret
3
+ def initialize(secret, encrypt)
4
+ @secret = secret
5
+ @encrypt = encrypt
6
+ end
7
+
8
+ def encryption_key
9
+ @secret.slice(@secret.size/2, @secret.size)
10
+ end
11
+
12
+ def signing_key
13
+ if @encrypt
14
+ @secret.slice(0, @secret.size/2)
15
+ else
16
+ @secret
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,102 @@
1
+ require 'base64'
2
+ require 'multi_json'
3
+ require 'openssl'
4
+ require 'date'
5
+
6
+ module Legacy::Fernet
7
+ class Verifier
8
+ attr_reader :token, :data
9
+ attr_accessor :ttl, :enforce_ttl
10
+
11
+ def initialize(secret, decrypt)
12
+ @secret = Secret.new(secret, decrypt)
13
+ @decrypt = decrypt
14
+ @ttl = Configuration.ttl
15
+ @enforce_ttl = Configuration.enforce_ttl
16
+ end
17
+
18
+ def verify_token(token)
19
+ @token = token
20
+ deconstruct
21
+
22
+ if block_given?
23
+ custom_verification = yield self
24
+ else
25
+ custom_verification = true
26
+ end
27
+
28
+ @valid = signatures_match? && token_recent_enough? && custom_verification
29
+ end
30
+
31
+ def valid?
32
+ @valid
33
+ end
34
+
35
+ def inspect
36
+ "#<Legacy::Fernet::Verifier @secret=[masked] @token=#{@token} @data=#{@data.inspect} @ttl=#{@ttl}>"
37
+ end
38
+ alias to_s inspect
39
+
40
+ private
41
+ attr_reader :secret
42
+
43
+ def deconstruct
44
+ parts = @token.split('|')
45
+ if decrypt?
46
+ encrypted_data, iv, @received_signature = *parts
47
+ @data = MultiJson.load(decrypt!(encrypted_data, Base64.urlsafe_decode64(iv)))
48
+ signing_blob = "#{encrypted_data}|#{iv}"
49
+ else
50
+ encoded_data, @received_signature = *parts
51
+ signing_blob = encoded_data
52
+ @data = MultiJson.load(Base64.urlsafe_decode64(encoded_data))
53
+ end
54
+ @regenerated_mac = OpenSSL::HMAC.hexdigest('sha256', signing_blob, signing_key)
55
+ end
56
+
57
+ def token_recent_enough?
58
+ if enforce_ttl?
59
+ good_till = DateTime.parse(data['issued_at']) + (ttl.to_f / 24 / 60 / 60)
60
+ good_till > now
61
+ else
62
+ true
63
+ end
64
+ end
65
+
66
+ def signatures_match?
67
+ regenerated_bytes = @regenerated_mac.bytes.to_a
68
+ received_bytes = @received_signature.bytes.to_a
69
+ received_bytes.inject(0) do |accum, byte|
70
+ accum |= byte ^ regenerated_bytes.shift
71
+ end.zero?
72
+ end
73
+
74
+ def decrypt!(encrypted_data, iv)
75
+ decipher = OpenSSL::Cipher.new('AES-128-CBC')
76
+ decipher.decrypt
77
+ decipher.iv = iv
78
+ decipher.key = encryption_key
79
+ decipher.update(Base64.urlsafe_decode64(encrypted_data)) + decipher.final
80
+ end
81
+
82
+ def encryption_key
83
+ @secret.encryption_key
84
+ end
85
+
86
+ def signing_key
87
+ @secret.signing_key
88
+ end
89
+
90
+ def decrypt?
91
+ @decrypt
92
+ end
93
+
94
+ def enforce_ttl?
95
+ @enforce_ttl
96
+ end
97
+
98
+ def now
99
+ DateTime.now
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,5 @@
1
+ module Legacy
2
+ module Fernet
3
+ VERSION = "1.6.1"
4
+ end
5
+ 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
@@ -0,0 +1,164 @@
1
+ require 'spec_helper'
2
+ require 'fernet'
3
+
4
+ describe Legacy::Fernet do
5
+ after { Legacy::Fernet::Configuration.run }
6
+
7
+ let(:token_data) do
8
+ { :email => 'harold@heroku.com', :id => '123', :arbitrary => 'data' }
9
+ end
10
+
11
+ let(:secret) { 'JrdICDH6x3M7duQeM8dJEMK4Y5TkBIsYDw1lPy35RiY=' }
12
+ let(:bad_secret) { 'badICDH6x3M7duQeM8dJEMK4Y5TkBIsYDw1lPy35RiY=' }
13
+
14
+ it 'can verify tokens it generates' do
15
+ token = Legacy::Fernet.generate(secret) do |generator|
16
+ generator.data = token_data
17
+ end
18
+
19
+ expect(
20
+ Legacy::Fernet.verify(secret, token) do |verifier|
21
+ verifier.data['email'] == 'harold@heroku.com'
22
+ end
23
+ ).to be_true
24
+ end
25
+
26
+ it 'fails with a bad secret' do
27
+ token = Legacy::Fernet.generate(secret) do |generator|
28
+ generator.data = token_data
29
+ end
30
+
31
+ expect(
32
+ Legacy::Fernet.verify(bad_secret, token) do |verifier|
33
+ verifier.data['email'] == 'harold@heroku.com'
34
+ end
35
+ ).to be_false
36
+ end
37
+
38
+ it 'fails with a bad custom verification' do
39
+ token = Legacy::Fernet.generate(secret) do |generator|
40
+ generator.data = { :email => 'harold@heroku.com' }
41
+ end
42
+
43
+ expect(
44
+ Legacy::Fernet.verify(secret, token) do |verifier|
45
+ verifier.data['email'] == 'lol@heroku.com'
46
+ end
47
+ ).to be_false
48
+ end
49
+
50
+ it 'fails if the token is too old' do
51
+ token = Legacy::Fernet.generate(secret) do |generator|
52
+ generator.data = token_data
53
+ end
54
+
55
+ expect(
56
+ Legacy::Fernet.verify(secret, token) do |verifier|
57
+ verifier.ttl = 1
58
+
59
+ def verifier.now
60
+ now = DateTime.now
61
+ DateTime.new(now.year, now.month, now.day, now.hour,
62
+ now.min, now.sec + 2, now.offset)
63
+ end
64
+ true
65
+ end
66
+ ).to be_false
67
+ end
68
+
69
+ it 'verifies without a custom verification' do
70
+ token = Legacy::Fernet.generate(secret) do |generator|
71
+ generator.data = token_data
72
+ end
73
+
74
+ expect(Legacy::Fernet.verify(secret, token)).to be_true
75
+ end
76
+
77
+ it 'can ignore TTL enforcement' do
78
+ token = Legacy::Fernet.generate(secret) do |generator|
79
+ generator.data = token_data
80
+ end
81
+
82
+ expect(
83
+ Legacy::Fernet.verify(secret, token) do |verifier|
84
+ def verifier.now
85
+ Time.now + 99999999999
86
+ end
87
+ verifier.enforce_ttl = false
88
+ true
89
+ end
90
+ ).to be_true
91
+ end
92
+
93
+ it 'can ignore TTL enforcement via global config' do
94
+ Legacy::Fernet::Configuration.run do |config|
95
+ config.enforce_ttl = false
96
+ end
97
+
98
+ token = Legacy::Fernet.generate(secret) do |generator|
99
+ generator.data = token_data
100
+ end
101
+
102
+ expect(
103
+ Legacy::Fernet.verify(secret, token) do |verifier|
104
+ def verifier.now
105
+ Time.now + 99999999999
106
+ end
107
+ true
108
+ end
109
+ ).to be_true
110
+ end
111
+
112
+ it 'generates without custom data' do
113
+ token = Legacy::Fernet.generate(secret)
114
+
115
+ expect(Legacy::Fernet.verify(secret, token)).to be_true
116
+ end
117
+
118
+ it 'can encrypt the payload' do
119
+ token = Legacy::Fernet.generate(secret, true) do |generator|
120
+ generator.data['password'] = 'password1'
121
+ end
122
+
123
+ expect(Base64.decode64(token)).not_to match /password1/
124
+
125
+ Legacy::Fernet.verify(secret, token) do |verifier|
126
+ expect(verifier.data['password']).to eq('password1')
127
+ end
128
+ end
129
+
130
+ it 'does not encrypt when asked nicely' do
131
+ token = Legacy::Fernet.generate(secret, false) do |generator|
132
+ generator.data['password'] = 'password1'
133
+ end
134
+
135
+ expect(Base64.decode64(token)).to match /password1/
136
+
137
+ Legacy::Fernet.verify(secret, token, false) do |verifier|
138
+ expect(verifier.data['password']).to eq('password1')
139
+ end
140
+ end
141
+
142
+ it 'can disable encryption via global configuration' do
143
+ Legacy::Fernet::Configuration.run { |c| c.encrypt = false }
144
+ token = Legacy::Fernet.generate(secret) do |generator|
145
+ generator.data['password'] = 'password1'
146
+ end
147
+
148
+ expect(Base64.decode64(token)).to match /password1/
149
+
150
+ Legacy::Fernet.verify(secret, token) do |verifier|
151
+ expect(verifier.data['password']).to eq('password1')
152
+ end
153
+ end
154
+
155
+ it 'returns the unencrypted message upon verify' do
156
+ token = Legacy::Fernet.generate(secret) do |generator|
157
+ generator.data['password'] = 'password1'
158
+ end
159
+
160
+ verifier = Legacy::Fernet.verifier(secret, token)
161
+ expect(verifier.valid?).to be_true
162
+ expect(verifier.data['password']).to eq('password1')
163
+ end
164
+ end
@@ -0,0 +1,21 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+
18
+ config.expect_with :rspec do |c|
19
+ c.syntax = :expect
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: legacy-fernet
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.6.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Harold Giménez
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-08-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: oj
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: multi_json
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Delicious HMAC Digest(if) authentication and encryption
63
+ email:
64
+ - harold.gimenez@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - Gemfile
70
+ - Gemfile.lock
71
+ - LICENSE
72
+ - README.md
73
+ - Rakefile
74
+ - fernet.gemspec
75
+ - lib/fernet.rb
76
+ - lib/fernet/configuration.rb
77
+ - lib/fernet/generator.rb
78
+ - lib/fernet/secret.rb
79
+ - lib/fernet/verifier.rb
80
+ - lib/fernet/version.rb
81
+ - lib/shim/base64.rb
82
+ - spec/fernet_spec.rb
83
+ - spec/spec_helper.rb
84
+ homepage: ''
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.23
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Easily generate and verify AES encrypted HMAC based authentication tokens
108
+ test_files:
109
+ - spec/fernet_spec.rb
110
+ - spec/spec_helper.rb