class Cryptopay::Callbacks

Attributes

secret[R]

Public Class Methods

new(secret) click to toggle source
# File lib/cryptopay/callbacks.rb, line 5
def initialize(secret)
  @secret = secret
end

Public Instance Methods

verify(body, signature) click to toggle source

Verifies callback body and builds Callback object @param body [String] Raw request body string @param signature [String] Value of the X-Cryptopay-Signature header @return [Object] Callback

# File lib/cryptopay/callbacks.rb, line 13
def verify(body, signature)
  expected_signature = OpenSSL::HMAC.hexdigest('SHA256', secret, body)

  equals = secure_compare(signature, expected_signature)
  raise(SignatureVerificationError, 'Signature mismatch') unless equals

  data = JSON.parse(body, symbolize_names: true)
  Callback.build_from_hash(data)
end

Private Instance Methods

secure_compare(str1, str2) click to toggle source

Constant-time comparison algorithm to prevent timing attacks

# File lib/cryptopay/callbacks.rb, line 28
def secure_compare(str1, str2)
  return false if str1.empty? || str2.empty? || str1.bytesize != str2.bytesize

  l = str1.unpack("C#{str1.bytesize}")

  res = 0
  str2.each_byte { |byte| res |= byte ^ l.shift }
  res.zero?
end