json-jwt 0.6.0 → 0.6.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.
Potentially problematic release.
This version of json-jwt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.rdoc +1 -1
- data/Rakefile +7 -6
- data/VERSION +1 -1
- data/json-jwt.gemspec +21 -19
- data/lib/json/jose.rb +4 -0
- data/lib/json/jwe.rb +24 -8
- data/lib/json/jws.rb +3 -2
- data/lib/json/jwt.rb +6 -6
- data/spec/json/jwe_spec.rb +15 -4
- data/spec/spec_helper.rb +6 -1
- metadata +42 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cfafaeda298c56aa5cd5f1056f33b31ed7b31bb8
|
4
|
+
data.tar.gz: fe6fd7d8d776f0b197add6a79f2b11a03afc9af7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0ead0b472adcf5fab5203765d2b83ea4afeb131510d4765b0f884867de2affeac688d72c8bbc64626498680e0b6c55a1f351d9fcd07fde418342be7ef9ab92c
|
7
|
+
data.tar.gz: adca33ab7ec94e4a92a70585cf3c3e441f2f22c56701071adc79f1d5ecd6a0bc28fbb9cbb13ce74b9869c8dfe274c3da1d65b49621e5fbe1ce944e1c6204caab
|
data/README.rdoc
CHANGED
@@ -34,7 +34,7 @@ JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and JSON
|
|
34
34
|
|
35
35
|
# With signature & encryption
|
36
36
|
jwe = jws.encrypt(key, algorithm, encryption_method) # algorithm & encryption_method are optional. default RSA1_5 & A128CBC-HS256
|
37
|
-
jws.to_s # => header.
|
37
|
+
jws.to_s # => header.encrypted_key.iv.cipher_text.authentication_tag
|
38
38
|
|
39
39
|
For details about <code>key</code> and <code>algorithm</code>, see
|
40
40
|
{JWS Spec}[https://github.com/nov/json-jwt/blob/master/spec/json/jws_spec.rb] and
|
data/Rakefile
CHANGED
@@ -4,15 +4,16 @@ Bundler::GemHelper.install_tasks
|
|
4
4
|
require 'rspec/core/rake_task'
|
5
5
|
RSpec::Core::RakeTask.new(:spec)
|
6
6
|
|
7
|
-
namespace :
|
8
|
-
desc "
|
7
|
+
namespace :coverage do
|
8
|
+
desc "Open coverage report"
|
9
9
|
task :report do
|
10
|
-
require '
|
11
|
-
|
10
|
+
require 'simplecov'
|
11
|
+
`open "#{File.join SimpleCov.coverage_path, 'index.html'}"`
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
14
15
|
task :spec do
|
15
|
-
Rake::Task['
|
16
|
+
Rake::Task[:'coverage:report'].invoke unless ENV['TRAVIS_RUBY_VERSION']
|
16
17
|
end
|
17
18
|
|
18
|
-
task default
|
19
|
+
task :default => :spec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.6.
|
1
|
+
0.6.1
|
data/json-jwt.gemspec
CHANGED
@@ -1,20 +1,22 @@
|
|
1
|
-
Gem::Specification.new do |
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = "json-jwt"
|
3
|
+
gem.version = File.read("VERSION")
|
4
|
+
gem.authors = ["nov matake"]
|
5
|
+
gem.email = ["nov@matake.jp"]
|
6
|
+
gem.homepage = "https://github.com/nov/json-jwt"
|
7
|
+
gem.summary = %q{JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and JSON Web Key) in Ruby}
|
8
|
+
gem.description = %q{JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and JSON Web Key) in Ruby}
|
9
|
+
gem.license = 'MIT'
|
10
|
+
gem.files = `git ls-files`.split("\n")
|
11
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
12
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
13
|
+
gem.require_paths = ["lib"]
|
14
|
+
gem.add_runtime_dependency "multi_json", ">= 1.3"
|
15
|
+
gem.add_runtime_dependency "url_safe_base64"
|
16
|
+
gem.add_runtime_dependency "activesupport"
|
17
|
+
gem.add_runtime_dependency "bindata"
|
18
|
+
gem.add_runtime_dependency "securecompare"
|
19
|
+
gem.add_development_dependency "rake", ">= 0.8"
|
20
|
+
gem.add_development_dependency "simplecov"
|
21
|
+
gem.add_development_dependency "rspec", ">= 2"
|
20
22
|
end
|
data/lib/json/jose.rb
CHANGED
data/lib/json/jwe.rb
CHANGED
@@ -7,6 +7,8 @@ module JSON
|
|
7
7
|
class DecryptionFailed < JWT::VerificationFailed; end
|
8
8
|
class UnexpectedAlgorithm < JWT::UnexpectedAlgorithm; end
|
9
9
|
|
10
|
+
NUM_OF_SEGMENTS = 5
|
11
|
+
|
10
12
|
attr_accessor(
|
11
13
|
:public_key_or_secret, :private_key_or_secret, :mode,
|
12
14
|
:input, :plain_text, :cipher_text, :authentication_tag, :iv,
|
@@ -41,7 +43,7 @@ module JSON
|
|
41
43
|
cipher.decrypt
|
42
44
|
restore_cipher_keys!
|
43
45
|
self.plain_text = cipher.update(cipher_text) + cipher.final
|
44
|
-
|
46
|
+
verify_cbc_authentication_tag! if cbc?
|
45
47
|
self
|
46
48
|
end
|
47
49
|
|
@@ -119,6 +121,17 @@ module JSON
|
|
119
121
|
OpenSSL::Digest::Digest.new "SHA#{sha_size}"
|
120
122
|
end
|
121
123
|
|
124
|
+
def derive_encryption_and_mac_keys_cbc!
|
125
|
+
self.mac_key, self.encryption_key = content_encryption_key.unpack("a#{content_encryption_key.length / 2}" * 2)
|
126
|
+
self
|
127
|
+
end
|
128
|
+
|
129
|
+
def derive_encryption_and_mac_keys_gcm!
|
130
|
+
self.encryption_key = content_encryption_key
|
131
|
+
self.mac_key = :wont_be_used
|
132
|
+
self
|
133
|
+
end
|
134
|
+
|
122
135
|
# encyption
|
123
136
|
|
124
137
|
def jwe_encrypted_key
|
@@ -165,7 +178,7 @@ module JSON
|
|
165
178
|
else
|
166
179
|
cipher.random_key
|
167
180
|
end
|
168
|
-
|
181
|
+
derive_encryption_and_mac_keys_gcm!
|
169
182
|
self
|
170
183
|
end
|
171
184
|
|
@@ -175,7 +188,7 @@ module JSON
|
|
175
188
|
else
|
176
189
|
SecureRandom.random_bytes sha_size / 8
|
177
190
|
end
|
178
|
-
|
191
|
+
derive_encryption_and_mac_keys_cbc!
|
179
192
|
self
|
180
193
|
end
|
181
194
|
|
@@ -200,6 +213,9 @@ module JSON
|
|
200
213
|
# decryption
|
201
214
|
|
202
215
|
def decode_segments!
|
216
|
+
unless input.count('.') + 1 == NUM_OF_SEGMENTS
|
217
|
+
raise InvalidFormat.new("Invalid JWE Format. JWE should include #{NUM_OF_SEGMENTS} segments.")
|
218
|
+
end
|
203
219
|
_header_json_, self.jwe_encrypted_key, self.iv, self.cipher_text, self.authentication_tag = input.split('.').collect do |segment|
|
204
220
|
UrlSafeBase64.decode64 segment
|
205
221
|
end
|
@@ -233,9 +249,9 @@ module JSON
|
|
233
249
|
self.content_encryption_key = decrypt_content_encryption_key
|
234
250
|
case
|
235
251
|
when gcm?
|
236
|
-
|
252
|
+
derive_encryption_and_mac_keys_gcm!
|
237
253
|
when cbc?
|
238
|
-
|
254
|
+
derive_encryption_and_mac_keys_cbc!
|
239
255
|
end
|
240
256
|
cipher.key = encryption_key
|
241
257
|
cipher.iv = iv # NOTE: 'iv' has to be set after 'key' for GCM
|
@@ -245,7 +261,7 @@ module JSON
|
|
245
261
|
end
|
246
262
|
end
|
247
263
|
|
248
|
-
def
|
264
|
+
def verify_cbc_authentication_tag!
|
249
265
|
auth_data = input.split('.').first
|
250
266
|
secured_input = [
|
251
267
|
auth_data,
|
@@ -256,8 +272,8 @@ module JSON
|
|
256
272
|
expected_authentication_tag = OpenSSL::HMAC.digest(
|
257
273
|
sha_digest, mac_key, secured_input
|
258
274
|
)[0, sha_size / 2 / 8]
|
259
|
-
unless authentication_tag
|
260
|
-
raise DecryptionFailed.new('Invalid
|
275
|
+
unless secure_compare(authentication_tag, expected_authentication_tag)
|
276
|
+
raise DecryptionFailed.new('Invalid authentication tag')
|
261
277
|
end
|
262
278
|
end
|
263
279
|
end
|
data/lib/json/jws.rb
CHANGED
@@ -4,6 +4,8 @@ module JSON
|
|
4
4
|
class VerificationFailed < JWT::VerificationFailed; end
|
5
5
|
class UnexpectedAlgorithm < JWT::UnexpectedAlgorithm; end
|
6
6
|
|
7
|
+
NUM_OF_SEGMENTS = 3
|
8
|
+
|
7
9
|
def initialize(jwt)
|
8
10
|
replace jwt
|
9
11
|
raise InvalidFormat.new('Signature Algorithm Required') unless algorithm
|
@@ -66,8 +68,7 @@ module JSON
|
|
66
68
|
def valid?(signature_base_string, public_key_or_secret)
|
67
69
|
case
|
68
70
|
when hmac?
|
69
|
-
|
70
|
-
sign(signature_base_string, secret) == signature
|
71
|
+
secure_compare sign(signature_base_string, public_key_or_secret), signature
|
71
72
|
when rsa?
|
72
73
|
public_key = public_key_or_secret
|
73
74
|
public_key.verify digest, signature, signature_base_string
|
data/lib/json/jwt.rb
CHANGED
@@ -78,15 +78,15 @@ module JSON
|
|
78
78
|
|
79
79
|
class << self
|
80
80
|
def decode(jwt_string, key_or_secret = nil)
|
81
|
-
case jwt_string.count('.')
|
82
|
-
when
|
83
|
-
header, claims, signature = jwt_string.split('.',
|
81
|
+
case jwt_string.count('.') + 1
|
82
|
+
when JWS::NUM_OF_SEGMENTS # JWT / JWS
|
83
|
+
header, claims, signature = jwt_string.split('.', JWS::NUM_OF_SEGMENTS).collect do |segment|
|
84
84
|
UrlSafeBase64.decode64 segment.to_s
|
85
85
|
end
|
86
86
|
header, claims = [header, claims].collect do |json|
|
87
87
|
MultiJson.load(json).with_indifferent_access
|
88
88
|
end
|
89
|
-
signature_base_string = jwt_string.split('.')[0,
|
89
|
+
signature_base_string = jwt_string.split('.')[0, JWS::NUM_OF_SEGMENTS - 1].join('.')
|
90
90
|
jwt = new claims
|
91
91
|
jwt.header = header
|
92
92
|
jwt.signature = signature
|
@@ -96,7 +96,7 @@ module JSON
|
|
96
96
|
# So we need to use raw base64 strings for signature verification.
|
97
97
|
jwt.verify signature_base_string, key_or_secret unless key_or_secret == :skip_verification
|
98
98
|
jwt
|
99
|
-
when
|
99
|
+
when JWE::NUM_OF_SEGMENTS
|
100
100
|
jwe = JWE.new jwt_string
|
101
101
|
jwe.header = MultiJson.load(
|
102
102
|
UrlSafeBase64.decode64 jwt_string.split('.').first
|
@@ -104,7 +104,7 @@ module JSON
|
|
104
104
|
jwe.decrypt! key_or_secret unless key_or_secret == :skip_decryption
|
105
105
|
jwe
|
106
106
|
else
|
107
|
-
raise InvalidFormat.new(
|
107
|
+
raise InvalidFormat.new("Invalid JWT Format. JWT should include #{JWS::NUM_OF_SEGMENTS} or #{JWE::NUM_OF_SEGMENTS} segments.")
|
108
108
|
end
|
109
109
|
rescue MultiJson::DecodeError
|
110
110
|
raise InvalidFormat.new("Invalid JSON Format")
|
data/spec/json/jwe_spec.rb
CHANGED
@@ -227,7 +227,7 @@ describe JSON::JWE do
|
|
227
227
|
end
|
228
228
|
end
|
229
229
|
|
230
|
-
shared_examples_for :
|
230
|
+
shared_examples_for :verify_cbc_authentication_tag do
|
231
231
|
let(:input) do
|
232
232
|
_jwe_ = JSON::JWE.new plain_text
|
233
233
|
_jwe_.alg, _jwe_.enc = alg, enc
|
@@ -316,13 +316,13 @@ describe JSON::JWE do
|
|
316
316
|
context 'when enc=A128CBC-HS256' do
|
317
317
|
let(:enc) { :'A128CBC-HS256' }
|
318
318
|
it_behaves_like :decryptable
|
319
|
-
it_behaves_like :
|
319
|
+
it_behaves_like :verify_cbc_authentication_tag
|
320
320
|
end
|
321
321
|
|
322
322
|
context 'when enc=A256CBC-HS512' do
|
323
323
|
let(:enc) { :'A256CBC-HS512' }
|
324
324
|
it_behaves_like :decryptable
|
325
|
-
it_behaves_like :
|
325
|
+
it_behaves_like :verify_cbc_authentication_tag
|
326
326
|
end
|
327
327
|
end
|
328
328
|
|
@@ -333,7 +333,7 @@ describe JSON::JWE do
|
|
333
333
|
end
|
334
334
|
|
335
335
|
context 'when unknonw/unsupported algorithm given' do
|
336
|
-
let(:input) { '
|
336
|
+
let(:input) { 'header.key.iv.cipher_text.auth_tag' }
|
337
337
|
let(:key) { public_key }
|
338
338
|
let(:alg) { :RSA1_5 }
|
339
339
|
let(:enc) { :'A128CBC-HS256' }
|
@@ -355,5 +355,16 @@ describe JSON::JWE do
|
|
355
355
|
end
|
356
356
|
end
|
357
357
|
end
|
358
|
+
|
359
|
+
context 'when invalid format of input given' do
|
360
|
+
let(:input) { 'header.payload.signature' }
|
361
|
+
let(:alg) { :RSA1_5 }
|
362
|
+
let(:enc) { :'A128CBC-HS256' }
|
363
|
+
it do
|
364
|
+
expect do
|
365
|
+
jwe.decrypt! public_key
|
366
|
+
end.to raise_error JSON::JWE::InvalidFormat
|
367
|
+
end
|
368
|
+
end
|
358
369
|
end
|
359
370
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,111 +1,125 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json-jwt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nov matake
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.3'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: url_safe_base64
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: activesupport
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: bindata
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: securecompare
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rake
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
|
-
- -
|
87
|
+
- - ">="
|
74
88
|
- !ruby/object:Gem::Version
|
75
89
|
version: '0.8'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- -
|
94
|
+
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0.8'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
98
|
+
name: simplecov
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- -
|
101
|
+
- - ">="
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
103
|
+
version: '0'
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
|
-
- -
|
108
|
+
- - ">="
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
110
|
+
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: rspec
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- -
|
115
|
+
- - ">="
|
102
116
|
- !ruby/object:Gem::Version
|
103
117
|
version: '2'
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
|
-
- -
|
122
|
+
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '2'
|
111
125
|
description: JSON Web Token and its family (JSON Web Signature, JSON Web Encryption
|
@@ -116,10 +130,10 @@ executables: []
|
|
116
130
|
extensions: []
|
117
131
|
extra_rdoc_files: []
|
118
132
|
files:
|
119
|
-
- .gitignore
|
120
|
-
- .gitmodules
|
121
|
-
- .rspec
|
122
|
-
- .travis.yml
|
133
|
+
- ".gitignore"
|
134
|
+
- ".gitmodules"
|
135
|
+
- ".rspec"
|
136
|
+
- ".travis.yml"
|
123
137
|
- Gemfile
|
124
138
|
- LICENSE
|
125
139
|
- README.rdoc
|
@@ -150,7 +164,8 @@ files:
|
|
150
164
|
- spec/json/jwt_spec.rb
|
151
165
|
- spec/spec_helper.rb
|
152
166
|
homepage: https://github.com/nov/json-jwt
|
153
|
-
licenses:
|
167
|
+
licenses:
|
168
|
+
- MIT
|
154
169
|
metadata: {}
|
155
170
|
post_install_message:
|
156
171
|
rdoc_options: []
|
@@ -158,17 +173,17 @@ require_paths:
|
|
158
173
|
- lib
|
159
174
|
required_ruby_version: !ruby/object:Gem::Requirement
|
160
175
|
requirements:
|
161
|
-
- -
|
176
|
+
- - ">="
|
162
177
|
- !ruby/object:Gem::Version
|
163
178
|
version: '0'
|
164
179
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
180
|
requirements:
|
166
|
-
- -
|
181
|
+
- - ">="
|
167
182
|
- !ruby/object:Gem::Version
|
168
183
|
version: '0'
|
169
184
|
requirements: []
|
170
185
|
rubyforge_project:
|
171
|
-
rubygems_version: 2.
|
186
|
+
rubygems_version: 2.2.1
|
172
187
|
signing_key:
|
173
188
|
specification_version: 4
|
174
189
|
summary: JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and
|