lib/jwt.rb in jwt-0.1.8 vs lib/jwt.rb in jwt-0.1.10
- old
+ new
@@ -9,71 +9,76 @@
require "multi_json"
module JWT
class DecodeError < StandardError; end
- def self.sign(algorithm, msg, key)
+ module_function
+
+ def sign(algorithm, msg, key)
if ["HS256", "HS384", "HS512"].include?(algorithm)
sign_hmac(algorithm, msg, key)
elsif ["RS256", "RS384", "RS512"].include?(algorithm)
sign_rsa(algorithm, msg, key)
else
raise NotImplementedError.new("Unsupported signing method")
end
end
- def self.sign_rsa(algorithm, msg, private_key)
- private_key.sign(OpenSSL::Digest::Digest.new(algorithm.sub('RS', 'sha')), msg)
+ def sign_rsa(algorithm, msg, private_key)
+ private_key.sign(OpenSSL::Digest.new(algorithm.sub("RS", "sha")), msg)
end
- def self.verify_rsa(algorithm, public_key, signing_input, signature)
- public_key.verify(OpenSSL::Digest::Digest.new(algorithm.sub('RS', 'sha')), signature, signing_input)
+ def verify_rsa(algorithm, public_key, signing_input, signature)
+ public_key.verify(OpenSSL::Digest.new(algorithm.sub("RS", "sha")), signature, signing_input)
end
- def self.sign_hmac(algorithm, msg, key)
- OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new(algorithm.sub('HS', 'sha')), key, msg)
+ def sign_hmac(algorithm, msg, key)
+ OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub("HS", "sha")), key, msg)
end
- def self.base64url_decode(str)
- str += '=' * (4 - str.length.modulo(4))
- Base64.decode64(str.gsub("-", "+").gsub("_", "/"))
+ def base64url_decode(str)
+ str += "=" * (4 - str.length.modulo(4))
+ Base64.decode64(str.tr("-_", "+/"))
end
- def self.base64url_encode(str)
- Base64.encode64(str).gsub("+", "-").gsub("/", "_").gsub("\n", "").gsub('=', '')
+ def base64url_encode(str)
+ Base64.encode64(str).tr("-_", "+/").gsub(/[\n=]/, "")
end
- def self.encode(payload, key, algorithm='HS256', header_fields={})
+ def encode(payload, key, algorithm="HS256", header_fields={})
algorithm ||= "none"
segments = []
header = {"typ" => "JWT", "alg" => algorithm}.merge(header_fields)
segments << base64url_encode(MultiJson.encode(header))
segments << base64url_encode(MultiJson.encode(payload))
- signing_input = segments.join('.')
- if algorithm != "none"
+ signing_input = segments.join(".")
+ if algorithm == "none"
+ segments << ""
+ else
signature = sign(algorithm, signing_input, key)
segments << base64url_encode(signature)
- else
- segments << ""
end
- segments.join('.')
+ segments.join(".")
end
- def self.decode(jwt, key=nil, verify=true, &keyfinder)
- segments = jwt.split('.')
+ def decode(jwt, key=nil, verify=true, &keyfinder)
+ segments = jwt.split(".")
raise JWT::DecodeError.new("Not enough or too many segments") unless [2,3].include? segments.length
header_segment, payload_segment, crypto_segment = segments
- signing_input = [header_segment, payload_segment].join('.')
+ signing_input = [header_segment, payload_segment].join(".")
begin
header = MultiJson.decode(base64url_decode(header_segment))
payload = MultiJson.decode(base64url_decode(payload_segment))
- signature = base64url_decode(crypto_segment) if verify
- rescue MultiJson::LoadError => e
+ signature = base64url_decode(crypto_segment.to_s) if verify
+ rescue MultiJson::LoadError
raise JWT::DecodeError.new("Invalid segment encoding")
end
+
+ raise JWT::DecodeError.new("Not enough or too many segments") unless header && payload
+
if verify
- algo = header['alg']
+ algo = header["alg"]
if keyfinder
key = keyfinder.call(header)
end
@@ -85,17 +90,19 @@
else
raise JWT::DecodeError.new("Algorithm not supported")
end
rescue OpenSSL::PKey::PKeyError
raise JWT::DecodeError.new("Signature verification failed")
+ ensure
+ OpenSSL.errors.clear
end
end
payload
end
# From devise
# constant-time comparison algorithm to prevent timing attacks
- def self.secure_compare(a, b)
+ def secure_compare(a, b)
return false if a.nil? || b.nil? || a.empty? || b.empty? || a.bytesize != b.bytesize
l = a.unpack "C#{a.bytesize}"
res = 0
b.each_byte { |byte| res |= byte ^ l.shift }