jwt 1.5.6 → 2.2.3
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 +5 -5
- data/.github/workflows/test.yml +74 -0
- data/.gitignore +1 -1
- data/.rspec +1 -0
- data/.rubocop.yml +95 -0
- data/.rubocop_todo.yml +191 -0
- data/.sourcelevel.yml +18 -0
- data/AUTHORS +101 -0
- data/Appraisals +10 -0
- data/CHANGELOG.md +349 -8
- data/Gemfile +2 -1
- data/README.md +225 -68
- data/Rakefile +4 -1
- data/lib/jwt.rb +14 -176
- data/lib/jwt/algos.rb +44 -0
- data/lib/jwt/algos/ecdsa.rb +35 -0
- data/lib/jwt/algos/eddsa.rb +23 -0
- data/lib/jwt/algos/hmac.rb +34 -0
- data/lib/jwt/algos/none.rb +15 -0
- data/lib/jwt/algos/ps.rb +43 -0
- data/lib/jwt/algos/rsa.rb +19 -0
- data/lib/jwt/algos/unsupported.rb +17 -0
- data/lib/jwt/base64.rb +19 -0
- data/lib/jwt/claims_validator.rb +35 -0
- data/lib/jwt/decode.rb +83 -31
- data/lib/jwt/default_options.rb +15 -0
- data/lib/jwt/encode.rb +69 -0
- data/lib/jwt/error.rb +6 -0
- data/lib/jwt/json.rb +10 -9
- data/lib/jwt/jwk.rb +51 -0
- data/lib/jwt/jwk/ec.rb +150 -0
- data/lib/jwt/jwk/hmac.rb +58 -0
- data/lib/jwt/jwk/key_base.rb +18 -0
- data/lib/jwt/jwk/key_finder.rb +62 -0
- data/lib/jwt/jwk/rsa.rb +115 -0
- data/lib/jwt/security_utils.rb +57 -0
- data/lib/jwt/signature.rb +39 -0
- data/lib/jwt/verify.rb +45 -53
- data/lib/jwt/version.rb +3 -3
- data/ruby-jwt.gemspec +6 -8
- metadata +39 -95
- data/.codeclimate.yml +0 -20
- data/.travis.yml +0 -13
- data/Manifest +0 -8
- data/spec/fixtures/certs/ec256-private.pem +0 -8
- data/spec/fixtures/certs/ec256-public.pem +0 -4
- data/spec/fixtures/certs/ec256-wrong-private.pem +0 -8
- data/spec/fixtures/certs/ec256-wrong-public.pem +0 -4
- data/spec/fixtures/certs/ec384-private.pem +0 -9
- data/spec/fixtures/certs/ec384-public.pem +0 -5
- data/spec/fixtures/certs/ec384-wrong-private.pem +0 -9
- data/spec/fixtures/certs/ec384-wrong-public.pem +0 -5
- data/spec/fixtures/certs/ec512-private.pem +0 -10
- data/spec/fixtures/certs/ec512-public.pem +0 -6
- data/spec/fixtures/certs/ec512-wrong-private.pem +0 -10
- data/spec/fixtures/certs/ec512-wrong-public.pem +0 -6
- data/spec/fixtures/certs/rsa-1024-private.pem +0 -15
- data/spec/fixtures/certs/rsa-1024-public.pem +0 -6
- data/spec/fixtures/certs/rsa-2048-private.pem +0 -27
- data/spec/fixtures/certs/rsa-2048-public.pem +0 -9
- data/spec/fixtures/certs/rsa-2048-wrong-private.pem +0 -27
- data/spec/fixtures/certs/rsa-2048-wrong-public.pem +0 -9
- data/spec/fixtures/certs/rsa-4096-private.pem +0 -51
- data/spec/fixtures/certs/rsa-4096-public.pem +0 -14
- data/spec/integration/readme_examples_spec.rb +0 -190
- data/spec/jwt/verify_spec.rb +0 -197
- data/spec/jwt_spec.rb +0 -240
- data/spec/spec_helper.rb +0 -31
data/Rakefile
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
+
require 'bundler/setup'
|
1
2
|
require 'bundler/gem_tasks'
|
2
3
|
|
3
4
|
begin
|
4
5
|
require 'rspec/core/rake_task'
|
6
|
+
require 'rubocop/rake_task'
|
5
7
|
|
6
8
|
RSpec::Core::RakeTask.new(:test)
|
9
|
+
RuboCop::RakeTask.new(:rubocop)
|
7
10
|
|
8
|
-
task default:
|
11
|
+
task default: %i[rubocop test]
|
9
12
|
rescue LoadError
|
10
13
|
puts 'RSpec rake tasks not available. Please run "bundle install" to install missing dependencies.'
|
11
14
|
end
|
data/lib/jwt.rb
CHANGED
@@ -1,192 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require '
|
2
|
+
|
3
|
+
require 'jwt/base64'
|
4
|
+
require 'jwt/json'
|
4
5
|
require 'jwt/decode'
|
6
|
+
require 'jwt/default_options'
|
7
|
+
require 'jwt/encode'
|
5
8
|
require 'jwt/error'
|
6
|
-
require 'jwt/
|
9
|
+
require 'jwt/jwk'
|
7
10
|
|
8
11
|
# JSON Web Token implementation
|
9
12
|
#
|
10
13
|
# Should be up to date with the latest spec:
|
11
|
-
# https://tools.ietf.org/html/rfc7519
|
14
|
+
# https://tools.ietf.org/html/rfc7519
|
12
15
|
module JWT
|
13
|
-
|
14
|
-
|
15
|
-
NAMED_CURVES = {
|
16
|
-
'prime256v1' => 'ES256',
|
17
|
-
'secp384r1' => 'ES384',
|
18
|
-
'secp521r1' => 'ES512'
|
19
|
-
}.freeze
|
20
|
-
|
21
|
-
DEFAULT_OPTIONS = {
|
22
|
-
verify_expiration: true,
|
23
|
-
verify_not_before: true,
|
24
|
-
verify_iss: false,
|
25
|
-
verify_iat: false,
|
26
|
-
verify_jti: false,
|
27
|
-
verify_aud: false,
|
28
|
-
verify_sub: false,
|
29
|
-
leeway: 0
|
30
|
-
}.freeze
|
16
|
+
include JWT::DefaultOptions
|
31
17
|
|
32
18
|
module_function
|
33
19
|
|
34
|
-
def sign(algorithm, msg, key)
|
35
|
-
if %w(HS256 HS384 HS512).include?(algorithm)
|
36
|
-
sign_hmac(algorithm, msg, key)
|
37
|
-
elsif %w(RS256 RS384 RS512).include?(algorithm)
|
38
|
-
sign_rsa(algorithm, msg, key)
|
39
|
-
elsif %w(ES256 ES384 ES512).include?(algorithm)
|
40
|
-
sign_ecdsa(algorithm, msg, key)
|
41
|
-
else
|
42
|
-
raise NotImplementedError, 'Unsupported signing method'
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def sign_rsa(algorithm, msg, private_key)
|
47
|
-
private_key.sign(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), msg)
|
48
|
-
end
|
49
|
-
|
50
|
-
def sign_ecdsa(algorithm, msg, private_key)
|
51
|
-
key_algorithm = NAMED_CURVES[private_key.group.curve_name]
|
52
|
-
if algorithm != key_algorithm
|
53
|
-
raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} signing key was provided"
|
54
|
-
end
|
55
|
-
|
56
|
-
digest = OpenSSL::Digest.new(algorithm.sub('ES', 'sha'))
|
57
|
-
asn1_to_raw(private_key.dsa_sign_asn1(digest.digest(msg)), private_key)
|
58
|
-
end
|
59
|
-
|
60
|
-
def verify_rsa(algorithm, public_key, signing_input, signature)
|
61
|
-
public_key.verify(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), signature, signing_input)
|
62
|
-
end
|
63
|
-
|
64
|
-
def verify_ecdsa(algorithm, public_key, signing_input, signature)
|
65
|
-
key_algorithm = NAMED_CURVES[public_key.group.curve_name]
|
66
|
-
if algorithm != key_algorithm
|
67
|
-
raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} verification key was provided"
|
68
|
-
end
|
69
|
-
|
70
|
-
digest = OpenSSL::Digest.new(algorithm.sub('ES', 'sha'))
|
71
|
-
public_key.dsa_verify_asn1(digest.digest(signing_input), raw_to_asn1(signature, public_key))
|
72
|
-
end
|
73
|
-
|
74
|
-
def sign_hmac(algorithm, msg, key)
|
75
|
-
OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub('HS', 'sha')), key, msg)
|
76
|
-
end
|
77
|
-
|
78
|
-
def base64url_encode(str)
|
79
|
-
Base64.encode64(str).tr('+/', '-_').gsub(/[\n=]/, '')
|
80
|
-
end
|
81
|
-
|
82
|
-
def encoded_header(algorithm = 'HS256', header_fields = {})
|
83
|
-
header = { 'typ' => 'JWT', 'alg' => algorithm }.merge(header_fields)
|
84
|
-
base64url_encode(encode_json(header))
|
85
|
-
end
|
86
|
-
|
87
|
-
def encoded_payload(payload)
|
88
|
-
raise InvalidPayload, 'exp claim must be an integer' if payload['exp'] && payload['exp'].is_a?(Time)
|
89
|
-
base64url_encode(encode_json(payload))
|
90
|
-
end
|
91
|
-
|
92
|
-
def encoded_signature(signing_input, key, algorithm)
|
93
|
-
if algorithm == 'none'
|
94
|
-
''
|
95
|
-
else
|
96
|
-
signature = sign(algorithm, signing_input, key)
|
97
|
-
base64url_encode(signature)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
20
|
def encode(payload, key, algorithm = 'HS256', header_fields = {})
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
segments << encoded_signature(segments.join('.'), key, algorithm)
|
107
|
-
segments.join('.')
|
108
|
-
end
|
109
|
-
|
110
|
-
def decoded_segments(jwt, key = nil, verify = true, custom_options = {}, &keyfinder)
|
111
|
-
raise(JWT::DecodeError, 'Nil JSON web token') unless jwt
|
112
|
-
|
113
|
-
merged_options = DEFAULT_OPTIONS.merge(custom_options)
|
114
|
-
|
115
|
-
decoder = Decode.new jwt, key, verify, merged_options, &keyfinder
|
116
|
-
decoder.decode_segments
|
117
|
-
end
|
118
|
-
|
119
|
-
def decode(jwt, key = nil, verify = true, custom_options = {}, &keyfinder)
|
120
|
-
raise(JWT::DecodeError, 'Nil JSON web token') unless jwt
|
121
|
-
|
122
|
-
merged_options = DEFAULT_OPTIONS.merge(custom_options)
|
123
|
-
decoder = Decode.new jwt, key, verify, merged_options, &keyfinder
|
124
|
-
header, payload, signature, signing_input = decoder.decode_segments
|
125
|
-
decode_verify_signature(key, header, signature, signing_input, merged_options, &keyfinder) if verify
|
126
|
-
decoder.verify
|
127
|
-
|
128
|
-
raise(JWT::DecodeError, 'Not enough or too many segments') unless header && payload
|
129
|
-
|
130
|
-
[payload, header]
|
131
|
-
end
|
132
|
-
|
133
|
-
def decode_verify_signature(key, header, signature, signing_input, options, &keyfinder)
|
134
|
-
algo, key = signature_algorithm_and_key(header, key, &keyfinder)
|
135
|
-
if options[:algorithm] && algo != options[:algorithm]
|
136
|
-
raise JWT::IncorrectAlgorithm, 'Expected a different algorithm'
|
137
|
-
end
|
138
|
-
verify_signature(algo, key, signing_input, signature)
|
139
|
-
end
|
140
|
-
|
141
|
-
def signature_algorithm_and_key(header, key, &keyfinder)
|
142
|
-
key = yield(header) if keyfinder
|
143
|
-
[header['alg'], key]
|
144
|
-
end
|
145
|
-
|
146
|
-
def verify_signature(algo, key, signing_input, signature)
|
147
|
-
verify_signature_algo(algo, key, signing_input, signature)
|
148
|
-
rescue OpenSSL::PKey::PKeyError
|
149
|
-
raise JWT::VerificationError, 'Signature verification raised'
|
150
|
-
ensure
|
151
|
-
OpenSSL.errors.clear
|
152
|
-
end
|
153
|
-
|
154
|
-
def verify_signature_algo(algo, key, signing_input, signature)
|
155
|
-
if %w(HS256 HS384 HS512).include?(algo)
|
156
|
-
raise(JWT::VerificationError, 'Signature verification raised') unless secure_compare(signature, sign_hmac(algo, signing_input, key))
|
157
|
-
elsif %w(RS256 RS384 RS512).include?(algo)
|
158
|
-
raise(JWT::VerificationError, 'Signature verification raised') unless verify_rsa(algo, key, signing_input, signature)
|
159
|
-
elsif %w(ES256 ES384 ES512).include?(algo)
|
160
|
-
raise(JWT::VerificationError, 'Signature verification raised') unless verify_ecdsa(algo, key, signing_input, signature)
|
161
|
-
else
|
162
|
-
raise JWT::VerificationError, 'Algorithm not supported'
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
# From devise
|
167
|
-
# constant-time comparison algorithm to prevent timing attacks
|
168
|
-
def secure_compare(a, b)
|
169
|
-
return false if a.nil? || b.nil? || a.empty? || b.empty? || a.bytesize != b.bytesize
|
170
|
-
l = a.unpack "C#{a.bytesize}"
|
171
|
-
|
172
|
-
res = 0
|
173
|
-
b.each_byte { |byte| res |= byte ^ l.shift }
|
174
|
-
res.zero?
|
175
|
-
end
|
176
|
-
|
177
|
-
def raw_to_asn1(signature, private_key)
|
178
|
-
byte_size = (private_key.group.degree + 7) / 8
|
179
|
-
r = signature[0..(byte_size - 1)]
|
180
|
-
s = signature[byte_size..-1]
|
181
|
-
OpenSSL::ASN1::Sequence.new([r, s].map { |int| OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(int, 2)) }).to_der
|
182
|
-
end
|
183
|
-
|
184
|
-
def asn1_to_raw(signature, public_key)
|
185
|
-
byte_size = (public_key.group.degree + 7) / 8
|
186
|
-
OpenSSL::ASN1.decode(signature).value.map { |value| value.value.to_s(2).rjust(byte_size, "\x00") }.join
|
21
|
+
Encode.new(payload: payload,
|
22
|
+
key: key,
|
23
|
+
algorithm: algorithm,
|
24
|
+
headers: header_fields).segments
|
187
25
|
end
|
188
26
|
|
189
|
-
def
|
190
|
-
Decode.
|
27
|
+
def decode(jwt, key = nil, verify = true, options = {}, &keyfinder)
|
28
|
+
Decode.new(jwt, key, verify, DEFAULT_OPTIONS.merge(options), &keyfinder).decode_segments
|
191
29
|
end
|
192
30
|
end
|
data/lib/jwt/algos.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jwt/algos/hmac'
|
4
|
+
require 'jwt/algos/eddsa'
|
5
|
+
require 'jwt/algos/ecdsa'
|
6
|
+
require 'jwt/algos/rsa'
|
7
|
+
require 'jwt/algos/ps'
|
8
|
+
require 'jwt/algos/none'
|
9
|
+
require 'jwt/algos/unsupported'
|
10
|
+
|
11
|
+
# JWT::Signature module
|
12
|
+
module JWT
|
13
|
+
# Signature logic for JWT
|
14
|
+
module Algos
|
15
|
+
extend self
|
16
|
+
|
17
|
+
ALGOS = [
|
18
|
+
Algos::Hmac,
|
19
|
+
Algos::Ecdsa,
|
20
|
+
Algos::Rsa,
|
21
|
+
Algos::Eddsa,
|
22
|
+
Algos::Ps,
|
23
|
+
Algos::None,
|
24
|
+
Algos::Unsupported
|
25
|
+
].freeze
|
26
|
+
|
27
|
+
def find(algorithm)
|
28
|
+
indexed[algorithm && algorithm.downcase]
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def indexed
|
34
|
+
@indexed ||= begin
|
35
|
+
fallback = [Algos::Unsupported, nil]
|
36
|
+
ALGOS.each_with_object(Hash.new(fallback)) do |alg, hash|
|
37
|
+
alg.const_get(:SUPPORTED).each do |code|
|
38
|
+
hash[code.downcase] = [alg, code]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module JWT
|
2
|
+
module Algos
|
3
|
+
module Ecdsa
|
4
|
+
module_function
|
5
|
+
|
6
|
+
SUPPORTED = %w[ES256 ES384 ES512].freeze
|
7
|
+
NAMED_CURVES = {
|
8
|
+
'prime256v1' => 'ES256',
|
9
|
+
'secp384r1' => 'ES384',
|
10
|
+
'secp521r1' => 'ES512'
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
def sign(to_sign)
|
14
|
+
algorithm, msg, key = to_sign.values
|
15
|
+
key_algorithm = NAMED_CURVES[key.group.curve_name]
|
16
|
+
if algorithm != key_algorithm
|
17
|
+
raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} signing key was provided"
|
18
|
+
end
|
19
|
+
|
20
|
+
digest = OpenSSL::Digest.new(algorithm.sub('ES', 'sha'))
|
21
|
+
SecurityUtils.asn1_to_raw(key.dsa_sign_asn1(digest.digest(msg)), key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def verify(to_verify)
|
25
|
+
algorithm, public_key, signing_input, signature = to_verify.values
|
26
|
+
key_algorithm = NAMED_CURVES[public_key.group.curve_name]
|
27
|
+
if algorithm != key_algorithm
|
28
|
+
raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} verification key was provided"
|
29
|
+
end
|
30
|
+
digest = OpenSSL::Digest.new(algorithm.sub('ES', 'sha'))
|
31
|
+
public_key.dsa_verify_asn1(digest.digest(signing_input), SecurityUtils.raw_to_asn1(signature, public_key))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module JWT
|
2
|
+
module Algos
|
3
|
+
module Eddsa
|
4
|
+
module_function
|
5
|
+
|
6
|
+
SUPPORTED = %w[ED25519].freeze
|
7
|
+
|
8
|
+
def sign(to_sign)
|
9
|
+
algorithm, msg, key = to_sign.values
|
10
|
+
raise EncodeError, "Key given is a #{key.class} but has to be an RbNaCl::Signatures::Ed25519::SigningKey" if key.class != RbNaCl::Signatures::Ed25519::SigningKey
|
11
|
+
raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key.primitive} signing key was provided" if algorithm.downcase.to_sym != key.primitive
|
12
|
+
key.sign(msg)
|
13
|
+
end
|
14
|
+
|
15
|
+
def verify(to_verify)
|
16
|
+
algorithm, public_key, signing_input, signature = to_verify.values
|
17
|
+
raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{public_key.primitive} verification key was provided" if algorithm.downcase.to_sym != public_key.primitive
|
18
|
+
raise DecodeError, "key given is a #{public_key.class} but has to be a RbNaCl::Signatures::Ed25519::VerifyKey" if public_key.class != RbNaCl::Signatures::Ed25519::VerifyKey
|
19
|
+
public_key.verify(signature, signing_input)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module JWT
|
2
|
+
module Algos
|
3
|
+
module Hmac
|
4
|
+
module_function
|
5
|
+
|
6
|
+
SUPPORTED = %w[HS256 HS512256 HS384 HS512].freeze
|
7
|
+
|
8
|
+
def sign(to_sign)
|
9
|
+
algorithm, msg, key = to_sign.values
|
10
|
+
key ||= ''
|
11
|
+
authenticator, padded_key = SecurityUtils.rbnacl_fixup(algorithm, key)
|
12
|
+
if authenticator && padded_key
|
13
|
+
authenticator.auth(padded_key, msg.encode('binary'))
|
14
|
+
else
|
15
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub('HS', 'sha')), key, msg)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def verify(to_verify)
|
20
|
+
algorithm, public_key, signing_input, signature = to_verify.values
|
21
|
+
authenticator, padded_key = SecurityUtils.rbnacl_fixup(algorithm, public_key)
|
22
|
+
if authenticator && padded_key
|
23
|
+
begin
|
24
|
+
authenticator.verify(padded_key, signature.encode('binary'), signing_input.encode('binary'))
|
25
|
+
rescue RbNaCl::BadAuthenticatorError
|
26
|
+
false
|
27
|
+
end
|
28
|
+
else
|
29
|
+
SecurityUtils.secure_compare(signature, sign(JWT::Signature::ToSign.new(algorithm, signing_input, public_key)))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/jwt/algos/ps.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module JWT
|
2
|
+
module Algos
|
3
|
+
module Ps
|
4
|
+
# RSASSA-PSS signing algorithms
|
5
|
+
|
6
|
+
module_function
|
7
|
+
|
8
|
+
SUPPORTED = %w[PS256 PS384 PS512].freeze
|
9
|
+
|
10
|
+
def sign(to_sign)
|
11
|
+
require_openssl!
|
12
|
+
|
13
|
+
algorithm, msg, key = to_sign.values
|
14
|
+
|
15
|
+
key_class = key.class
|
16
|
+
|
17
|
+
raise EncodeError, "The given key is a #{key_class}. It has to be an OpenSSL::PKey::RSA instance." if key_class == String
|
18
|
+
|
19
|
+
translated_algorithm = algorithm.sub('PS', 'sha')
|
20
|
+
|
21
|
+
key.sign_pss(translated_algorithm, msg, salt_length: :digest, mgf1_hash: translated_algorithm)
|
22
|
+
end
|
23
|
+
|
24
|
+
def verify(to_verify)
|
25
|
+
require_openssl!
|
26
|
+
|
27
|
+
SecurityUtils.verify_ps(to_verify.algorithm, to_verify.public_key, to_verify.signing_input, to_verify.signature)
|
28
|
+
end
|
29
|
+
|
30
|
+
def require_openssl!
|
31
|
+
if Object.const_defined?('OpenSSL')
|
32
|
+
major, minor = OpenSSL::VERSION.split('.').first(2)
|
33
|
+
|
34
|
+
unless major.to_i >= 2 && minor.to_i >= 1
|
35
|
+
raise JWT::RequiredDependencyError, "You currently have OpenSSL #{OpenSSL::VERSION}. PS support requires >= 2.1"
|
36
|
+
end
|
37
|
+
else
|
38
|
+
raise JWT::RequiredDependencyError, 'PS signing requires OpenSSL +2.1'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module JWT
|
2
|
+
module Algos
|
3
|
+
module Rsa
|
4
|
+
module_function
|
5
|
+
|
6
|
+
SUPPORTED = %w[RS256 RS384 RS512].freeze
|
7
|
+
|
8
|
+
def sign(to_sign)
|
9
|
+
algorithm, msg, key = to_sign.values
|
10
|
+
raise EncodeError, "The given key is a #{key.class}. It has to be an OpenSSL::PKey::RSA instance." if key.class == String
|
11
|
+
key.sign(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), msg)
|
12
|
+
end
|
13
|
+
|
14
|
+
def verify(to_verify)
|
15
|
+
SecurityUtils.verify_rsa(to_verify.algorithm, to_verify.public_key, to_verify.signing_input, to_verify.signature)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|