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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 973c4dc365edec01a991491309d0332b3898dd57
|
4
|
+
data.tar.gz: 05d71d73011230c2b2f074eed6d2ea86bf0be1cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 640c8738d52377295275bc4c5498b02a7fd427ffdf2b8d14b5765acc90fd8868c401799f0ccbb0535d37143ee90138ff5f80621edee6c902344106a5f1727786
|
7
|
+
data.tar.gz: fa2e818be12da6b351eb202b4ca2de9ab0efdd48f789d1e61e2e3683ae7fa9f50026e716d69578eb2c850266f72b5cc6bac4c94d570148cd4194d06ceb67b49f
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# JSON Web Token [![travis][ci_img]][travis] [![
|
1
|
+
# JSON Web Token [![travis][ci_img]][travis] [![yard docs][yd_img]][yard_docs] [![code climate][cc_img]][code_climate]
|
2
2
|
|
3
3
|
## A JSON Web Token implementation for Ruby
|
4
4
|
|
@@ -36,7 +36,7 @@ Returns a JSON Web Token string
|
|
36
36
|
|
37
37
|
`claims` (required) string or hash
|
38
38
|
|
39
|
-
`options` (
|
39
|
+
`options` (required) hash
|
40
40
|
|
41
41
|
* **alg** (optional, default: `HS256`)
|
42
42
|
* **key** (required unless alg is 'none')
|
@@ -70,7 +70,7 @@ Returns either:
|
|
70
70
|
|
71
71
|
`jwt` (required) is a JSON web token string
|
72
72
|
|
73
|
-
`options` (
|
73
|
+
`options` (required) hash
|
74
74
|
|
75
75
|
* **alg** (optional, default: `HS256`)
|
76
76
|
* **key** (required unless alg is 'none')
|
@@ -141,5 +141,7 @@ Future implementation may include these features:
|
|
141
141
|
|
142
142
|
[travis]: https://travis-ci.org/garyf/json_web_token
|
143
143
|
[ci_img]: https://travis-ci.org/garyf/json_web_token.svg?branch=master
|
144
|
+
[yard_docs]: http://www.rubydoc.info/gems/json_web_token
|
145
|
+
[yd_img]: http://img.shields.io/badge/yard-docs-blue.svg
|
144
146
|
[code_climate]: https://codeclimate.com/github/garyf/json_web_token
|
145
147
|
[cc_img]: https://codeclimate.com/github/garyf/json_web_token/badges/gpa.svg
|
data/json_web_token.gemspec
CHANGED
@@ -16,6 +16,6 @@ Gem::Specification.new do |s|
|
|
16
16
|
# optional
|
17
17
|
s.add_runtime_dependency 'json', '~> 1.8', '>= 1.8.3'
|
18
18
|
s.add_development_dependency 'rspec', '~> 3.3'
|
19
|
-
s.description = 'Ruby implementation of the JSON Web Token
|
19
|
+
s.description = 'Ruby implementation of the JSON Web Token standard, RFC 7519'
|
20
20
|
s.required_ruby_version = '>= 2.0.0'
|
21
21
|
end
|
data/lib/json_web_token.rb
CHANGED
@@ -3,6 +3,8 @@ require 'json_web_token/format/asn1'
|
|
3
3
|
|
4
4
|
module JsonWebToken
|
5
5
|
module Algorithm
|
6
|
+
# Sign or verify a JSON Web Signature (JWS) structure using EDCSA
|
7
|
+
# @see http://tools.ietf.org/html/rfc7518#section-3.4
|
6
8
|
module Ecdsa
|
7
9
|
|
8
10
|
extend JsonWebToken::Algorithm::Common
|
@@ -16,30 +18,43 @@ module JsonWebToken
|
|
16
18
|
|
17
19
|
module_function
|
18
20
|
|
19
|
-
|
21
|
+
# @param sha_bits [String] desired security level in bits of the signature scheme
|
22
|
+
# @param private_key [OpenSSL::PKey::EC] key used to sign a digital signature, or mac
|
23
|
+
# @param signing_input [String] input payload for a mac computation
|
24
|
+
# @return [BinaryString] a digital signature, or mac
|
25
|
+
# @example
|
26
|
+
# Ecdsa.sign('256', private_key, 'signing_input').bytes
|
27
|
+
# # => [90, 34, 44, 252, 147, 130, 167, 173, 86, 191, 247, 93, 94, 12, 200, 30, 173, 115, 248, 89, 246, 222, 4, 213, 119, 74, 70, 20, 231, 194, 104, 103]
|
28
|
+
def sign(sha_bits, private_key, signing_input)
|
20
29
|
validate_key(private_key, sha_bits)
|
21
|
-
der = private_key.dsa_sign_asn1(ssl_digest_hash sha_bits,
|
30
|
+
der = private_key.dsa_sign_asn1(ssl_digest_hash sha_bits, signing_input)
|
22
31
|
der_to_signature(der, sha_bits)
|
23
32
|
end
|
24
33
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
34
|
+
# @param mac [BinaryString] a digital signature, or mac
|
35
|
+
# @param sha_bits [String] desired security level in bits of the signature scheme
|
36
|
+
# @param public_key [OpenSSL::PKey::EC] key used to verify a digital signature, or mac
|
37
|
+
# @param signing_input [String] input payload for a mac computation
|
38
|
+
# @return [Boolean] a predicate to verify the signing_input for a given +mac+
|
39
|
+
# @example
|
40
|
+
# Ecdsa.verify?(< binary_string >, '256', < public_key >, 'signing_input')
|
41
|
+
# # => true
|
42
|
+
def verify?(mac, sha_bits, public_key, signing_input)
|
43
|
+
validate_key(public_key, sha_bits)
|
44
|
+
validate_signature_size(mac, sha_bits)
|
45
|
+
der = signature_to_der(mac, sha_bits)
|
46
|
+
public_key.dsa_verify_asn1(ssl_digest_hash(sha_bits, signing_input), der)
|
30
47
|
end
|
31
48
|
|
32
|
-
# private
|
33
|
-
|
34
49
|
def validate_key_size(_key, _sha_bits); end
|
35
50
|
|
36
|
-
def ssl_digest_hash(sha_bits,
|
37
|
-
digest_new(sha_bits).digest(
|
51
|
+
def ssl_digest_hash(sha_bits, signing_input)
|
52
|
+
digest_new(sha_bits).digest(signing_input)
|
38
53
|
end
|
39
54
|
|
40
|
-
def validate_signature_size(
|
55
|
+
def validate_signature_size(mac, sha_bits)
|
41
56
|
n = MAC_BYTE_COUNT[sha_bits]
|
42
|
-
fail('Invalid signature') unless
|
57
|
+
fail('Invalid signature') unless mac && mac.bytesize == n
|
43
58
|
end
|
44
59
|
|
45
60
|
private_class_method :validate_key_size,
|
@@ -3,27 +3,43 @@ require 'json_web_token/util'
|
|
3
3
|
|
4
4
|
module JsonWebToken
|
5
5
|
module Algorithm
|
6
|
+
# Sign or verify a JSON Web Signature (JWS) structure using HMAC with SHA-2 algorithms
|
7
|
+
# @see http://tools.ietf.org/html/rfc7518#section-3.2
|
6
8
|
module Hmac
|
7
9
|
|
8
10
|
extend JsonWebToken::Algorithm::Common
|
9
11
|
|
10
12
|
module_function
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
# @param sha_bits [String] size of the hash output
|
15
|
+
# @param shared_key [String] secret key used to sign and verify a digital signature, or mac
|
16
|
+
# @param signing_input [String] input payload for a mac computation
|
17
|
+
# @return [BinaryString] a digital signature, or mac
|
18
|
+
# @example
|
19
|
+
# shared_key = "gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C"
|
20
|
+
# Hmac.sign('256', shared_key, 'signing_input').bytes
|
21
|
+
# # => [90, 34, 44, 252, 147, 130, 167, 173, 86, 191, 247, 93, 94, 12, 200, 30, 173, 115, 248, 89, 246, 222, 4, 213, 119, 74, 70, 20, 231, 194, 104, 103]
|
22
|
+
def sign(sha_bits, shared_key, signing_input)
|
23
|
+
validate_key(shared_key, sha_bits)
|
24
|
+
OpenSSL::HMAC.digest(digest_new(sha_bits), shared_key, signing_input)
|
15
25
|
end
|
16
26
|
|
17
|
-
|
18
|
-
|
19
|
-
|
27
|
+
# @param mac [BinaryString] a digital signature, or mac
|
28
|
+
# @param (see #sign)
|
29
|
+
# @return [Boolean] a predicate to verify the signing_input by comparing a given +mac+
|
30
|
+
# to the +mac+ for a newly signed message; comparison done in a constant-time manner
|
31
|
+
# to thwart timing attacks
|
32
|
+
# @example
|
33
|
+
# shared_key = "gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C"
|
34
|
+
# Hmac.verify?(< binary_string >, '256', shared_key, 'signing_input')
|
35
|
+
# # => true
|
36
|
+
def verify?(mac, sha_bits, shared_key, signing_input)
|
37
|
+
validate_key(shared_key, sha_bits)
|
38
|
+
Util.constant_time_compare?(mac, sign(sha_bits, shared_key, signing_input))
|
20
39
|
end
|
21
40
|
|
22
|
-
# private
|
23
|
-
|
24
|
-
# http://tools.ietf.org/html/rfc7518#section-3.2
|
25
41
|
def validate_key_size(key, sha_bits)
|
26
|
-
fail('Invalid key') unless key && key.bytesize * 8 >= sha_bits.to_i
|
42
|
+
fail('Invalid shared key') unless key && key.bytesize * 8 >= sha_bits.to_i
|
27
43
|
end
|
28
44
|
|
29
45
|
private_class_method :validate_key_size
|
@@ -2,6 +2,8 @@ require 'json_web_token/algorithm/common'
|
|
2
2
|
|
3
3
|
module JsonWebToken
|
4
4
|
module Algorithm
|
5
|
+
# Sign or verify a JSON Web Signature (JWS) structure using RSASSA-PKCS-v1_5
|
6
|
+
# @see http://tools.ietf.org/html/rfc7518#section-3.3
|
5
7
|
module Rsa
|
6
8
|
|
7
9
|
extend JsonWebToken::Algorithm::Common
|
@@ -10,19 +12,29 @@ module JsonWebToken
|
|
10
12
|
|
11
13
|
module_function
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
# @param sha_bits [String] desired security level in bits of the signature scheme
|
16
|
+
# @param private_key [OpenSSL::PKey::RSA] key used to sign a digital signature, or mac
|
17
|
+
# @param signing_input [String] input payload for a mac computation
|
18
|
+
# @return [BinaryString] a digital signature, or mac
|
19
|
+
# @example
|
20
|
+
# Rsa.sign('256', < private_key >, 'signing_input').bytes.length
|
21
|
+
# # => 256
|
22
|
+
def sign(sha_bits, private_key, signing_input)
|
23
|
+
validate_key(private_key, sha_bits)
|
24
|
+
private_key.sign(digest_new(sha_bits), signing_input)
|
16
25
|
end
|
17
26
|
|
18
|
-
|
19
|
-
|
20
|
-
|
27
|
+
# @param mac [BinaryString] a digital signature, or mac
|
28
|
+
# @param public_key [OpenSSL::PKey::RSA] key used to verify a digital signature, or mac
|
29
|
+
# @return [Boolean] a predicate to verify the signing_input for a given +mac+
|
30
|
+
# @example
|
31
|
+
# Rsa.verify?(< binary_string >, '256', < public_key >, 'signing_input')
|
32
|
+
# # => true
|
33
|
+
def verify?(mac, sha_bits, public_key, signing_input)
|
34
|
+
validate_key(public_key, sha_bits)
|
35
|
+
public_key.verify(digest_new(sha_bits), mac, signing_input)
|
21
36
|
end
|
22
37
|
|
23
|
-
# private
|
24
|
-
|
25
|
-
# http://tools.ietf.org/html/rfc7518#section-3.3
|
26
38
|
# https://github.com/ruby/openssl/issues/5
|
27
39
|
def validate_key_size(key, sha_bits)
|
28
40
|
fail('Invalid private key') unless key && key.n.num_bits >= KEY_BITS_MIN
|
@@ -2,44 +2,43 @@ require 'base64'
|
|
2
2
|
|
3
3
|
module JsonWebToken
|
4
4
|
module Format
|
5
|
+
# Provide base64url encoding and decoding functions without padding, based upon standard
|
6
|
+
# base64 encoding and decoding functions that do use padding
|
7
|
+
# @see http://tools.ietf.org/html/rfc7515#appendix-C
|
5
8
|
module Base64Url
|
6
|
-
|
7
9
|
module_function
|
8
10
|
|
11
|
+
# @param str [String]
|
12
|
+
# @return [String] a urlsafe_encode64 string with all trailing '=' padding removed
|
13
|
+
# @example
|
14
|
+
# Base64Url.encode('foo')
|
15
|
+
# # => 'Zm9v'
|
9
16
|
def encode(str)
|
10
|
-
|
17
|
+
base64_padding_removed(Base64.urlsafe_encode64(str))
|
11
18
|
end
|
12
19
|
|
20
|
+
# @param str [String] encoded as url_encode64
|
21
|
+
# @return [String] with trailing '=' padding added before decoding
|
22
|
+
# @example
|
23
|
+
# Base64Url.decode("YmFy")
|
24
|
+
# # => 'bar'
|
13
25
|
def decode(str)
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
# private
|
18
|
-
|
19
|
-
# http://tools.ietf.org/html/rfc7515#appendix-C
|
20
|
-
def url_safe_encode(str)
|
21
|
-
remove_base64_padding(Base64.urlsafe_encode64 str)
|
22
|
-
end
|
23
|
-
|
24
|
-
def url_safe_decode(str)
|
25
|
-
Base64.urlsafe_decode64(add_base64_padding str)
|
26
|
+
Base64.urlsafe_decode64(base64_padding_added(str))
|
26
27
|
end
|
27
28
|
|
28
|
-
def
|
29
|
+
def base64_padding_removed(encoded)
|
29
30
|
encoded.gsub(/[=]/, '')
|
30
31
|
end
|
31
32
|
|
32
|
-
def
|
33
|
+
def base64_padding_added(str)
|
33
34
|
mod = str.length % 4
|
34
35
|
return str if mod == 0
|
35
36
|
fail('Invalid base64 string') if mod == 1
|
36
37
|
"#{str}#{'=' * (4 - mod)}"
|
37
38
|
end
|
38
39
|
|
39
|
-
private_class_method :
|
40
|
-
:
|
41
|
-
:remove_base64_padding,
|
42
|
-
:add_base64_padding
|
40
|
+
private_class_method :base64_padding_removed,
|
41
|
+
:base64_padding_added
|
43
42
|
end
|
44
43
|
end
|
45
44
|
end
|
data/lib/json_web_token/jwa.rb
CHANGED
@@ -3,6 +3,8 @@ require 'json_web_token/algorithm/hmac'
|
|
3
3
|
require 'json_web_token/algorithm/rsa'
|
4
4
|
|
5
5
|
module JsonWebToken
|
6
|
+
# Choose a cryptographic algorithm to be used for a JSON Web Signature (JWS)
|
7
|
+
# @see http://tools.ietf.org/html/rfc7518
|
6
8
|
module Jwa
|
7
9
|
|
8
10
|
ALGORITHMS = /(HS|RS|ES)(256|384|512)?/i
|
@@ -10,18 +12,34 @@ module JsonWebToken
|
|
10
12
|
|
11
13
|
module_function
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
# @param algorithm [String] 'alg' header parameter value for JWS
|
16
|
+
# @param key [String | OpenSSL::PKey::RSA | OpenSSL::PKey::EC] secret key used to sign
|
17
|
+
# a digital signature, or mac
|
18
|
+
# @param signing_input [String] input payload for a mac computation
|
19
|
+
# @return [BinaryString] a digital signature, or mac
|
20
|
+
# @example
|
21
|
+
# key = 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C'
|
22
|
+
# Jwa.sign('HS256', key, 'signing_input').bytes
|
23
|
+
# # => [90, 34, 44, 252, 147, 130, 167, 173, 86, 191, 247, 93, 94, 12, 200, 30, 173, 115, 248, 89, 246, 222, 4, 213, 119, 74, 70, 20, 231, 194, 104, 103]
|
24
|
+
def sign(algorithm, key, signing_input)
|
25
|
+
alg_module, sha_bits = validated_alg(algorithm)
|
26
|
+
alg_module.sign(sha_bits, key, signing_input)
|
16
27
|
end
|
17
28
|
|
18
|
-
|
19
|
-
|
20
|
-
|
29
|
+
# @param mac [BinaryString] a digital signature, or mac
|
30
|
+
# @param algorithm [String] 'alg' header parameter value for JWS
|
31
|
+
# @param key [String | OpenSSL::PKey::RSA | OpenSSL::PKey::EC] key used to verify
|
32
|
+
# a digital signature, or mac
|
33
|
+
# @param signing_input [String] input payload for a mac computation
|
34
|
+
# @example
|
35
|
+
# key = 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C'
|
36
|
+
# Jwa.verify?(< binary_string >, 'HS256', key, 'signing_input')
|
37
|
+
# # => true
|
38
|
+
def verify?(mac, algorithm, key, signing_input)
|
39
|
+
alg_module, sha_bits = validated_alg(algorithm)
|
40
|
+
alg_module.verify?(mac, sha_bits, key, signing_input)
|
21
41
|
end
|
22
42
|
|
23
|
-
# private
|
24
|
-
|
25
43
|
def validated_alg(algorithm)
|
26
44
|
alg = destructured_alg(algorithm)
|
27
45
|
alg ? alg : fail('Unrecognized algorithm')
|
@@ -30,10 +48,9 @@ module JsonWebToken
|
|
30
48
|
def destructured_alg(algorithm)
|
31
49
|
match = algorithm.match(ALGORITHMS)
|
32
50
|
return unless match && match[0].length == ALG_LENGTH
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
}
|
51
|
+
alg_module = validated_constant(match[1].downcase)
|
52
|
+
sha_bits = match[2]
|
53
|
+
[alg_module, sha_bits]
|
37
54
|
end
|
38
55
|
|
39
56
|
def validated_constant(str)
|
@@ -46,7 +63,7 @@ module JsonWebToken
|
|
46
63
|
end
|
47
64
|
|
48
65
|
private_class_method :validated_alg,
|
49
|
-
:destructured_alg
|
66
|
+
:destructured_alg,
|
50
67
|
:validated_constant
|
51
68
|
end
|
52
69
|
end
|
data/lib/json_web_token/jws.rb
CHANGED
@@ -4,45 +4,72 @@ require 'json_web_token/jwa'
|
|
4
4
|
require 'json_web_token/util'
|
5
5
|
|
6
6
|
module JsonWebToken
|
7
|
+
# Represent content to be secured with digital signatures or Message Authentication Codes (MACs)
|
8
|
+
# @see http://tools.ietf.org/html/rfc7515
|
7
9
|
module Jws
|
8
10
|
|
9
11
|
MESSAGE_SIGNATURE_PARTS = 3
|
10
12
|
|
11
13
|
module_function
|
12
14
|
|
13
|
-
#
|
14
|
-
|
15
|
+
# @param header [Hash] the desired set of JWS header parameters
|
16
|
+
# @param payload [String] content to be used as the JWS payload
|
17
|
+
# @param key [String | OpenSSL::PKey::RSA | OpenSSL::PKey::EC] secret key used to sign
|
18
|
+
# a digital signature, or mac
|
19
|
+
# @return [String] a JSON Web Signature, representing a digitally signed payload
|
20
|
+
# @example
|
21
|
+
# header = {alg: 'HS256'}
|
22
|
+
# key = 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C'
|
23
|
+
# Jws.sign(header, 'payload', key)
|
24
|
+
# # => 'eyJhbGciOiJIUzI1NiJ9.cGF5bG9hZA.uVTaOdyzp_f4mT_hfzU8LnCzdmlVC4t2itHDEYUZym4'
|
25
|
+
# @see http://tools.ietf.org/html/rfc7515#page-15
|
26
|
+
def sign(header, payload, key)
|
15
27
|
alg = alg_parameter(header)
|
16
|
-
|
17
|
-
"#{
|
28
|
+
signing_input = encode_input(header, payload)
|
29
|
+
"#{signing_input}.#{signature(alg, key, signing_input)}"
|
18
30
|
end
|
19
31
|
|
20
|
-
#
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# http://tools.ietf.org/html/rfc7515#page-47
|
28
|
-
def
|
32
|
+
# @param header [Hash] the desired set of JWS header parameters
|
33
|
+
# @param payload [String] content to be used as the JWS payload
|
34
|
+
# @return [String] a JWS that provides no integrity protection (i.e. lacks a signature)
|
35
|
+
# @example
|
36
|
+
# header = {alg: 'none'}
|
37
|
+
# Jws.sign(header, 'payload')
|
38
|
+
# # => 'eyJhbGciOiJub25lIn0.cGF5bG9hZA.'
|
39
|
+
# @see http://tools.ietf.org/html/rfc7515#page-47
|
40
|
+
def unsecured_message(header, payload)
|
29
41
|
fail("Invalid 'alg' header parameter") unless alg_parameter(header) == 'none'
|
30
|
-
"#{
|
42
|
+
"#{encode_input(header, payload)}." # note trailing '.'
|
31
43
|
end
|
32
44
|
|
33
|
-
#
|
45
|
+
# @param jws [String] a JSON Web Signature
|
46
|
+
# @param algorithm [String] 'alg' header parameter value for JWS
|
47
|
+
# @param key [String | OpenSSL::PKey::RSA | OpenSSL::PKey::EC] key used to verify
|
48
|
+
# a digital signature, or mac
|
49
|
+
# @return [String | Boolean] a JWS if the mac verifies, or +false+ otherwise
|
50
|
+
# @example
|
51
|
+
# jws = 'eyJhbGciOiJIUzI1NiJ9.cGF5bG9hZA.uVTaOdyzp_f4mT_hfzU8LnCzdmlVC4t2itHDEYUZym4'
|
52
|
+
# key = 'gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr9C'
|
53
|
+
# Jws.verify(jws, 'HS256', key)
|
54
|
+
# # => 'eyJhbGciOiJIUzI1NiJ9.cGF5bG9hZA.uVTaOdyzp_f4mT_hfzU8LnCzdmlVC4t2itHDEYUZym4'
|
55
|
+
# @see http://tools.ietf.org/html/rfc7515#page-16
|
56
|
+
def verify(jws, algorithm, key = nil)
|
57
|
+
compare_alg(jws, algorithm)
|
58
|
+
return jws if algorithm == 'none'
|
59
|
+
signature_verify?(jws, algorithm, key) ? jws : false
|
60
|
+
end
|
34
61
|
|
35
62
|
def alg_parameter(header)
|
36
63
|
alg = Util.symbolize_keys(header)[:alg]
|
37
64
|
alg && !alg.empty? ? alg : fail("Missing required 'alg' header parameter")
|
38
65
|
end
|
39
66
|
|
40
|
-
def
|
41
|
-
"#{Format::Base64Url.encode
|
67
|
+
def encode_input(header, payload)
|
68
|
+
"#{Format::Base64Url.encode(header.to_json)}.#{Format::Base64Url.encode(payload)}"
|
42
69
|
end
|
43
70
|
|
44
71
|
def signature(algorithm, key, data)
|
45
|
-
Format::Base64Url.encode(Jwa.
|
72
|
+
Format::Base64Url.encode(Jwa.sign(algorithm, key, data))
|
46
73
|
end
|
47
74
|
|
48
75
|
# http://tools.ietf.org/html/rfc7515#section-4.1.1
|
@@ -54,22 +81,22 @@ module JsonWebToken
|
|
54
81
|
end
|
55
82
|
|
56
83
|
def decoded_header_json_to_hash(jws)
|
57
|
-
JSON.parse(Format::Base64Url.decode
|
84
|
+
JSON.parse(Format::Base64Url.decode(jws.split('.')[0]))
|
58
85
|
end
|
59
86
|
|
60
|
-
def
|
87
|
+
def signature_verify?(jws, algorithm, key)
|
61
88
|
ary = jws.split('.')
|
62
89
|
return unless key && ary.length == MESSAGE_SIGNATURE_PARTS
|
63
90
|
decoded_signature = Format::Base64Url.decode(ary[2])
|
64
91
|
payload = "#{ary[0]}.#{ary[1]}"
|
65
|
-
Jwa.
|
92
|
+
Jwa.verify?(decoded_signature, algorithm, key, payload)
|
66
93
|
end
|
67
94
|
|
68
95
|
private_class_method :alg_parameter,
|
69
|
-
:
|
96
|
+
:encode_input,
|
70
97
|
:signature,
|
71
98
|
:compare_alg,
|
72
99
|
:decoded_header_json_to_hash,
|
73
|
-
:
|
100
|
+
:signature_verify?
|
74
101
|
end
|
75
102
|
end
|