jwt 2.8.1 → 2.9.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/jwt/decode.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
-
5
- require 'jwt/verify'
6
4
  require 'jwt/x5c_key_finder'
7
5
 
8
6
  # JWT::Decode module
@@ -10,7 +8,7 @@ module JWT
10
8
  # Decoding logic for JWT
11
9
  class Decode
12
10
  def initialize(jwt, key, verify, options, &keyfinder)
13
- raise(JWT::DecodeError, 'Nil JSON web token') unless jwt
11
+ raise JWT::DecodeError, 'Nil JSON web token' unless jwt
14
12
 
15
13
  @jwt = jwt
16
14
  @key = key
@@ -30,7 +28,7 @@ module JWT
30
28
  verify_signature
31
29
  verify_claims
32
30
  end
33
- raise(JWT::DecodeError, 'Not enough or too many segments') unless header && payload
31
+ raise JWT::DecodeError, 'Not enough or too many segments' unless header && payload
34
32
 
35
33
  [payload, header]
36
34
  end
@@ -46,21 +44,22 @@ module JWT
46
44
 
47
45
  return if Array(@key).any? { |key| verify_signature_for?(key) }
48
46
 
49
- raise(JWT::VerificationError, 'Signature verification failed')
47
+ raise JWT::VerificationError, 'Signature verification failed'
50
48
  end
51
49
 
52
50
  def verify_algo
53
- raise(JWT::IncorrectAlgorithm, 'An algorithm must be specified') if allowed_algorithms.empty?
54
- raise(JWT::IncorrectAlgorithm, 'Token is missing alg header') unless alg_in_header
55
- raise(JWT::IncorrectAlgorithm, 'Expected a different algorithm') if allowed_and_valid_algorithms.empty?
51
+ raise JWT::IncorrectAlgorithm, 'An algorithm must be specified' if allowed_algorithms.empty?
52
+ raise JWT::DecodeError, 'Token header not a JSON object' unless header.is_a?(Hash)
53
+ raise JWT::IncorrectAlgorithm, 'Token is missing alg header' unless alg_in_header
54
+ raise JWT::IncorrectAlgorithm, 'Expected a different algorithm' if allowed_and_valid_algorithms.empty?
56
55
  end
57
56
 
58
57
  def set_key
59
58
  @key = find_key(&@keyfinder) if @keyfinder
60
59
  @key = ::JWT::JWK::KeyFinder.new(jwks: @options[:jwks], allow_nil_kid: @options[:allow_nil_kid]).key_for(header['kid']) if @options[:jwks]
61
- if (x5c_options = @options[:x5c])
62
- @key = X5cKeyFinder.new(x5c_options[:root_certificates], x5c_options[:crls]).from(header['x5c'])
63
- end
60
+ return unless (x5c_options = @options[:x5c])
61
+
62
+ @key = X5cKeyFinder.new(x5c_options[:root_certificates], x5c_options[:crls]).from(header['x5c'])
64
63
  end
65
64
 
66
65
  def verify_signature_for?(key)
@@ -92,7 +91,7 @@ module JWT
92
91
  end
93
92
 
94
93
  def resolve_allowed_algorithms
95
- algs = given_algorithms.map { |alg| JWA.create(alg) }
94
+ algs = given_algorithms.map { |alg| JWA.resolve(alg) }
96
95
 
97
96
  sort_by_alg_header(algs)
98
97
  end
@@ -113,8 +112,7 @@ module JWT
113
112
  end
114
113
 
115
114
  def verify_claims
116
- Verify.verify_claims(payload, @options)
117
- Verify.verify_required_claims(payload, @options)
115
+ Claims::DecodeVerifier.verify!(payload, @options)
118
116
  end
119
117
 
120
118
  def validate_segment_count!
@@ -122,7 +120,7 @@ module JWT
122
120
  return if !@verify && segment_length == 2 # If no verifying required, the signature is not needed
123
121
  return if segment_length == 2 && none_algorithm?
124
122
 
125
- raise(JWT::DecodeError, 'Not enough or too many segments')
123
+ raise JWT::DecodeError, 'Not enough or too many segments'
126
124
  end
127
125
 
128
126
  def segment_length
@@ -4,15 +4,34 @@ module JWT
4
4
  # Deprecations module to handle deprecation warnings in the gem
5
5
  module Deprecations
6
6
  class << self
7
- def warning(message)
7
+ def context
8
+ yield.tap { emit_warnings }
9
+ ensure
10
+ Thread.current[:jwt_warning_store] = nil
11
+ end
12
+
13
+ def warning(message, only_if_valid: false)
14
+ method_name = only_if_valid ? :store : :warn
8
15
  case JWT.configuration.deprecation_warnings
9
- when :warn
10
- warn("[DEPRECATION WARNING] #{message}")
11
16
  when :once
12
17
  return if record_warned(message)
13
-
14
- warn("[DEPRECATION WARNING] #{message}")
18
+ when :warn
19
+ # noop
20
+ else
21
+ return
15
22
  end
23
+
24
+ send(method_name, "[DEPRECATION WARNING] #{message}")
25
+ end
26
+
27
+ def store(message)
28
+ (Thread.current[:jwt_warning_store] ||= []) << message
29
+ end
30
+
31
+ def emit_warnings
32
+ return if Thread.current[:jwt_warning_store].nil?
33
+
34
+ Thread.current[:jwt_warning_store].each { |warning| warn(warning) }
16
35
  end
17
36
 
18
37
  private
data/lib/jwt/encode.rb CHANGED
@@ -1,20 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'jwa'
4
- require_relative 'claims_validator'
5
4
 
6
5
  # JWT::Encode module
7
6
  module JWT
8
7
  # Encoding logic for JWT
9
8
  class Encode
10
- ALG_KEY = 'alg'
11
-
12
9
  def initialize(options)
13
10
  @payload = options[:payload]
14
11
  @key = options[:key]
15
- @algorithm = JWA.create(options[:algorithm])
12
+ @algorithm = JWA.resolve(options[:algorithm])
16
13
  @headers = options[:headers].transform_keys(&:to_s)
17
- @headers[ALG_KEY] = @algorithm.alg
18
14
  end
19
15
 
20
16
  def segments
@@ -41,7 +37,7 @@ module JWT
41
37
  end
42
38
 
43
39
  def encode_header
44
- encode_data(@headers)
40
+ encode_data(@headers.merge(@algorithm.header(signing_key: @key)))
45
41
  end
46
42
 
47
43
  def encode_payload
@@ -55,7 +51,7 @@ module JWT
55
51
  def validate_claims!
56
52
  return unless @payload.is_a?(Hash)
57
53
 
58
- ClaimsValidator.new(@payload).validate!
54
+ Claims.verify_payload!(@payload, :numeric)
59
55
  end
60
56
 
61
57
  def encode_signature
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JWT
4
+ module JWA
5
+ module Compat
6
+ module ClassMethods
7
+ def from_algorithm(algorithm)
8
+ new(algorithm)
9
+ end
10
+
11
+ def sign(algorithm, msg, key)
12
+ Deprecations.warning('Support for calling sign with positional arguments will be removed in future ruby-jwt versions')
13
+
14
+ from_algorithm(algorithm).sign(data: msg, signing_key: key)
15
+ end
16
+
17
+ def verify(algorithm, key, signing_input, signature)
18
+ Deprecations.warning('Support for calling verify with positional arguments will be removed in future ruby-jwt versions')
19
+
20
+ from_algorithm(algorithm).verify(data: signing_input, signature: signature, verification_key: key)
21
+ end
22
+ end
23
+
24
+ def self.included(klass)
25
+ klass.extend(ClassMethods)
26
+ end
27
+ end
28
+ end
29
+ end
data/lib/jwt/jwa/ecdsa.rb CHANGED
@@ -2,8 +2,35 @@
2
2
 
3
3
  module JWT
4
4
  module JWA
5
- module Ecdsa
6
- module_function
5
+ class Ecdsa
6
+ include JWT::JWA::SigningAlgorithm
7
+
8
+ def initialize(alg, digest)
9
+ @alg = alg
10
+ @digest = OpenSSL::Digest.new(digest)
11
+ end
12
+
13
+ def sign(data:, signing_key:)
14
+ curve_definition = curve_by_name(signing_key.group.curve_name)
15
+ key_algorithm = curve_definition[:algorithm]
16
+ if alg != key_algorithm
17
+ raise IncorrectAlgorithm, "payload algorithm is #{alg} but #{key_algorithm} signing key was provided"
18
+ end
19
+
20
+ asn1_to_raw(signing_key.dsa_sign_asn1(digest.digest(data)), signing_key)
21
+ end
22
+
23
+ def verify(data:, signature:, verification_key:)
24
+ curve_definition = curve_by_name(verification_key.group.curve_name)
25
+ key_algorithm = curve_definition[:algorithm]
26
+ if alg != key_algorithm
27
+ raise IncorrectAlgorithm, "payload algorithm is #{alg} but #{key_algorithm} verification key was provided"
28
+ end
29
+
30
+ verification_key.dsa_verify_asn1(digest.digest(data), raw_to_asn1(signature, verification_key))
31
+ rescue OpenSSL::PKey::PKeyError
32
+ raise JWT::VerificationError, 'Signature verification raised'
33
+ end
7
34
 
8
35
  NAMED_CURVES = {
9
36
  'prime256v1' => {
@@ -28,38 +55,28 @@ module JWT
28
55
  }
29
56
  }.freeze
30
57
 
31
- SUPPORTED = NAMED_CURVES.map { |_, c| c[:algorithm] }.uniq.freeze
32
-
33
- def sign(algorithm, msg, key)
34
- curve_definition = curve_by_name(key.group.curve_name)
35
- key_algorithm = curve_definition[:algorithm]
36
- if algorithm != key_algorithm
37
- raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} signing key was provided"
38
- end
39
-
40
- digest = OpenSSL::Digest.new(curve_definition[:digest])
41
- asn1_to_raw(key.dsa_sign_asn1(digest.digest(msg)), key)
58
+ NAMED_CURVES.each_value do |v|
59
+ register_algorithm(new(v[:algorithm], v[:digest]))
42
60
  end
43
61
 
44
- def verify(algorithm, public_key, signing_input, signature)
45
- curve_definition = curve_by_name(public_key.group.curve_name)
46
- key_algorithm = curve_definition[:algorithm]
47
- if algorithm != key_algorithm
48
- raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} verification key was provided"
49
- end
50
-
51
- digest = OpenSSL::Digest.new(curve_definition[:digest])
52
- public_key.dsa_verify_asn1(digest.digest(signing_input), raw_to_asn1(signature, public_key))
53
- rescue OpenSSL::PKey::PKeyError
54
- raise JWT::VerificationError, 'Signature verification raised'
62
+ def self.from_algorithm(algorithm)
63
+ new(algorithm, algorithm.downcase.gsub('es', 'sha'))
55
64
  end
56
65
 
57
- def curve_by_name(name)
66
+ def self.curve_by_name(name)
58
67
  NAMED_CURVES.fetch(name) do
59
68
  raise UnsupportedEcdsaCurve, "The ECDSA curve '#{name}' is not supported"
60
69
  end
61
70
  end
62
71
 
72
+ private
73
+
74
+ attr_reader :digest
75
+
76
+ def curve_by_name(name)
77
+ self.class.curve_by_name(name)
78
+ end
79
+
63
80
  def raw_to_asn1(signature, private_key)
64
81
  byte_size = (private_key.group.degree + 7) / 8
65
82
  sig_bytes = signature[0..(byte_size - 1)]
data/lib/jwt/jwa/eddsa.rb CHANGED
@@ -2,41 +2,33 @@
2
2
 
3
3
  module JWT
4
4
  module JWA
5
- module Eddsa
6
- SUPPORTED = %w[ED25519 EdDSA].freeze
7
- SUPPORTED_DOWNCASED = SUPPORTED.map(&:downcase).freeze
5
+ class Eddsa
6
+ include JWT::JWA::SigningAlgorithm
8
7
 
9
- class << self
10
- def sign(algorithm, msg, key)
11
- unless key.is_a?(RbNaCl::Signatures::Ed25519::SigningKey)
12
- raise EncodeError, "Key given is a #{key.class} but has to be an RbNaCl::Signatures::Ed25519::SigningKey"
13
- end
14
-
15
- validate_algorithm!(algorithm)
8
+ def initialize(alg)
9
+ @alg = alg
10
+ end
16
11
 
17
- key.sign(msg)
12
+ def sign(data:, signing_key:)
13
+ unless signing_key.is_a?(RbNaCl::Signatures::Ed25519::SigningKey)
14
+ raise_encode_error!("Key given is a #{signing_key.class} but has to be an RbNaCl::Signatures::Ed25519::SigningKey")
18
15
  end
19
16
 
20
- def verify(algorithm, public_key, signing_input, signature)
21
- unless public_key.is_a?(RbNaCl::Signatures::Ed25519::VerifyKey)
22
- raise DecodeError, "key given is a #{public_key.class} but has to be a RbNaCl::Signatures::Ed25519::VerifyKey"
23
- end
24
-
25
- validate_algorithm!(algorithm)
17
+ signing_key.sign(data)
18
+ end
26
19
 
27
- public_key.verify(signature, signing_input)
28
- rescue RbNaCl::CryptoError
29
- false
20
+ def verify(data:, signature:, verification_key:)
21
+ unless verification_key.is_a?(RbNaCl::Signatures::Ed25519::VerifyKey)
22
+ raise_decode_error!("key given is a #{verification_key.class} but has to be a RbNaCl::Signatures::Ed25519::VerifyKey")
30
23
  end
31
24
 
32
- private
33
-
34
- def validate_algorithm!(algorithm)
35
- return if SUPPORTED_DOWNCASED.include?(algorithm.downcase)
36
-
37
- raise IncorrectAlgorithm, "Algorithm #{algorithm} not supported. Supported algoritms are #{SUPPORTED.join(', ')}"
38
- end
25
+ verification_key.verify(signature, data)
26
+ rescue RbNaCl::CryptoError
27
+ false
39
28
  end
29
+
30
+ register_algorithm(new('ED25519'))
31
+ register_algorithm(new('EdDSA'))
40
32
  end
41
33
  end
42
34
  end
data/lib/jwt/jwa/hmac.rb CHANGED
@@ -2,35 +2,43 @@
2
2
 
3
3
  module JWT
4
4
  module JWA
5
- module Hmac
6
- module_function
5
+ class Hmac
6
+ include JWT::JWA::SigningAlgorithm
7
7
 
8
- MAPPING = {
9
- 'HS256' => OpenSSL::Digest::SHA256,
10
- 'HS384' => OpenSSL::Digest::SHA384,
11
- 'HS512' => OpenSSL::Digest::SHA512
12
- }.freeze
13
-
14
- SUPPORTED = MAPPING.keys
8
+ def self.from_algorithm(algorithm)
9
+ new(algorithm, OpenSSL::Digest.new(algorithm.downcase.gsub('hs', 'sha')))
10
+ end
15
11
 
16
- def sign(algorithm, msg, key)
17
- key ||= ''
12
+ def initialize(alg, digest)
13
+ @alg = alg
14
+ @digest = digest
15
+ end
18
16
 
19
- raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
17
+ def sign(data:, signing_key:)
18
+ signing_key ||= ''
19
+ raise_verify_error!('HMAC key expected to be a String') unless signing_key.is_a?(String)
20
20
 
21
- OpenSSL::HMAC.digest(MAPPING[algorithm].new, key, msg)
21
+ OpenSSL::HMAC.digest(digest.new, signing_key, data)
22
22
  rescue OpenSSL::HMACError => e
23
- if key == '' && e.message == 'EVP_PKEY_new_mac_key: malloc failure'
24
- raise JWT::DecodeError, 'OpenSSL 3.0 does not support nil or empty hmac_secret'
23
+ if signing_key == '' && e.message == 'EVP_PKEY_new_mac_key: malloc failure'
24
+ raise_verify_error!('OpenSSL 3.0 does not support nil or empty hmac_secret')
25
25
  end
26
26
 
27
27
  raise e
28
28
  end
29
29
 
30
- def verify(algorithm, key, signing_input, signature)
31
- SecurityUtils.secure_compare(signature, sign(algorithm, signing_input, key))
30
+ def verify(data:, signature:, verification_key:)
31
+ SecurityUtils.secure_compare(signature, sign(data: data, signing_key: verification_key))
32
32
  end
33
33
 
34
+ register_algorithm(new('HS256', OpenSSL::Digest::SHA256))
35
+ register_algorithm(new('HS384', OpenSSL::Digest::SHA384))
36
+ register_algorithm(new('HS512', OpenSSL::Digest::SHA512))
37
+
38
+ private
39
+
40
+ attr_reader :digest
41
+
34
42
  # Copy of https://github.com/rails/rails/blob/v7.0.3.1/activesupport/lib/active_support/security_utils.rb
35
43
  # rubocop:disable Naming/MethodParameterName, Style/StringLiterals, Style/NumericPredicate
36
44
  module SecurityUtils
@@ -1,49 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWT
4
- module Algos
5
- module HmacRbNaCl
6
- MAPPING = { 'HS512256' => ::RbNaCl::HMAC::SHA512256 }.freeze
7
- SUPPORTED = MAPPING.keys
8
- class << self
9
- def sign(algorithm, msg, key)
10
- Deprecations.warning("The use of the algorithm #{algorithm} is deprecated and will be removed in the next major version of ruby-jwt")
11
- if (hmac = resolve_algorithm(algorithm))
12
- hmac.auth(key_for_rbnacl(hmac, key).encode('binary'), msg.encode('binary'))
13
- else
14
- Hmac.sign(algorithm, msg, key)
15
- end
16
- end
17
-
18
- def verify(algorithm, key, signing_input, signature)
19
- Deprecations.warning("The use of the algorithm #{algorithm} is deprecated and will be removed in the next major version of ruby-jwt")
20
- if (hmac = resolve_algorithm(algorithm))
21
- hmac.verify(key_for_rbnacl(hmac, key).encode('binary'), signature.encode('binary'), signing_input.encode('binary'))
22
- else
23
- Hmac.verify(algorithm, key, signing_input, signature)
24
- end
25
- rescue ::RbNaCl::BadAuthenticatorError, ::RbNaCl::LengthError
26
- false
27
- end
28
-
29
- private
30
-
31
- def key_for_rbnacl(hmac, key)
32
- key ||= ''
33
- raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
34
-
35
- return padded_empty_key(hmac.key_bytes) if key == ''
36
-
37
- key
38
- end
39
-
40
- def resolve_algorithm(algorithm)
41
- MAPPING.fetch(algorithm)
42
- end
43
-
44
- def padded_empty_key(length)
45
- Array.new(length, 0x0).pack('C*').encode('binary')
46
- end
4
+ module JWA
5
+ class HmacRbNaCl
6
+ include JWT::JWA::SigningAlgorithm
7
+
8
+ def self.from_algorithm(algorithm)
9
+ new(algorithm, ::RbNaCl::HMAC.const_get(algorithm.upcase.gsub('HS', 'SHA')))
10
+ end
11
+
12
+ def initialize(alg, hmac)
13
+ @alg = alg
14
+ @hmac = hmac
15
+ end
16
+
17
+ def sign(data:, signing_key:)
18
+ Deprecations.warning("The use of the algorithm #{alg} is deprecated and will be removed in the next major version of ruby-jwt")
19
+ hmac.auth(key_for_rbnacl(hmac, signing_key).encode('binary'), data.encode('binary'))
20
+ end
21
+
22
+ def verify(data:, signature:, verification_key:)
23
+ Deprecations.warning("The use of the algorithm #{alg} is deprecated and will be removed in the next major version of ruby-jwt")
24
+ hmac.verify(key_for_rbnacl(hmac, verification_key).encode('binary'), signature.encode('binary'), data.encode('binary'))
25
+ rescue ::RbNaCl::BadAuthenticatorError, ::RbNaCl::LengthError
26
+ false
27
+ end
28
+
29
+ register_algorithm(new('HS512256', ::RbNaCl::HMAC::SHA512256))
30
+
31
+ private
32
+
33
+ attr_reader :hmac
34
+
35
+ def key_for_rbnacl(hmac, key)
36
+ key ||= ''
37
+ raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
38
+
39
+ return padded_empty_key(hmac.key_bytes) if key == ''
40
+
41
+ key
42
+ end
43
+
44
+ def padded_empty_key(length)
45
+ Array.new(length, 0x0).pack('C*').encode('binary')
47
46
  end
48
47
  end
49
48
  end
@@ -1,45 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWT
4
- module Algos
5
- module HmacRbNaClFixed
6
- MAPPING = { 'HS512256' => ::RbNaCl::HMAC::SHA512256 }.freeze
7
- SUPPORTED = MAPPING.keys
8
-
9
- class << self
10
- def sign(algorithm, msg, key)
11
- key ||= ''
12
- Deprecations.warning("The use of the algorithm #{algorithm} is deprecated and will be removed in the next major version of ruby-jwt")
13
- raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
14
-
15
- if (hmac = resolve_algorithm(algorithm)) && key.bytesize <= hmac.key_bytes
16
- hmac.auth(padded_key_bytes(key, hmac.key_bytes), msg.encode('binary'))
17
- else
18
- Hmac.sign(algorithm, msg, key)
19
- end
20
- end
21
-
22
- def verify(algorithm, key, signing_input, signature)
23
- key ||= ''
24
- Deprecations.warning("The use of the algorithm #{algorithm} is deprecated and will be removed in the next major version of ruby-jwt")
25
- raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
26
-
27
- if (hmac = resolve_algorithm(algorithm)) && key.bytesize <= hmac.key_bytes
28
- hmac.verify(padded_key_bytes(key, hmac.key_bytes), signature.encode('binary'), signing_input.encode('binary'))
29
- else
30
- Hmac.verify(algorithm, key, signing_input, signature)
31
- end
32
- rescue ::RbNaCl::BadAuthenticatorError, ::RbNaCl::LengthError
33
- false
34
- end
35
-
36
- def resolve_algorithm(algorithm)
37
- MAPPING.fetch(algorithm)
38
- end
39
-
40
- def padded_key_bytes(key, bytesize)
41
- key.bytes.fill(0, key.bytesize...bytesize).pack('C*')
42
- end
4
+ module JWA
5
+ class HmacRbNaClFixed
6
+ include JWT::JWA::SigningAlgorithm
7
+
8
+ def self.from_algorithm(algorithm)
9
+ new(algorithm, ::RbNaCl::HMAC.const_get(algorithm.upcase.gsub('HS', 'SHA')))
10
+ end
11
+
12
+ def initialize(alg, hmac)
13
+ @alg = alg
14
+ @hmac = hmac
15
+ end
16
+
17
+ def sign(data:, signing_key:)
18
+ signing_key ||= ''
19
+ Deprecations.warning("The use of the algorithm #{alg} is deprecated and will be removed in the next major version of ruby-jwt")
20
+ raise JWT::DecodeError, 'HMAC key expected to be a String' unless signing_key.is_a?(String)
21
+
22
+ hmac.auth(padded_key_bytes(signing_key, hmac.key_bytes), data.encode('binary'))
23
+ end
24
+
25
+ def verify(data:, signature:, verification_key:)
26
+ verification_key ||= ''
27
+ Deprecations.warning("The use of the algorithm #{alg} is deprecated and will be removed in the next major version of ruby-jwt")
28
+ raise JWT::DecodeError, 'HMAC key expected to be a String' unless verification_key.is_a?(String)
29
+
30
+ hmac.verify(padded_key_bytes(verification_key, hmac.key_bytes), signature.encode('binary'), data.encode('binary'))
31
+ rescue ::RbNaCl::BadAuthenticatorError, ::RbNaCl::LengthError
32
+ false
33
+ end
34
+
35
+ register_algorithm(new('HS512256', ::RbNaCl::HMAC::SHA512256))
36
+
37
+ private
38
+
39
+ attr_reader :hmac
40
+
41
+ def padded_key_bytes(key, bytesize)
42
+ key.bytes.fill(0, key.bytesize...bytesize).pack('C*')
43
43
  end
44
44
  end
45
45
  end
data/lib/jwt/jwa/none.rb CHANGED
@@ -2,10 +2,12 @@
2
2
 
3
3
  module JWT
4
4
  module JWA
5
- module None
6
- module_function
5
+ class None
6
+ include JWT::JWA::SigningAlgorithm
7
7
 
8
- SUPPORTED = %w[none].freeze
8
+ def initialize
9
+ @alg = 'none'
10
+ end
9
11
 
10
12
  def sign(*)
11
13
  ''
@@ -14,6 +16,8 @@ module JWT
14
16
  def verify(*)
15
17
  true
16
18
  end
19
+
20
+ register_algorithm(new)
17
21
  end
18
22
  end
19
23
  end
data/lib/jwt/jwa/ps.rb CHANGED
@@ -2,29 +2,35 @@
2
2
 
3
3
  module JWT
4
4
  module JWA
5
- module Ps
6
- # RSASSA-PSS signing algorithms
5
+ class Ps
6
+ include JWT::JWA::SigningAlgorithm
7
7
 
8
- module_function
9
-
10
- SUPPORTED = %w[PS256 PS384 PS512].freeze
8
+ def initialize(alg)
9
+ @alg = alg
10
+ @digest_algorithm = alg.sub('PS', 'sha')
11
+ end
11
12
 
12
- def sign(algorithm, msg, key)
13
- unless key.is_a?(::OpenSSL::PKey::RSA)
14
- raise EncodeError, "The given key is a #{key_class}. It has to be an OpenSSL::PKey::RSA instance."
13
+ def sign(data:, signing_key:)
14
+ unless signing_key.is_a?(::OpenSSL::PKey::RSA)
15
+ raise_sign_error!("The given key is a #{signing_key.class}. It has to be an OpenSSL::PKey::RSA instance.")
15
16
  end
16
17
 
17
- translated_algorithm = algorithm.sub('PS', 'sha')
18
-
19
- key.sign_pss(translated_algorithm, msg, salt_length: :digest, mgf1_hash: translated_algorithm)
18
+ signing_key.sign_pss(digest_algorithm, data, salt_length: :digest, mgf1_hash: digest_algorithm)
20
19
  end
21
20
 
22
- def verify(algorithm, public_key, signing_input, signature)
23
- translated_algorithm = algorithm.sub('PS', 'sha')
24
- public_key.verify_pss(translated_algorithm, signature, signing_input, salt_length: :auto, mgf1_hash: translated_algorithm)
21
+ def verify(data:, signature:, verification_key:)
22
+ verification_key.verify_pss(digest_algorithm, signature, data, salt_length: :auto, mgf1_hash: digest_algorithm)
25
23
  rescue OpenSSL::PKey::PKeyError
26
24
  raise JWT::VerificationError, 'Signature verification raised'
27
25
  end
26
+
27
+ register_algorithm(new('PS256'))
28
+ register_algorithm(new('PS384'))
29
+ register_algorithm(new('PS512'))
30
+
31
+ private
32
+
33
+ attr_reader :digest_algorithm
28
34
  end
29
35
  end
30
36
  end