json-jwt 1.5.2 → 1.6.3
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/.travis.yml +3 -5
- data/VERSION +1 -1
- data/lib/json/jose.rb +13 -0
- data/lib/json/jwe.rb +2 -2
- data/lib/json/jwk.rb +1 -0
- data/lib/json/jws.rb +1 -14
- data/lib/json/jwt.rb +10 -1
- data/spec/json/jwe_spec.rb +32 -3
- data/spec/json/jwk_spec.rb +28 -6
- data/spec/json/jws_spec.rb +1 -1
- data/spec/json/jwt_spec.rb +83 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d76ce03978dc2dcfb42f7061d0613fdf9d8dba2
|
4
|
+
data.tar.gz: ad36d966f39107a7e9e7ecd0521780674d7b31b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9fff9a8a5519bcec6cb67eb2153c2ca6f852191b18ddc98011e56fa228bcc94be9c1621fcef734402053d4755b83120e0b1a89b7396a0ea26396cdedda17f9d
|
7
|
+
data.tar.gz: 258a78cfd221accbf30f91ff35c0b5774cc1f463a61311b5412bacb0425fb0bbf1887f900a39197bd2d83bd7210b40c215824dd5a71a4b508f2b91b5e6cbadb1
|
data/.travis.yml
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.6.3
|
data/lib/json/jose.rb
CHANGED
@@ -20,6 +20,19 @@ module JSON
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
def with_jwk_support(key)
|
24
|
+
case key
|
25
|
+
when JSON::JWK
|
26
|
+
key.to_key
|
27
|
+
when JSON::JWK::Set
|
28
|
+
key.detect do |jwk|
|
29
|
+
jwk[:kid] && jwk[:kid] == kid
|
30
|
+
end.try(:to_key) or raise JWK::Set::KidNotFound
|
31
|
+
else
|
32
|
+
key
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
23
36
|
module ClassMethods
|
24
37
|
def register_header_keys(*keys)
|
25
38
|
keys.each do |header_key|
|
data/lib/json/jwe.rb
CHANGED
@@ -25,7 +25,7 @@ module JSON
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def encrypt!(public_key_or_secret)
|
28
|
-
self.public_key_or_secret = public_key_or_secret
|
28
|
+
self.public_key_or_secret = with_jwk_support public_key_or_secret
|
29
29
|
cipher.encrypt
|
30
30
|
generate_cipher_keys!
|
31
31
|
self.cipher_text = cipher.update(plain_text) + cipher.final
|
@@ -33,7 +33,7 @@ module JSON
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def decrypt!(private_key_or_secret)
|
36
|
-
self.private_key_or_secret = private_key_or_secret
|
36
|
+
self.private_key_or_secret = with_jwk_support private_key_or_secret
|
37
37
|
cipher.decrypt
|
38
38
|
restore_cipher_keys!
|
39
39
|
self.plain_text = cipher.update(cipher_text) + cipher.final
|
data/lib/json/jwk.rb
CHANGED
data/lib/json/jws.rb
CHANGED
@@ -30,7 +30,7 @@ module JSON
|
|
30
30
|
def update(hash_or_jwt)
|
31
31
|
super
|
32
32
|
if hash_or_jwt.is_a? JSON::JWT
|
33
|
-
self.header
|
33
|
+
self.header.update hash_or_jwt.header
|
34
34
|
self.signature = hash_or_jwt.signature
|
35
35
|
end
|
36
36
|
self
|
@@ -106,19 +106,6 @@ module JSON
|
|
106
106
|
raise UnexpectedAlgorithm.new(e.message)
|
107
107
|
end
|
108
108
|
|
109
|
-
def with_jwk_support(key)
|
110
|
-
case key
|
111
|
-
when JSON::JWK
|
112
|
-
key.to_key
|
113
|
-
when JSON::JWK::Set
|
114
|
-
key.detect do |jwk|
|
115
|
-
jwk[:kid] && jwk[:kid] == kid
|
116
|
-
end.try(:to_key) or raise JWK::Set::KidNotFound
|
117
|
-
else
|
118
|
-
key
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
109
|
def verify_ecdsa_group!(key)
|
123
110
|
group_name = case digest.digest_length * 8
|
124
111
|
when 256
|
data/lib/json/jwt.rb
CHANGED
@@ -26,14 +26,23 @@ module JSON
|
|
26
26
|
update claims
|
27
27
|
end
|
28
28
|
|
29
|
-
def sign(private_key_or_secret, algorithm = :
|
29
|
+
def sign(private_key_or_secret, algorithm = :autodetect)
|
30
|
+
if algorithm == :autodetect
|
31
|
+
# NOTE:
|
32
|
+
# I'd like to make :RS256 default.
|
33
|
+
# However, by histrical reasons, :HS256 was default.
|
34
|
+
# This code is needed to keep legacy behavior.
|
35
|
+
algorithm = private_key_or_secret.is_a?(String) ? :HS256 : :RS256
|
36
|
+
end
|
30
37
|
jws = JWS.new self
|
38
|
+
jws.kid ||= private_key_or_secret[:kid] if private_key_or_secret.is_a? JSON::JWK
|
31
39
|
jws.alg = algorithm
|
32
40
|
jws.sign! private_key_or_secret
|
33
41
|
end
|
34
42
|
|
35
43
|
def encrypt(public_key_or_secret, algorithm = :RSA1_5, encryption_method = :'A128CBC-HS256')
|
36
44
|
jwe = JWE.new self
|
45
|
+
jwe.kid ||= public_key_or_secret[:kid] if public_key_or_secret.is_a? JSON::JWK
|
37
46
|
jwe.alg = algorithm
|
38
47
|
jwe.enc = encryption_method
|
39
48
|
jwe.encrypt! public_key_or_secret
|
data/spec/json/jwe_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe JSON::JWE do
|
4
|
-
let(:shared_key) { SecureRandom.hex
|
4
|
+
let(:shared_key) { SecureRandom.hex 32 } # default shared key is too short
|
5
5
|
let(:private_key_path) { der_file_path 'rsa/private_key' }
|
6
6
|
|
7
7
|
describe '#content_type' do
|
@@ -248,8 +248,37 @@ describe JSON::JWE do
|
|
248
248
|
|
249
249
|
context 'when alg=dir' do
|
250
250
|
let(:alg) { :dir }
|
251
|
-
let(:key) {
|
252
|
-
|
251
|
+
let(:key) { shared_key }
|
252
|
+
|
253
|
+
context 'when enc=A128GCM' do
|
254
|
+
let(:enc) { :A128GCM }
|
255
|
+
if gcm_supported?
|
256
|
+
it_behaves_like :decryptable
|
257
|
+
else
|
258
|
+
it_behaves_like :gcm_decryption_unsupported
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
context 'when enc=A256GCM' do
|
263
|
+
let(:enc) { :A256GCM }
|
264
|
+
if gcm_supported?
|
265
|
+
it_behaves_like :decryptable
|
266
|
+
else
|
267
|
+
it_behaves_like :gcm_decryption_unsupported
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
context 'when enc=A128CBC-HS256' do
|
272
|
+
let(:enc) { :'A128CBC-HS256' }
|
273
|
+
it_behaves_like :decryptable
|
274
|
+
it_behaves_like :verify_cbc_authentication_tag
|
275
|
+
end
|
276
|
+
|
277
|
+
context 'when enc=A256CBC-HS512' do
|
278
|
+
let(:enc) { :'A256CBC-HS512' }
|
279
|
+
it_behaves_like :decryptable
|
280
|
+
it_behaves_like :verify_cbc_authentication_tag
|
281
|
+
end
|
253
282
|
end
|
254
283
|
|
255
284
|
context 'when unknonw/unsupported algorithm given' do
|
data/spec/json/jwk_spec.rb
CHANGED
@@ -2,21 +2,38 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe JSON::JWK do
|
4
4
|
describe '#initialize' do
|
5
|
-
|
5
|
+
let(:jwk) { JSON::JWK.new key }
|
6
|
+
subject { jwk }
|
7
|
+
|
8
|
+
shared_examples_for :jwk_with_kid do
|
9
|
+
it { should be_instance_of JSON::JWK }
|
10
|
+
describe 'kid' do
|
11
|
+
subject { jwk[:kid] }
|
12
|
+
it { should == jwk.thumbprint }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
shared_examples_for :jwk_without_kid do
|
17
|
+
it { should be_instance_of JSON::JWK }
|
18
|
+
describe 'kid' do
|
19
|
+
subject { jwk[:kid] }
|
20
|
+
it { should be_blank }
|
21
|
+
end
|
22
|
+
end
|
6
23
|
|
7
24
|
context 'with OpenSSL::PKey::RSA' do
|
8
25
|
let(:key) { public_key }
|
9
|
-
|
26
|
+
it_behaves_like :jwk_with_kid
|
10
27
|
end
|
11
28
|
|
12
29
|
context 'with OpenSSL::PKey::EC' do
|
13
30
|
let(:key) { public_key :ecdsa }
|
14
|
-
|
31
|
+
it_behaves_like :jwk_with_kid
|
15
32
|
end
|
16
33
|
|
17
34
|
context 'with String' do
|
18
35
|
let(:key) { 'secret' }
|
19
|
-
|
36
|
+
it_behaves_like :jwk_with_kid
|
20
37
|
end
|
21
38
|
|
22
39
|
context 'with JSON::JWK' do
|
@@ -26,7 +43,7 @@ describe JSON::JWK do
|
|
26
43
|
kty: :oct
|
27
44
|
)
|
28
45
|
end
|
29
|
-
|
46
|
+
it_behaves_like :jwk_with_kid
|
30
47
|
end
|
31
48
|
|
32
49
|
context 'with Hash' do
|
@@ -36,7 +53,12 @@ describe JSON::JWK do
|
|
36
53
|
kty: :oct
|
37
54
|
}
|
38
55
|
end
|
39
|
-
|
56
|
+
it_behaves_like :jwk_with_kid
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'with nothing' do
|
60
|
+
let(:jwk) { JSON::JWK.new }
|
61
|
+
it_behaves_like :jwk_without_kid
|
40
62
|
end
|
41
63
|
end
|
42
64
|
|
data/spec/json/jws_spec.rb
CHANGED
data/spec/json/jwt_spec.rb
CHANGED
@@ -47,6 +47,72 @@ describe JSON::JWT do
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
context 'when no algirithm specified' do
|
52
|
+
subject { jwt.sign(key) }
|
53
|
+
|
54
|
+
context 'when key is String' do
|
55
|
+
let(:key) { shared_secret }
|
56
|
+
its(:alg) { should == :HS256 }
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'otherwise' do
|
60
|
+
let(:key) { private_key }
|
61
|
+
its(:alg) { should == :RS256 }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when non-JWK key is given' do
|
66
|
+
let(:key) { private_key }
|
67
|
+
it 'should not set kid header automatically' do
|
68
|
+
jws = jwt.sign(key, :RS256)
|
69
|
+
jws.kid.should be_blank
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'when JWK is given' do
|
74
|
+
let(:key) { JSON::JWK.new private_key }
|
75
|
+
it 'should set kid header automatically' do
|
76
|
+
jws = jwt.sign(key, :RS256)
|
77
|
+
jwt.kid.should be_blank
|
78
|
+
jws.kid.should == key[:kid]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'object copy behaviour' do
|
83
|
+
before do
|
84
|
+
@jwt = JSON::JWT.new(obj: {foo: :bar})
|
85
|
+
@jws = @jwt.sign('secret')
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when original JWT is modified' do
|
89
|
+
before do
|
90
|
+
@jwt.header[:x] = :x
|
91
|
+
@jwt[:obj][:x] = :x
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'copied JWS' do
|
95
|
+
it 'should be affected as shallow copy, but not as a simple reference' do
|
96
|
+
@jws.header.should_not include :x
|
97
|
+
@jws[:obj].should include :x
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'when copied JWS is modified' do
|
103
|
+
before do
|
104
|
+
@jws.header[:x] = :x
|
105
|
+
@jws[:obj][:x] = :x
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'original JWT' do
|
109
|
+
it 'should be affected as shallow copy, but not as a simple reference' do
|
110
|
+
@jwt.header.should_not include :x
|
111
|
+
@jwt[:obj].should include :x
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
50
116
|
end
|
51
117
|
|
52
118
|
describe '#encrypt' do
|
@@ -67,6 +133,23 @@ describe JSON::JWT do
|
|
67
133
|
it 'should accept optional algorithm and encryption method' do
|
68
134
|
jwt.encrypt(SecureRandom.hex(32), :dir, :'A256CBC-HS512').should be_a JSON::JWE
|
69
135
|
end
|
136
|
+
|
137
|
+
context 'when non-JWK key is given' do
|
138
|
+
let(:key) { shared_key }
|
139
|
+
it 'should not set kid header automatically' do
|
140
|
+
jwe = jwt.encrypt(key, :dir)
|
141
|
+
jwe.kid.should be_blank
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'when JWK is given' do
|
146
|
+
let(:key) { JSON::JWK.new shared_key }
|
147
|
+
it 'should set kid header automatically' do
|
148
|
+
jwe = jwt.encrypt(key, :dir)
|
149
|
+
jwt.kid.should be_blank
|
150
|
+
jwe.kid.should == key[:kid]
|
151
|
+
end
|
152
|
+
end
|
70
153
|
end
|
71
154
|
|
72
155
|
describe '.decode' do
|
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: 1.
|
4
|
+
version: 1.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nov matake
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|