lib/ey-hmac/adapter.rb in ey-hmac-2.3.0 vs lib/ey-hmac/adapter.rb in ey-hmac-2.3.1

- old
+ new

@@ -1,24 +1,27 @@ +# frozen_string_literal: true + # This class is responsible for forming the canonical string to used to sign requests # @abstract override methods {#method}, {#path}, {#body}, {#content_type} and {#content_digest} class Ey::Hmac::Adapter - AUTHORIZATION_REGEXP = /\w+ ([^:]+):(.+)$/ + AUTHORIZATION_REGEXP = /\w+ ([^:]+):(.+)$/.freeze - autoload :Rack, "ey-hmac/adapter/rack" - autoload :Faraday, "ey-hmac/adapter/faraday" + autoload :Rack, 'ey-hmac/adapter/rack' + autoload :Faraday, 'ey-hmac/adapter/faraday' attr_reader :request, :options, :authorization_header, :service, :sign_with, :accept_digests # @param [Object] request signer-specific request implementation # @option options [Integer] :version signature version # @option options [Integer] :ttl (nil) duration during which HMAC is valid after signed date # @option options [String] :authorization_header ('Authorization') Authorization header key. # @option options [String] :server ('EyHmac') service name prefixed to {#authorization}. set to {#service} # @option options [Symbol] :sign_with (:sha_256) outgoing signature digest algorithm. See {OpenSSL::Digest#new} # @option options [Array] :accepted_digests ([:sha_256]) accepted incoming signature digest algorithm. See {OpenSSL::Digest#new} - def initialize(request, options={}) - @request, @options = request, options + def initialize(request, options = {}) + @request = request + @options = options @ttl = options[:ttl] @authorization_header = options[:authorization_header] || 'Authorization' @service = options[:service] || 'EyHmac' @sign_with = options[:sign_with] || :sha256 @@ -34,14 +37,16 @@ end # @param [String] key_secret private HMAC key # @param [String] signature digest hash function. Defaults to #sign_with # @return [String] HMAC signature of {#request} - def signature(key_secret, digest = self.sign_with) + def signature(key_secret, digest = sign_with) Base64.strict_encode64( OpenSSL::HMAC.digest( - OpenSSL::Digest.new(digest.to_s), key_secret, canonicalize)).strip + OpenSSL::Digest.new(digest.to_s), key_secret, canonicalize + ) + ).strip end # @param [String] key_id public HMAC key # @param [String] key_secret private HMAC key # @return [String] HMAC header value of {#request} @@ -104,11 +109,11 @@ # Check {#authorization_signature} against calculated {#signature} # @yieldparam key_id [String] public HMAC key # @return [Boolean] true if block yields matching private key and signature matches, else false # @see #authenticated! - def authenticated?(options={}, &block) + def authenticated?(_options = {}, &block) authenticated!(&block) rescue Ey::Hmac::Error false end @@ -117,22 +122,19 @@ key_id, signature_value = check_signature! key_secret = block.call(key_id) unless key_secret raise Ey::Hmac::MissingSecret, - "Failed to find secret matching #{key_id.inspect}" + "Failed to find secret matching #{key_id.inspect}" end check_ttl! calculated_signatures = accept_digests.map { |ad| signature(key_secret, ad) } matching_signature = calculated_signatures.any? { |cs| secure_compare(signature_value, cs) } - unless matching_signature - raise Ey::Hmac::SignatureMismatch, - "Calculated signature #{signature_value} does not match #{calculated_signatures.inspect} using #{canonicalize.inspect}" - end + raise Ey::Hmac::SignatureMismatch unless matching_signature true end alias authenticate! authenticated! @@ -141,34 +143,35 @@ # Constant time string comparison. # pulled from https://github.com/rack/rack/blob/master/lib/rack/utils.rb#L399 def secure_compare(a, b) return false unless a.bytesize == b.bytesize - l = a.unpack("C*") + l = a.unpack('C*') - r, i = 0, -1 - b.each_byte { |v| r |= v ^ l[i+=1] } - r == 0 + r = 0 + i = -1 + b.each_byte { |v| r |= v ^ l[i += 1] } + r.zero? end def check_ttl! if @ttl && date expiry = Time.parse(date).to_i + @ttl current_time = Time.now.to_i unless expiry > current_time raise Ey::Hmac::ExpiredHmac, - "Signature has expired passed #{expiry}. Current time is #{current_time}" + "Signature has expired passed #{expiry}. Current time is #{current_time}" end end end def check_signature! authorization_match = AUTHORIZATION_REGEXP.match(authorization_signature) unless authorization_match raise Ey::Hmac::MissingAuthorization, - "Failed to parse authorization_signature #{authorization_signature}" + "Failed to parse authorization_signature #{authorization_signature}" end [authorization_match[1], authorization_match[2]] end end