sigflint 1.0.1 → 1.0.2
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 +8 -0
- package/README.md +10 -6
- package/dist/bun.js +259 -140
- package/dist/node.js +273 -149
- package/index.d.ts +8 -2
- package/package.json +47 -38
- package/src/base.js +261 -58
- package/src/bun.js +11 -0
- package/src/chunks.js +65 -20
- package/src/ecdsa-node.js +16 -1
- package/src/events.js +44 -6
- package/src/node.js +30 -4
- package/src/presign.js +78 -12
- package/src/v4a.js +89 -19
- package/src/web.js +194 -29
- package/types/base.d.ts +80 -33
- package/types/chunks.d.ts +37 -11
- package/types/ecdsa-node.d.ts +7 -2
- package/types/events.d.ts +26 -6
- package/types/presign.d.ts +20 -10
- package/types/v4a.d.ts +42 -13
package/dist/bun.js
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
|
+
// @bun
|
|
1
2
|
// src/bun.js
|
|
2
|
-
import crypto2 from "
|
|
3
|
+
import crypto2 from "crypto";
|
|
3
4
|
|
|
4
5
|
// src/base.js
|
|
5
6
|
var emptyBodyHash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
|
|
6
|
-
var symmetric = {
|
|
7
|
+
var symmetric = {
|
|
8
|
+
algorithm: "AWS4-HMAC-SHA256",
|
|
9
|
+
scope: (date, region, service) => `${date}/${region}/${service}/aws4_request`
|
|
10
|
+
};
|
|
7
11
|
var reSafePath = /^[A-Za-z0-9\-._~/]*$/;
|
|
8
12
|
var reSafeQuery = /^[A-Za-z0-9\-._~=&]*$/;
|
|
9
13
|
var reSpaces = /[ \t]+/g;
|
|
10
|
-
var reDirty = /\t|
|
|
14
|
+
var reDirty = /\t| {2}/;
|
|
11
15
|
var pathTable;
|
|
12
16
|
var queryTable;
|
|
13
17
|
function tables() {
|
|
14
|
-
if (pathTable !==
|
|
18
|
+
if (pathTable !== undefined) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
15
21
|
pathTable = new Array(256);
|
|
16
22
|
queryTable = new Array(256);
|
|
17
|
-
for (let b = 0;
|
|
23
|
+
for (let b = 0;b < 256; b++) {
|
|
18
24
|
const c = String.fromCharCode(b);
|
|
19
25
|
const unreserved = /[A-Za-z0-9\-._~]/.test(c);
|
|
20
26
|
const escaped = (b < 16 ? "%0" : "%") + b.toString(16).toUpperCase();
|
|
@@ -23,18 +29,26 @@ function tables() {
|
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
function hexValue(code) {
|
|
26
|
-
if (code >= 48 && code <= 57)
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
if (code >= 48 && code <= 57) {
|
|
33
|
+
return code - 48;
|
|
34
|
+
}
|
|
35
|
+
if (code >= 65 && code <= 70) {
|
|
36
|
+
return code - 55;
|
|
37
|
+
}
|
|
38
|
+
if (code >= 97 && code <= 102) {
|
|
39
|
+
return code - 87;
|
|
40
|
+
}
|
|
29
41
|
return -1;
|
|
30
42
|
}
|
|
31
43
|
function canonicalEncode(string, table) {
|
|
32
44
|
let out = "";
|
|
33
45
|
let start = 0;
|
|
34
|
-
for (let i = 0;
|
|
46
|
+
for (let i = 0;i < string.length; i++) {
|
|
35
47
|
const code = string.charCodeAt(i);
|
|
36
48
|
const same = table[code];
|
|
37
|
-
if (same.length === 1 && code !== 43)
|
|
49
|
+
if (same.length === 1 && code !== 43) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
38
52
|
out += string.slice(start, i);
|
|
39
53
|
start = i + 1;
|
|
40
54
|
if (code === 37) {
|
|
@@ -56,21 +70,32 @@ function canonicalEncode(string, table) {
|
|
|
56
70
|
function canonicalPathGeneral(pathname) {
|
|
57
71
|
const parts = pathname.split("/");
|
|
58
72
|
const kept = [];
|
|
59
|
-
for (let i = 0;
|
|
73
|
+
for (let i = 0;i < parts.length; i++) {
|
|
60
74
|
const part = parts[i];
|
|
61
|
-
if (part === "" || part === ".")
|
|
62
|
-
|
|
63
|
-
|
|
75
|
+
if (part === "" || part === ".") {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (part === "..") {
|
|
79
|
+
kept.pop();
|
|
80
|
+
} else {
|
|
81
|
+
kept.push(part);
|
|
82
|
+
}
|
|
64
83
|
}
|
|
65
84
|
const path = (pathname.startsWith("/") ? "/" : "") + kept.join("/") + (pathname.endsWith("/") && kept.length > 0 ? "/" : "");
|
|
66
|
-
if (reSafePath.test(path))
|
|
85
|
+
if (reSafePath.test(path)) {
|
|
86
|
+
return path === "" ? "/" : path;
|
|
87
|
+
}
|
|
67
88
|
tables();
|
|
68
89
|
let out = "";
|
|
69
|
-
for (let i = 0;
|
|
90
|
+
for (let i = 0;i < path.length; i++) {
|
|
91
|
+
out += queryTable[path.charCodeAt(i)] === path[i] || path[i] === "/" ? path[i] : queryTable[path.charCodeAt(i)];
|
|
92
|
+
}
|
|
70
93
|
return out;
|
|
71
94
|
}
|
|
72
95
|
function canonicalPathS3(pathname) {
|
|
73
|
-
if (reSafePath.test(pathname))
|
|
96
|
+
if (reSafePath.test(pathname)) {
|
|
97
|
+
return pathname === "" ? "/" : pathname;
|
|
98
|
+
}
|
|
74
99
|
tables();
|
|
75
100
|
return canonicalEncode(pathname, pathTable);
|
|
76
101
|
}
|
|
@@ -79,24 +104,34 @@ function comparePairs(a, b) {
|
|
|
79
104
|
return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0;
|
|
80
105
|
}
|
|
81
106
|
function canonicalQuery(search) {
|
|
82
|
-
if (search.length < 2)
|
|
107
|
+
if (search.length < 2) {
|
|
108
|
+
return "";
|
|
109
|
+
}
|
|
83
110
|
const query = search.slice(1);
|
|
84
111
|
const simple = reSafeQuery.test(query);
|
|
85
112
|
if (simple) {
|
|
86
|
-
let
|
|
113
|
+
let out = "";
|
|
87
114
|
let previousName = "";
|
|
88
115
|
let previousValue = "";
|
|
89
116
|
let start = 0;
|
|
90
|
-
for (
|
|
117
|
+
for (;; ) {
|
|
91
118
|
let end = query.indexOf("&", start);
|
|
92
|
-
if (end === -1)
|
|
119
|
+
if (end === -1) {
|
|
120
|
+
end = query.length;
|
|
121
|
+
}
|
|
93
122
|
let eq = query.indexOf("=", start);
|
|
94
|
-
if (eq === -1 || eq > end)
|
|
123
|
+
if (eq === -1 || eq > end) {
|
|
124
|
+
eq = end;
|
|
125
|
+
}
|
|
95
126
|
const name = query.slice(start, eq);
|
|
96
127
|
const value = query.slice(eq + 1, end);
|
|
97
|
-
if (end === start || eq === start || value.includes("=") || start > 0 && (name < previousName || name === previousName && value <= previousValue))
|
|
98
|
-
|
|
99
|
-
|
|
128
|
+
if (end === start || eq === start || value.includes("=") || start > 0 && (name < previousName || name === previousName && value <= previousValue)) {
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
out += (start === 0 ? "" : "&") + name + "=" + value;
|
|
132
|
+
if (end === query.length) {
|
|
133
|
+
return out;
|
|
134
|
+
}
|
|
100
135
|
previousName = name;
|
|
101
136
|
previousValue = value;
|
|
102
137
|
start = end + 1;
|
|
@@ -105,25 +140,36 @@ function canonicalQuery(search) {
|
|
|
105
140
|
tables();
|
|
106
141
|
const pairs = [];
|
|
107
142
|
for (const part of query.split("&")) {
|
|
108
|
-
if (part === "")
|
|
143
|
+
if (part === "") {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
109
146
|
const eq = part.indexOf("=");
|
|
110
147
|
const rawName = eq === -1 ? part : part.slice(0, eq);
|
|
111
148
|
const rawValue = eq === -1 ? "" : part.slice(eq + 1);
|
|
112
|
-
pairs.push(simple && !rawValue.includes("=") ? [rawName, rawValue] : [
|
|
149
|
+
pairs.push(simple && !rawValue.includes("=") ? [rawName, rawValue] : [
|
|
150
|
+
canonicalEncode(rawName, queryTable),
|
|
151
|
+
canonicalEncode(rawValue, queryTable)
|
|
152
|
+
]);
|
|
153
|
+
}
|
|
154
|
+
if (pairs.length > 1) {
|
|
155
|
+
pairs.sort(comparePairs);
|
|
113
156
|
}
|
|
114
|
-
if (pairs.length > 1) pairs.sort(comparePairs);
|
|
115
157
|
let out = "";
|
|
116
|
-
for (let i = 0;
|
|
158
|
+
for (let i = 0;i < pairs.length; i++) {
|
|
159
|
+
out += (i === 0 ? "" : "&") + pairs[i][0] + "=" + pairs[i][1];
|
|
160
|
+
}
|
|
117
161
|
return out;
|
|
118
162
|
}
|
|
119
163
|
function insert(names, values, name, value) {
|
|
120
164
|
let i = names.length;
|
|
121
|
-
while (i > 0 && names[i - 1] > name)
|
|
165
|
+
while (i > 0 && names[i - 1] > name) {
|
|
166
|
+
i--;
|
|
167
|
+
}
|
|
122
168
|
if (i > 0 && names[i - 1] === name) {
|
|
123
169
|
values[i - 1] = value;
|
|
124
170
|
return;
|
|
125
171
|
}
|
|
126
|
-
for (let j = names.length;
|
|
172
|
+
for (let j = names.length;j > i; j--) {
|
|
127
173
|
names[j] = names[j - 1];
|
|
128
174
|
values[j] = values[j - 1];
|
|
129
175
|
}
|
|
@@ -132,8 +178,12 @@ function insert(names, values, name, value) {
|
|
|
132
178
|
}
|
|
133
179
|
function signHeaderName(name, value) {
|
|
134
180
|
const lowerName = name.toLowerCase();
|
|
135
|
-
if (lowerName === "x-amz-date" || lowerName === "authorization" || lowerName === "__proto__")
|
|
136
|
-
|
|
181
|
+
if (lowerName === "x-amz-date" || lowerName === "authorization" || lowerName === "__proto__") {
|
|
182
|
+
throw new TypeError(`signHeaders cannot contain ${lowerName}`);
|
|
183
|
+
}
|
|
184
|
+
if (/[\r\n]/.test(value)) {
|
|
185
|
+
throw new TypeError(`signHeaders ${lowerName} has a line break in its value`);
|
|
186
|
+
}
|
|
137
187
|
return lowerName;
|
|
138
188
|
}
|
|
139
189
|
var headerValue = (value) => {
|
|
@@ -143,17 +193,17 @@ var headerValue = (value) => {
|
|
|
143
193
|
var lastSecond = NaN;
|
|
144
194
|
var lastDatetime = "";
|
|
145
195
|
function amzDatetime(now) {
|
|
146
|
-
const second = Math.floor(now /
|
|
196
|
+
const second = Math.floor(now / 1000);
|
|
147
197
|
if (second !== lastSecond) {
|
|
148
|
-
const iso = new Date(second *
|
|
198
|
+
const iso = new Date(second * 1000).toISOString();
|
|
149
199
|
lastDatetime = iso.slice(0, 4) + iso.slice(5, 7) + iso.slice(8, 10) + "T" + iso.slice(11, 13) + iso.slice(14, 16) + iso.slice(17, 19) + "Z";
|
|
150
200
|
lastSecond = second;
|
|
151
201
|
}
|
|
152
202
|
return lastDatetime;
|
|
153
203
|
}
|
|
154
|
-
function payloadHashOf(request,
|
|
204
|
+
function payloadHashOf(request, hexHash) {
|
|
155
205
|
const body = request.body ?? "";
|
|
156
|
-
return request.unsignedPayload ? "UNSIGNED-PAYLOAD" : body.length === 0 ? emptyBodyHash :
|
|
206
|
+
return request.unsignedPayload ? "UNSIGNED-PAYLOAD" : body.length === 0 ? emptyBodyHash : hexHash(body);
|
|
157
207
|
}
|
|
158
208
|
function prepare(request, credentials, payloadHash, scheme = symmetric) {
|
|
159
209
|
const { url, signHeaders } = request;
|
|
@@ -165,7 +215,7 @@ function prepare(request, credentials, payloadHash, scheme = symmetric) {
|
|
|
165
215
|
const datetime = amzDatetime(request.now ?? Date.now());
|
|
166
216
|
const date = datetime.slice(0, 8);
|
|
167
217
|
const headers = withHash ? { "x-amz-date": datetime, "x-amz-content-sha256": payloadHash } : { "x-amz-date": datetime };
|
|
168
|
-
const extraNames = signHeaders ===
|
|
218
|
+
const extraNames = signHeaders === undefined ? [] : Object.keys(signHeaders);
|
|
169
219
|
let canonicalHeaders;
|
|
170
220
|
let signedHeaders;
|
|
171
221
|
if (extraNames.length === 0 && !sessionToken) {
|
|
@@ -184,10 +234,7 @@ x-amz-date:${datetime}
|
|
|
184
234
|
insert(names, values, "x-amz-security-token", sessionToken.trim());
|
|
185
235
|
}
|
|
186
236
|
for (const name of extraNames) {
|
|
187
|
-
const value =
|
|
188
|
-
/** @type {Record<string, string>} */
|
|
189
|
-
signHeaders[name]
|
|
190
|
-
);
|
|
237
|
+
const value = signHeaders[name];
|
|
191
238
|
const lowerName = signHeaderName(name, value);
|
|
192
239
|
headers[lowerName] = value;
|
|
193
240
|
insert(names, values, lowerName, headerValue(value));
|
|
@@ -205,12 +252,16 @@ x-amz-date:${datetime}
|
|
|
205
252
|
if (j === nBase || i < names.length && names[i] <= baseNames[j]) {
|
|
206
253
|
name = names[i];
|
|
207
254
|
value = values[i++];
|
|
208
|
-
if (j < nBase && name === baseNames[j])
|
|
255
|
+
if (j < nBase && name === baseNames[j]) {
|
|
256
|
+
j++;
|
|
257
|
+
}
|
|
209
258
|
} else {
|
|
210
259
|
name = baseNames[j];
|
|
211
260
|
value = baseValues[j++];
|
|
212
261
|
}
|
|
213
|
-
if (name === "x-amz-content-sha256")
|
|
262
|
+
if (name === "x-amz-content-sha256") {
|
|
263
|
+
payloadHash = value;
|
|
264
|
+
}
|
|
214
265
|
canonicalHeaders += `${name}:${value}
|
|
215
266
|
`;
|
|
216
267
|
signedHeaders += signedHeaders === "" ? name : ";" + name;
|
|
@@ -222,7 +273,17 @@ ${canonicalQuery(url.search)}
|
|
|
222
273
|
${canonicalHeaders}
|
|
223
274
|
${signedHeaders}
|
|
224
275
|
${payloadHash}`;
|
|
225
|
-
return {
|
|
276
|
+
return {
|
|
277
|
+
headers,
|
|
278
|
+
canonicalRequest,
|
|
279
|
+
datetime,
|
|
280
|
+
date,
|
|
281
|
+
region,
|
|
282
|
+
service,
|
|
283
|
+
credentialScope: scheme.scope(date, region, service),
|
|
284
|
+
signedHeaders,
|
|
285
|
+
algorithm: scheme.algorithm
|
|
286
|
+
};
|
|
226
287
|
}
|
|
227
288
|
var stringToSign = (prepared, canonicalRequestHash) => `${prepared.algorithm}
|
|
228
289
|
${prepared.datetime}
|
|
@@ -232,24 +293,28 @@ function authorize(prepared, accessKeyId, signature) {
|
|
|
232
293
|
prepared.headers.authorization = `${prepared.algorithm} Credential=${accessKeyId}/${prepared.credentialScope}, SignedHeaders=${prepared.signedHeaders}, Signature=${signature}`;
|
|
233
294
|
return prepared.headers;
|
|
234
295
|
}
|
|
235
|
-
function createKeys(
|
|
236
|
-
const signingKeys =
|
|
237
|
-
const maxSigningKeys =
|
|
296
|
+
function createKeys(hmac) {
|
|
297
|
+
const signingKeys = new Map;
|
|
298
|
+
const maxSigningKeys = 1000;
|
|
238
299
|
let lastSecret;
|
|
239
300
|
let lastDate;
|
|
240
301
|
let lastRegion;
|
|
241
302
|
let lastService;
|
|
242
303
|
let lastKey;
|
|
243
|
-
return function
|
|
244
|
-
if (secretAccessKey === lastSecret && date === lastDate && region === lastRegion && service === lastService)
|
|
304
|
+
return function getSigningKey(secretAccessKey, date, region, service) {
|
|
305
|
+
if (secretAccessKey === lastSecret && date === lastDate && region === lastRegion && service === lastService) {
|
|
306
|
+
return lastKey;
|
|
307
|
+
}
|
|
245
308
|
const cacheKey = `${date}
|
|
246
309
|
${region}
|
|
247
310
|
${service}
|
|
248
311
|
${secretAccessKey}`;
|
|
249
312
|
let signingKey = signingKeys.get(cacheKey);
|
|
250
|
-
if (signingKey ===
|
|
251
|
-
signingKey =
|
|
252
|
-
if (signingKeys.size >= maxSigningKeys)
|
|
313
|
+
if (signingKey === undefined) {
|
|
314
|
+
signingKey = hmac(hmac(hmac(hmac("AWS4" + secretAccessKey, date), region), service), "aws4_request");
|
|
315
|
+
if (signingKeys.size >= maxSigningKeys) {
|
|
316
|
+
signingKeys.delete(signingKeys.keys().next().value);
|
|
317
|
+
}
|
|
253
318
|
signingKeys.set(cacheKey, signingKey);
|
|
254
319
|
}
|
|
255
320
|
lastSecret = secretAccessKey;
|
|
@@ -260,14 +325,10 @@ ${secretAccessKey}`;
|
|
|
260
325
|
return signingKey;
|
|
261
326
|
};
|
|
262
327
|
}
|
|
263
|
-
function createSigner({ hexHash
|
|
264
|
-
return function
|
|
265
|
-
const prepared = prepare(request, credentials, payloadHashOf(request,
|
|
266
|
-
return authorize(
|
|
267
|
-
prepared,
|
|
268
|
-
credentials.accessKeyId,
|
|
269
|
-
hmacHex(getSigningKey2(credentials.secretAccessKey, prepared.date, prepared.region, prepared.service), stringToSign(prepared, hexHash2(prepared.canonicalRequest)))
|
|
270
|
-
);
|
|
328
|
+
function createSigner({ hexHash, hmacHex, getSigningKey }) {
|
|
329
|
+
return function getAuthHeaders(request, credentials) {
|
|
330
|
+
const prepared = prepare(request, credentials, payloadHashOf(request, hexHash));
|
|
331
|
+
return authorize(prepared, credentials.accessKeyId, hmacHex(getSigningKey(credentials.secretAccessKey, prepared.date, prepared.region, prepared.service), stringToSign(prepared, hexHash(prepared.canonicalRequest))));
|
|
271
332
|
};
|
|
272
333
|
}
|
|
273
334
|
|
|
@@ -276,10 +337,16 @@ var encodeQueryPart = (text) => encodeURIComponent(text).replace(/[!'()*]/g, (c)
|
|
|
276
337
|
function preparePresign(request, credentials, payloadHash, scheme = symmetric, extra = "") {
|
|
277
338
|
const { url, signHeaders } = request;
|
|
278
339
|
const method = request.method.toUpperCase();
|
|
279
|
-
if (url.protocol !== "https:" && url.protocol !== "http:")
|
|
280
|
-
|
|
340
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
341
|
+
throw new TypeError("presign needs an http or https URL");
|
|
342
|
+
}
|
|
343
|
+
if (url.search.length > 1 && (url.search.includes("X-Amz-Signature=") || url.search.includes("X-Amz-Algorithm="))) {
|
|
344
|
+
throw new TypeError("the URL is already presigned");
|
|
345
|
+
}
|
|
281
346
|
const expires = request.expires ?? 3600;
|
|
282
|
-
if (!Number.isInteger(expires) || expires < 1 || expires > 604800)
|
|
347
|
+
if (!Number.isInteger(expires) || expires < 1 || expires > 604800) {
|
|
348
|
+
throw new RangeError("expires must be a whole number of seconds from 1 to 604800 (7 days)");
|
|
349
|
+
}
|
|
283
350
|
const region = request.region ?? "";
|
|
284
351
|
const service = request.service ?? "s3";
|
|
285
352
|
const datetime = amzDatetime(request.now ?? Date.now());
|
|
@@ -287,13 +354,21 @@ function preparePresign(request, credentials, payloadHash, scheme = symmetric, e
|
|
|
287
354
|
const credentialScope = scheme.scope(date, region, service);
|
|
288
355
|
const names = ["host"];
|
|
289
356
|
const values = [url.host];
|
|
290
|
-
if (signHeaders !==
|
|
357
|
+
if (signHeaders !== undefined) {
|
|
358
|
+
for (const name of Object.keys(signHeaders)) {
|
|
359
|
+
insert(names, values, signHeaderName(name, signHeaders[name]), headerValue(signHeaders[name]));
|
|
360
|
+
}
|
|
361
|
+
}
|
|
291
362
|
let canonicalHeaders = "";
|
|
292
|
-
for (let i = 0;
|
|
363
|
+
for (let i = 0;i < names.length; i++) {
|
|
364
|
+
canonicalHeaders += `${names[i]}:${values[i]}
|
|
293
365
|
`;
|
|
366
|
+
}
|
|
294
367
|
const signedHeaders = names.join(";");
|
|
295
368
|
let auth = `X-Amz-Algorithm=${scheme.algorithm}&X-Amz-Credential=${encodeQueryPart(`${credentials.accessKeyId}/${credentialScope}`)}&X-Amz-Date=${datetime}&X-Amz-Expires=${expires}&X-Amz-SignedHeaders=${encodeQueryPart(signedHeaders)}`;
|
|
296
|
-
if (credentials.sessionToken)
|
|
369
|
+
if (credentials.sessionToken) {
|
|
370
|
+
auth += `&X-Amz-Security-Token=${encodeQueryPart(credentials.sessionToken)}`;
|
|
371
|
+
}
|
|
297
372
|
auth += extra;
|
|
298
373
|
const query = url.search.length > 1 ? url.search + "&" + auth : "?" + auth;
|
|
299
374
|
const hash = service === "s3" || request.unsignedPayload ? "UNSIGNED-PAYLOAD" : payloadHash;
|
|
@@ -303,99 +378,137 @@ ${canonicalQuery(query)}
|
|
|
303
378
|
${canonicalHeaders}
|
|
304
379
|
${signedHeaders}
|
|
305
380
|
${hash}`;
|
|
306
|
-
return {
|
|
381
|
+
return {
|
|
382
|
+
canonicalRequest,
|
|
383
|
+
datetime,
|
|
384
|
+
date,
|
|
385
|
+
region,
|
|
386
|
+
service,
|
|
387
|
+
credentialScope,
|
|
388
|
+
signedHeaders,
|
|
389
|
+
algorithm: scheme.algorithm,
|
|
390
|
+
base: url.origin + url.pathname,
|
|
391
|
+
query
|
|
392
|
+
};
|
|
307
393
|
}
|
|
308
394
|
var presignedUrl = (prepared, signature) => `${prepared.base}${prepared.query}&X-Amz-Signature=${signature}`;
|
|
309
|
-
function createPresigner({ hexHash
|
|
310
|
-
return function
|
|
311
|
-
const prepared = preparePresign(request, credentials, payloadHashOf(request,
|
|
312
|
-
return presignedUrl(
|
|
313
|
-
prepared,
|
|
314
|
-
hmacHex(getSigningKey2(credentials.secretAccessKey, prepared.date, prepared.region, prepared.service), stringToSign(prepared, hexHash2(prepared.canonicalRequest)))
|
|
315
|
-
);
|
|
395
|
+
function createPresigner({ hexHash, hmacHex, getSigningKey }) {
|
|
396
|
+
return function presign(request, credentials) {
|
|
397
|
+
const prepared = preparePresign(request, credentials, payloadHashOf(request, hexHash));
|
|
398
|
+
return presignedUrl(prepared, hmacHex(getSigningKey(credentials.secretAccessKey, prepared.date, prepared.region, prepared.service), stringToSign(prepared, hexHash(prepared.canonicalRequest))));
|
|
316
399
|
};
|
|
317
400
|
}
|
|
318
401
|
|
|
319
402
|
// src/v4a.js
|
|
320
|
-
var asymmetric = {
|
|
403
|
+
var asymmetric = {
|
|
404
|
+
algorithm: "AWS4-ECDSA-P256-SHA256",
|
|
405
|
+
scope: (date, _region, service) => `${date}/${service}/aws4_request`
|
|
406
|
+
};
|
|
321
407
|
function regionSetOf(request) {
|
|
322
408
|
const regionSet = request.regionSet;
|
|
323
|
-
if (typeof regionSet !== "string" || regionSet === "")
|
|
409
|
+
if (typeof regionSet !== "string" || regionSet === "") {
|
|
410
|
+
throw new TypeError("SigV4a needs request.regionSet, for example 'us-east-1,us-west-2' or '*'");
|
|
411
|
+
}
|
|
324
412
|
return regionSet;
|
|
325
413
|
}
|
|
326
|
-
var withRegionSet = (request) => ({
|
|
414
|
+
var withRegionSet = (request) => ({
|
|
415
|
+
...request,
|
|
416
|
+
signHeaders: { ...request.signHeaders, "x-amz-region-set": regionSetOf(request) }
|
|
417
|
+
});
|
|
327
418
|
var regionSetQuery = (request) => `&X-Amz-Region-Set=${encodeQueryPart(regionSetOf(request))}`;
|
|
328
|
-
var kdfInput = (accessKeyId, counter) => `\
|
|
419
|
+
var kdfInput = (accessKeyId, counter) => `\x00\x00\x00\x01AWS4-ECDSA-P256-SHA256\x00${accessKeyId}${String.fromCharCode(counter)}\x00\x00\x01\x00`;
|
|
329
420
|
function scalarFrom(k) {
|
|
330
421
|
const nMinusTwo = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fn;
|
|
331
422
|
let c = 0n;
|
|
332
|
-
for (let i = 0;
|
|
333
|
-
|
|
423
|
+
for (let i = 0;i < 32; i++) {
|
|
424
|
+
c = c << 8n | BigInt(k[i]);
|
|
425
|
+
}
|
|
426
|
+
if (c > nMinusTwo) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
334
429
|
c += 1n;
|
|
335
430
|
const d = new Uint8Array(32);
|
|
336
|
-
for (let i = 31;
|
|
431
|
+
for (let i = 31;i >= 0; i--, c >>= 8n) {
|
|
432
|
+
d[i] = Number(c & 0xffn);
|
|
433
|
+
}
|
|
337
434
|
return d;
|
|
338
435
|
}
|
|
339
|
-
function deriveP256(
|
|
340
|
-
for (let counter = 1;
|
|
341
|
-
const d = scalarFrom(
|
|
342
|
-
if (d !==
|
|
436
|
+
function deriveP256(hmac, accessKeyId, secretAccessKey) {
|
|
437
|
+
for (let counter = 1;counter < 128; counter++) {
|
|
438
|
+
const d = scalarFrom(hmac("AWS4A" + secretAccessKey, kdfInput(accessKeyId, counter)));
|
|
439
|
+
if (d !== undefined) {
|
|
440
|
+
return d;
|
|
441
|
+
}
|
|
343
442
|
}
|
|
344
443
|
throw new Error("no SigV4a key for these credentials");
|
|
345
444
|
}
|
|
346
|
-
var signers = /* @__PURE__ */ new WeakMap
|
|
347
|
-
function createAsymmetric(
|
|
348
|
-
let sign = signers.get(
|
|
349
|
-
if (sign ===
|
|
445
|
+
var signers = /* @__PURE__ */ new WeakMap;
|
|
446
|
+
function createAsymmetric(hmac, ecdsa) {
|
|
447
|
+
let sign = signers.get(ecdsa);
|
|
448
|
+
if (sign === undefined) {
|
|
449
|
+
signers.set(ecdsa, sign = signerFor(hmac, ecdsa));
|
|
450
|
+
}
|
|
350
451
|
return sign;
|
|
351
452
|
}
|
|
352
|
-
function signerFor(
|
|
353
|
-
const keys =
|
|
453
|
+
function signerFor(hmac, ecdsa) {
|
|
454
|
+
const keys = new Map;
|
|
354
455
|
return function sign(credentials, text) {
|
|
355
456
|
const id = `${credentials.accessKeyId}/${credentials.secretAccessKey}`;
|
|
356
457
|
let key = keys.get(id);
|
|
357
|
-
if (key ===
|
|
358
|
-
key =
|
|
359
|
-
if (keys.size >=
|
|
458
|
+
if (key === undefined) {
|
|
459
|
+
key = ecdsa.key(deriveP256(hmac, credentials.accessKeyId, credentials.secretAccessKey));
|
|
460
|
+
if (keys.size >= 1000) {
|
|
461
|
+
keys.delete(keys.keys().next().value);
|
|
462
|
+
}
|
|
360
463
|
keys.set(id, key);
|
|
361
464
|
}
|
|
362
|
-
return
|
|
465
|
+
return ecdsa.sign(key, text);
|
|
363
466
|
};
|
|
364
467
|
}
|
|
365
|
-
function createSignerV4a({ hexHash
|
|
366
|
-
const sign = createAsymmetric(
|
|
367
|
-
return function
|
|
368
|
-
const prepared = prepare(withRegionSet(request), credentials, payloadHashOf(request,
|
|
369
|
-
return authorize(prepared, credentials.accessKeyId, sign(credentials, stringToSign(prepared,
|
|
468
|
+
function createSignerV4a({ hexHash, hmac, ecdsa }) {
|
|
469
|
+
const sign = createAsymmetric(hmac, ecdsa);
|
|
470
|
+
return function getAuthHeadersV4a(request, credentials) {
|
|
471
|
+
const prepared = prepare(withRegionSet(request), credentials, payloadHashOf(request, hexHash), asymmetric);
|
|
472
|
+
return authorize(prepared, credentials.accessKeyId, sign(credentials, stringToSign(prepared, hexHash(prepared.canonicalRequest))));
|
|
370
473
|
};
|
|
371
474
|
}
|
|
372
|
-
function createPresignerV4a({ hexHash
|
|
373
|
-
const sign = createAsymmetric(
|
|
374
|
-
return function
|
|
375
|
-
const prepared = preparePresign(request, credentials, payloadHashOf(request,
|
|
376
|
-
return presignedUrl(prepared, sign(credentials, stringToSign(prepared,
|
|
475
|
+
function createPresignerV4a({ hexHash, hmac, ecdsa }) {
|
|
476
|
+
const sign = createAsymmetric(hmac, ecdsa);
|
|
477
|
+
return function presignV4a(request, credentials) {
|
|
478
|
+
const prepared = preparePresign(request, credentials, payloadHashOf(request, hexHash), asymmetric, regionSetQuery(request));
|
|
479
|
+
return presignedUrl(prepared, sign(credentials, stringToSign(prepared, hexHash(prepared.canonicalRequest))));
|
|
377
480
|
};
|
|
378
481
|
}
|
|
379
482
|
|
|
380
483
|
// src/ecdsa-node.js
|
|
381
|
-
import crypto from "
|
|
484
|
+
import crypto from "crypto";
|
|
382
485
|
var b64url = (bytes) => Buffer.from(bytes).toString("base64url");
|
|
383
486
|
var ecdsa = {
|
|
384
487
|
key(d) {
|
|
385
488
|
const ecdh = crypto.createECDH("prime256v1");
|
|
386
489
|
ecdh.setPrivateKey(d);
|
|
387
490
|
const point = ecdh.getPublicKey();
|
|
388
|
-
return crypto.createPrivateKey({
|
|
491
|
+
return crypto.createPrivateKey({
|
|
492
|
+
key: {
|
|
493
|
+
kty: "EC",
|
|
494
|
+
crv: "P-256",
|
|
495
|
+
d: b64url(d),
|
|
496
|
+
x: b64url(point.subarray(1, 33)),
|
|
497
|
+
y: b64url(point.subarray(33))
|
|
498
|
+
},
|
|
499
|
+
format: "jwk"
|
|
500
|
+
});
|
|
389
501
|
},
|
|
390
502
|
sign: (key, text) => crypto.sign("sha256", text, { key, dsaEncoding: "der" }).toString("hex")
|
|
391
503
|
};
|
|
392
504
|
|
|
393
505
|
// src/chunks.js
|
|
394
|
-
var utf8 = /* @__PURE__ */ new TextEncoder
|
|
506
|
+
var utf8 = /* @__PURE__ */ new TextEncoder;
|
|
395
507
|
function seedOf(authHeaders) {
|
|
396
508
|
const auth = authHeaders.authorization;
|
|
397
|
-
if (typeof auth !== "string" || !auth.startsWith("AWS4-HMAC-SHA256 "))
|
|
509
|
+
if (typeof auth !== "string" || !auth.startsWith("AWS4-HMAC-SHA256 ")) {
|
|
398
510
|
throw new TypeError("authHeaders must be the headers getAuthHeaders returned (a SigV4a signature cannot start a chunk or event stream)");
|
|
511
|
+
}
|
|
399
512
|
const scope = auth.slice(auth.indexOf("Credential=") + 11, auth.indexOf(",")).split("/");
|
|
400
513
|
return {
|
|
401
514
|
signature: auth.slice(auth.lastIndexOf("Signature=") + 10),
|
|
@@ -420,7 +533,9 @@ ${trailerHash}`;
|
|
|
420
533
|
function canonicalTrailers(trailers) {
|
|
421
534
|
return Object.keys(trailers).map((name) => {
|
|
422
535
|
const value = String(trailers[name]);
|
|
423
|
-
if (/[\r\n]/.test(name) || /[\r\n]/.test(value))
|
|
536
|
+
if (/[\r\n]/.test(name) || /[\r\n]/.test(value)) {
|
|
537
|
+
throw new TypeError("a trailer name or value cannot hold a line break");
|
|
538
|
+
}
|
|
424
539
|
return [name.toLowerCase(), value.trim()];
|
|
425
540
|
}).sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0).map(([name, value]) => `${name}:${value}
|
|
426
541
|
`).join("");
|
|
@@ -436,29 +551,29 @@ function frameChunk(signature, data) {
|
|
|
436
551
|
return out;
|
|
437
552
|
}
|
|
438
553
|
function frameEnd(signature, trailers, trailerSignature) {
|
|
439
|
-
return utf8.encode(
|
|
440
|
-
trailers === void 0 ? `0;chunk-signature=${signature}\r
|
|
554
|
+
return utf8.encode(trailers === undefined ? `0;chunk-signature=${signature}\r
|
|
441
555
|
\r
|
|
442
556
|
` : `0;chunk-signature=${signature}\r
|
|
443
|
-
${trailers.replace(/\n/g,
|
|
557
|
+
${trailers.replace(/\n/g, `\r
|
|
558
|
+
`)}x-amz-trailer-signature:${trailerSignature}\r
|
|
444
559
|
\r
|
|
445
|
-
`
|
|
446
|
-
);
|
|
560
|
+
`);
|
|
447
561
|
}
|
|
448
|
-
function createChunkSigner({ hexHash
|
|
449
|
-
return function
|
|
562
|
+
function createChunkSigner({ hexHash, hmacHex, getSigningKey }) {
|
|
563
|
+
return function chunkSigner(authHeaders, credentials) {
|
|
450
564
|
const seed = seedOf(authHeaders);
|
|
451
|
-
const key =
|
|
565
|
+
const key = getSigningKey(credentials.secretAccessKey, seed.date, seed.region, seed.service);
|
|
452
566
|
let previous = seed.signature;
|
|
453
|
-
const sign = (data) => previous = hmacHex(key, chunkStringToSign(seed.datetime, seed.scope, previous,
|
|
567
|
+
const sign = (data) => previous = hmacHex(key, chunkStringToSign(seed.datetime, seed.scope, previous, hexHash(data)));
|
|
454
568
|
return {
|
|
455
569
|
chunk: (data) => data.length === 0 ? data : frameChunk(sign(data), data),
|
|
456
|
-
// a zero-length chunk would end the upload; it is not sent
|
|
457
570
|
end(trailers) {
|
|
458
|
-
const text = trailers ===
|
|
571
|
+
const text = trailers === undefined ? undefined : canonicalTrailers(trailers);
|
|
459
572
|
const signature = sign(new Uint8Array(0));
|
|
460
|
-
if (text ===
|
|
461
|
-
|
|
573
|
+
if (text === undefined) {
|
|
574
|
+
return frameEnd(signature);
|
|
575
|
+
}
|
|
576
|
+
const trailerSignature = hmacHex(key, trailerStringToSign(seed.datetime, seed.scope, signature, hexHash(text)));
|
|
462
577
|
return frameEnd(signature, text, trailerSignature);
|
|
463
578
|
}
|
|
464
579
|
};
|
|
@@ -468,16 +583,20 @@ function createChunkSigner({ hexHash: hexHash2, hmacHex, getSigningKey: getSigni
|
|
|
468
583
|
// src/events.js
|
|
469
584
|
var crcTable;
|
|
470
585
|
function crc32(bytes, start, end) {
|
|
471
|
-
if (crcTable ===
|
|
586
|
+
if (crcTable === undefined) {
|
|
472
587
|
crcTable = new Int32Array(256);
|
|
473
|
-
for (let n = 0;
|
|
588
|
+
for (let n = 0;n < 256; n++) {
|
|
474
589
|
let c = n;
|
|
475
|
-
for (let k = 0;
|
|
590
|
+
for (let k = 0;k < 8; k++) {
|
|
591
|
+
c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
592
|
+
}
|
|
476
593
|
crcTable[n] = c;
|
|
477
594
|
}
|
|
478
595
|
}
|
|
479
596
|
let crc = -1;
|
|
480
|
-
for (let i = start;
|
|
597
|
+
for (let i = start;i < end; i++) {
|
|
598
|
+
crc = crcTable[(crc ^ bytes[i]) & 255] ^ crc >>> 8;
|
|
599
|
+
}
|
|
481
600
|
return ~crc >>> 0;
|
|
482
601
|
}
|
|
483
602
|
function dateHeader(ms) {
|
|
@@ -503,7 +622,9 @@ function frameEvent(dateBytes, signatureHex, inner) {
|
|
|
503
622
|
out[at++] = 6;
|
|
504
623
|
view.setUint16(at, 32);
|
|
505
624
|
at += 2;
|
|
506
|
-
for (let i = 0;
|
|
625
|
+
for (let i = 0;i < 32; i++) {
|
|
626
|
+
out[at + i] = parseInt(signatureHex.slice(2 * i, 2 * i + 2), 16);
|
|
627
|
+
}
|
|
507
628
|
at += 32;
|
|
508
629
|
out.set(inner, at);
|
|
509
630
|
view.setUint32(out.length - 4, crc32(out, 0, out.length - 4));
|
|
@@ -517,20 +638,21 @@ ${headersHash}
|
|
|
517
638
|
${payloadHash}`;
|
|
518
639
|
var eventScope = (ms, region, service) => {
|
|
519
640
|
const datetime = amzDatetime(ms);
|
|
520
|
-
return {
|
|
641
|
+
return {
|
|
642
|
+
datetime,
|
|
643
|
+
scope: `${datetime.slice(0, 8)}/${region}/${service}/aws4_request`,
|
|
644
|
+
date: datetime.slice(0, 8)
|
|
645
|
+
};
|
|
521
646
|
};
|
|
522
|
-
function createEventSigner({ hexHash
|
|
523
|
-
return function
|
|
647
|
+
function createEventSigner({ hexHash, hmacHex, getSigningKey }) {
|
|
648
|
+
return function eventSigner(authHeaders, credentials) {
|
|
524
649
|
const seed = seedOf(authHeaders);
|
|
525
650
|
let previous = seed.signature;
|
|
526
651
|
return {
|
|
527
652
|
sign(message, now = Date.now()) {
|
|
528
653
|
const { datetime, scope, date } = eventScope(now, seed.region, seed.service);
|
|
529
654
|
const header = dateHeader(now);
|
|
530
|
-
previous = hmacHex(
|
|
531
|
-
getSigningKey2(credentials.secretAccessKey, date, seed.region, seed.service),
|
|
532
|
-
eventStringToSign(datetime, scope, previous, hexHash2(header), hexHash2(message))
|
|
533
|
-
);
|
|
655
|
+
previous = hmacHex(getSigningKey(credentials.secretAccessKey, date, seed.region, seed.service), eventStringToSign(datetime, scope, previous, hexHash(header), hexHash(message)));
|
|
534
656
|
return frameEvent(header, previous, message);
|
|
535
657
|
}
|
|
536
658
|
};
|
|
@@ -538,10 +660,7 @@ function createEventSigner({ hexHash: hexHash2, hmacHex, getSigningKey: getSigni
|
|
|
538
660
|
}
|
|
539
661
|
|
|
540
662
|
// src/bun.js
|
|
541
|
-
var bun =
|
|
542
|
-
/** @type {any} */
|
|
543
|
-
globalThis.Bun
|
|
544
|
-
);
|
|
663
|
+
var bun = globalThis.Bun;
|
|
545
664
|
var baseKey;
|
|
546
665
|
var base;
|
|
547
666
|
var hmac = (key, data) => crypto2.createHmac("sha256", key).update(data).digest();
|