/** * Minimal AWS Signature Version 4 — exactly the subset the S3 segment * store needs (header-signed requests and presigned GET URLs), hand-rolled * per the dependency-light doctrine: SigV4 is small and * well-specified, so no SDK. * * Runtime-neutral: the crypto primitives are Web Crypto * (`crypto.subtle`), not `node:crypto`, so this module runs unchanged on * Cloudflare Workers / Deno / browsers as well as Bun/Node. `crypto.subtle` * is async, so signing is async throughout; the `S3SegmentStore` consumers * are already async, and the `DelegatedPresignConfig.presign` seam already * accepts a `Promise`. * * Pinned by the published AWS SigV4 example vectors in * `test/sigv4.test.ts`; the hermetic S3 stub re-derives every signature * from the incoming request, so an asymmetric signing bug fails tests. */ export interface SigV4Credentials { readonly accessKeyId: string; readonly secretAccessKey: string; /** Optional STS session token (signed as `x-amz-security-token`). */ readonly sessionToken?: string; } /** Hex SHA-256 of an empty body — the payload hash for GET/HEAD/DELETE. */ export declare const EMPTY_PAYLOAD_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; /** The presigned-URL payload sentinel (S3 presigns never hash the body). */ export declare const UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD"; export declare function sha256Hex(data: Uint8Array | string): Promise; /** * AWS canonical URI-encoding: RFC 3986 unreserved characters only — * stricter than `encodeURIComponent` (which leaves `!'()*` alone). */ export declare function uriEncode(value: string, encodeSlash: boolean): string; /** `YYYYMMDD'T'HHMMSS'Z'` plus its date-only prefix, from epoch ms. */ export declare function amzTimestamps(nowMs: number): { amzDate: string; dateStamp: string; }; export interface CanonicalRequestArgs { readonly method: string; /** The URI-encoded absolute path exactly as sent on the request line. */ readonly canonicalPath: string; /** Decoded query pairs; `X-Amz-Signature` must already be excluded. */ readonly query: Iterable; /** Only the headers being signed (name → raw value). */ readonly headers: Readonly>; readonly payloadHash: string; } export declare function canonicalRequest(args: CanonicalRequestArgs): { text: string; signedHeaders: string; }; export declare function stringToSign(amzDate: string, scope: string, canonicalRequestText: string): Promise; export declare function sigV4Signature(args: { readonly secretAccessKey: string; readonly dateStamp: string; readonly region: string; readonly service: string; readonly stringToSign: string; }): Promise; export interface SignRequestArgs { readonly method: string; /** Full request URL (host is taken from here and always signed). */ readonly url: URL; readonly region: string; /** Defaults to `s3`. */ readonly service?: string; readonly credentials: SigV4Credentials; readonly nowMs: number; /** Hex SHA-256 of the request body (`EMPTY_PAYLOAD_SHA256` if none). */ readonly payloadHash: string; /** Extra headers to send *and* sign (e.g. content-type, x-amz-meta-*). */ readonly headers?: Readonly>; } /** * Headers for a header-authenticated request: the caller's headers plus * `x-amz-date`, `x-amz-content-sha256`, optional `x-amz-security-token`, * and `authorization`. `host` is signed but not returned — fetch derives * it from the URL. */ export declare function signRequest(args: SignRequestArgs): Promise>; export interface PresignArgs { /** Defaults to `GET`. */ readonly method?: string; /** Object URL without any `X-Amz-*` query parameters. */ readonly url: URL; readonly region: string; /** Defaults to `s3`. */ readonly service?: string; readonly credentials: SigV4Credentials; readonly nowMs: number; readonly expiresSeconds: number; } /** Query-authenticated (presigned) URL; only the `host` header is signed. */ export declare function presignUrl(args: PresignArgs): Promise;