Module: Linzer::Signer

Extended by:
Common
Defined in:
lib/linzer/signer.rb

Overview

Handles HTTP message signing according to RFC 9421.

This module provides the core signing functionality. It creates signatures by computing a signature base from the message components and signing it with the provided key.

Examples:

Direct usage (prefer Linzer.sign for convenience)

message = Linzer::Message.new(request)
components = %w[@method @path content-type]
signature = Linzer::Signer.sign(key, message, components)

See Also:

Constant Summary collapse

DEFAULT_LABEL =

Default label used for signatures when none is specified.

"sig1"

Class Method Summary collapse

Methods included from Common

signature_base, signature_base_line, signature_params_line

Class Method Details

.default_labelString

Returns the default signature label.



86
87
88
# File 'lib/linzer/signer.rb', line 86

def default_label
  DEFAULT_LABEL
end

.sign(key, message, components, options = {}) ⇒ Linzer::Signature

Signs an HTTP message.

Creates a signature by:

  1. Serializing the component identifiers

  2. Building the signature base from the message and parameters

  3. Signing the signature base with the key

  4. Returning a Signature object with the result

Examples:

Basic signing

signature = Linzer::Signer.sign(key, message, %w[@method @path])

With all options

signature = Linzer::Signer.sign(key, message, %w[@method @path date],
  created: Time.now.to_i,
  keyid: "my-key-2024",
  label: "request-sig",
  nonce: SecureRandom.hex(16),
  tag: "my-app"
)

Options Hash (options):

  • :created (Integer)

    Unix timestamp for signature creation. Defaults to the current UTC time.

  • :keyid (String)

    Key identifier. If not provided, uses the key’s key_id if available.

  • :label (String)

    The signature label (defaults to “sig1”). Multiple signatures on a message must have distinct labels.

  • :nonce (String)

    A unique nonce value to prevent replay

  • :tag (String)

    Application-specific tag

  • :expires (Integer)

    Unix timestamp when signature expires

  • :alg (String)

    Algorithm identifier (usually inferred from key)

Raises:

  • (SigningError)

    If the message, key, or components are invalid

  • (SigningError)

    If required components are missing from the message

  • (SigningError)

    If components are duplicated

  • (SigningError)

    If ‘@signature-params` is included in components



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/linzer/signer.rb', line 70

def sign(key, message, components, options = {})
  serialized_components = FieldId.serialize_components(Array(components))
  validate key, message, serialized_components

  parameters = populate_parameters(key, options)
  signature_base = signature_base(message, serialized_components, parameters)

  signature = key.sign(signature_base)
  label = options[:label] || DEFAULT_LABEL

  Linzer::Signature.build(serialize(signature, serialized_components, parameters, label))
end