json-jwt 0.5.6 → 0.6.0

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: 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