Class: Shmac::SignatureCalculator

Inherits:
Object
  • Object
show all
Defined in:
lib/shmac/signature_calculator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(secret:, request:, header_namespace: nil) ⇒ SignatureCalculator

Returns a new instance of SignatureCalculator.



8
9
10
11
12
# File 'lib/shmac/signature_calculator.rb', line 8

def initialize secret:, request:, header_namespace: nil
  @secret = secret
  @request = request
  @header_namespace = header_namespace.downcase if header_namespace
end

Instance Attribute Details

#header_namespaceObject (readonly)

Returns the value of attribute header_namespace.



6
7
8
# File 'lib/shmac/signature_calculator.rb', line 6

def header_namespace
  @header_namespace
end

#requestObject (readonly)

Returns the value of attribute request.



6
7
8
# File 'lib/shmac/signature_calculator.rb', line 6

def request
  @request
end

#secretObject (readonly)

Returns the value of attribute secret.



6
7
8
# File 'lib/shmac/signature_calculator.rb', line 6

def secret
  @secret
end

Instance Method Details

#canonicalized_platform_headersObject



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/shmac/signature_calculator.rb', line 42

def canonicalized_platform_headers
  return unless self.header_namespace

  normalize_key = -> (key) { key.to_s.downcase.strip }
  normalize_value = -> (value) { value.to_s.strip }
  canonicalized_header_row = -> (k,v) {
    "%s:%s" % [normalize_key.(k), normalize_value.(v)]
  }
  matches_namespace = ->(value) { value.start_with?(header_namespace) }

  self.request.headers
    .map(&canonicalized_header_row)
    .find_all(&matches_namespace)
    .sort
    .join("\n")
end

#signatureObject



18
19
20
21
22
# File 'lib/shmac/signature_calculator.rb', line 18

def signature
  digest = OpenSSL::Digest.new "sha1"
  hmac = OpenSSL::HMAC.digest digest, secret, string_to_sign
  Base64.strict_encode64 hmac
end

#string_to_signObject



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/shmac/signature_calculator.rb', line 24

def string_to_sign
  parts = [
    request.method,
    request.content_md5,
    request.content_type,
    request.date(self.header_namespace)
  ]

  platform_headers = canonicalized_platform_headers.to_s.strip
  parts << platform_headers unless platform_headers.empty?

  # The path is expected by spec but the DPO sends the same message (including headers) to several endpoints
  # We introduce an api version so we do not lose messages
  parts << request.path unless request.api_version > 0

  parts.join("\n")
end

#to_sObject



14
15
16
# File 'lib/shmac/signature_calculator.rb', line 14

def to_s
  signature
end