fernet 2.1.1 → 2.2

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.
@@ -23,6 +23,13 @@ module Fernet
23
23
  #
24
24
  # Returns the fernet token as a string
25
25
  def self.generate(secret, message = '', opts = {})
26
+ # OpenSSL::Cipher loses all encoding informaion upon decoding ciphertext
27
+ # and everything comes out as ASCII. To prevent that, let's just explicitly
28
+ # convert input value to UTF-8 so we can assume the decrypted value will
29
+ # also be unicode. This is not exactly a wonderful solution, but it's
30
+ # better than just returning ASCII with mangled unicode bytes in it.
31
+ message = message.encode(Encoding::UTF_8) if message
32
+
26
33
  Generator.new(opts.merge({secret: secret, message: message})).
27
34
  generate
28
35
  end
@@ -35,7 +35,7 @@ module Fernet
35
35
 
36
36
  # Public: Returns the token's message
37
37
  def message
38
- @token.message
38
+ @token.message.dup.force_encoding(Encoding::UTF_8)
39
39
  end
40
40
 
41
41
  # Deprecated: returns the token's message
@@ -1,3 +1,3 @@
1
1
  module Fernet
2
- VERSION = "2.1.1"
2
+ VERSION = "2.2"
3
3
  end
metadata CHANGED
@@ -1,18 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fernet
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: '2.2'
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Harold Giménez
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2015-04-09 00:00:00.000000000 Z
12
+ date: 2015-12-17 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: valcro
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
19
  - - '='
18
20
  - !ruby/object:Gem::Version
@@ -20,6 +22,7 @@ dependencies:
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
27
  - - '='
25
28
  - !ruby/object:Gem::Version
@@ -27,17 +30,35 @@ dependencies:
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: rspec
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
- - - ">="
35
+ - - ~>
32
36
  - !ruby/object:Gem::Version
33
- version: '0'
37
+ version: '3.4'
34
38
  type: :development
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
- - - ">="
43
+ - - ~>
39
44
  - !ruby/object:Gem::Version
40
- version: '0'
45
+ version: '3.4'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '10.4'
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: '10.4'
41
62
  description: Delicious HMAC Digest(if) authentication and AES-128-CBC encryption
42
63
  email:
43
64
  - harold.gimenez@gmail.com
@@ -45,17 +66,8 @@ executables: []
45
66
  extensions: []
46
67
  extra_rdoc_files: []
47
68
  files:
48
- - ".gitignore"
49
- - ".gitmodules"
50
- - ".rdoc_options"
51
- - ".rspec"
52
- - ".travis.yml"
53
- - Gemfile
54
69
  - LICENSE
55
70
  - README.md
56
- - Rakefile
57
- - fernet.gemspec
58
- - lib/fernet.rb
59
71
  - lib/fernet/bit_packing.rb
60
72
  - lib/fernet/configuration.rb
61
73
  - lib/fernet/encryption.rb
@@ -65,41 +77,35 @@ files:
65
77
  - lib/fernet/token.rb
66
78
  - lib/fernet/verifier.rb
67
79
  - lib/fernet/version.rb
68
- - spec/acceptance/generate_spec.rb
69
- - spec/acceptance/verify_spec.rb
70
- - spec/bit_packing_spec.rb
71
- - spec/fernet_spec.rb
72
- - spec/secret_spec.rb
73
- - spec/spec_helper.rb
74
- - spec/token_spec.rb
75
- homepage: ''
80
+ - lib/fernet.rb
81
+ homepage: https://github.com/fernet/fernet-rb
76
82
  licenses: []
77
- metadata: {}
78
83
  post_install_message:
79
84
  rdoc_options: []
80
85
  require_paths:
81
86
  - lib
82
87
  required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
83
89
  requirements:
84
- - - ">="
90
+ - - ! '>='
85
91
  - !ruby/object:Gem::Version
86
92
  version: '0'
93
+ segments:
94
+ - 0
95
+ hash: 4235098473398822064
87
96
  required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
88
98
  requirements:
89
- - - ">="
99
+ - - ! '>='
90
100
  - !ruby/object:Gem::Version
91
101
  version: '0'
102
+ segments:
103
+ - 0
104
+ hash: 4235098473398822064
92
105
  requirements: []
93
106
  rubyforge_project:
94
- rubygems_version: 2.4.5
107
+ rubygems_version: 1.8.23.2
95
108
  signing_key:
96
- specification_version: 4
109
+ specification_version: 3
97
110
  summary: Easily generate and verify AES encrypted HMAC based authentication tokens
98
- test_files:
99
- - spec/acceptance/generate_spec.rb
100
- - spec/acceptance/verify_spec.rb
101
- - spec/bit_packing_spec.rb
102
- - spec/fernet_spec.rb
103
- - spec/secret_spec.rb
104
- - spec/spec_helper.rb
105
- - spec/token_spec.rb
111
+ test_files: []
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 8306def467a28bb3eeda6f4eb57c0dcc0b6f73a2
4
- data.tar.gz: 3f124ffeff277310fb3df669d78f4e41c26cdb4d
5
- SHA512:
6
- metadata.gz: c3954ecff3c25ff7142d950303206b6a437705537fdf3add03b66d4e8489aecbcd217c99927a6ce147ba08e3907dd6fa9ebdf91146cf353ca18d5a34230da158
7
- data.tar.gz: b8fb5061d5d37d287ec20fedf5df2cdd44dd103ae3d91df746037b51e8e8fa714670c48fd85abb6735ed0d4b7be46867eb5db7cb09ae3103061abcf253019907
data/.gitignore DELETED
@@ -1,19 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
- .rbenv-version
19
- .ruby-version
@@ -1,3 +0,0 @@
1
- [submodule "spec/fernet-spec"]
2
- path = spec/fernet-spec
3
- url = git://github.com/kr/fernet-spec.git
@@ -1,16 +0,0 @@
1
- --- !ruby/object:RDoc::Options
2
- encoding: UTF-8
3
- static_path: []
4
- rdoc_include:
5
- - .
6
- charset: UTF-8
7
- exclude:
8
- hyperlink_all: false
9
- line_numbers: false
10
- main_page:
11
- markup: tomdoc
12
- show_hash: false
13
- tab_width: 8
14
- title:
15
- visibility: :protected
16
- webcvs:
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --format progress
@@ -1,8 +0,0 @@
1
- language: ruby
2
-
3
- rvm:
4
- - "1.9.3"
5
- - "1.9.2"
6
- - "2.0.0"
7
-
8
- script: bundle exec rspec -b spec
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in fernet.gemspec
4
- gemspec
data/Rakefile DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env rake
2
- require "bundler/gem_tasks"
@@ -1,20 +0,0 @@
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 AES-128-CBC 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 = "fernet"
15
- gem.require_paths = ["lib"]
16
- gem.version = Fernet::VERSION
17
-
18
- gem.add_runtime_dependency "valcro", "0.1"
19
- gem.add_development_dependency "rspec"
20
- end
@@ -1,27 +0,0 @@
1
- require 'spec_helper'
2
- require 'fernet'
3
- require 'json'
4
- require 'base64'
5
-
6
- describe Fernet::Generator do
7
- it 'generates tokens according to the spec' do
8
- path = File.expand_path(
9
- './../fernet-spec/generate.json', File.dirname(__FILE__)
10
- )
11
- generate_json = JSON.parse(File.read(path))
12
- generate_json.each do |test_data|
13
- message = test_data['src']
14
- iv = test_data['iv'].pack("C*")
15
- secret = test_data['secret']
16
- now = DateTime.parse(test_data['now']).to_time
17
- expected_token = test_data['token']
18
-
19
- generator = Fernet::Generator.new(secret: secret,
20
- message: message,
21
- iv: iv,
22
- now: now)
23
-
24
- expect(generator.generate).to eq(expected_token)
25
- end
26
- end
27
- end
@@ -1,52 +0,0 @@
1
- require 'spec_helper'
2
- require 'fernet'
3
- require 'json'
4
- require 'base64'
5
-
6
- describe Fernet::Verifier do
7
- it 'verifies tokens according to the spec' do
8
- path = File.expand_path(
9
- './../fernet-spec/verify.json', File.dirname(__FILE__)
10
- )
11
- verify_json = JSON.parse(File.read(path))
12
-
13
- verify_json.each do |test_data|
14
- token = test_data['token']
15
- ttl = test_data['ttl_sec']
16
- now = DateTime.parse(test_data['now']).to_time
17
- secret = test_data['secret']
18
- message = test_data['src']
19
-
20
- verifier = Fernet::Verifier.new(token: token,
21
- secret: secret,
22
- now: now,
23
- ttl: ttl)
24
- expect(
25
- verifier.message
26
- ).to eq(message)
27
- end
28
- end
29
-
30
- context 'invalid tokens' do
31
- path = File.expand_path(
32
- './../fernet-spec/invalid.json', File.dirname(__FILE__)
33
- )
34
- invalid_json = JSON.parse(File.read(path))
35
- invalid_json.each do |test_data|
36
- it "detects #{test_data['desc']}" do
37
- token = test_data['token']
38
- ttl = test_data['ttl_sec']
39
- now = DateTime.parse(test_data['now']).to_time
40
- secret = test_data['secret']
41
-
42
- verifier = Fernet::Verifier.new(token: token,
43
- secret: secret,
44
- now: now,
45
- ttl: ttl)
46
-
47
- expect { verifier.message }.to raise_error(Fernet::Token::InvalidToken)
48
- end
49
- end
50
- end
51
-
52
- end
@@ -1,36 +0,0 @@
1
- require 'spec_helper'
2
- require 'fernet/bit_packing'
3
-
4
- describe Fernet::BitPacking do
5
- VALUE_TO_BYTES = {
6
- 0x0000000000000000 => [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
7
- 0x00000000000000FF => [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF ],
8
- 0x000000FF00000000 => [ 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00 ],
9
- 0x00000000FF000000 => [ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 ],
10
- 0xFF00000000000000 => [ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
11
- 0xFFFFFFFFFFFFFFFF => [ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ]
12
- }
13
-
14
- def self.pretty(bytea)
15
- "0x#{bytea.map { |b| sprintf("%.2x", b) }.join}"
16
- end
17
-
18
- def self.bytestr(bytea)
19
- bytea.map(&:chr).join
20
- end
21
-
22
- VALUE_TO_BYTES.each do |value, bytes|
23
- pretty_bytes = pretty(bytes).rjust(20)
24
- pretty_val = value.to_s.rjust(20)
25
- bytestr = bytestr(bytes)
26
- it "encodes #{pretty_val} to #{pretty_bytes}" do
27
- expect(Fernet::BitPacking.pack_int64_bigendian(value)).to eq(bytestr)
28
- end
29
-
30
- # N.B.: we have two extra spaces in the spec description for
31
- # aligned formatting w.r.t. the 'encode' specs
32
- it "decodes #{pretty_bytes} to #{pretty_val}" do
33
- expect(Fernet::BitPacking.unpack_int64_bigendian(bytestr)).to eq(value)
34
- end
35
- end
36
- end
@@ -1,75 +0,0 @@
1
- require 'spec_helper'
2
- require 'fernet'
3
-
4
- describe Fernet do
5
- after { Fernet::Configuration.run }
6
-
7
- let(:secret) { 'JrdICDH6x3M7duQeM8dJEMK4Y5TkBIsYDw1lPy35RiY=' }
8
- let(:bad_secret) { 'badICDH6x3M7duQeM8dJEMK4Y5TkBIsYDw1lPy35RiY=' }
9
-
10
- it 'can verify tokens it generates' do
11
- token = Fernet.generate(secret, 'harold@heroku.com')
12
-
13
- verifier = Fernet.verifier(secret, token)
14
- expect(verifier).to be_valid
15
- expect(verifier.message).to eq('harold@heroku.com')
16
- end
17
-
18
- it 'fails with a bad secret' do
19
- token = Fernet.generate(secret, 'harold@heroku.com')
20
-
21
- verifier = Fernet.verifier(bad_secret, token)
22
- expect(verifier.valid?).to eq(false)
23
- expect {
24
- verifier.message
25
- }.to raise_error Fernet::Token::InvalidToken
26
- end
27
-
28
- it 'fails if the token is too old' do
29
- token = Fernet.generate(secret, 'harold@heroku.com', now: (Time.now - 61))
30
-
31
- verifier = Fernet.verifier(secret, token)
32
- expect(verifier.valid?).to eq(false)
33
- end
34
-
35
- it 'can ignore TTL enforcement' do
36
- Fernet::Configuration.run do |config|
37
- config.enforce_ttl = true
38
- end
39
-
40
- token = Fernet.generate(secret, 'harold@heroku.com')
41
-
42
- verifier = Fernet.verifier(secret, token, enforce_ttl: false,
43
- now: Time.now + 9999)
44
- expect(verifier.valid?).to eq(true)
45
- end
46
-
47
- it 'can ignore TTL enforcement via global config' do
48
- Fernet::Configuration.run do |config|
49
- config.enforce_ttl = false
50
- end
51
-
52
- token = Fernet.generate(secret, 'harold@heroku.com')
53
-
54
- verifier = Fernet.verifier(secret, token, now: Time.now + 999999)
55
- expect(verifier.valid?).to eq(true)
56
- end
57
-
58
- it 'does not send the message in plain text' do
59
- token = Fernet.generate(secret, 'password1')
60
-
61
- expect(Base64.urlsafe_decode64(token)).not_to match /password1/
62
- end
63
-
64
- it 'allows overriding enforce_ttl on a verifier' do
65
- Fernet::Configuration.run do |config|
66
- config.enforce_ttl = true
67
- config.ttl = 0
68
- end
69
- token = Fernet.generate(secret, 'password1')
70
- verifier = Fernet.verifier(secret, token, now: Time.now + 999999)
71
- verifier.enforce_ttl = false
72
- expect(verifier.valid?).to eq(true)
73
- expect(verifier.message).to eq('password1')
74
- end
75
- end
@@ -1,35 +0,0 @@
1
- require 'spec_helper'
2
- require 'fernet/secret'
3
-
4
- describe Fernet::Secret do
5
- it "can resolve a URL safe base64 encoded 32 byte string" do
6
- resolves_input(Base64.urlsafe_encode64("A"*16 + "B"*16))
7
- end
8
-
9
- it "can resolve a base64 encoded 32 byte string" do
10
- resolves_input(Base64.encode64("A"*16 + "B"*16))
11
- end
12
-
13
- it "can resolve a 32 byte string without encoding" do
14
- resolves_input("A"*16 + "B"*16)
15
- end
16
-
17
- it "fails loudly when an invalid secret is provided" do
18
- secret = Base64.urlsafe_encode64("bad")
19
- expect do
20
- Fernet::Secret.new(secret)
21
- end.to raise_error(Fernet::Secret::InvalidSecret)
22
- end
23
-
24
- def resolves_input(input)
25
- secret = Fernet::Secret.new(input)
26
-
27
- expect(
28
- secret.signing_key
29
- ).to eq("A"*16)
30
-
31
- expect(
32
- secret.encryption_key
33
- ).to eq("B"*16)
34
- end
35
- end
@@ -1,20 +0,0 @@
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.run_all_when_everything_filtered = true
9
- config.filter_run :focus
10
-
11
- # Run specs in random order to surface order dependencies. If you find an
12
- # order dependency and want to debug it, you can fix the order by providing
13
- # the seed, which is printed after each run.
14
- # --seed 1234
15
- config.order = 'random'
16
-
17
- config.expect_with :rspec do |c|
18
- c.syntax = :expect
19
- end
20
- end
@@ -1,106 +0,0 @@
1
- require 'spec_helper'
2
- require 'fernet'
3
- require 'json'
4
-
5
- describe Fernet::Token, 'validation' do
6
- let(:secret) { 'odN/0Yu+Pwp3oIvvG8OiE5w4LsLrqfWYRb3knQtSyKI=' }
7
- it 'is invalid with a bad MAC signature' do
8
- generated = Fernet::Token.generate(secret: secret,
9
- message: 'hello')
10
-
11
- bogus_hmac = "1" * 32
12
- allow(Fernet::Encryption).to receive(:hmac_digest).and_return(bogus_hmac)
13
-
14
- token = Fernet::Token.new(generated.to_s, secret: secret)
15
-
16
- expect(token.valid?).to eq(false)
17
- expect(token.errors[:signature]).to include("does not match")
18
- end
19
-
20
- it 'is invalid if too old' do
21
- generated = Fernet::Token.generate(secret: secret,
22
- message: 'hello',
23
- now: Time.now - 61)
24
- token = Fernet::Token.new(generated.to_s, enforce_ttl: true,
25
- ttl: 60,
26
- secret: secret)
27
- expect(token.valid?).to eq(false)
28
- expect(token.errors[:issued_timestamp]).to include("is too far in the past: token expired")
29
- end
30
-
31
- it 'is invalid with a large clock skew' do
32
- generated = Fernet::Token.generate(secret: secret,
33
- message: 'hello',
34
- now: Time.at(Time.now.to_i + 61))
35
- token = Fernet::Token.new(generated.to_s, secret: secret)
36
-
37
- expect(token.valid?).to eq(false)
38
- expect(token.errors[:issued_timestamp]).to include("is too far in the future")
39
- end
40
-
41
- it 'is invalid with bad base64' do
42
- token = Fernet::Token.new('bad', secret: secret)
43
-
44
- expect(token.valid?).to eq(false)
45
- expect(token.errors[:token]).to include("invalid base64")
46
- end
47
-
48
- it 'is invalid with an unknown token version' do
49
- invalid1 = Fernet::Token.generate(message: 'message', version: 0x00, secret: secret)
50
- invalid2 = Fernet::Token.generate(message: 'message', version: 0x81, secret: secret)
51
- valid = Fernet::Token.generate(message: 'message', secret: secret)
52
-
53
- [invalid1, invalid2].each do |token|
54
- expect(token.valid?).to eq(false)
55
- expect(token.errors[:version]).to include("is unknown")
56
- end
57
- expect(valid.valid?).to eq(true)
58
- end
59
-
60
- it 'is invalid with bad base64 encodings' do
61
- token = Fernet::Token.generate(message: 'message', secret: secret)
62
- invalid = Fernet::Token.new("\n#{token}", secret: secret)
63
-
64
- ["\n#{token}", "#{token} ", "#{token}+",
65
- token.to_s.gsub(/(.)$/, "1"),
66
- token.to_s.gsub(/(.)$/, "+"),
67
- token.to_s.gsub(/(.)$/, "\\"),
68
- ].each do |invalid_string|
69
- invalid = Fernet::Token.new(invalid_string, secret: secret)
70
- expect(invalid.valid?).to be(false)
71
- end
72
- end
73
- end
74
-
75
- describe Fernet::Token, 'message' do
76
- let(:secret) { 'odN/0Yu+Pwp3oIvvG8OiE5w4LsLrqfWYRb3knQtSyKI=' }
77
- it 'refuses to decrypt if invalid' do
78
- generated = Fernet::Token.generate(secret: secret,
79
- message: 'hello',
80
- now: Time.now + 61)
81
- token = Fernet::Token.new(generated.to_s, secret: secret)
82
-
83
- !token.valid? or raise "invalid token"
84
-
85
- expect {
86
- token.message
87
- }.to raise_error Fernet::Token::InvalidToken,
88
- /issued_timestamp is too far in the future/
89
- end
90
-
91
- it 'gives back the original message in plain text' do
92
- token = Fernet::Token.generate(secret: secret,
93
- message: 'hello')
94
- token.valid? or raise "invalid token"
95
-
96
- expect(token.message).to eq('hello')
97
- end
98
-
99
- it 'correctly handles an empty message' do
100
- token = Fernet::Token.generate(secret: secret,
101
- message: '')
102
- token.valid? or raise "invalid token"
103
-
104
- expect(token.message).to eq('')
105
- end
106
- end