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.
- data/lib/fernet.rb +7 -0
- data/lib/fernet/verifier.rb +1 -1
- data/lib/fernet/version.rb +1 -1
- metadata +42 -36
- checksums.yaml +0 -7
- data/.gitignore +0 -19
- data/.gitmodules +0 -3
- data/.rdoc_options +0 -16
- data/.rspec +0 -2
- data/.travis.yml +0 -8
- data/Gemfile +0 -4
- data/Rakefile +0 -2
- data/fernet.gemspec +0 -20
- data/spec/acceptance/generate_spec.rb +0 -27
- data/spec/acceptance/verify_spec.rb +0 -52
- data/spec/bit_packing_spec.rb +0 -36
- data/spec/fernet_spec.rb +0 -75
- data/spec/secret_spec.rb +0 -35
- data/spec/spec_helper.rb +0 -20
- data/spec/token_spec.rb +0 -106
data/lib/fernet.rb
CHANGED
@@ -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
|
data/lib/fernet/verifier.rb
CHANGED
data/lib/fernet/version.rb
CHANGED
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.
|
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-
|
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: '
|
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: '
|
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
|
-
-
|
69
|
-
|
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:
|
107
|
+
rubygems_version: 1.8.23.2
|
95
108
|
signing_key:
|
96
|
-
specification_version:
|
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
data/.gitmodules
DELETED
data/.rdoc_options
DELETED
@@ -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
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
data/fernet.gemspec
DELETED
@@ -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
|
data/spec/bit_packing_spec.rb
DELETED
@@ -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
|
data/spec/fernet_spec.rb
DELETED
@@ -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
|
data/spec/secret_spec.rb
DELETED
@@ -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
|
data/spec/spec_helper.rb
DELETED
@@ -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
|
data/spec/token_spec.rb
DELETED
@@ -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
|