json_web_token 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -0
- data/README.md +5 -3
- data/json_web_token.gemspec +1 -1
- data/lib/json_web_token.rb +2 -2
- data/lib/json_web_token/algorithm/ecdsa.rb +28 -13
- data/lib/json_web_token/algorithm/hmac.rb +26 -10
- data/lib/json_web_token/algorithm/rsa.rb +21 -9
- data/lib/json_web_token/format/base64_url.rb +19 -20
- data/lib/json_web_token/jwa.rb +30 -13
- data/lib/json_web_token/jws.rb +50 -23
- data/lib/json_web_token/jwt.rb +31 -12
- data/lib/json_web_token/util.rb +1 -1
- data/lib/json_web_token/version.rb +1 -1
- data/spec/json_web_token/algorithm/ecdsa_spec.rb +17 -17
- data/spec/json_web_token/algorithm/hmac_spec.rb +44 -45
- data/spec/json_web_token/algorithm/rsa_spec.rb +21 -23
- data/spec/json_web_token/jwa_spec.rb +16 -17
- data/spec/json_web_token/jws_spec.rb +40 -32
- data/spec/json_web_token/jwt_spec.rb +55 -45
- data/spec/json_web_token/util_spec.rb +6 -6
- data/spec/json_web_token_spec.rb +1 -1
- data/spec/support/plausible_jwt.rb +1 -1
- metadata +4 -3
data/lib/json_web_token/jwt.rb
CHANGED
@@ -1,32 +1,51 @@
|
|
1
1
|
require 'json_web_token/jws'
|
2
2
|
|
3
3
|
module JsonWebToken
|
4
|
+
# Encode claims for transmission as a JSON object that is used as the payload of a JSON Web
|
5
|
+
# Signature (JWS) structure, enabling the claims to be integrity protected with a Message
|
6
|
+
# Authentication Code (MAC), to be later verified
|
4
7
|
module Jwt
|
5
8
|
|
6
|
-
|
9
|
+
ALG_DEFAULT = 'HS256'
|
7
10
|
HEADER_DEFAULT = {
|
8
11
|
typ: 'JWT',
|
9
|
-
alg:
|
12
|
+
alg: ALG_DEFAULT
|
10
13
|
}
|
11
14
|
|
12
15
|
module_function
|
13
16
|
|
14
|
-
#
|
15
|
-
|
17
|
+
# @param claims [Hash] a collection of name/value pairs asserting information about a subject
|
18
|
+
# @param options [Hash] specify the desired signing algorithm and signing key
|
19
|
+
# (e.g String for Hmac | OpenSSL::PKey::RSA | OpenSSL::PKey::EC)
|
20
|
+
# @return [String] a JSON Web Token, representing digitally signed claims
|
21
|
+
# @example
|
22
|
+
# claims = {iss: 'joe', exp: 1300819380, 'http://example.com/is_root' => true}
|
23
|
+
# options = {alg: 'HS256', key: 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C'}
|
24
|
+
# Jwt.sign(claims, options)
|
25
|
+
# # => 'eyJhbGciOiJIUzI1NiJ9.cGF5bG9hZA.uVTaOdyzp_f4mT_hfzU8LnCzdmlVC4t2itHDEYUZym4'
|
26
|
+
# @see http://tools.ietf.org/html/rfc7519#section-7.1
|
27
|
+
def sign(claims, options = {})
|
16
28
|
message = validated_message(claims)
|
17
29
|
header = config_header(options)
|
18
|
-
return Jws.
|
19
|
-
Jws.
|
30
|
+
return Jws.unsecured_message(header, message) if header[:alg] == 'none'
|
31
|
+
Jws.sign(header, message, options[:key])
|
20
32
|
end
|
21
33
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
34
|
+
# @param jwt [String] a JSON Web Token
|
35
|
+
# @param options [Hash] specify the desired verifying algorithm and verifying key
|
36
|
+
# @return [Hash] a JWT claims set if the jwt verifies, or +{error: 'Invalid'}+ otherwise
|
37
|
+
# @example
|
38
|
+
# jwt = 'eyJhbGciOiJIUzI1NiJ9.cGF5bG9hZA.uVTaOdyzp_f4mT_hfzU8LnCzdmlVC4t2itHDEYUZym4'
|
39
|
+
# options = {alg: 'HS256', key: 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C'}
|
40
|
+
# Jwt.verify(jwt, options)
|
41
|
+
# # => {iss: 'joe', exp: 1300819380, 'http://example.com/is_root' => true}
|
42
|
+
# @see see http://tools.ietf.org/html/rfc7519#section-7.2
|
43
|
+
def verify(jwt, options = {})
|
44
|
+
alg = options[:alg] || ALG_DEFAULT
|
45
|
+
jws = Jws.verify(jwt, alg, options[:key])
|
46
|
+
jws ? Util.symbolize_keys(decoded_message_json_to_hash jws) : {error: 'invalid'}
|
26
47
|
end
|
27
48
|
|
28
|
-
# private
|
29
|
-
|
30
49
|
def validated_message(claims)
|
31
50
|
fail('Claims blank') if !claims || claims.empty?
|
32
51
|
claims.to_json
|
data/lib/json_web_token/util.rb
CHANGED
@@ -4,7 +4,7 @@ module JsonWebToken
|
|
4
4
|
module_function
|
5
5
|
|
6
6
|
# https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-3.2
|
7
|
-
def constant_time_compare(a, b)
|
7
|
+
def constant_time_compare?(a, b)
|
8
8
|
return false if a.nil? || b.nil? || a.empty? || b.empty?
|
9
9
|
secure_compare(a, b)
|
10
10
|
end
|
@@ -4,51 +4,51 @@ require 'support/ecdsa_key'
|
|
4
4
|
module JsonWebToken
|
5
5
|
module Algorithm
|
6
6
|
describe Ecdsa do
|
7
|
+
let(:signing_input_0) { '{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}' }
|
8
|
+
let(:signing_input_1) { '{"iss":"mike","exp":1300819380,"http://example.com/is_root":false}' }
|
7
9
|
describe 'detect changed signature or data' do
|
8
|
-
|
9
|
-
|
10
|
-
shared_examples_for '#signed' do
|
11
|
-
it 'is #verified?' do
|
10
|
+
shared_examples_for '#sign' do
|
11
|
+
it 'does #verify?' do
|
12
12
|
private_key_0 = EcdsaKey.curve_new(sha_bits)
|
13
13
|
public_key_str_0 = EcdsaKey.public_key_str(private_key_0)
|
14
14
|
public_key_0 = EcdsaKey.public_key_new(sha_bits, public_key_str_0)
|
15
15
|
|
16
|
-
mac_0 = Ecdsa.
|
16
|
+
mac_0 = Ecdsa.sign(sha_bits, private_key_0, signing_input_0)
|
17
17
|
expect(mac_0.bytes.count).to eql expected_mac_byte_count
|
18
|
-
expect(Ecdsa.
|
18
|
+
expect(Ecdsa.verify? mac_0, sha_bits, public_key_0, signing_input_0).to be true
|
19
19
|
|
20
20
|
private_key_1 = EcdsaKey.curve_new(sha_bits)
|
21
21
|
public_key_str_1 = EcdsaKey.public_key_str(private_key_1)
|
22
22
|
public_key_1 = EcdsaKey.public_key_new(sha_bits, public_key_str_1)
|
23
23
|
|
24
|
-
expect(Ecdsa.
|
25
|
-
expect(Ecdsa.
|
26
|
-
expect(Ecdsa.
|
24
|
+
expect(Ecdsa.verify? mac_0, sha_bits, public_key_0, signing_input_1).to be false
|
25
|
+
expect(Ecdsa.verify? mac_0, sha_bits, public_key_1, signing_input_0).to be false
|
26
|
+
expect(Ecdsa.verify? mac_0, sha_bits, public_key_1, signing_input_1).to be false
|
27
27
|
|
28
|
-
mac_1 = Ecdsa.
|
29
|
-
expect(Ecdsa.
|
30
|
-
expect(Ecdsa.
|
31
|
-
expect(Ecdsa.
|
32
|
-
expect(Ecdsa.
|
28
|
+
mac_1 = Ecdsa.sign(sha_bits, private_key_1, signing_input_1)
|
29
|
+
expect(Ecdsa.verify? mac_1, sha_bits, public_key_0, signing_input_0).to be false
|
30
|
+
expect(Ecdsa.verify? mac_1, sha_bits, public_key_0, signing_input_1).to be false
|
31
|
+
expect(Ecdsa.verify? mac_1, sha_bits, public_key_1, signing_input_0).to be false
|
32
|
+
expect(Ecdsa.verify? mac_1, sha_bits, public_key_1, signing_input_1).to be true
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
describe 'ES256' do
|
37
37
|
let(:sha_bits) { '256' }
|
38
38
|
let(:expected_mac_byte_count) { 64 }
|
39
|
-
it_behaves_like '#
|
39
|
+
it_behaves_like '#sign'
|
40
40
|
end
|
41
41
|
|
42
42
|
describe 'ES384' do
|
43
43
|
let(:sha_bits) { '384' }
|
44
44
|
let(:expected_mac_byte_count) { 96 }
|
45
|
-
it_behaves_like '#
|
45
|
+
it_behaves_like '#sign'
|
46
46
|
end
|
47
47
|
|
48
48
|
describe 'ES512' do
|
49
49
|
let(:sha_bits) { '512' }
|
50
50
|
let(:expected_mac_byte_count) { 132 }
|
51
|
-
it_behaves_like '#
|
51
|
+
it_behaves_like '#sign'
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -3,80 +3,79 @@ require 'json_web_token/algorithm/hmac'
|
|
3
3
|
module JsonWebToken
|
4
4
|
module Algorithm
|
5
5
|
describe Hmac do
|
6
|
+
let(:signing_input_0) { '{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}' }
|
7
|
+
let(:signing_input_1) { '{"iss":"mike","exp":1300819380,"http://example.com/is_root":false}' }
|
6
8
|
context 'detect changed signing_input or MAC' do
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
mac
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
changed_mac = Hmac.signed(sha_bits, key, changed_signing_input)
|
16
|
-
expect(Hmac.verified? changed_mac, sha_bits, key, signing_input).to be false
|
9
|
+
shared_examples_for '#sign' do
|
10
|
+
it 'does #verify?' do
|
11
|
+
mac = Hmac.sign(sha_bits, shared_key, signing_input_0)
|
12
|
+
expect(Hmac.verify? mac, sha_bits, shared_key, signing_input_0).to be true
|
13
|
+
expect(Hmac.verify? mac, sha_bits, shared_key, signing_input_1).to be false
|
14
|
+
|
15
|
+
changed_mac = Hmac.sign(sha_bits, shared_key, signing_input_1)
|
16
|
+
expect(Hmac.verify? changed_mac, sha_bits, shared_key, signing_input_0).to be false
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
describe 'HS256' do
|
21
21
|
let(:sha_bits) { '256' }
|
22
|
-
let(:
|
23
|
-
it_behaves_like '#
|
22
|
+
let(:shared_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C' }
|
23
|
+
it_behaves_like '#sign'
|
24
24
|
end
|
25
25
|
|
26
26
|
describe 'HS384' do
|
27
27
|
let(:sha_bits) { '384' }
|
28
|
-
let(:
|
29
|
-
it_behaves_like '#
|
28
|
+
let(:shared_key) { 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS' }
|
29
|
+
it_behaves_like '#sign'
|
30
30
|
end
|
31
31
|
|
32
32
|
describe 'HS512' do
|
33
33
|
let(:sha_bits) { '512' }
|
34
|
-
let(:
|
35
|
-
it_behaves_like '#
|
34
|
+
let(:shared_key) { 'ysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hc' }
|
35
|
+
it_behaves_like '#sign'
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
describe 'changed key' do
|
40
40
|
let(:sha_bits) { '256' }
|
41
|
-
let(:
|
41
|
+
let(:shared_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C' }
|
42
42
|
let(:changed_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9Z' }
|
43
|
-
|
44
|
-
|
45
|
-
mac
|
46
|
-
expect(Hmac.
|
47
|
-
expect(Hmac.verified? mac, sha_bits, changed_key, data).to be false
|
43
|
+
it 'fails to #verify?' do
|
44
|
+
mac = Hmac.sign(sha_bits, shared_key, signing_input_0)
|
45
|
+
expect(Hmac.verify? mac, sha_bits, shared_key, signing_input_0).to be true
|
46
|
+
expect(Hmac.verify? mac, sha_bits, changed_key, signing_input_0).to be false
|
48
47
|
end
|
49
48
|
end
|
50
49
|
|
51
50
|
context 'param validation' do
|
52
|
-
let(:data) { 'data' }
|
53
51
|
shared_examples_for 'invalid key' do
|
54
52
|
it 'raises' do
|
55
|
-
expect { Hmac.
|
53
|
+
expect { Hmac.sign(sha_bits, shared_key, signing_input_0) }
|
54
|
+
.to raise_error(RuntimeError, 'Invalid shared key')
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
59
58
|
context 'w 256 sha_bits' do
|
60
59
|
let(:sha_bits) { '256' }
|
61
|
-
describe '
|
62
|
-
let(:
|
60
|
+
describe 'shared_key nil' do
|
61
|
+
let(:shared_key) { nil }
|
63
62
|
it_behaves_like 'invalid key'
|
64
63
|
end
|
65
64
|
|
66
|
-
describe "
|
67
|
-
let(:
|
65
|
+
describe "shared_key 'empty string'" do
|
66
|
+
let(:shared_key) { '' }
|
68
67
|
it_behaves_like 'invalid key'
|
69
68
|
end
|
70
69
|
|
71
|
-
describe '
|
72
|
-
let(:
|
70
|
+
describe 'shared_key length (31) < MAC length (32)' do
|
71
|
+
let(:shared_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9' }
|
73
72
|
it_behaves_like 'invalid key'
|
74
73
|
end
|
75
74
|
|
76
|
-
describe '
|
77
|
-
let(:
|
75
|
+
describe 'shared_key length (32) == MAC length (32)' do
|
76
|
+
let(:shared_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C' }
|
78
77
|
it 'returns a 32-byte MAC string' do
|
79
|
-
mac = Hmac.
|
78
|
+
mac = Hmac.sign(sha_bits, shared_key, signing_input_0)
|
80
79
|
expect(mac.bytesize).to eql 32
|
81
80
|
end
|
82
81
|
end
|
@@ -84,15 +83,15 @@ module JsonWebToken
|
|
84
83
|
|
85
84
|
context 'w 384 sha_bits' do
|
86
85
|
let(:sha_bits) { '384' }
|
87
|
-
describe '
|
88
|
-
let(:
|
86
|
+
describe 'shared_key length (47) < MAC length (48)' do
|
87
|
+
let(:shared_key) { 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1q' }
|
89
88
|
it_behaves_like 'invalid key'
|
90
89
|
end
|
91
90
|
|
92
|
-
describe '
|
93
|
-
let(:
|
91
|
+
describe 'shared_key length (48) == MAC length (48)' do
|
92
|
+
let(:shared_key) { 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS' }
|
94
93
|
it 'returns a 48-byte MAC string' do
|
95
|
-
mac = Hmac.
|
94
|
+
mac = Hmac.sign(sha_bits, shared_key, signing_input_0)
|
96
95
|
expect(mac.bytesize).to eql 48
|
97
96
|
end
|
98
97
|
end
|
@@ -100,15 +99,15 @@ module JsonWebToken
|
|
100
99
|
|
101
100
|
context 'w 512 sha_bits' do
|
102
101
|
let(:sha_bits) { '512' }
|
103
|
-
describe '
|
104
|
-
let(:
|
102
|
+
describe 'shared_key length (63) < MAC length (64)' do
|
103
|
+
let(:shared_key) { 'ysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4h' }
|
105
104
|
it_behaves_like 'invalid key'
|
106
105
|
end
|
107
106
|
|
108
|
-
describe '
|
109
|
-
let(:
|
107
|
+
describe 'shared_key length (64) == MAC length (64)' do
|
108
|
+
let(:shared_key) { 'ysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hc' }
|
110
109
|
it 'returns a 64-byte MAC string' do
|
111
|
-
mac = Hmac.
|
110
|
+
mac = Hmac.sign(sha_bits, shared_key, signing_input_0)
|
112
111
|
expect(mac.bytesize).to eql 64
|
113
112
|
end
|
114
113
|
end
|
@@ -116,9 +115,9 @@ module JsonWebToken
|
|
116
115
|
|
117
116
|
describe 'w unrecognized sha_bits' do
|
118
117
|
let(:sha_bits) { '257' }
|
119
|
-
let(:
|
118
|
+
let(:shared_key) { 'ysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hc' }
|
120
119
|
it 'raises' do
|
121
|
-
expect { Hmac.
|
120
|
+
expect { Hmac.sign(sha_bits, shared_key, signing_input_0) }
|
122
121
|
.to raise_error(RuntimeError, 'Invalid sha_bits')
|
123
122
|
end
|
124
123
|
end
|
@@ -3,53 +3,51 @@ require 'json_web_token/algorithm/rsa'
|
|
3
3
|
module JsonWebToken
|
4
4
|
module Algorithm
|
5
5
|
describe Rsa do
|
6
|
+
let(:signing_input_0) { '{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}' }
|
7
|
+
let(:signing_input_1) { '{"iss":"mike","exp":1300819380,"http://example.com/is_root":false}' }
|
6
8
|
context 'detect changed signing_input or MAC' do
|
7
9
|
let(:private_key) { OpenSSL::PKey::RSA.generate(Rsa::KEY_BITS_MIN) }
|
8
10
|
let(:public_key) { private_key.public_key }
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
mac
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
changed_mac = Rsa.signed(sha_bits, private_key, changed_signing_input)
|
18
|
-
expect(Rsa.verified? changed_mac, sha_bits, public_key, signing_input).to be false
|
11
|
+
shared_examples_for '#sign' do
|
12
|
+
it 'does #verify?' do
|
13
|
+
mac = Rsa.sign(sha_bits, private_key, signing_input_0)
|
14
|
+
expect(Rsa.verify? mac, sha_bits, public_key, signing_input_0).to be true
|
15
|
+
expect(Rsa.verify? mac, sha_bits, public_key, signing_input_1).to be false
|
16
|
+
|
17
|
+
changed_mac = Rsa.sign(sha_bits, private_key, signing_input_1)
|
18
|
+
expect(Rsa.verify? changed_mac, sha_bits, public_key, signing_input_0).to be false
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
context 'RS256' do
|
23
23
|
let(:sha_bits) { '256' }
|
24
|
-
it_behaves_like '#
|
24
|
+
it_behaves_like '#sign'
|
25
25
|
|
26
26
|
describe 'changed key' do
|
27
27
|
let(:changed_public_key) { OpenSSL::PKey::RSA.generate(Rsa::KEY_BITS_MIN).public_key }
|
28
|
-
|
29
|
-
|
30
|
-
mac
|
31
|
-
expect(Rsa.
|
32
|
-
expect(Rsa.verified? mac, sha_bits, changed_public_key, data).to be false
|
28
|
+
it 'fails to #verify?' do
|
29
|
+
mac = Rsa.sign(sha_bits, private_key, signing_input_0)
|
30
|
+
expect(Rsa.verify? mac, sha_bits, public_key, signing_input_0).to be true
|
31
|
+
expect(Rsa.verify? mac, sha_bits, changed_public_key, signing_input_0).to be false
|
33
32
|
end
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
37
36
|
describe 'RS384' do
|
38
37
|
let(:sha_bits) { '384' }
|
39
|
-
it_behaves_like '#
|
38
|
+
it_behaves_like '#sign'
|
40
39
|
end
|
41
40
|
|
42
41
|
describe 'RS512' do
|
43
42
|
let(:sha_bits) { '512' }
|
44
|
-
it_behaves_like '#
|
43
|
+
it_behaves_like '#sign'
|
45
44
|
end
|
46
45
|
end
|
47
46
|
|
48
47
|
context 'param validation' do
|
49
|
-
let(:data) { 'data' }
|
50
48
|
shared_examples_for 'invalid private_key' do
|
51
49
|
it 'raises' do
|
52
|
-
expect { Rsa.
|
50
|
+
expect { Rsa.sign(sha_bits, private_key, signing_input_0) }.to raise_error(RuntimeError, 'Invalid private key')
|
53
51
|
end
|
54
52
|
end
|
55
53
|
|
@@ -73,7 +71,7 @@ module JsonWebToken
|
|
73
71
|
|
74
72
|
shared_examples_for '2048 bit private_key' do
|
75
73
|
it 'returns a 256-byte MAC string' do
|
76
|
-
mac = Rsa.
|
74
|
+
mac = Rsa.sign(sha_bits, private_key, signing_input_0)
|
77
75
|
expect(mac.bytesize).to eql 256
|
78
76
|
end
|
79
77
|
end
|
@@ -106,7 +104,7 @@ module JsonWebToken
|
|
106
104
|
describe 'empty string' do
|
107
105
|
let(:private_key) { '' }
|
108
106
|
it 'raises' do
|
109
|
-
expect { Rsa.
|
107
|
+
expect { Rsa.sign(sha_bits, private_key, signing_input_0) }.to raise_error(NoMethodError)
|
110
108
|
end
|
111
109
|
end
|
112
110
|
end
|
@@ -115,7 +113,7 @@ module JsonWebToken
|
|
115
113
|
let(:sha_bits) { '257' }
|
116
114
|
let(:private_key) { 'private_key' }
|
117
115
|
it 'raises' do
|
118
|
-
expect { Rsa.
|
116
|
+
expect { Rsa.sign(sha_bits, private_key, signing_input_0) }
|
119
117
|
.to raise_error(RuntimeError, 'Invalid sha_bits')
|
120
118
|
end
|
121
119
|
end
|
@@ -3,19 +3,19 @@ require 'support/ecdsa_key'
|
|
3
3
|
|
4
4
|
module JsonWebToken
|
5
5
|
describe Jwa do
|
6
|
-
|
6
|
+
let(:signing_input) { '{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}' }
|
7
|
+
shared_examples_for 'w #verify?' do
|
7
8
|
it 'true' do
|
8
|
-
expect(Jwa.
|
9
|
+
expect(Jwa.verify? mac, algorithm, verifying_key, signing_input).to be true
|
9
10
|
end
|
10
11
|
end
|
11
|
-
context '#
|
12
|
-
let(:
|
13
|
-
let(:mac) { Jwa.signed(algorithm, private_key, signing_input) }
|
12
|
+
context '#sign' do
|
13
|
+
let(:mac) { Jwa.sign(algorithm, signing_key, signing_input) }
|
14
14
|
describe 'HS256' do
|
15
15
|
let(:algorithm) { 'HS256' }
|
16
|
-
let(:
|
17
|
-
let(:verifying_key) {
|
18
|
-
it_behaves_like 'w #
|
16
|
+
let(:signing_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C' }
|
17
|
+
let(:verifying_key) { signing_key }
|
18
|
+
it_behaves_like 'w #verify?'
|
19
19
|
|
20
20
|
it 'returns a 32-byte MAC' do
|
21
21
|
expect(mac.bytesize).to eql 32
|
@@ -24,9 +24,9 @@ module JsonWebToken
|
|
24
24
|
|
25
25
|
describe 'RS256' do
|
26
26
|
let(:algorithm) { 'RS256' }
|
27
|
-
let(:
|
28
|
-
let(:verifying_key) {
|
29
|
-
it_behaves_like 'w #
|
27
|
+
let(:signing_key) { OpenSSL::PKey::RSA.generate(2048) }
|
28
|
+
let(:verifying_key) { signing_key.public_key }
|
29
|
+
it_behaves_like 'w #verify?'
|
30
30
|
|
31
31
|
it 'returns a 256-byte MAC' do
|
32
32
|
expect(mac.bytesize).to eql 256
|
@@ -35,13 +35,13 @@ module JsonWebToken
|
|
35
35
|
|
36
36
|
describe 'ES256' do
|
37
37
|
let(:algorithm) { 'ES256' }
|
38
|
-
it 'w #
|
38
|
+
it 'w #verify? true, returns a 64-byte MAC' do
|
39
39
|
private_key = EcdsaKey.curve_new('256')
|
40
40
|
public_key_str = EcdsaKey.public_key_str(private_key)
|
41
41
|
public_key = EcdsaKey.public_key_new('256', public_key_str)
|
42
42
|
|
43
|
-
mac = Jwa.
|
44
|
-
expect(Jwa.
|
43
|
+
mac = Jwa.sign(algorithm, private_key, signing_input)
|
44
|
+
expect(Jwa.verify? mac, algorithm, public_key, signing_input).to be true
|
45
45
|
|
46
46
|
expect(mac.bytesize).to eql 64
|
47
47
|
end
|
@@ -49,14 +49,13 @@ module JsonWebToken
|
|
49
49
|
end
|
50
50
|
|
51
51
|
context 'param validation' do
|
52
|
-
let(:data) { 'data' }
|
53
52
|
context 'w HS256 key' do
|
54
|
-
let(:
|
53
|
+
let(:shared_key) { 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C' }
|
55
54
|
describe 'unrecognized algorithm' do
|
56
55
|
['HT256', 'HS257', '', nil].each do |elt|
|
57
56
|
let(:algorithm) { "#{elt}" }
|
58
57
|
it 'raises' do
|
59
|
-
expect { Jwa.
|
58
|
+
expect { Jwa.sign(algorithm, shared_key, signing_input) }
|
60
59
|
.to raise_error(RuntimeError, 'Unrecognized algorithm')
|
61
60
|
end
|
62
61
|
end
|