json-jwt 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of json-jwt might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ed6b68461d916fd8be52e755b8bb2c77253149d
4
- data.tar.gz: 8f0b99b938171b21ab88d259471ec72622c979bb
3
+ metadata.gz: cfafaeda298c56aa5cd5f1056f33b31ed7b31bb8
4
+ data.tar.gz: fe6fd7d8d776f0b197add6a79f2b11a03afc9af7
5
5
  SHA512:
6
- metadata.gz: 07c51fe7a0b6b66ce4e4504f36baf1698c76537fa8f38513d2cc3fc67dd33208c88b64b8fbe8d0c6feafbf457d10e1ccdf2f3f2adc148035577ed3d5c37cedfb
7
- data.tar.gz: 44ae1afcca4d398d46fedacfa69e3403d484f77011af870b7e77f38496a4b1177d3b8fad54a014b49a980dc0f871135b3eed27354cc3035e3cba80b1d36d7d22
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.master_key.iv.cipher_text.integrity_value
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 :cover_me do
8
- desc "Generates and opens code coverage report."
7
+ namespace :coverage do
8
+ desc "Open coverage report"
9
9
  task :report do
10
- require 'cover_me'
11
- CoverMe.complete!
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['cover_me:report'].invoke unless ENV['TRAVIS_RUBY_VERSION']
16
+ Rake::Task[:'coverage:report'].invoke unless ENV['TRAVIS_RUBY_VERSION']
16
17
  end
17
18
 
18
- task default: :spec
19
+ task :default => :spec
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.0
1
+ 0.6.1
data/json-jwt.gemspec CHANGED
@@ -1,20 +1,22 @@
1
- Gem::Specification.new do |s|
2
- s.name = "json-jwt"
3
- s.version = File.read("VERSION")
4
- s.authors = ["nov matake"]
5
- s.email = ["nov@matake.jp"]
6
- s.homepage = "https://github.com/nov/json-jwt"
7
- s.summary = %q{JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and JSON Web Key) in Ruby}
8
- s.description = %q{JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and JSON Web Key) in Ruby}
9
- s.files = `git ls-files`.split("\n")
10
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
11
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
- s.require_paths = ["lib"]
13
- s.add_runtime_dependency "multi_json", ">= 1.3"
14
- s.add_runtime_dependency "url_safe_base64"
15
- s.add_runtime_dependency "activesupport"
16
- s.add_runtime_dependency "bindata"
17
- s.add_development_dependency "rake", ">= 0.8"
18
- s.add_development_dependency "cover_me", ">= 1.2.0"
19
- s.add_development_dependency "rspec", ">= 2"
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
@@ -1,5 +1,9 @@
1
+ require 'securecompare'
2
+
1
3
  module JSON
2
4
  class JOSE < JWT
5
+ include SecureCompare
6
+
3
7
  def content_type
4
8
  'application/jose'
5
9
  end
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
- verify_cbc_integirity_value! if cbc?
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
- self.encryption_key = content_encryption_key
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
- self.mac_key, self.encryption_key = content_encryption_key.unpack("a#{content_encryption_key.length / 2}" * 2)
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
- self.encryption_key = content_encryption_key
252
+ derive_encryption_and_mac_keys_gcm!
237
253
  when cbc?
238
- self.mac_key, self.encryption_key = content_encryption_key.unpack("a#{content_encryption_key.length / 2}" * 2)
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 verify_cbc_integirity_value!
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 == expected_authentication_tag
260
- raise DecryptionFailed.new('Invalid integrity value')
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
- secret = public_key_or_secret
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 2 # JWT / JWS
83
- header, claims, signature = jwt_string.split('.', 3).collect do |segment|
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, 2].join('.')
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 4 # JWE
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('Invalid JWT Format. JWT should include 2 or 3 dots.')
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")
@@ -227,7 +227,7 @@ describe JSON::JWE do
227
227
  end
228
228
  end
229
229
 
230
- shared_examples_for :verify_cbc_integrity_value do
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 :verify_cbc_integrity_value
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 :verify_cbc_integrity_value
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) { 'whatever' }
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
@@ -1,4 +1,9 @@
1
- require 'cover_me'
1
+ require 'simplecov'
2
+
3
+ SimpleCov.start do
4
+ add_filter 'spec'
5
+ end
6
+
2
7
  require 'rspec'
3
8
  require 'json/jwt'
4
9
 
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.0
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: 2013-10-24 00:00:00.000000000 Z
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: cover_me
98
+ name: simplecov
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
- - - '>='
101
+ - - ">="
88
102
  - !ruby/object:Gem::Version
89
- version: 1.2.0
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: 1.2.0
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.0.3
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