Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Docs know what code they describe; a project's docs folder in Docs; Docs events; files on any S3 store | 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; | |
| 3 | ||
| 4 | import { amzDate, sha256Hex, sign, uriEncode } from "./sigv4.ts"; | |
| 5 | ||
| 6 | const EMPTY = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; | |
| 7 | ||
| 8 | // AWS's SigV4 test suite, `get-vanilla`: the plainest request there is. | |
| 9 | test("signs AWS's get-vanilla test vector", async () => { | |
| 10 | const signed = await sign({ | |
| 11 | method: "GET", | |
| 12 | url: "https://example.amazonaws.com/", | |
| 13 | payload_hash: EMPTY, | |
| 14 | region: "us-east-1", | |
| 15 | service: "service", | |
| 16 | credentials: { access_key_id: "AKIDEXAMPLE", secret_access_key: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY" }, | |
| 17 | date: new Date("2015-08-30T12:36:00Z"), | |
| 18 | }); | |
| 19 | assert.equal(signed.canonical_request, `GET\n/\n\nhost:example.amazonaws.com\nx-amz-date:20150830T123600Z\n\nhost;x-amz-date\n${EMPTY}`); | |
| 20 | assert.equal(signed.string_to_sign, "AWS4-HMAC-SHA256\n20150830T123600Z\n20150830/us-east-1/service/aws4_request\nbb579772317eb040ac9ed261061d46c1f17a8133879d6129b6e1c25292927e63"); | |
| 21 | assert.equal(signed.signature, "5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31"); | |
| 22 | assert.equal( | |
| 23 | signed.headers.authorization, | |
| 24 | "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31", | |
| 25 | ); | |
| 26 | }); | |
| 27 | ||
| 28 | // The S3 documentation's worked example: GET Object with a Range header. | |
| 29 | test("signs the S3 GET Object example", async () => { | |
| 30 | const signed = await sign({ | |
| 31 | method: "GET", | |
| 32 | url: "https://examplebucket.s3.amazonaws.com/test.txt", | |
| 33 | headers: { range: "bytes=0-9", "x-amz-content-sha256": EMPTY }, | |
| 34 | payload_hash: EMPTY, | |
| 35 | region: "us-east-1", | |
| 36 | service: "s3", | |
| 37 | credentials: { access_key_id: "AKIAIOSFODNN7EXAMPLE", secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" }, | |
| 38 | date: new Date("2013-05-24T00:00:00Z"), | |
| 39 | }); | |
| 40 | assert.equal(signed.signature, "f0e8bdb87c964420e857bd35b5d6ed310bd44f0170aba48dd91039c6036bdb41"); | |
| 41 | assert.match(signed.headers.authorization!, /SignedHeaders=host;range;x-amz-content-sha256;x-amz-date,/); | |
| 42 | }); | |
| 43 | ||
| 44 | test("hashes and encodes as SigV4 wants", async () => { | |
| 45 | assert.equal(await sha256Hex(""), EMPTY); | |
| 46 | assert.equal(uriEncode("a b/c*~"), "a%20b%2Fc%2A~"); | |
| 47 | assert.equal(amzDate(new Date("2015-08-30T12:36:00.123Z")), "20150830T123600Z"); | |
| 48 | }); | |
| 49 | ||
| 50 | test("puts the query in order", async () => { | |
| 51 | const signed = await sign({ | |
| 52 | method: "GET", | |
| 53 | url: "https://example.amazonaws.com/?Param2=value2&Param1=value1", | |
| 54 | payload_hash: EMPTY, | |
| 55 | region: "us-east-1", | |
| 56 | service: "service", | |
| 57 | credentials: { access_key_id: "AKIDEXAMPLE", secret_access_key: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY" }, | |
| 58 | date: new Date("2015-08-30T12:36:00Z"), | |
| 59 | }); | |
| 60 | assert.equal(signed.canonical_request.split("\n")[2], "Param1=value1&Param2=value2"); | |
| 61 | // AWS's `get-vanilla-query-order-key-case`. | |
| 62 | assert.equal(signed.signature, "b97d918cfa904a5beff61c982a1b6f458b799221646efd99d3219ec94cdf2500"); | |
| 63 | }); |