json-jwt 0.5.6 → 0.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f19422f66eb5b83b9e0bd358351adae0079ef23b
4
- data.tar.gz: 9fcfb99e7aefa37537925233bf1669706ec30b9a
3
+ metadata.gz: 9ed6b68461d916fd8be52e755b8bb2c77253149d
4
+ data.tar.gz: 8f0b99b938171b21ab88d259471ec72622c979bb
5
5
  SHA512:
6
- metadata.gz: 43e31546b57bcf852d496a588d444669ca48060191cec2c5283eadca9c6da5c7e69d337df9f40a240798a88c9e14316d9ad0a20c2bcbe7f7d0ede3e4cad6daee
7
- data.tar.gz: 867b59f52a7937a7c86fe6b159038506e2821899872b7e4bb9bbcc6ac6d18310ee6e7cd31216180eabaff1072b3cb487253fb20e26ccdb163efde2a57005fed6
6
+ metadata.gz: 07c51fe7a0b6b66ce4e4504f36baf1698c76537fa8f38513d2cc3fc67dd33208c88b64b8fbe8d0c6feafbf457d10e1ccdf2f3f2adc148035577ed3d5c37cedfb
7
+ data.tar.gz: 44ae1afcca4d398d46fedacfa69e3403d484f77011af870b7e77f38496a4b1177d3b8fad54a014b49a980dc0f871135b3eed27354cc3035e3cba80b1d36d7d22
data/README.rdoc CHANGED
@@ -33,7 +33,7 @@ JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and JSON
33
33
  jws.to_s # => header.payload.signature
34
34
 
35
35
  # With signature & encryption
36
- jwe = jws.encrypt(key, algorithm, encryption_method) # algorithm & encryption_method are optional. default RSA1_5 & A128CBC+HS256
36
+ jwe = jws.encrypt(key, algorithm, encryption_method) # algorithm & encryption_method are optional. default RSA1_5 & A128CBC-HS256
37
37
  jws.to_s # => header.master_key.iv.cipher_text.integrity_value
38
38
 
39
39
  For details about <code>key</code> and <code>algorithm</code>, see
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.6
1
+ 0.6.0
data/lib/json/jwe.rb CHANGED
@@ -9,8 +9,8 @@ module JSON
9
9
 
10
10
  attr_accessor(
11
11
  :public_key_or_secret, :private_key_or_secret, :mode,
12
- :input, :plain_text, :cipher_text, :integrity_value, :iv,
13
- :master_key, :encrypted_master_key, :encryption_key, :integrity_key
12
+ :input, :plain_text, :cipher_text, :authentication_tag, :iv,
13
+ :content_encryption_key, :jwe_encrypted_key, :encryption_key, :mac_key
14
14
  )
15
15
 
16
16
  register_header_keys :enc, :epk, :zip, :apu, :apv
@@ -49,10 +49,10 @@ module JSON
49
49
  if mode == :encyption
50
50
  [
51
51
  header.to_json,
52
- encrypted_master_key,
52
+ jwe_encrypted_key,
53
53
  iv,
54
54
  cipher_text,
55
- integrity_value
55
+ authentication_tag
56
56
  ].collect do |segment|
57
57
  UrlSafeBase64.encode64 segment.to_s
58
58
  end.join('.')
@@ -74,7 +74,7 @@ module JSON
74
74
  end
75
75
 
76
76
  def cbc?
77
- [:'A128CBC+HS256', :'A256CBC+HS512'].collect(&:to_s).include? encryption_method.to_s
77
+ [:'A128CBC-HS256', :'A256CBC-HS512'].collect(&:to_s).include? encryption_method.to_s
78
78
  end
79
79
 
80
80
  def dir?
@@ -95,9 +95,9 @@ module JSON
95
95
  'aes-128-gcm'
96
96
  when :A256GCM.to_s
97
97
  'aes-256-gcm'
98
- when :'A128CBC+HS256'.to_s
98
+ when :'A128CBC-HS256'.to_s
99
99
  'aes-128-cbc'
100
- when :'A256CBC+HS512'.to_s
100
+ when :'A256CBC-HS512'.to_s
101
101
  'aes-256-cbc'
102
102
  else
103
103
  raise UnexpectedAlgorithm.new('Unknown Encryption Algorithm')
@@ -106,9 +106,9 @@ module JSON
106
106
 
107
107
  def sha_size
108
108
  case encryption_method.to_s
109
- when :'A128CBC+HS256'.to_s
109
+ when :'A128CBC-HS256'.to_s
110
110
  256
111
- when :'A256CBC+HS512'.to_s
111
+ when :'A256CBC-HS512'.to_s
112
112
  512
113
113
  else
114
114
  raise UnexpectedAlgorithm.new('Unknown Hash Size')
@@ -119,50 +119,14 @@ module JSON
119
119
  OpenSSL::Digest::Digest.new "SHA#{sha_size}"
120
120
  end
121
121
 
122
- def derive_cbc_encryption_and_integirity_keys!
123
- encryption_key_size = sha_size / 2
124
- integrity_key_size = sha_size
125
- encryption_segments = [
126
- 1,
127
- master_key,
128
- encryption_key_size,
129
- encryption_method,
130
- 0,
131
- 0,
132
- 'Encryption'
133
- ]
134
- integrity_segments = [
135
- 1,
136
- master_key,
137
- integrity_key_size,
138
- encryption_method,
139
- 0,
140
- 0,
141
- 'Integrity'
142
- ]
143
- encryption_hash_input, integrity_hash_input = [encryption_segments, integrity_segments].collect do |segments|
144
- segments.collect do |segment|
145
- case segment
146
- when Integer
147
- BinData::Int32be.new(segment).to_binary_s
148
- else
149
- segment.to_s
150
- end
151
- end.join
152
- end
153
- self.encryption_key = sha_digest.digest(encryption_hash_input)[0, encryption_key_size / 8]
154
- self.integrity_key = sha_digest.digest integrity_hash_input
155
- self
156
- end
157
-
158
122
  # encyption
159
123
 
160
- def encrypted_master_key
161
- @encrypted_master_key ||= case algorithm.to_s
124
+ def jwe_encrypted_key
125
+ @jwe_encrypted_key ||= case algorithm.to_s
162
126
  when :RSA1_5.to_s
163
- public_key_or_secret.public_encrypt master_key
127
+ public_key_or_secret.public_encrypt content_encryption_key
164
128
  when :'RSA-OAEP'.to_s
165
- public_key_or_secret.public_encrypt master_key, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
129
+ public_key_or_secret.public_encrypt content_encryption_key, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
166
130
  when :A128KW.to_s
167
131
  raise NotImplementedError.new('A128KW not supported yet')
168
132
  when :A256KW.to_s
@@ -190,65 +154,64 @@ module JSON
190
154
  cipher.key = encryption_key
191
155
  self.iv = cipher.random_iv
192
156
  if gcm?
193
- cipher.auth_data = [header.to_json, encrypted_master_key, iv].collect do |segment|
194
- UrlSafeBase64.encode64 segment.to_s
195
- end.join('.')
157
+ cipher.auth_data = UrlSafeBase64.encode64 header.to_json
196
158
  end
197
159
  self
198
160
  end
199
161
 
200
162
  def generate_gcm_keys!
201
- self.master_key ||= if dir?
163
+ self.content_encryption_key ||= if dir?
202
164
  public_key_or_secret
203
165
  else
204
166
  cipher.random_key
205
167
  end
206
- self.encryption_key = master_key
207
- self.integrity_key = :wont_be_used
168
+ self.encryption_key = content_encryption_key
208
169
  self
209
170
  end
210
171
 
211
172
  def generate_cbc_keys!
212
- self.master_key ||= if dir?
173
+ self.content_encryption_key ||= if dir?
213
174
  public_key_or_secret
214
175
  else
215
176
  SecureRandom.random_bytes sha_size / 8
216
177
  end
217
- derive_cbc_encryption_and_integirity_keys!
178
+ self.mac_key, self.encryption_key = content_encryption_key.unpack("a#{content_encryption_key.length / 2}" * 2)
179
+ self
218
180
  end
219
181
 
220
- def integrity_value
221
- @integrity_value ||= case
182
+ def authentication_tag
183
+ @authentication_tag ||= case
222
184
  when gcm?
223
185
  cipher.auth_tag
224
186
  when cbc?
187
+ auth_data = UrlSafeBase64.encode64 header.to_json
225
188
  secured_input = [
226
- header.to_json,
227
- encrypted_master_key,
189
+ auth_data,
228
190
  iv,
229
- cipher_text
230
- ].collect do |segment|
231
- UrlSafeBase64.encode64 segment.to_s
232
- end.join('.')
233
- OpenSSL::HMAC.digest sha_digest, integrity_key, secured_input
191
+ cipher_text,
192
+ BinData::Uint64be.new(auth_data.length * 8).to_binary_s
193
+ ].join
194
+ OpenSSL::HMAC.digest(
195
+ sha_digest, mac_key, secured_input
196
+ )[0, sha_size / 2 / 8]
234
197
  end
235
198
  end
236
199
 
237
200
  # decryption
238
201
 
239
202
  def decode_segments!
240
- _header_json_, self.encrypted_master_key, self.iv, self.cipher_text, self.integrity_value = input.split('.').collect do |segment|
203
+ _header_json_, self.jwe_encrypted_key, self.iv, self.cipher_text, self.authentication_tag = input.split('.').collect do |segment|
241
204
  UrlSafeBase64.decode64 segment
242
205
  end
243
206
  self
244
207
  end
245
208
 
246
- def decrypt_master_key
209
+ def decrypt_content_encryption_key
247
210
  case algorithm.to_s
248
211
  when :RSA1_5.to_s
249
- private_key_or_secret.private_decrypt encrypted_master_key
212
+ private_key_or_secret.private_decrypt jwe_encrypted_key
250
213
  when :'RSA-OAEP'.to_s
251
- private_key_or_secret.private_decrypt encrypted_master_key, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
214
+ private_key_or_secret.private_decrypt jwe_encrypted_key, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
252
215
  when :A128KW.to_s
253
216
  raise NotImplementedError.new('A128KW not supported yet')
254
217
  when :A256KW.to_s
@@ -267,26 +230,33 @@ module JSON
267
230
  end
268
231
 
269
232
  def restore_cipher_keys!
270
- self.master_key = decrypt_master_key
233
+ self.content_encryption_key = decrypt_content_encryption_key
271
234
  case
272
235
  when gcm?
273
- self.encryption_key = master_key
274
- self.integrity_key = :wont_be_used
236
+ self.encryption_key = content_encryption_key
275
237
  when cbc?
276
- derive_cbc_encryption_and_integirity_keys!
238
+ self.mac_key, self.encryption_key = content_encryption_key.unpack("a#{content_encryption_key.length / 2}" * 2)
277
239
  end
278
240
  cipher.key = encryption_key
279
241
  cipher.iv = iv # NOTE: 'iv' has to be set after 'key' for GCM
280
242
  if gcm?
281
- cipher.auth_tag = integrity_value
282
- cipher.auth_data = input.split('.')[0, 3].join('.')
243
+ cipher.auth_tag = authentication_tag
244
+ cipher.auth_data = input.split('.').first
283
245
  end
284
246
  end
285
247
 
286
248
  def verify_cbc_integirity_value!
287
- secured_input = input.split('.')[0, 4].join('.')
288
- expected_integrity_value = OpenSSL::HMAC.digest sha_digest, integrity_key, secured_input
289
- unless integrity_value == expected_integrity_value
249
+ auth_data = input.split('.').first
250
+ secured_input = [
251
+ auth_data,
252
+ iv,
253
+ cipher_text,
254
+ BinData::Uint64be.new(auth_data.length * 8).to_binary_s
255
+ ].join
256
+ expected_authentication_tag = OpenSSL::HMAC.digest(
257
+ sha_digest, mac_key, secured_input
258
+ )[0, sha_size / 2 / 8]
259
+ unless authentication_tag == expected_authentication_tag
290
260
  raise DecryptionFailed.new('Invalid integrity value')
291
261
  end
292
262
  end
data/lib/json/jwt.rb CHANGED
@@ -59,7 +59,7 @@ module JSON
59
59
  end
60
60
  end
61
61
 
62
- def encrypt(public_key_or_secret, algorithm = :RSA1_5, encryption_method = :'A128CBC+HS256')
62
+ def encrypt(public_key_or_secret, algorithm = :RSA1_5, encryption_method = :'A128CBC-HS256')
63
63
  jwe = JWE.new(self)
64
64
  jwe.alg = algorithm
65
65
  jwe.enc = encryption_method
@@ -59,8 +59,8 @@ describe JSON::JWE do
59
59
  end
60
60
 
61
61
  shared_examples_for :cbc_encryption do
62
- context 'when enc=A128CBC+HS256' do
63
- before { jwe.enc = :'A128CBC+HS256' }
62
+ context 'when enc=A128CBC-HS256' do
63
+ before { jwe.enc = :'A128CBC-HS256' }
64
64
 
65
65
  it 'should decryptable by Nimbus JOSE JWT' do
66
66
  jwe.encrypt! key
@@ -68,8 +68,8 @@ describe JSON::JWE do
68
68
  end
69
69
  end
70
70
 
71
- context 'when enc=A256CBC+HS512' do
72
- before { jwe.enc = :'A256CBC+HS512' }
71
+ context 'when enc=A256CBC-HS512' do
72
+ before { jwe.enc = :'A256CBC-HS512' }
73
73
 
74
74
  it 'should decryptable by Nimbus JOSE JWT' do
75
75
  jwe.encrypt! key
@@ -137,7 +137,7 @@ describe JSON::JWE do
137
137
  context 'when unknonw/unsupported algorithm given' do
138
138
  let(:key) { public_key }
139
139
  let(:alg) { :RSA1_5 }
140
- let(:enc) { :'A128CBC+HS256' }
140
+ let(:enc) { :'A128CBC-HS256' }
141
141
  before { jwe.alg, jwe.enc = alg, enc }
142
142
 
143
143
  context 'when alg=unknown' do
@@ -280,13 +280,13 @@ describe JSON::JWE do
280
280
  end
281
281
  end
282
282
 
283
- context 'when enc=A128CBC+HS256' do
284
- let(:enc) { :'A128CBC+HS256' }
283
+ context 'when enc=A128CBC-HS256' do
284
+ let(:enc) { :'A128CBC-HS256' }
285
285
  it_behaves_like :decryptable
286
286
  end
287
287
 
288
- context 'when enc=A256CBC+HS512' do
289
- let(:enc) { :'A256CBC+HS512' }
288
+ context 'when enc=A256CBC-HS512' do
289
+ let(:enc) { :'A256CBC-HS512' }
290
290
  it_behaves_like :decryptable
291
291
  end
292
292
  end
@@ -313,14 +313,14 @@ describe JSON::JWE do
313
313
  end
314
314
  end
315
315
 
316
- context 'when enc=A128CBC+HS256' do
317
- let(:enc) { :'A128CBC+HS256' }
316
+ context 'when enc=A128CBC-HS256' do
317
+ let(:enc) { :'A128CBC-HS256' }
318
318
  it_behaves_like :decryptable
319
319
  it_behaves_like :verify_cbc_integrity_value
320
320
  end
321
321
 
322
- context 'when enc=A256CBC+HS512' do
323
- let(:enc) { :'A256CBC+HS512' }
322
+ context 'when enc=A256CBC-HS512' do
323
+ let(:enc) { :'A256CBC-HS512' }
324
324
  it_behaves_like :decryptable
325
325
  it_behaves_like :verify_cbc_integrity_value
326
326
  end
@@ -336,7 +336,7 @@ describe JSON::JWE do
336
336
  let(:input) { 'whatever' }
337
337
  let(:key) { public_key }
338
338
  let(:alg) { :RSA1_5 }
339
- let(:enc) { :'A128CBC+HS256' }
339
+ let(:enc) { :'A128CBC-HS256' }
340
340
 
341
341
  context 'when alg=unknown' do
342
342
  let(:alg) { :unknown }
@@ -115,7 +115,7 @@ describe JSON::JWT do
115
115
  end
116
116
 
117
117
  it 'should accept optional algorithm and encryption method' do
118
- jwt.encrypt(shared_key, :dir, :'A256CBC+HS512').should be_a JSON::JWE
118
+ jwt.encrypt(SecureRandom.hex(32), :dir, :'A256CBC-HS512').should be_a JSON::JWE
119
119
  end
120
120
  end
121
121
 
@@ -167,7 +167,7 @@ describe JSON::JWT do
167
167
  it 'should skip verification' do
168
168
  expect do
169
169
  jwe = JSON::JWT.decode input, :skip_decryption
170
- jwe.header.should == {'alg' => 'RSA1_5', 'enc' => 'A128CBC+HS256'}
170
+ jwe.header.should == {'alg' => 'RSA1_5', 'enc' => 'A128CBC-HS256'}
171
171
  end.not_to raise_error
172
172
  end
173
173
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-jwt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.6
4
+ version: 0.6.0
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-01 00:00:00.000000000 Z
11
+ date: 2013-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json