json-jwt 1.2.2 → 1.2.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/README.md +73 -6
- data/VERSION +1 -1
- data/lib/json/jwk.rb +15 -9
- data/lib/json/jwk/jwkizable.rb +7 -1
- data/spec/json/jwk_spec.rb +71 -1
- data/spec/json/jws_spec.rb +81 -19
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1815ea41a4fd9ae6a1d6232259a7956ba070b713
|
4
|
+
data.tar.gz: 2efa46ef39b82e61e5d58817cd804eb3dd50d053
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3ecc9a34475f36916f12242f2293db9d9c5a0382619bf250ef1b5aa5650ae0030cfbcc533a56ebbd63a2f43e065f27322c4dc747fee850310f6d8ecab30ce93
|
7
|
+
data.tar.gz: e4c2d71d75053fc1357e1d0e88b9f88e048587d11189dfdb934e24f3a74b33f7e9dec885aeb1874ffff16609e4bcae15b893efd68d5e5cf6490a90771a4dd3e3
|
data/README.md
CHANGED
@@ -15,7 +15,9 @@ JSON Web Token and its family (JSON Web Signature, JSON Web Encryption and JSON
|
|
15
15
|
|
16
16
|
## Examples
|
17
17
|
|
18
|
-
###
|
18
|
+
### JWT, JWS and JWE
|
19
|
+
|
20
|
+
#### Encoding
|
19
21
|
|
20
22
|
```ruby
|
21
23
|
require 'json/jwt'
|
@@ -40,11 +42,38 @@ jwe = jws.encrypt(key, algorithm, encryption_method) # algorithm & encryption_me
|
|
40
42
|
jwe.to_s # => header.encrypted_key.iv.cipher_text.authentication_tag
|
41
43
|
```
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
Supported `key` are
|
46
|
+
* `String`
|
47
|
+
* `OpenSSL::PKey::RSA`
|
48
|
+
* `OpenSSL::PKey::EC`
|
49
|
+
* `JSON::JWK`
|
50
|
+
* `JSON::JWK::Set` # NOTE: proper `JSON::JWK` in the set will be selected by `kid` in the header.
|
51
|
+
|
52
|
+
Supported `algorithm` are
|
53
|
+
|
54
|
+
For JWS
|
55
|
+
* `HS256`
|
56
|
+
* `HS384`
|
57
|
+
* `HS512`
|
58
|
+
* `RS256`
|
59
|
+
* `RS384`
|
60
|
+
* `RS512`
|
61
|
+
* `ES256`
|
62
|
+
* `ES384`
|
63
|
+
* `ES512`
|
64
|
+
|
65
|
+
For JWE
|
66
|
+
* `RSA1_5`
|
67
|
+
* `RSA-OAEP`
|
68
|
+
* `dir`
|
69
|
+
|
70
|
+
Supported `encryption_method` are
|
71
|
+
* `A128GCM`
|
72
|
+
* `A256GCM`
|
73
|
+
* `A128CBC-HS256`
|
74
|
+
* `A256CBC-HS512`
|
75
|
+
|
76
|
+
#### Decoding
|
48
77
|
|
49
78
|
```ruby
|
50
79
|
jwt_string = "jwt_header.jwt_claims.jwt_signature"
|
@@ -52,6 +81,44 @@ jwt_string = "jwt_header.jwt_claims.jwt_signature"
|
|
52
81
|
JSON::JWT.decode(jwt_string, key)
|
53
82
|
```
|
54
83
|
|
84
|
+
### JWK
|
85
|
+
|
86
|
+
#### RSA
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
k = OpenSSL::PKey::RSA.new(2048)
|
90
|
+
p k.to_jwk
|
91
|
+
# => JSON::JWK
|
92
|
+
|
93
|
+
jwk = JSON::JWK.new(
|
94
|
+
kty: "RSA",
|
95
|
+
e: "AQAB",
|
96
|
+
n: "utwietJHu65N7kIa52bMkKgbS1CGmhKNDx3gTBEvQmQhg1BbKHfdmqapMt699T-aloeslYxeO9ItOhprnE0vG-pbDUE7Jg51gtK6kjpLFZOLNpRHJnRikyF6dav1IdJa4fSpOiEJiHk_DuFnAMI04_1H_NISn1TzEBflbyb6BSyIPkfO9433zR2-clvHdIXppq-N272vHA64Xp5hslzY91QodXo5--9iIblPVxzd9aH-aBMSkRbmlIKuz14tWhR-6RLNsWtqxWfKvgeoBLh5e9E5MrlNuRnaaLqHOMWrW1l9985eqmCD3PD4wjwINFKrU4L0fMBCHgCDAZLhbLfUJw",
|
97
|
+
d: "NtFBpDpwJNT7s7vc3KnBtWY7q5qSAj0S-K5REL-x1448bqNyOqr_bdEarfu-SmZAWYyvyqeFNZNxBSyfCRlzioLz9y19xqpTOu_LH_7N7CR-oKJbRSK7kGIv5Llvjl6BnuwBgTYT799x6lGhwA05KvEw3zBZmjh3ne8Etdj_W-i2LDBDUimgmVrgXWY1KvWFgh2zpptIINX2Q8UxV121bdcBIbj008Cs64m2mMpaa3ggqqNoXnYb8HnJDnYx-WIbUMHJ2-hpZAsVFNet8ZVEMt4cTKaTHY23m9Ditj-7VfFzkoiH9Yj45ewJMpcssadnAPrBgKbjTFuTdJfP8IqMoQ"
|
98
|
+
)
|
99
|
+
jwk.to_key
|
100
|
+
# => OpenSSL::PKey::RSA
|
101
|
+
```
|
102
|
+
|
103
|
+
#### EC
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
k = OpenSSL::PKey::RSA.new(2048)
|
107
|
+
k.to_jwk
|
108
|
+
# => JSON::JWK
|
109
|
+
|
110
|
+
jwk = JSON::JWK.new(
|
111
|
+
kty: "RSA",
|
112
|
+
e: "AQAB",
|
113
|
+
n: "0OIOijENzP0AXnxP-X8Dnazt3m4NTamfNsSCkH4xzgZAJj2Eur9-zmq9IukwN37lIrm3oAE6lL4ytNkv-DQpAivKLE8bh4c9qlB9o32VWyg-mg-2af-JlfGXYoaCW2GDMOV6EKqHBxE0x1EI0tG4gcNwO6A_kYtK6_ACgTQudWz_gnPrL-QCunjIMbbrK9JqgMZhgMARMQpB-j8oet2FFsEcquR5MWtBeAn7qC1AD2ya0EmzplZJP6oCka_VVuxAnyWfRGA0bzCBRIVbcGUXVNIXpRtA_4960e7AlGfMSA-ofN-vo7v0CMkA8BwpZHai9CAJ-cTCX1AVbov83LVIWw",
|
114
|
+
d: "BZCgNopMBdQPuHSzZMA_hmnfBHgGHrWQKlNd7x-NkCGWf-5PpPIJHNK3K0DvKetVi3FLNRYTS3ctvqeyoXgyR36HKlsJLrkpqWnvjvV_jygpUs1sXLKUJcyD7foLawfUCO90KxF_-24367967rLrqXldehkw2F3Ppy2Dw5FyU2qBqcpLeruBt6-UdMmBufzNQLisPJ67vhCTVrTNaHDDeCK2gHI3gqsnnbzOMS45VknmFOgKUp1C8GZu5BsT-AdDApEtY-DRZqnr6BxZv4-hG5OdEUA4_LCaI6JwlaAzv0Z74jpBZDC73cXWKJPgVuhARZcll5cexB2_EpgZDB6akQ",
|
115
|
+
p: "6GFVNgaXcW39NG-sRqKPzFtz1usfAkdCydPmfZirfHRhSh3OojX3Glbe7BI_SRSOLc2d2xw2_ZwKRlruY44aGEf4s5gD_nKgq2QS-1cA5uNAU91wRtY2rdoAuCnk2BX3WTZPnzyxkokFY0S0R_9IpJhRz72ggxYyhx0ymRUBIWc",
|
116
|
+
q: "5h1QX2JWLbcIT_cfrkmMoES1z06Fu88MLORYppiRDqkXl3CJFxKFtKJtDPLTf0MeTFexh81V52Ztsd8UttPInyDl9l5T0AOy8NmqHKqjI1063uy4bnHWetN7ovHftc_TOlnldAoQh9bmhZAhEyGlwa5Kros2YD2amIgDhcOmRO0"
|
117
|
+
)
|
118
|
+
jwk.to_key
|
119
|
+
# => OpenSSL::PKey::EC
|
120
|
+
```
|
121
|
+
|
55
122
|
## Note on Patches/Pull Requests
|
56
123
|
|
57
124
|
* Fork the project.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.2.
|
1
|
+
1.2.3
|
data/lib/json/jwk.rb
CHANGED
@@ -2,15 +2,19 @@ module JSON
|
|
2
2
|
class JWK < ActiveSupport::HashWithIndifferentAccess
|
3
3
|
class UnknownAlgorithm < JWT::Exception; end
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
def initialize(params = {}, ex_params = {})
|
6
|
+
case params
|
7
|
+
when OpenSSL::PKey::RSA, OpenSSL::PKey::EC
|
8
|
+
super params.to_jwk(ex_params)
|
9
|
+
when OpenSSL::PKey::PKey
|
10
|
+
raise UnknownAlgorithm.new('Unknown Key Type')
|
11
|
+
when String
|
12
|
+
super(
|
13
|
+
k: params,
|
14
|
+
kty: :oct
|
15
|
+
)
|
12
16
|
else
|
13
|
-
super
|
17
|
+
super params
|
14
18
|
merge! ex_params
|
15
19
|
end
|
16
20
|
end
|
@@ -88,7 +92,7 @@ module JSON
|
|
88
92
|
end
|
89
93
|
|
90
94
|
def to_rsa_key
|
91
|
-
e, n, d = [:e, :n, :d].collect do |key|
|
95
|
+
e, n, d, p, q = [:e, :n, :d, :p, :q].collect do |key|
|
92
96
|
if self[key]
|
93
97
|
OpenSSL::BN.new UrlSafeBase64.decode64(self[key]), 2
|
94
98
|
end
|
@@ -97,6 +101,8 @@ module JSON
|
|
97
101
|
key.e = e
|
98
102
|
key.n = n
|
99
103
|
key.d = d if d
|
104
|
+
key.p = p if p
|
105
|
+
key.q = q if q
|
100
106
|
key
|
101
107
|
end
|
102
108
|
|
data/lib/json/jwk/jwkizable.rb
CHANGED
@@ -8,7 +8,13 @@ module JSON
|
|
8
8
|
e: UrlSafeBase64.encode64(e.to_s(2)),
|
9
9
|
n: UrlSafeBase64.encode64(n.to_s(2))
|
10
10
|
}.merge ex_params
|
11
|
-
|
11
|
+
if private?
|
12
|
+
params.merge!(
|
13
|
+
d: UrlSafeBase64.encode64(d.to_s(2)),
|
14
|
+
p: UrlSafeBase64.encode64(p.to_s(2)),
|
15
|
+
q: UrlSafeBase64.encode64(q.to_s(2))
|
16
|
+
)
|
17
|
+
end
|
12
18
|
JWK.new params
|
13
19
|
end
|
14
20
|
end
|
data/spec/json/jwk_spec.rb
CHANGED
@@ -2,7 +2,42 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe JSON::JWK do
|
4
4
|
describe '#initialize' do
|
5
|
-
|
5
|
+
subject { JSON::JWK.new key }
|
6
|
+
|
7
|
+
context 'with OpenSSL::PKey::RSA' do
|
8
|
+
let(:key) { public_key }
|
9
|
+
it { should be_instance_of JSON::JWK }
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'with OpenSSL::PKey::EC' do
|
13
|
+
let(:key) { public_key :ecdsa }
|
14
|
+
it { should be_instance_of JSON::JWK }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'with String' do
|
18
|
+
let(:key) { 'secret' }
|
19
|
+
it { should be_instance_of JSON::JWK }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with JSON::JWK' do
|
23
|
+
let(:key) do
|
24
|
+
JSON::JWK.new(
|
25
|
+
k: 'secret',
|
26
|
+
kty: :oct
|
27
|
+
)
|
28
|
+
end
|
29
|
+
it { should be_instance_of JSON::JWK }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with Hash' do
|
33
|
+
let(:key) do
|
34
|
+
{
|
35
|
+
k: 'secret',
|
36
|
+
kty: :oct
|
37
|
+
}
|
38
|
+
end
|
39
|
+
it { should be_instance_of JSON::JWK }
|
40
|
+
end
|
6
41
|
end
|
7
42
|
|
8
43
|
describe '#content_type' do
|
@@ -85,6 +120,41 @@ describe JSON::JWK do
|
|
85
120
|
end
|
86
121
|
end
|
87
122
|
|
123
|
+
describe '#thumbprint' do
|
124
|
+
context 'when kty=RSA' do
|
125
|
+
subject do
|
126
|
+
JSON::JWK.new(
|
127
|
+
kty: :RSA,
|
128
|
+
e: 'AQAB',
|
129
|
+
n: '0OIOijENzP0AXnxP-X8Dnazt3m4NTamfNsSCkH4xzgZAJj2Eur9-zmq9IukwN37lIrm3oAE6lL4ytNkv-DQpAivKLE8bh4c9qlB9o32VWyg-mg-2af-JlfGXYoaCW2GDMOV6EKqHBxE0x1EI0tG4gcNwO6A_kYtK6_ACgTQudWz_gnPrL-QCunjIMbbrK9JqgMZhgMARMQpB-j8oet2FFsEcquR5MWtBeAn7qC1AD2ya0EmzplZJP6oCka_VVuxAnyWfRGA0bzCBRIVbcGUXVNIXpRtA_4960e7AlGfMSA-ofN-vo7v0CMkA8BwpZHai9CAJ-cTCX1AVbov83LVIWw'
|
130
|
+
)
|
131
|
+
end
|
132
|
+
its(:thumbprint) { should == 'fFn3D1P0H7Qo1ugQ-5LM6LC63LtArbkPsbQcs2F-1yA' }
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'when kty=EC' do
|
136
|
+
subject do
|
137
|
+
JSON::JWK.new(
|
138
|
+
kty: 'EC',
|
139
|
+
crv: 'P-256',
|
140
|
+
x: 'saPyrO4Lh9kh2FxrF9y1QVmZznWnRRJwpr12UHqzrVY',
|
141
|
+
y: 'MMz4W9zzqlrJhqr-JyrpvlnaIIyZQE6DfrgPkxMAw1M'
|
142
|
+
)
|
143
|
+
end
|
144
|
+
its(:thumbprint) { should == '-egRpLjyZCqxBh4OOfd8JSvXwayHmNFAUNkbi8exfhc' }
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'when kty=oct' do
|
148
|
+
subject do
|
149
|
+
JSON::JWK.new(
|
150
|
+
kty: 'oct',
|
151
|
+
k: 'secret'
|
152
|
+
)
|
153
|
+
end
|
154
|
+
its(:thumbprint) { should == 'XZPWsTEZFIerowAF9GHzBtq5CkAOcVvIBnkMu0IIQH0' }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
88
158
|
describe '.decode' do
|
89
159
|
context 'when RSA' do
|
90
160
|
subject do
|
data/spec/json/jws_spec.rb
CHANGED
@@ -55,25 +55,45 @@ describe JSON::JWS do
|
|
55
55
|
|
56
56
|
[:HS256, :HS384, :HS512].each do |algorithm|
|
57
57
|
describe algorithm do
|
58
|
-
let(:private_key_or_secret) { shared_secret }
|
59
58
|
let(:alg) { algorithm }
|
60
|
-
|
61
|
-
|
59
|
+
|
60
|
+
context 'when String key given' do
|
61
|
+
let(:private_key_or_secret) { shared_secret }
|
62
|
+
it_behaves_like :jwt_with_alg
|
63
|
+
it_behaves_like :generate_expected_signature
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when JSON::JWK key given' do
|
67
|
+
let(:private_key_or_secret) { JSON::JWK.new shared_secret }
|
68
|
+
it_behaves_like :jwt_with_alg
|
69
|
+
it_behaves_like :generate_expected_signature
|
70
|
+
end
|
62
71
|
end
|
63
72
|
end
|
64
73
|
|
65
74
|
[:RS256, :RS384, :RS512].each do |algorithm|
|
66
75
|
describe algorithm do
|
67
|
-
let(:private_key_or_secret) { private_key }
|
68
76
|
let(:alg) { algorithm }
|
69
|
-
|
70
|
-
|
77
|
+
|
78
|
+
context 'when OpenSSL::PKey::RSA key given' do
|
79
|
+
let(:private_key_or_secret) { private_key }
|
80
|
+
it_behaves_like :jwt_with_alg
|
81
|
+
it_behaves_like :generate_expected_signature
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when JSON::JWK key given' do
|
85
|
+
let(:private_key_or_secret) { JSON::JWK.new private_key }
|
86
|
+
it_behaves_like :jwt_with_alg
|
87
|
+
it_behaves_like :generate_expected_signature
|
88
|
+
end
|
71
89
|
end
|
90
|
+
end
|
72
91
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
92
|
+
[:ES256, :ES384, :ES512].each do |algorithm|
|
93
|
+
describe algorithm do
|
94
|
+
let(:alg) { algorithm }
|
95
|
+
|
96
|
+
shared_examples_for :self_verifiable do
|
77
97
|
it 'should be self-verifiable' do
|
78
98
|
expect do
|
79
99
|
JSON::JWT.decode(
|
@@ -84,9 +104,27 @@ describe JSON::JWS do
|
|
84
104
|
end.not_to raise_error
|
85
105
|
end
|
86
106
|
end
|
107
|
+
|
108
|
+
context 'when OpenSSL::PKey::EC key given' do
|
109
|
+
let(:private_key_or_secret) { private_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
110
|
+
let(:public_key_or_secret) { public_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
111
|
+
it_behaves_like :jwt_with_alg
|
112
|
+
it_behaves_like :self_verifiable
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'when JSON::JWK key given' do
|
116
|
+
let(:private_key_or_secret) { JSON::JWK.new(private_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i) }
|
117
|
+
let(:public_key_or_secret) { JSON::JWK.new(public_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i) }
|
118
|
+
it_behaves_like :jwt_with_alg
|
119
|
+
it_behaves_like :self_verifiable
|
120
|
+
end
|
87
121
|
end
|
88
122
|
end
|
89
123
|
|
124
|
+
context 'when JSON::JWK::Set key given' do
|
125
|
+
it :TODO
|
126
|
+
end
|
127
|
+
|
90
128
|
describe 'unknown algorithm' do
|
91
129
|
let(:alg) { :unknown }
|
92
130
|
it do
|
@@ -124,28 +162,52 @@ describe JSON::JWS do
|
|
124
162
|
|
125
163
|
[:HS256, :HS384, :HS512].each do |algorithm|
|
126
164
|
describe algorithm do
|
127
|
-
let(:private_key_or_secret) { shared_secret }
|
128
|
-
let(:public_key_or_secret) { shared_secret }
|
129
165
|
let(:alg) { algorithm }
|
130
|
-
|
166
|
+
let(:private_key_or_secret) { shared_secret }
|
167
|
+
|
168
|
+
context 'when String key given' do
|
169
|
+
let(:public_key_or_secret) { shared_secret }
|
170
|
+
it_behaves_like :success_signature_verification
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'when JSON::JWK key given' do
|
174
|
+
let(:public_key_or_secret) { JSON::JWK.new shared_secret }
|
175
|
+
it_behaves_like :success_signature_verification
|
176
|
+
end
|
131
177
|
end
|
132
178
|
end
|
133
179
|
|
134
180
|
[:RS256, :RS384, :RS512].each do |algorithm|
|
135
181
|
describe algorithm do
|
136
|
-
let(:private_key_or_secret) { private_key }
|
137
|
-
let(:public_key_or_secret) { public_key }
|
138
182
|
let(:alg) { algorithm }
|
139
|
-
|
183
|
+
let(:private_key_or_secret) { private_key }
|
184
|
+
|
185
|
+
context 'when OpenSSL::PKey::RSA key given' do
|
186
|
+
let(:public_key_or_secret) { public_key }
|
187
|
+
it_behaves_like :success_signature_verification
|
188
|
+
end
|
189
|
+
|
190
|
+
context 'when JSON::JWK key given' do
|
191
|
+
let(:public_key_or_secret) { JSON::JWK.new public_key }
|
192
|
+
it_behaves_like :success_signature_verification
|
193
|
+
end
|
140
194
|
end
|
141
195
|
end
|
142
196
|
|
143
197
|
[:ES256, :ES384, :ES512].each do |algorithm|
|
144
198
|
describe algorithm do
|
145
|
-
let(:private_key_or_secret) { private_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
146
|
-
let(:public_key_or_secret) { public_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
147
199
|
let(:alg) { algorithm }
|
148
|
-
|
200
|
+
let(:private_key_or_secret) { private_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
201
|
+
|
202
|
+
context 'when OpenSSL::PKey::EC key given' do
|
203
|
+
let(:public_key_or_secret) { public_key :ecdsa, digest_length: algorithm.to_s[2,3].to_i }
|
204
|
+
it_behaves_like :success_signature_verification
|
205
|
+
end
|
206
|
+
|
207
|
+
context 'when JSON::JWK key given' do
|
208
|
+
let(:public_key_or_secret) { JSON::JWK.new public_key(:ecdsa, digest_length: algorithm.to_s[2,3].to_i) }
|
209
|
+
it_behaves_like :success_signature_verification
|
210
|
+
end
|
149
211
|
end
|
150
212
|
end
|
151
213
|
|