sigflint 0.0.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0 - 2026-10-16
4
+
5
+ First version: AWS Signature Version 4 signing for every AWS service.
6
+
7
+ - `getAuthHeaders(request, credentials)` returns the headers to send, for S3 and, with `request.service`, any other service. It never modifies the request or its URL.
8
+ - `presign(request, credentials)` returns a presigned URL.
9
+ - `getAuthHeadersV4a` and `presignV4a` sign with SigV4a (ECDSA P-256) for the regions in `request.regionSet`.
10
+ - `chunkSigner(authHeaders, credentials)` signs aws-chunked uploads, with signed trailing headers; `eventSigner(authHeaders, credentials)` signs event-stream messages.
11
+ - Session tokens (`credentials.sessionToken`) and unsigned payloads (`request.unsignedPayload`).
12
+ - Path and query encoding, query sorting and header trimming follow the specification; a raw `+` in an S3 path is a space, as S3 reads it. Other services normalise the path and encode it twice.
13
+ - Input that cannot be signed correctly throws: `signHeaders` that name `x-amz-date`, `authorization` or `__proto__` or hold a line break, a presigned URL that is not http or https or is already presigned, an `expires` outside 1 to 604800 seconds, and the headers of a SigV4a signature given to `chunkSigner` or `eventSigner`. An empty chunk is not signed, because it would end the upload.
14
+ - No dependencies. Node.js 22.12 and later, Bun, Deno and Cloudflare Workers; the signing-key cache is shared by an entry's signers.
15
+ - Each signer is its own module and export, so a bundle holds only what it imports. Node and Bun load one built file (`dist/`) instead of six modules; the `workerd`, `worker` and `browser` conditions and bundlers keep the per-signer modules.
16
+ - Cloudflare Workers and browsers get a WebCrypto implementation through the `workerd`, `worker` and `browser` export conditions, with or without `nodejs_compat`. There every signer returns a promise (the chunk and event signers' methods do); the types are `x | Promise<x>`, so always `await`. `sigflint/web` imports that implementation directly.
17
+ - Speed, memory and size are measured against six other libraries (`docs/benchmarks.md`, `bench/`).
package/README.md CHANGED
@@ -1,5 +1,101 @@
1
- # sigflint
1
+ <h1 align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/banner-dark.png">
4
+ <img src="docs/assets/banner-light.png" alt="sigflint: Fast SigV4 and SigV4a signing for every AWS service" width="100%">
5
+ </picture>
6
+ </h1>
2
7
 
3
- This version only reserves the package name. It contains no code. sigflint 1.0.0 follows.
8
+ Fast AWS Signature Version 4 request signing for every AWS service, with no dependencies. It runs on Node.js, Bun, Deno, Cloudflare Workers and browsers.
4
9
 
5
- Source: https://github.com/bompus/sigflint
10
+ ```js
11
+ import { getAuthHeaders } from 'sigflint';
12
+
13
+ const url = new URL('https://my-bucket.s3.us-east-1.amazonaws.com/photos/cat.jpg');
14
+ const headers = await getAuthHeaders(
15
+ { method: 'GET', url, region: 'us-east-1' },
16
+ { accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY },
17
+ );
18
+ const response = await fetch(url, { headers });
19
+ ```
20
+
21
+ It signs requests with the `Authorization` header or as a presigned URL, for S3 and for any other service (`service: 'dynamodb'`, `'sqs'`, `'execute-api'`, ...), and it also does multi-region signatures (SigV4a), chunked uploads and event streams.
22
+
23
+ - **Correct.** It returns the same signature as botocore for all 3,360 S3 requests in its test corpus, and for 1,622 requests to other services and 1,600 presigned URLs. For S3, botocore signs the request after this repository's own path and query normalization (`conformance/oracle.py`), so that step is not checked independently by the corpus; the four S3 examples published by AWS, which are in it, are. SigV4a signatures verify against the AWS CRT's, and chunk and event signatures match the AWS SDK's. See [how it is tested](docs/benchmarks.md#how-it-is-tested).
24
+ - **Fast.** 1.3 to 3.7 µs per header or presigned-URL signature on Node and 1.5 to 5.1 µs on Bun. The other libraries take 2.4 to 507 times as long on the requests they sign correctly (one Bun presigned-URL comparison with `minio` is not clear and is left out). See [speed](docs/benchmarks.md#speed).
25
+ - **Small, and you pay only for what you import.** Signing headers is 5.7 kB minified, 2.8 kB gzipped; presigned URLs, SigV4a, chunked uploads and event streams each add to a bundle only when imported. Nothing to install with it. See [size](docs/benchmarks.md#size).
26
+ - **Everywhere.** One import on Node, Bun, Deno and Cloudflare Workers, with or without `nodejs_compat`. See [runtimes](#runtimes).
27
+
28
+ ## Install
29
+
30
+ ```sh
31
+ npm install sigflint
32
+ ```
33
+
34
+ Node.js 22.12 or newer (it is an ES module; Node 22.12 can also `require()` it). Bun and Deno need no setup.
35
+
36
+ ## Usage
37
+
38
+ Sign a request and send the returned headers with it. The `host` header is signed but not returned; your HTTP client sets it from the URL.
39
+
40
+ ```js
41
+ import { getAuthHeaders } from 'sigflint';
42
+
43
+ const credentials = { accessKeyId, secretAccessKey, sessionToken }; // sessionToken is optional
44
+
45
+ // upload an object: the body is hashed into x-amz-content-sha256
46
+ const url = new URL('https://my-bucket.s3.us-east-1.amazonaws.com/notes/today.json');
47
+ const body = JSON.stringify({ done: true });
48
+ const headers = await getAuthHeaders(
49
+ { method: 'PUT', url, region: 'us-east-1', body, signHeaders: { 'content-type': 'application/json' } },
50
+ credentials,
51
+ );
52
+ await fetch(url, { method: 'PUT', headers, body });
53
+ ```
54
+
55
+ For a large or binary body, skip hashing and send `unsignedPayload: true`. S3 accepts that over HTTPS.
56
+
57
+ ```js
58
+ const headers = await getAuthHeaders({ method: 'PUT', url, region, unsignedPayload: true }, credentials);
59
+ ```
60
+
61
+ For another S3-compatible service, pass its region name and URL (`https://us-sea-1.linodeobjects.com/bucket/key`, `http://127.0.0.1:9000/bucket/key`). These are examples of the form, not endpoints that were tried: signatures are checked against botocore, the AWS CRT, the AWS SDK's signer and the AWS documentation examples, and nothing has been sent to AWS S3 or any other server, so a service that canonicalizes requests differently from S3 may reject them.
62
+
63
+ More in the [guide](docs/guide.md): [other services](docs/guide.md#other-services), [presigned URLs](docs/guide.md#presigned-urls), [SigV4a](docs/guide.md#sigv4a-multi-region), [chunked uploads](docs/guide.md#chunked-uploads), [event streams](docs/guide.md#event-streams), why to always `await`, and the [full API](docs/guide.md#api).
64
+
65
+ ## Runtimes
66
+
67
+ Node.js 22.12 and later, Bun, Deno, and Cloudflare Workers with or without `nodejs_compat`; browsers get the same WebCrypto code. Each runtime was checked against botocore's signature for one S3 request. The grid, with the other libraries, is in the [benchmarks](docs/benchmarks.md#runtimes).
68
+
69
+ ## Benchmarks
70
+
71
+ <picture>
72
+ <source media="(prefers-color-scheme: dark)" srcset="docs/speed-dark.svg">
73
+ <img alt="Bar chart: time in microseconds to sign one S3 request on Node.js and Bun, for sigflint and six other libraries" src="docs/speed-light.svg">
74
+ </picture>
75
+
76
+ Correctness, [speed](docs/benchmarks.md#speed), [memory](docs/benchmarks.md#memory) and [size](docs/benchmarks.md#size), the [test corpora](docs/benchmarks.md#how-it-is-tested) and the [methodology and limits](docs/benchmarks.md#methodology-and-limits) are in [docs/benchmarks.md](docs/benchmarks.md). Every figure there comes from raw results committed in `bench/results/`. The speed, memory and import figures were measured on the code in this release and are re-run before each release.
77
+
78
+ ## Scope
79
+
80
+ 1.0 signs requests for every AWS service in header form and as presigned URLs, plus SigV4a, chunked uploads and event streams. Not included, and not promised:
81
+
82
+ - hashing binary request bodies for you: hash them yourself, or use `unsignedPayload`
83
+ - an HTTP client, retries, credential providers or region lookup
84
+ - anything that is not SigV4 or SigV4a
85
+
86
+ Open an issue describing the use case if you need one of them.
87
+
88
+ ## Security
89
+
90
+ See [SECURITY.md](SECURITY.md). sigflint never logs credentials or writes them anywhere. Its signing-key caches keep secret keys in process memory: each cached signing key (up to 1,000 per cache) is stored under a lookup string that contains the secret access key it was derived from.
91
+
92
+ ## Sponsoring
93
+
94
+ sigflint is built and maintained by one person. If it saves you time, you can
95
+ sponsor it monthly or once through
96
+ [GitHub Sponsors](https://github.com/sponsors/bompus), or leave a tip on
97
+ [Ko-fi](https://ko-fi.com/bompus).
98
+
99
+ ## License
100
+
101
+ [MIT](LICENSE). `CODE_OF_CONDUCT.md` is the Contributor Covenant under CC BY 4.0; see `THIRD_PARTY_NOTICES.md`.