jwt 2.2.1 → 2.7.1

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.
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