Files
skills/docs/media/image/caddy-imgproxy/src/signing/sign-path.md
2026-05-29 08:20:56 +01:00

3.3 KiB

signImgproxyPath

(no submodules)

Purpose

signImgproxyPath computes the HMAC-SHA256 URL signature that imgproxy requires when it is configured with a key + salt. It is the single source of truth for how the TypeScript port and the upstream Go module agree on bytes: any URL signed here verifies against the Go implementation and vice-versa.

The function decodes the hex-encoded key and salt into raw bytes, concatenates the salt with the UTF-8 encoded path, runs HMAC-SHA256 under the key, and base64url-encodes the digest without padding. Bad hex on either input raises a typed CaddyImgproxyError (INVALID_KEY / INVALID_SALT) so misconfiguration surfaces immediately rather than at the imgproxy boundary.

Features

  • Verbatim byte-level port of the Go signPath function.
  • Pluggable hash via the optional hash parameter — supply a native / HSM / WebCrypto-backed implementation when needed.
  • Hex validation stricter than @suaveplan/crypto-hash's fromHex (lower-case only) to keep wire-format round-trips deterministic.
  • Throws typed CaddyImgproxyError on every failure path.

Usage: Basic

import { signImgproxyPath } from "@suaveplan/caddy-imgproxy";

const signature = signImgproxyPath({
    key: "aa11bbcc",
    salt: "deadbeef",
    path: "/g:ce/rs:fill:800:450/plain/s3://images/example.com/avatar@png",
});
signature; // "E3ytdnTM6THWihFdTWqY4YGQIV-6K969S-8jb4AaE4U"

Usage: Advanced

import { signImgproxyPath, type SignerHashLike } from "@suaveplan/caddy-imgproxy";

// Plug a WebCrypto-backed signer in a Cloudflare Worker:
const wcHash: SignerHashLike = {
    hmac(_algo, key, data) {
        // ... call into crypto.subtle.sign synchronously via a vendored
        // implementation, return the digest as Uint8Array.
        return data;
    },
};

const sig = signImgproxyPath({
    key: "deadbeef",
    salt: "feedface",
    path: "/plain/s3://images/example.com/photo@webp",
    hash: wcHash,
});

API Reference

signImgproxyPath(options: SignImgproxyPathOptions): string

  • Parameters:
    • options.key — lower-hex HMAC key, even length, non-empty.
    • options.salt — lower-hex salt, even length, non-empty.
    • options.path — the imgproxy path being signed.
    • options.hash — optional SignerHashLike injection seam.
  • Returns: base64url-encoded signature, no padding.
  • Throws:
    • CaddyImgproxyError(INVALID_KEY) for malformed / empty / odd-length key.
    • CaddyImgproxyError(INVALID_SALT) for malformed / empty / odd-length salt.

SignerHashLike

Structural type with a single hmac(algorithm, key, data) method returning a Uint8Array. Lets callers swap the default Noble-backed implementation for a native, HSM, or WebCrypto-backed alternative.

Implementation Notes

The function pre-allocates the salt || path buffer in one Uint8Array(saltBytes.length + pathBytes.length) allocation so the hot path never reallocates. UTF-8 encoding goes through TextEncoder, which is available in every modern JS runtime (Node ≥ 14, all browsers, Cloudflare Workers, Deno, Bun). The Go reference uses []byte(path) which is identical for ASCII paths and spec-compliant for arbitrary UTF-8 (the imgproxy upstream uses the same convention).