jwt 2.2.1 → 2.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHORS +79 -44
  3. data/CHANGELOG.md +271 -20
  4. data/CODE_OF_CONDUCT.md +84 -0
  5. data/CONTRIBUTING.md +99 -0
  6. data/README.md +253 -35
  7. data/lib/jwt/algos/algo_wrapper.rb +26 -0
  8. data/lib/jwt/algos/ecdsa.rb +55 -14
  9. data/lib/jwt/algos/eddsa.rb +18 -8
  10. data/lib/jwt/algos/hmac.rb +57 -17
  11. data/lib/jwt/algos/hmac_rbnacl.rb +53 -0
  12. data/lib/jwt/algos/hmac_rbnacl_fixed.rb +52 -0
  13. data/lib/jwt/algos/none.rb +19 -0
  14. data/lib/jwt/algos/ps.rb +10 -12
  15. data/lib/jwt/algos/rsa.rb +9 -5
  16. data/lib/jwt/algos/unsupported.rb +7 -4
  17. data/lib/jwt/algos.rb +66 -0
  18. data/lib/jwt/claims_validator.rb +12 -8
  19. data/lib/jwt/configuration/container.rb +21 -0
  20. data/lib/jwt/configuration/decode_configuration.rb +46 -0
  21. data/lib/jwt/configuration/jwk_configuration.rb +27 -0
  22. data/lib/jwt/configuration.rb +15 -0
  23. data/lib/jwt/decode.rb +85 -17
  24. data/lib/jwt/encode.rb +30 -19
  25. data/lib/jwt/error.rb +16 -14
  26. data/lib/jwt/jwk/ec.rb +236 -0
  27. data/lib/jwt/jwk/hmac.rb +103 -0
  28. data/lib/jwt/jwk/key_base.rb +55 -0
  29. data/lib/jwt/jwk/key_finder.rb +19 -30
  30. data/lib/jwt/jwk/kid_as_key_digest.rb +15 -0
  31. data/lib/jwt/jwk/okp_rbnacl.rb +110 -0
  32. data/lib/jwt/jwk/rsa.rb +181 -25
  33. data/lib/jwt/jwk/set.rb +80 -0
  34. data/lib/jwt/jwk/thumbprint.rb +26 -0
  35. data/lib/jwt/jwk.rb +39 -15
  36. data/lib/jwt/verify.rb +18 -3
  37. data/lib/jwt/version.rb +23 -3
  38. data/lib/jwt/x5c_key_finder.rb +55 -0
  39. data/lib/jwt.rb +5 -4
  40. data/ruby-jwt.gemspec +15 -10
  41. metadata +30 -90
  42. data/.codeclimate.yml +0 -20
  43. data/.ebert.yml +0 -18
  44. data/.gitignore +0 -11
  45. data/.rspec +0 -1
  46. data/.rubocop.yml +0 -98
  47. data/.travis.yml +0 -20
  48. data/Appraisals +0 -14
  49. data/Gemfile +0 -3
  50. data/Rakefile +0 -11
  51. data/lib/jwt/default_options.rb +0 -15
  52. data/lib/jwt/security_utils.rb +0 -57
  53. data/lib/jwt/signature.rb +0 -52
data/lib/jwt/version.rb CHANGED
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  # Moments version builder module
@@ -12,13 +11,34 @@ module JWT
12
11
  # major version
13
12
  MAJOR = 2
14
13
  # minor version
15
- MINOR = 2
14
+ MINOR = 7
16
15
  # tiny version
17
16
  TINY = 1
18
17
  # alpha, beta, etc. tag
19
18
  PRE = nil
20
19
 
21
20
  # Build version string
22
- STRING = [[MAJOR, MINOR, TINY].compact.join('.'), PRE].compact.join('-')
21
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
22
+ end
23
+
24
+ def self.openssl_3?
25
+ return false if OpenSSL::OPENSSL_VERSION.include?('LibreSSL')
26
+ return true if OpenSSL::OPENSSL_VERSION_NUMBER >= 3 * 0x10000000
27
+ end
28
+
29
+ def self.rbnacl?
30
+ defined?(::RbNaCl)
31
+ end
32
+
33
+ def self.rbnacl_6_or_greater?
34
+ rbnacl? && ::Gem::Version.new(::RbNaCl::VERSION) >= ::Gem::Version.new('6.0.0')
35
+ end
36
+
37
+ def self.openssl_3_hmac_empty_key_regression?
38
+ openssl_3? && openssl_version <= ::Gem::Version.new('3.0.0')
39
+ end
40
+
41
+ def self.openssl_version
42
+ @openssl_version ||= ::Gem::Version.new(OpenSSL::VERSION)
23
43
  end
24
44
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ require 'jwt/error'
5
+
6
+ module JWT
7
+ # If the x5c header certificate chain can be validated by trusted root
8
+ # certificates, and none of the certificates are revoked, returns the public
9
+ # key from the first certificate.
10
+ # See https://tools.ietf.org/html/rfc7515#section-4.1.6
11
+ class X5cKeyFinder
12
+ def initialize(root_certificates, crls = nil)
13
+ raise(ArgumentError, 'Root certificates must be specified') unless root_certificates
14
+
15
+ @store = build_store(root_certificates, crls)
16
+ end
17
+
18
+ def from(x5c_header_or_certificates)
19
+ signing_certificate, *certificate_chain = parse_certificates(x5c_header_or_certificates)
20
+ store_context = OpenSSL::X509::StoreContext.new(@store, signing_certificate, certificate_chain)
21
+
22
+ if store_context.verify
23
+ signing_certificate.public_key
24
+ else
25
+ error = "Certificate verification failed: #{store_context.error_string}."
26
+ if (current_cert = store_context.current_cert)
27
+ error = "#{error} Certificate subject: #{current_cert.subject}."
28
+ end
29
+
30
+ raise(JWT::VerificationError, error)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def build_store(root_certificates, crls)
37
+ store = OpenSSL::X509::Store.new
38
+ store.purpose = OpenSSL::X509::PURPOSE_ANY
39
+ store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK | OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
40
+ root_certificates.each { |certificate| store.add_cert(certificate) }
41
+ crls&.each { |crl| store.add_crl(crl) }
42
+ store
43
+ end
44
+
45
+ def parse_certificates(x5c_header_or_certificates)
46
+ if x5c_header_or_certificates.all? { |obj| obj.is_a?(OpenSSL::X509::Certificate) }
47
+ x5c_header_or_certificates
48
+ else
49
+ x5c_header_or_certificates.map do |encoded|
50
+ OpenSSL::X509::Certificate.new(::JWT::Base64.url_decode(encoded))
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
data/lib/jwt.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'jwt/version'
3
4
  require 'jwt/base64'
4
5
  require 'jwt/json'
5
6
  require 'jwt/decode'
6
- require 'jwt/default_options'
7
+ require 'jwt/configuration'
7
8
  require 'jwt/encode'
8
9
  require 'jwt/error'
9
10
  require 'jwt/jwk'
@@ -13,7 +14,7 @@ require 'jwt/jwk'
13
14
  # Should be up to date with the latest spec:
14
15
  # https://tools.ietf.org/html/rfc7519
15
16
  module JWT
16
- include JWT::DefaultOptions
17
+ extend ::JWT::Configuration
17
18
 
18
19
  module_function
19
20
 
@@ -24,7 +25,7 @@ module JWT
24
25
  headers: header_fields).segments
25
26
  end
26
27
 
27
- def decode(jwt, key = nil, verify = true, options = {}, &keyfinder)
28
- Decode.new(jwt, key, verify, DEFAULT_OPTIONS.merge(options), &keyfinder).decode_segments
28
+ def decode(jwt, key = nil, verify = true, options = {}, &keyfinder) # rubocop:disable Style/OptionalBooleanParameter
29
+ Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments
29
30
  end
30
31
  end
data/ruby-jwt.gemspec CHANGED
@@ -1,4 +1,6 @@
1
- lib = File.expand_path('../lib/', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require 'jwt/version'
4
6
 
@@ -13,11 +15,20 @@ Gem::Specification.new do |spec|
13
15
  spec.description = 'A pure ruby implementation of the RFC 7519 OAuth JSON Web Token (JWT) standard.'
14
16
  spec.homepage = 'https://github.com/jwt/ruby-jwt'
15
17
  spec.license = 'MIT'
16
- spec.required_ruby_version = '>= 2.1'
18
+ spec.required_ruby_version = '>= 2.5'
19
+ spec.metadata = {
20
+ 'bug_tracker_uri' => 'https://github.com/jwt/ruby-jwt/issues',
21
+ 'changelog_uri' => "https://github.com/jwt/ruby-jwt/blob/v#{JWT.gem_version}/CHANGELOG.md",
22
+ 'rubygems_mfa_required' => 'true'
23
+ }
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(spec|gemfiles|coverage|bin)/}) || # Irrelevant folders
27
+ f.match(/^\.+/) || # Files and folders starting with .
28
+ f.match(/^(Appraisals|Gemfile|Rakefile)$/) # Irrelevant files
29
+ end
17
30
 
18
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|gemfiles|coverage|bin)/}) }
19
31
  spec.executables = []
20
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
32
  spec.require_paths = %w[lib]
22
33
 
23
34
  spec.add_development_dependency 'appraisal'
@@ -25,10 +36,4 @@ Gem::Specification.new do |spec|
25
36
  spec.add_development_dependency 'rake'
26
37
  spec.add_development_dependency 'rspec'
27
38
  spec.add_development_dependency 'simplecov'
28
- spec.add_development_dependency 'simplecov-json'
29
- spec.add_development_dependency 'codeclimate-test-reporter'
30
- spec.add_development_dependency 'codacy-coverage'
31
- spec.add_development_dependency 'rbnacl'
32
- # RSASSA-PSS support provided by OpenSSL +2.1
33
- spec.add_development_dependency 'openssl', '~> 2.1'
34
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwt
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Rudat
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-24 00:00:00.000000000 Z
11
+ date: 2023-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appraisal
@@ -80,76 +80,6 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: simplecov-json
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: codeclimate-test-reporter
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: codacy-coverage
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: rbnacl
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: openssl
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '2.1'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '2.1'
153
83
  description: A pure ruby implementation of the RFC 7519 OAuth JSON Web Token (JWT)
154
84
  standard.
155
85
  email: timrudat@gmail.com
@@ -157,46 +87,56 @@ executables: []
157
87
  extensions: []
158
88
  extra_rdoc_files: []
159
89
  files:
160
- - ".codeclimate.yml"
161
- - ".ebert.yml"
162
- - ".gitignore"
163
- - ".rspec"
164
- - ".rubocop.yml"
165
- - ".travis.yml"
166
90
  - AUTHORS
167
- - Appraisals
168
91
  - CHANGELOG.md
169
- - Gemfile
92
+ - CODE_OF_CONDUCT.md
93
+ - CONTRIBUTING.md
170
94
  - LICENSE
171
95
  - README.md
172
- - Rakefile
173
96
  - lib/jwt.rb
97
+ - lib/jwt/algos.rb
98
+ - lib/jwt/algos/algo_wrapper.rb
174
99
  - lib/jwt/algos/ecdsa.rb
175
100
  - lib/jwt/algos/eddsa.rb
176
101
  - lib/jwt/algos/hmac.rb
102
+ - lib/jwt/algos/hmac_rbnacl.rb
103
+ - lib/jwt/algos/hmac_rbnacl_fixed.rb
104
+ - lib/jwt/algos/none.rb
177
105
  - lib/jwt/algos/ps.rb
178
106
  - lib/jwt/algos/rsa.rb
179
107
  - lib/jwt/algos/unsupported.rb
180
108
  - lib/jwt/base64.rb
181
109
  - lib/jwt/claims_validator.rb
110
+ - lib/jwt/configuration.rb
111
+ - lib/jwt/configuration/container.rb
112
+ - lib/jwt/configuration/decode_configuration.rb
113
+ - lib/jwt/configuration/jwk_configuration.rb
182
114
  - lib/jwt/decode.rb
183
- - lib/jwt/default_options.rb
184
115
  - lib/jwt/encode.rb
185
116
  - lib/jwt/error.rb
186
117
  - lib/jwt/json.rb
187
118
  - lib/jwt/jwk.rb
119
+ - lib/jwt/jwk/ec.rb
120
+ - lib/jwt/jwk/hmac.rb
121
+ - lib/jwt/jwk/key_base.rb
188
122
  - lib/jwt/jwk/key_finder.rb
123
+ - lib/jwt/jwk/kid_as_key_digest.rb
124
+ - lib/jwt/jwk/okp_rbnacl.rb
189
125
  - lib/jwt/jwk/rsa.rb
190
- - lib/jwt/security_utils.rb
191
- - lib/jwt/signature.rb
126
+ - lib/jwt/jwk/set.rb
127
+ - lib/jwt/jwk/thumbprint.rb
192
128
  - lib/jwt/verify.rb
193
129
  - lib/jwt/version.rb
130
+ - lib/jwt/x5c_key_finder.rb
194
131
  - ruby-jwt.gemspec
195
132
  homepage: https://github.com/jwt/ruby-jwt
196
133
  licenses:
197
134
  - MIT
198
- metadata: {}
199
- post_install_message:
135
+ metadata:
136
+ bug_tracker_uri: https://github.com/jwt/ruby-jwt/issues
137
+ changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.7.1/CHANGELOG.md
138
+ rubygems_mfa_required: 'true'
139
+ post_install_message:
200
140
  rdoc_options: []
201
141
  require_paths:
202
142
  - lib
@@ -204,15 +144,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
204
144
  requirements:
205
145
  - - ">="
206
146
  - !ruby/object:Gem::Version
207
- version: '2.1'
147
+ version: '2.5'
208
148
  required_rubygems_version: !ruby/object:Gem::Requirement
209
149
  requirements:
210
150
  - - ">="
211
151
  - !ruby/object:Gem::Version
212
152
  version: '0'
213
153
  requirements: []
214
- rubygems_version: 3.0.3
215
- signing_key:
154
+ rubygems_version: 3.3.7
155
+ signing_key:
216
156
  specification_version: 4
217
157
  summary: JSON Web Token implementation in Ruby
218
158
  test_files: []
data/.codeclimate.yml DELETED
@@ -1,20 +0,0 @@
1
- engines:
2
- rubocop:
3
- enabled: true
4
- golint:
5
- enabled: false
6
- gofmt:
7
- enabled: false
8
- eslint:
9
- enabled: false
10
- csslint:
11
- enabled: false
12
-
13
- ratings:
14
- paths:
15
- - lib/**
16
- - "**.rb"
17
-
18
- exclude_paths:
19
- - spec/**/*
20
- - vendor/**/*
data/.ebert.yml DELETED
@@ -1,18 +0,0 @@
1
- styleguide: excpt/linters
2
- engines:
3
- reek:
4
- enabled: true
5
- fixme:
6
- enabled: true
7
- rubocop:
8
- enabled: true
9
- channel: rubocop-0-49
10
- duplication:
11
- config:
12
- languages:
13
- - ruby
14
- enabled: true
15
- remark-lint:
16
- enabled: true
17
- exclude_paths:
18
- - spec
data/.gitignore DELETED
@@ -1,11 +0,0 @@
1
- .idea/
2
- jwt.gemspec
3
- pkg
4
- Gemfile.lock
5
- coverage/
6
- .DS_Store
7
- .rbenv-gemsets
8
- .ruby-version
9
- .vscode/
10
- .bundle
11
- *gemfile.lock
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --color
data/.rubocop.yml DELETED
@@ -1,98 +0,0 @@
1
- AllCops:
2
- Exclude:
3
- - 'bin/**/*'
4
- - 'db/**/*'
5
- - 'config/**/*'
6
- - 'script/**/*'
7
-
8
- Rails:
9
- Enabled: true
10
-
11
- Style/AlignParameters:
12
- EnforcedStyle: with_fixed_indentation
13
-
14
- Style/CaseIndentation:
15
- EnforcedStyle: end
16
-
17
- Style/AsciiComments:
18
- Enabled: false
19
-
20
- Style/IndentHash:
21
- Enabled: false
22
-
23
- Style/CollectionMethods:
24
- Enabled: true
25
- PreferredMethods:
26
- inject: 'inject'
27
-
28
- Style/Documentation:
29
- Enabled: false
30
-
31
- Style/BlockDelimiters:
32
- Exclude:
33
- - spec/**/*_spec.rb
34
-
35
- Style/BracesAroundHashParameters:
36
- Exclude:
37
- - spec/**/*_spec.rb
38
-
39
- Style/GuardClause:
40
- Enabled: false
41
-
42
- Style/IfUnlessModifier:
43
- Enabled: false
44
-
45
- Style/SpaceInsideHashLiteralBraces:
46
- Enabled: false
47
-
48
- Style/Lambda:
49
- Enabled: false
50
-
51
- Style/RaiseArgs:
52
- Enabled: false
53
-
54
- Style/SignalException:
55
- Enabled: false
56
-
57
- Metrics/AbcSize:
58
- Max: 20
59
-
60
- Metrics/ClassLength:
61
- Max: 100
62
-
63
- Metrics/ModuleLength:
64
- Max: 100
65
-
66
- Metrics/LineLength:
67
- Enabled: false
68
-
69
- Metrics/MethodLength:
70
- Max: 15
71
-
72
- Style/SingleLineBlockParams:
73
- Enabled: false
74
-
75
- Lint/EndAlignment:
76
- EnforcedStyleAlignWith: variable
77
-
78
- Style/FormatString:
79
- Enabled: false
80
-
81
- Style/MultilineMethodCallIndentation:
82
- EnforcedStyle: indented
83
-
84
- Style/MultilineOperationIndentation:
85
- EnforcedStyle: indented
86
-
87
- Style/WordArray:
88
- Enabled: false
89
-
90
- Style/RedundantSelf:
91
- Enabled: false
92
-
93
- Style/AlignHash:
94
- Enabled: true
95
- EnforcedLastArgumentHashStyle: always_ignore
96
-
97
- Style/TrivialAccessors:
98
- AllowPredicates: true
data/.travis.yml DELETED
@@ -1,20 +0,0 @@
1
- sudo: required
2
- cache: bundler
3
- dist: trusty
4
- language: ruby
5
- rvm:
6
- - 2.3
7
- - 2.4
8
- - 2.5
9
- - 2.6
10
- gemfiles:
11
- - gemfiles/standalone.gemfile
12
- - gemfiles/rails_5.0.gemfile
13
- - gemfiles/rails_5.1.gemfile
14
- - gemfiles/rails_5.2.gemfile
15
- script: "bundle exec rspec && bundle exec codeclimate-test-reporter"
16
- before_install:
17
- - sudo add-apt-repository ppa:chris-lea/libsodium -y
18
- - sudo apt-get update -q
19
- - sudo apt-get install libsodium-dev -y
20
- - gem install bundler
data/Appraisals DELETED
@@ -1,14 +0,0 @@
1
- appraise 'standalone' do
2
- end
3
-
4
- appraise 'rails-5.0' do
5
- gem 'rails', '~> 5.0.0'
6
- end
7
-
8
- appraise 'rails-5.1' do
9
- gem 'rails', '~> 5.1.0'
10
- end
11
-
12
- appraise 'rails-5.2' do
13
- gem 'rails', '~> 5.2.0'
14
- end
data/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
data/Rakefile DELETED
@@ -1,11 +0,0 @@
1
- require 'bundler/gem_tasks'
2
-
3
- begin
4
- require 'rspec/core/rake_task'
5
-
6
- RSpec::Core::RakeTask.new(:test)
7
-
8
- task default: :test
9
- rescue LoadError
10
- puts 'RSpec rake tasks not available. Please run "bundle install" to install missing dependencies.'
11
- end
@@ -1,15 +0,0 @@
1
- module JWT
2
- module DefaultOptions
3
- DEFAULT_OPTIONS = {
4
- verify_expiration: true,
5
- verify_not_before: true,
6
- verify_iss: false,
7
- verify_iat: false,
8
- verify_jti: false,
9
- verify_aud: false,
10
- verify_sub: false,
11
- leeway: 0,
12
- algorithms: ['HS256']
13
- }.freeze
14
- end
15
- end
@@ -1,57 +0,0 @@
1
- module JWT
2
- # Collection of security methods
3
- #
4
- # @see: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/security_utils.rb
5
- module SecurityUtils
6
- module_function
7
-
8
- def secure_compare(left, right)
9
- left_bytesize = left.bytesize
10
-
11
- return false unless left_bytesize == right.bytesize
12
-
13
- unpacked_left = left.unpack "C#{left_bytesize}"
14
- result = 0
15
- right.each_byte { |byte| result |= byte ^ unpacked_left.shift }
16
- result.zero?
17
- end
18
-
19
- def verify_rsa(algorithm, public_key, signing_input, signature)
20
- public_key.verify(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), signature, signing_input)
21
- end
22
-
23
- def verify_ps(algorithm, public_key, signing_input, signature)
24
- formatted_algorithm = algorithm.sub('PS', 'sha')
25
-
26
- public_key.verify_pss(formatted_algorithm, signature, signing_input, salt_length: :auto, mgf1_hash: formatted_algorithm)
27
- end
28
-
29
- def asn1_to_raw(signature, public_key)
30
- byte_size = (public_key.group.degree + 7) / 8
31
- OpenSSL::ASN1.decode(signature).value.map { |value| value.value.to_s(2).rjust(byte_size, "\x00") }.join
32
- end
33
-
34
- def raw_to_asn1(signature, private_key)
35
- byte_size = (private_key.group.degree + 7) / 8
36
- sig_bytes = signature[0..(byte_size - 1)]
37
- sig_char = signature[byte_size..-1] || ''
38
- OpenSSL::ASN1::Sequence.new([sig_bytes, sig_char].map { |int| OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(int, 2)) }).to_der
39
- end
40
-
41
- def rbnacl_fixup(algorithm, key)
42
- algorithm = algorithm.sub('HS', 'SHA').to_sym
43
-
44
- return [] unless defined?(RbNaCl) && RbNaCl::HMAC.constants(false).include?(algorithm)
45
-
46
- authenticator = RbNaCl::HMAC.const_get(algorithm)
47
-
48
- # Fall back to OpenSSL for keys larger than 32 bytes.
49
- return [] if key.bytesize > authenticator.key_bytes
50
-
51
- [
52
- authenticator,
53
- key.bytes.fill(0, key.bytesize...authenticator.key_bytes).pack('C*')
54
- ]
55
- end
56
- end
57
- end
data/lib/jwt/signature.rb DELETED
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'jwt/security_utils'
4
- require 'openssl'
5
- require 'jwt/algos/hmac'
6
- require 'jwt/algos/eddsa'
7
- require 'jwt/algos/ecdsa'
8
- require 'jwt/algos/rsa'
9
- require 'jwt/algos/ps'
10
- require 'jwt/algos/unsupported'
11
- begin
12
- require 'rbnacl'
13
- rescue LoadError
14
- raise if defined?(RbNaCl)
15
- end
16
-
17
- # JWT::Signature module
18
- module JWT
19
- # Signature logic for JWT
20
- module Signature
21
- extend self
22
- ALGOS = [
23
- Algos::Hmac,
24
- Algos::Ecdsa,
25
- Algos::Rsa,
26
- Algos::Eddsa,
27
- Algos::Ps,
28
- Algos::Unsupported
29
- ].freeze
30
- ToSign = Struct.new(:algorithm, :msg, :key)
31
- ToVerify = Struct.new(:algorithm, :public_key, :signing_input, :signature)
32
-
33
- def sign(algorithm, msg, key)
34
- algo = ALGOS.find do |alg|
35
- alg.const_get(:SUPPORTED).include? algorithm
36
- end
37
- algo.sign ToSign.new(algorithm, msg, key)
38
- end
39
-
40
- def verify(algorithm, key, signing_input, signature)
41
- algo = ALGOS.find do |alg|
42
- alg.const_get(:SUPPORTED).include? algorithm
43
- end
44
- verified = algo.verify(ToVerify.new(algorithm, key, signing_input, signature))
45
- raise(JWT::VerificationError, 'Signature verification raised') unless verified
46
- rescue OpenSSL::PKey::PKeyError
47
- raise JWT::VerificationError, 'Signature verification raised'
48
- ensure
49
- OpenSSL.errors.clear
50
- end
51
- end
52
- end