Class: Philiprehberger::WebhookSignature::Signer

Inherits:
Object
  • Object
show all
Defined in:
lib/philiprehberger/webhook_signature/signer.rb

Overview

Signs payloads with HMAC and a timestamp for replay prevention.

Constant Summary collapse

SUPPORTED_ALGORITHMS =
{
  sha256: 'SHA256',
  sha512: 'SHA512'
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(secret, algorithm: :sha256) ⇒ Signer

Returns a new instance of Signer.

Parameters:

  • secret (String)

    the shared secret key

  • algorithm (Symbol) (defaults to: :sha256)

    HMAC digest algorithm (:sha256 or :sha512)

Raises:

  • (ArgumentError)


17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/philiprehberger/webhook_signature/signer.rb', line 17

def initialize(secret, algorithm: :sha256)
  raise ArgumentError, 'Secret must be a non-empty string' if secret.nil? || secret.empty?

  unless SUPPORTED_ALGORITHMS.key?(algorithm)
    raise ArgumentError,
          "Unsupported algorithm: #{algorithm.inspect}. Supported algorithms: #{SUPPORTED_ALGORITHMS.keys.map(&:inspect).join(', ')}"
  end

  @secret = secret
  @algorithm = algorithm
  @digest_name = SUPPORTED_ALGORITHMS.fetch(algorithm)
end

Instance Method Details

#sign(payload, timestamp: Time.now.to_i) ⇒ Hash

Sign a payload.

Parameters:

  • payload (String)

    the raw payload body

  • timestamp (Integer) (defaults to: Time.now.to_i)

    Unix timestamp (default: current time)

Returns:

  • (Hash)

    signature components { timestamp:, signature: }



35
36
37
38
# File 'lib/philiprehberger/webhook_signature/signer.rb', line 35

def sign(payload, timestamp: Time.now.to_i)
  signature = compute_signature(payload, timestamp)
  { timestamp: timestamp, signature: signature }
end

#sign_header(payload, timestamp: Time.now.to_i) ⇒ String

Build a signature header value.

Parameters:

  • payload (String)

    the raw payload body

  • timestamp (Integer) (defaults to: Time.now.to_i)

    Unix timestamp (default: current time)

Returns:

  • (String)

    header value in “t=TIMESTAMP,v1=SIGNATURE” format



45
46
47
48
# File 'lib/philiprehberger/webhook_signature/signer.rb', line 45

def sign_header(payload, timestamp: Time.now.to_i)
  signature = compute_signature(payload, timestamp)
  "t=#{timestamp},v1=#{signature}"
end