@smithy/signature-v4 5.3.13 → 5.4.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/dist-cjs/index.js +178 -175
- package/dist-es/HeaderFormatter.js +1 -2
- package/dist-es/SignatureV4.js +14 -9
- package/dist-es/SignatureV4Base.js +3 -4
- package/dist-es/credentialDerivation.js +1 -2
- package/dist-es/getCanonicalQuery.js +1 -1
- package/dist-es/getPayloadHash.js +1 -3
- package/dist-es/moveHeadersToQuery.js +1 -1
- package/dist-es/prepareRequest.js +1 -1
- package/dist-types/SignatureV4.d.ts +4 -5
- package/dist-types/index.d.ts +1 -1
- package/package.json +3 -8
package/dist-cjs/index.js
CHANGED
|
@@ -1,129 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var protocolHttp = require('@smithy/protocol-http');
|
|
7
|
-
var utilMiddleware = require('@smithy/util-middleware');
|
|
8
|
-
var utilUriEscape = require('@smithy/util-uri-escape');
|
|
9
|
-
|
|
10
|
-
const ALGORITHM_QUERY_PARAM = "X-Amz-Algorithm";
|
|
11
|
-
const CREDENTIAL_QUERY_PARAM = "X-Amz-Credential";
|
|
12
|
-
const AMZ_DATE_QUERY_PARAM = "X-Amz-Date";
|
|
13
|
-
const SIGNED_HEADERS_QUERY_PARAM = "X-Amz-SignedHeaders";
|
|
14
|
-
const EXPIRES_QUERY_PARAM = "X-Amz-Expires";
|
|
15
|
-
const SIGNATURE_QUERY_PARAM = "X-Amz-Signature";
|
|
16
|
-
const TOKEN_QUERY_PARAM = "X-Amz-Security-Token";
|
|
17
|
-
const REGION_SET_PARAM = "X-Amz-Region-Set";
|
|
18
|
-
const AUTH_HEADER = "authorization";
|
|
19
|
-
const AMZ_DATE_HEADER = AMZ_DATE_QUERY_PARAM.toLowerCase();
|
|
20
|
-
const DATE_HEADER = "date";
|
|
21
|
-
const GENERATED_HEADERS = [AUTH_HEADER, AMZ_DATE_HEADER, DATE_HEADER];
|
|
22
|
-
const SIGNATURE_HEADER = SIGNATURE_QUERY_PARAM.toLowerCase();
|
|
23
|
-
const SHA256_HEADER = "x-amz-content-sha256";
|
|
24
|
-
const TOKEN_HEADER = TOKEN_QUERY_PARAM.toLowerCase();
|
|
25
|
-
const HOST_HEADER = "host";
|
|
26
|
-
const ALWAYS_UNSIGNABLE_HEADERS = {
|
|
27
|
-
authorization: true,
|
|
28
|
-
"cache-control": true,
|
|
29
|
-
connection: true,
|
|
30
|
-
expect: true,
|
|
31
|
-
from: true,
|
|
32
|
-
"keep-alive": true,
|
|
33
|
-
"max-forwards": true,
|
|
34
|
-
pragma: true,
|
|
35
|
-
referer: true,
|
|
36
|
-
te: true,
|
|
37
|
-
trailer: true,
|
|
38
|
-
"transfer-encoding": true,
|
|
39
|
-
upgrade: true,
|
|
40
|
-
"user-agent": true,
|
|
41
|
-
"x-amzn-trace-id": true,
|
|
42
|
-
};
|
|
43
|
-
const PROXY_HEADER_PATTERN = /^proxy-/;
|
|
44
|
-
const SEC_HEADER_PATTERN = /^sec-/;
|
|
45
|
-
const UNSIGNABLE_PATTERNS = [/^proxy-/i, /^sec-/i];
|
|
46
|
-
const ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256";
|
|
47
|
-
const ALGORITHM_IDENTIFIER_V4A = "AWS4-ECDSA-P256-SHA256";
|
|
48
|
-
const EVENT_ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256-PAYLOAD";
|
|
49
|
-
const UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";
|
|
50
|
-
const MAX_CACHE_SIZE = 50;
|
|
51
|
-
const KEY_TYPE_IDENTIFIER = "aws4_request";
|
|
52
|
-
const MAX_PRESIGNED_TTL = 60 * 60 * 24 * 7;
|
|
53
|
-
|
|
54
|
-
const signingKeyCache = {};
|
|
55
|
-
const cacheQueue = [];
|
|
56
|
-
const createScope = (shortDate, region, service) => `${shortDate}/${region}/${service}/${KEY_TYPE_IDENTIFIER}`;
|
|
57
|
-
const getSigningKey = async (sha256Constructor, credentials, shortDate, region, service) => {
|
|
58
|
-
const credsHash = await hmac(sha256Constructor, credentials.secretAccessKey, credentials.accessKeyId);
|
|
59
|
-
const cacheKey = `${shortDate}:${region}:${service}:${utilHexEncoding.toHex(credsHash)}:${credentials.sessionToken}`;
|
|
60
|
-
if (cacheKey in signingKeyCache) {
|
|
61
|
-
return signingKeyCache[cacheKey];
|
|
62
|
-
}
|
|
63
|
-
cacheQueue.push(cacheKey);
|
|
64
|
-
while (cacheQueue.length > MAX_CACHE_SIZE) {
|
|
65
|
-
delete signingKeyCache[cacheQueue.shift()];
|
|
66
|
-
}
|
|
67
|
-
let key = `AWS4${credentials.secretAccessKey}`;
|
|
68
|
-
for (const signable of [shortDate, region, service, KEY_TYPE_IDENTIFIER]) {
|
|
69
|
-
key = await hmac(sha256Constructor, key, signable);
|
|
70
|
-
}
|
|
71
|
-
return (signingKeyCache[cacheKey] = key);
|
|
72
|
-
};
|
|
73
|
-
const clearCredentialCache = () => {
|
|
74
|
-
cacheQueue.length = 0;
|
|
75
|
-
Object.keys(signingKeyCache).forEach((cacheKey) => {
|
|
76
|
-
delete signingKeyCache[cacheKey];
|
|
77
|
-
});
|
|
78
|
-
};
|
|
79
|
-
const hmac = (ctor, secret, data) => {
|
|
80
|
-
const hash = new ctor(secret);
|
|
81
|
-
hash.update(utilUtf8.toUint8Array(data));
|
|
82
|
-
return hash.digest();
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const getCanonicalHeaders = ({ headers }, unsignableHeaders, signableHeaders) => {
|
|
86
|
-
const canonical = {};
|
|
87
|
-
for (const headerName of Object.keys(headers).sort()) {
|
|
88
|
-
if (headers[headerName] == undefined) {
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
const canonicalHeaderName = headerName.toLowerCase();
|
|
92
|
-
if (canonicalHeaderName in ALWAYS_UNSIGNABLE_HEADERS ||
|
|
93
|
-
unsignableHeaders?.has(canonicalHeaderName) ||
|
|
94
|
-
PROXY_HEADER_PATTERN.test(canonicalHeaderName) ||
|
|
95
|
-
SEC_HEADER_PATTERN.test(canonicalHeaderName)) {
|
|
96
|
-
if (!signableHeaders || (signableHeaders && !signableHeaders.has(canonicalHeaderName))) {
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
canonical[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " ");
|
|
101
|
-
}
|
|
102
|
-
return canonical;
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
const getPayloadHash = async ({ headers, body }, hashConstructor) => {
|
|
106
|
-
for (const headerName of Object.keys(headers)) {
|
|
107
|
-
if (headerName.toLowerCase() === SHA256_HEADER) {
|
|
108
|
-
return headers[headerName];
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
if (body == undefined) {
|
|
112
|
-
return "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
|
|
113
|
-
}
|
|
114
|
-
else if (typeof body === "string" || ArrayBuffer.isView(body) || isArrayBuffer.isArrayBuffer(body)) {
|
|
115
|
-
const hashCtor = new hashConstructor();
|
|
116
|
-
hashCtor.update(utilUtf8.toUint8Array(body));
|
|
117
|
-
return utilHexEncoding.toHex(await hashCtor.digest());
|
|
118
|
-
}
|
|
119
|
-
return UNSIGNED_PAYLOAD;
|
|
120
|
-
};
|
|
3
|
+
var serde = require('@smithy/core/serde');
|
|
4
|
+
var client = require('@smithy/core/client');
|
|
5
|
+
var protocols = require('@smithy/core/protocols');
|
|
121
6
|
|
|
122
7
|
class HeaderFormatter {
|
|
123
8
|
format(headers) {
|
|
124
9
|
const chunks = [];
|
|
125
10
|
for (const headerName of Object.keys(headers)) {
|
|
126
|
-
const bytes =
|
|
11
|
+
const bytes = serde.fromUtf8(headerName);
|
|
127
12
|
chunks.push(Uint8Array.from([bytes.byteLength]), bytes, this.formatHeaderValue(headers[headerName]));
|
|
128
13
|
}
|
|
129
14
|
const out = new Uint8Array(chunks.reduce((carry, bytes) => carry + bytes.byteLength, 0));
|
|
@@ -163,7 +48,7 @@ class HeaderFormatter {
|
|
|
163
48
|
binBytes.set(header.value, 3);
|
|
164
49
|
return binBytes;
|
|
165
50
|
case "string":
|
|
166
|
-
const utf8Bytes =
|
|
51
|
+
const utf8Bytes = serde.fromUtf8(header.value);
|
|
167
52
|
const strView = new DataView(new ArrayBuffer(3 + utf8Bytes.byteLength));
|
|
168
53
|
strView.setUint8(0, 7);
|
|
169
54
|
strView.setUint16(1, utf8Bytes.byteLength, false);
|
|
@@ -181,7 +66,7 @@ class HeaderFormatter {
|
|
|
181
66
|
}
|
|
182
67
|
const uuidBytes = new Uint8Array(17);
|
|
183
68
|
uuidBytes[0] = 9;
|
|
184
|
-
uuidBytes.set(
|
|
69
|
+
uuidBytes.set(serde.fromHex(header.value.replace(/\-/g, "")), 1);
|
|
185
70
|
return uuidBytes;
|
|
186
71
|
}
|
|
187
72
|
}
|
|
@@ -227,7 +112,7 @@ class Int64 {
|
|
|
227
112
|
if (negative) {
|
|
228
113
|
negate(bytes);
|
|
229
114
|
}
|
|
230
|
-
return parseInt(
|
|
115
|
+
return parseInt(serde.toHex(bytes), 16) * (negative ? -1 : 1);
|
|
231
116
|
}
|
|
232
117
|
toString() {
|
|
233
118
|
return String(this.valueOf());
|
|
@@ -244,42 +129,49 @@ function negate(bytes) {
|
|
|
244
129
|
}
|
|
245
130
|
}
|
|
246
131
|
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return request;
|
|
132
|
+
const ALGORITHM_QUERY_PARAM = "X-Amz-Algorithm";
|
|
133
|
+
const CREDENTIAL_QUERY_PARAM = "X-Amz-Credential";
|
|
134
|
+
const AMZ_DATE_QUERY_PARAM = "X-Amz-Date";
|
|
135
|
+
const SIGNED_HEADERS_QUERY_PARAM = "X-Amz-SignedHeaders";
|
|
136
|
+
const EXPIRES_QUERY_PARAM = "X-Amz-Expires";
|
|
137
|
+
const SIGNATURE_QUERY_PARAM = "X-Amz-Signature";
|
|
138
|
+
const TOKEN_QUERY_PARAM = "X-Amz-Security-Token";
|
|
139
|
+
const REGION_SET_PARAM = "X-Amz-Region-Set";
|
|
140
|
+
const AUTH_HEADER = "authorization";
|
|
141
|
+
const AMZ_DATE_HEADER = AMZ_DATE_QUERY_PARAM.toLowerCase();
|
|
142
|
+
const DATE_HEADER = "date";
|
|
143
|
+
const GENERATED_HEADERS = [AUTH_HEADER, AMZ_DATE_HEADER, DATE_HEADER];
|
|
144
|
+
const SIGNATURE_HEADER = SIGNATURE_QUERY_PARAM.toLowerCase();
|
|
145
|
+
const SHA256_HEADER = "x-amz-content-sha256";
|
|
146
|
+
const TOKEN_HEADER = TOKEN_QUERY_PARAM.toLowerCase();
|
|
147
|
+
const HOST_HEADER = "host";
|
|
148
|
+
const ALWAYS_UNSIGNABLE_HEADERS = {
|
|
149
|
+
authorization: true,
|
|
150
|
+
"cache-control": true,
|
|
151
|
+
connection: true,
|
|
152
|
+
expect: true,
|
|
153
|
+
from: true,
|
|
154
|
+
"keep-alive": true,
|
|
155
|
+
"max-forwards": true,
|
|
156
|
+
pragma: true,
|
|
157
|
+
referer: true,
|
|
158
|
+
te: true,
|
|
159
|
+
trailer: true,
|
|
160
|
+
"transfer-encoding": true,
|
|
161
|
+
upgrade: true,
|
|
162
|
+
"user-agent": true,
|
|
163
|
+
"x-amzn-trace-id": true,
|
|
282
164
|
};
|
|
165
|
+
const PROXY_HEADER_PATTERN = /^proxy-/;
|
|
166
|
+
const SEC_HEADER_PATTERN = /^sec-/;
|
|
167
|
+
const UNSIGNABLE_PATTERNS = [/^proxy-/i, /^sec-/i];
|
|
168
|
+
const ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256";
|
|
169
|
+
const ALGORITHM_IDENTIFIER_V4A = "AWS4-ECDSA-P256-SHA256";
|
|
170
|
+
const EVENT_ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256-PAYLOAD";
|
|
171
|
+
const UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";
|
|
172
|
+
const MAX_CACHE_SIZE = 50;
|
|
173
|
+
const KEY_TYPE_IDENTIFIER = "aws4_request";
|
|
174
|
+
const MAX_PRESIGNED_TTL = 60 * 60 * 24 * 7;
|
|
283
175
|
|
|
284
176
|
const getCanonicalQuery = ({ query = {} }) => {
|
|
285
177
|
const keys = [];
|
|
@@ -288,16 +180,16 @@ const getCanonicalQuery = ({ query = {} }) => {
|
|
|
288
180
|
if (key.toLowerCase() === SIGNATURE_HEADER) {
|
|
289
181
|
continue;
|
|
290
182
|
}
|
|
291
|
-
const encodedKey =
|
|
183
|
+
const encodedKey = protocols.escapeUri(key);
|
|
292
184
|
keys.push(encodedKey);
|
|
293
185
|
const value = query[key];
|
|
294
186
|
if (typeof value === "string") {
|
|
295
|
-
serialized[encodedKey] = `${encodedKey}=${
|
|
187
|
+
serialized[encodedKey] = `${encodedKey}=${protocols.escapeUri(value)}`;
|
|
296
188
|
}
|
|
297
189
|
else if (Array.isArray(value)) {
|
|
298
190
|
serialized[encodedKey] = value
|
|
299
191
|
.slice(0)
|
|
300
|
-
.reduce((encoded, value) => encoded.concat([`${encodedKey}=${
|
|
192
|
+
.reduce((encoded, value) => encoded.concat([`${encodedKey}=${protocols.escapeUri(value)}`]), [])
|
|
301
193
|
.sort()
|
|
302
194
|
.join("&");
|
|
303
195
|
}
|
|
@@ -337,8 +229,8 @@ class SignatureV4Base {
|
|
|
337
229
|
this.sha256 = sha256;
|
|
338
230
|
this.uriEscapePath = uriEscapePath;
|
|
339
231
|
this.applyChecksum = typeof applyChecksum === "boolean" ? applyChecksum : true;
|
|
340
|
-
this.regionProvider =
|
|
341
|
-
this.credentialProvider =
|
|
232
|
+
this.regionProvider = client.normalizeProvider(region);
|
|
233
|
+
this.credentialProvider = client.normalizeProvider(credentials);
|
|
342
234
|
}
|
|
343
235
|
createCanonicalRequest(request, canonicalHeaders, payloadHash) {
|
|
344
236
|
const sortedHeaders = Object.keys(canonicalHeaders).sort();
|
|
@@ -352,12 +244,12 @@ ${payloadHash}`;
|
|
|
352
244
|
}
|
|
353
245
|
async createStringToSign(longDate, credentialScope, canonicalRequest, algorithmIdentifier) {
|
|
354
246
|
const hash = new this.sha256();
|
|
355
|
-
hash.update(
|
|
247
|
+
hash.update(serde.toUint8Array(canonicalRequest));
|
|
356
248
|
const hashedRequest = await hash.digest();
|
|
357
249
|
return `${algorithmIdentifier}
|
|
358
250
|
${longDate}
|
|
359
251
|
${credentialScope}
|
|
360
|
-
${
|
|
252
|
+
${serde.toHex(hashedRequest)}`;
|
|
361
253
|
}
|
|
362
254
|
getCanonicalPath({ path }) {
|
|
363
255
|
if (this.uriEscapePath) {
|
|
@@ -375,7 +267,7 @@ ${utilHexEncoding.toHex(hashedRequest)}`;
|
|
|
375
267
|
}
|
|
376
268
|
}
|
|
377
269
|
const normalizedPath = `${path?.startsWith("/") ? "/" : ""}${normalizedPathSegments.join("/")}${normalizedPathSegments.length > 0 && path?.endsWith("/") ? "/" : ""}`;
|
|
378
|
-
const doubleEncoded =
|
|
270
|
+
const doubleEncoded = protocols.escapeUri(normalizedPath);
|
|
379
271
|
return doubleEncoded.replace(/%2F/g, "/");
|
|
380
272
|
}
|
|
381
273
|
return path;
|
|
@@ -399,6 +291,111 @@ ${utilHexEncoding.toHex(hashedRequest)}`;
|
|
|
399
291
|
}
|
|
400
292
|
}
|
|
401
293
|
|
|
294
|
+
const signingKeyCache = {};
|
|
295
|
+
const cacheQueue = [];
|
|
296
|
+
const createScope = (shortDate, region, service) => `${shortDate}/${region}/${service}/${KEY_TYPE_IDENTIFIER}`;
|
|
297
|
+
const getSigningKey = async (sha256Constructor, credentials, shortDate, region, service) => {
|
|
298
|
+
const credsHash = await hmac(sha256Constructor, credentials.secretAccessKey, credentials.accessKeyId);
|
|
299
|
+
const cacheKey = `${shortDate}:${region}:${service}:${serde.toHex(credsHash)}:${credentials.sessionToken}`;
|
|
300
|
+
if (cacheKey in signingKeyCache) {
|
|
301
|
+
return signingKeyCache[cacheKey];
|
|
302
|
+
}
|
|
303
|
+
cacheQueue.push(cacheKey);
|
|
304
|
+
while (cacheQueue.length > MAX_CACHE_SIZE) {
|
|
305
|
+
delete signingKeyCache[cacheQueue.shift()];
|
|
306
|
+
}
|
|
307
|
+
let key = `AWS4${credentials.secretAccessKey}`;
|
|
308
|
+
for (const signable of [shortDate, region, service, KEY_TYPE_IDENTIFIER]) {
|
|
309
|
+
key = await hmac(sha256Constructor, key, signable);
|
|
310
|
+
}
|
|
311
|
+
return (signingKeyCache[cacheKey] = key);
|
|
312
|
+
};
|
|
313
|
+
const clearCredentialCache = () => {
|
|
314
|
+
cacheQueue.length = 0;
|
|
315
|
+
Object.keys(signingKeyCache).forEach((cacheKey) => {
|
|
316
|
+
delete signingKeyCache[cacheKey];
|
|
317
|
+
});
|
|
318
|
+
};
|
|
319
|
+
const hmac = (ctor, secret, data) => {
|
|
320
|
+
const hash = new ctor(secret);
|
|
321
|
+
hash.update(serde.toUint8Array(data));
|
|
322
|
+
return hash.digest();
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const getCanonicalHeaders = ({ headers }, unsignableHeaders, signableHeaders) => {
|
|
326
|
+
const canonical = {};
|
|
327
|
+
for (const headerName of Object.keys(headers).sort()) {
|
|
328
|
+
if (headers[headerName] == undefined) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
const canonicalHeaderName = headerName.toLowerCase();
|
|
332
|
+
if (canonicalHeaderName in ALWAYS_UNSIGNABLE_HEADERS ||
|
|
333
|
+
unsignableHeaders?.has(canonicalHeaderName) ||
|
|
334
|
+
PROXY_HEADER_PATTERN.test(canonicalHeaderName) ||
|
|
335
|
+
SEC_HEADER_PATTERN.test(canonicalHeaderName)) {
|
|
336
|
+
if (!signableHeaders || (signableHeaders && !signableHeaders.has(canonicalHeaderName))) {
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
canonical[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " ");
|
|
341
|
+
}
|
|
342
|
+
return canonical;
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const getPayloadHash = async ({ headers, body }, hashConstructor) => {
|
|
346
|
+
for (const headerName of Object.keys(headers)) {
|
|
347
|
+
if (headerName.toLowerCase() === SHA256_HEADER) {
|
|
348
|
+
return headers[headerName];
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (body == undefined) {
|
|
352
|
+
return "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
|
|
353
|
+
}
|
|
354
|
+
else if (typeof body === "string" || ArrayBuffer.isView(body) || serde.isArrayBuffer(body)) {
|
|
355
|
+
const hashCtor = new hashConstructor();
|
|
356
|
+
hashCtor.update(serde.toUint8Array(body));
|
|
357
|
+
return serde.toHex(await hashCtor.digest());
|
|
358
|
+
}
|
|
359
|
+
return UNSIGNED_PAYLOAD;
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
const hasHeader = (soughtHeader, headers) => {
|
|
363
|
+
soughtHeader = soughtHeader.toLowerCase();
|
|
364
|
+
for (const headerName of Object.keys(headers)) {
|
|
365
|
+
if (soughtHeader === headerName.toLowerCase()) {
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return false;
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
const moveHeadersToQuery = (request, options = {}) => {
|
|
373
|
+
const { headers, query = {} } = protocols.HttpRequest.clone(request);
|
|
374
|
+
for (const name of Object.keys(headers)) {
|
|
375
|
+
const lname = name.toLowerCase();
|
|
376
|
+
if ((lname.slice(0, 6) === "x-amz-" && !options.unhoistableHeaders?.has(lname)) ||
|
|
377
|
+
options.hoistableHeaders?.has(lname)) {
|
|
378
|
+
query[name] = headers[name];
|
|
379
|
+
delete headers[name];
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return {
|
|
383
|
+
...request,
|
|
384
|
+
headers,
|
|
385
|
+
query,
|
|
386
|
+
};
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
const prepareRequest = (request) => {
|
|
390
|
+
request = protocols.HttpRequest.clone(request);
|
|
391
|
+
for (const headerName of Object.keys(request.headers)) {
|
|
392
|
+
if (GENERATED_HEADERS.indexOf(headerName.toLowerCase()) > -1) {
|
|
393
|
+
delete request.headers[headerName];
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return request;
|
|
397
|
+
};
|
|
398
|
+
|
|
402
399
|
class SignatureV4 extends SignatureV4Base {
|
|
403
400
|
headerFormatter = new HeaderFormatter();
|
|
404
401
|
constructor({ applyChecksum, credentials, region, service, sha256, uriEscapePath = true, }) {
|
|
@@ -448,14 +445,14 @@ class SignatureV4 extends SignatureV4Base {
|
|
|
448
445
|
return this.signRequest(toSign, options);
|
|
449
446
|
}
|
|
450
447
|
}
|
|
451
|
-
async signEvent({ headers, payload }, { signingDate = new Date(), priorSignature, signingRegion, signingService }) {
|
|
448
|
+
async signEvent({ headers, payload }, { signingDate = new Date(), priorSignature, signingRegion, signingService, eventStreamCredentials, }) {
|
|
452
449
|
const region = signingRegion ?? (await this.regionProvider());
|
|
453
450
|
const { shortDate, longDate } = this.formatDate(signingDate);
|
|
454
451
|
const scope = createScope(shortDate, region, signingService ?? this.service);
|
|
455
452
|
const hashedPayload = await getPayloadHash({ headers: {}, body: payload }, this.sha256);
|
|
456
453
|
const hash = new this.sha256();
|
|
457
454
|
hash.update(headers);
|
|
458
|
-
const hashedHeaders =
|
|
455
|
+
const hashedHeaders = serde.toHex(await hash.digest());
|
|
459
456
|
const stringToSign = [
|
|
460
457
|
EVENT_ALGORITHM_IDENTIFIER,
|
|
461
458
|
longDate,
|
|
@@ -464,9 +461,14 @@ class SignatureV4 extends SignatureV4Base {
|
|
|
464
461
|
hashedHeaders,
|
|
465
462
|
hashedPayload,
|
|
466
463
|
].join("\n");
|
|
467
|
-
return this.signString(stringToSign, {
|
|
464
|
+
return this.signString(stringToSign, {
|
|
465
|
+
signingDate,
|
|
466
|
+
signingRegion: region,
|
|
467
|
+
signingService,
|
|
468
|
+
eventStreamCredentials,
|
|
469
|
+
});
|
|
468
470
|
}
|
|
469
|
-
async signMessage(signableMessage, { signingDate = new Date(), signingRegion, signingService }) {
|
|
471
|
+
async signMessage(signableMessage, { signingDate = new Date(), signingRegion, signingService, eventStreamCredentials }) {
|
|
470
472
|
const promise = this.signEvent({
|
|
471
473
|
headers: this.headerFormatter.format(signableMessage.message.headers),
|
|
472
474
|
payload: signableMessage.message.body,
|
|
@@ -475,19 +477,20 @@ class SignatureV4 extends SignatureV4Base {
|
|
|
475
477
|
signingRegion,
|
|
476
478
|
signingService,
|
|
477
479
|
priorSignature: signableMessage.priorSignature,
|
|
480
|
+
eventStreamCredentials,
|
|
478
481
|
});
|
|
479
482
|
return promise.then((signature) => {
|
|
480
483
|
return { message: signableMessage.message, signature };
|
|
481
484
|
});
|
|
482
485
|
}
|
|
483
|
-
async signString(stringToSign, { signingDate = new Date(), signingRegion, signingService } = {}) {
|
|
484
|
-
const credentials = await this.credentialProvider();
|
|
486
|
+
async signString(stringToSign, { signingDate = new Date(), signingRegion, signingService, eventStreamCredentials, } = {}) {
|
|
487
|
+
const credentials = eventStreamCredentials ?? (await this.credentialProvider());
|
|
485
488
|
this.validateResolvedCredentials(credentials);
|
|
486
489
|
const region = signingRegion ?? (await this.regionProvider());
|
|
487
490
|
const { shortDate } = this.formatDate(signingDate);
|
|
488
491
|
const hash = new this.sha256(await this.getSigningKey(credentials, region, shortDate, signingService));
|
|
489
|
-
hash.update(
|
|
490
|
-
return
|
|
492
|
+
hash.update(serde.toUint8Array(stringToSign));
|
|
493
|
+
return serde.toHex(await hash.digest());
|
|
491
494
|
}
|
|
492
495
|
async signRequest(requestToSign, { signingDate = new Date(), signableHeaders, unsignableHeaders, signingRegion, signingService, } = {}) {
|
|
493
496
|
const credentials = await this.credentialProvider();
|
|
@@ -516,8 +519,8 @@ class SignatureV4 extends SignatureV4Base {
|
|
|
516
519
|
async getSignature(longDate, credentialScope, keyPromise, canonicalRequest) {
|
|
517
520
|
const stringToSign = await this.createStringToSign(longDate, credentialScope, canonicalRequest, ALGORITHM_IDENTIFIER);
|
|
518
521
|
const hash = new this.sha256(await keyPromise);
|
|
519
|
-
hash.update(
|
|
520
|
-
return
|
|
522
|
+
hash.update(serde.toUint8Array(stringToSign));
|
|
523
|
+
return serde.toHex(await hash.digest());
|
|
521
524
|
}
|
|
522
525
|
getSigningKey(credentials, region, shortDate, service) {
|
|
523
526
|
return getSigningKey(this.sha256, credentials, shortDate, region, service || this.service);
|
package/dist-es/SignatureV4.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { toHex } from "@smithy/
|
|
2
|
-
import {
|
|
1
|
+
import { toHex, toUint8Array } from "@smithy/core/serde";
|
|
2
|
+
import { HeaderFormatter } from "./HeaderFormatter";
|
|
3
|
+
import { SignatureV4Base } from "./SignatureV4Base";
|
|
3
4
|
import { ALGORITHM_IDENTIFIER, ALGORITHM_QUERY_PARAM, AMZ_DATE_HEADER, AMZ_DATE_QUERY_PARAM, AUTH_HEADER, CREDENTIAL_QUERY_PARAM, EVENT_ALGORITHM_IDENTIFIER, EXPIRES_QUERY_PARAM, MAX_PRESIGNED_TTL, SHA256_HEADER, SIGNATURE_QUERY_PARAM, SIGNED_HEADERS_QUERY_PARAM, TOKEN_HEADER, TOKEN_QUERY_PARAM, } from "./constants";
|
|
4
5
|
import { createScope, getSigningKey } from "./credentialDerivation";
|
|
5
6
|
import { getCanonicalHeaders } from "./getCanonicalHeaders";
|
|
6
7
|
import { getPayloadHash } from "./getPayloadHash";
|
|
7
|
-
import { HeaderFormatter } from "./HeaderFormatter";
|
|
8
8
|
import { hasHeader } from "./headerUtil";
|
|
9
9
|
import { moveHeadersToQuery } from "./moveHeadersToQuery";
|
|
10
10
|
import { prepareRequest } from "./prepareRequest";
|
|
11
|
-
import { SignatureV4Base } from "./SignatureV4Base";
|
|
12
11
|
export class SignatureV4 extends SignatureV4Base {
|
|
13
12
|
headerFormatter = new HeaderFormatter();
|
|
14
13
|
constructor({ applyChecksum, credentials, region, service, sha256, uriEscapePath = true, }) {
|
|
@@ -58,7 +57,7 @@ export class SignatureV4 extends SignatureV4Base {
|
|
|
58
57
|
return this.signRequest(toSign, options);
|
|
59
58
|
}
|
|
60
59
|
}
|
|
61
|
-
async signEvent({ headers, payload }, { signingDate = new Date(), priorSignature, signingRegion, signingService }) {
|
|
60
|
+
async signEvent({ headers, payload }, { signingDate = new Date(), priorSignature, signingRegion, signingService, eventStreamCredentials, }) {
|
|
62
61
|
const region = signingRegion ?? (await this.regionProvider());
|
|
63
62
|
const { shortDate, longDate } = this.formatDate(signingDate);
|
|
64
63
|
const scope = createScope(shortDate, region, signingService ?? this.service);
|
|
@@ -74,9 +73,14 @@ export class SignatureV4 extends SignatureV4Base {
|
|
|
74
73
|
hashedHeaders,
|
|
75
74
|
hashedPayload,
|
|
76
75
|
].join("\n");
|
|
77
|
-
return this.signString(stringToSign, {
|
|
76
|
+
return this.signString(stringToSign, {
|
|
77
|
+
signingDate,
|
|
78
|
+
signingRegion: region,
|
|
79
|
+
signingService,
|
|
80
|
+
eventStreamCredentials,
|
|
81
|
+
});
|
|
78
82
|
}
|
|
79
|
-
async signMessage(signableMessage, { signingDate = new Date(), signingRegion, signingService }) {
|
|
83
|
+
async signMessage(signableMessage, { signingDate = new Date(), signingRegion, signingService, eventStreamCredentials }) {
|
|
80
84
|
const promise = this.signEvent({
|
|
81
85
|
headers: this.headerFormatter.format(signableMessage.message.headers),
|
|
82
86
|
payload: signableMessage.message.body,
|
|
@@ -85,13 +89,14 @@ export class SignatureV4 extends SignatureV4Base {
|
|
|
85
89
|
signingRegion,
|
|
86
90
|
signingService,
|
|
87
91
|
priorSignature: signableMessage.priorSignature,
|
|
92
|
+
eventStreamCredentials,
|
|
88
93
|
});
|
|
89
94
|
return promise.then((signature) => {
|
|
90
95
|
return { message: signableMessage.message, signature };
|
|
91
96
|
});
|
|
92
97
|
}
|
|
93
|
-
async signString(stringToSign, { signingDate = new Date(), signingRegion, signingService } = {}) {
|
|
94
|
-
const credentials = await this.credentialProvider();
|
|
98
|
+
async signString(stringToSign, { signingDate = new Date(), signingRegion, signingService, eventStreamCredentials, } = {}) {
|
|
99
|
+
const credentials = eventStreamCredentials ?? (await this.credentialProvider());
|
|
95
100
|
this.validateResolvedCredentials(credentials);
|
|
96
101
|
const region = signingRegion ?? (await this.regionProvider());
|
|
97
102
|
const { shortDate } = this.formatDate(signingDate);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { toUint8Array } from "@smithy/util-utf8";
|
|
1
|
+
import { normalizeProvider } from "@smithy/core/client";
|
|
2
|
+
import { escapeUri } from "@smithy/core/protocols";
|
|
3
|
+
import { toHex, toUint8Array } from "@smithy/core/serde";
|
|
5
4
|
import { getCanonicalQuery } from "./getCanonicalQuery";
|
|
6
5
|
import { iso8601 } from "./utilDate";
|
|
7
6
|
export class SignatureV4Base {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { toHex } from "@smithy/
|
|
2
|
-
import { toUint8Array } from "@smithy/util-utf8";
|
|
1
|
+
import { toHex, toUint8Array } from "@smithy/core/serde";
|
|
3
2
|
import { KEY_TYPE_IDENTIFIER, MAX_CACHE_SIZE } from "./constants";
|
|
4
3
|
const signingKeyCache = {};
|
|
5
4
|
const cacheQueue = [];
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { isArrayBuffer } from "@smithy/
|
|
2
|
-
import { toHex } from "@smithy/util-hex-encoding";
|
|
3
|
-
import { toUint8Array } from "@smithy/util-utf8";
|
|
1
|
+
import { isArrayBuffer, toHex, toUint8Array } from "@smithy/core/serde";
|
|
4
2
|
import { SHA256_HEADER, UNSIGNED_PAYLOAD } from "./constants";
|
|
5
3
|
export const getPayloadHash = async ({ headers, body }, hashConstructor) => {
|
|
6
4
|
for (const headerName of Object.keys(headers)) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HttpRequest } from "@smithy/
|
|
1
|
+
import { HttpRequest } from "@smithy/core/protocols";
|
|
2
2
|
export const moveHeadersToQuery = (request, options = {}) => {
|
|
3
3
|
const { headers, query = {} } = HttpRequest.clone(request);
|
|
4
4
|
for (const name of Object.keys(headers)) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { EventSigner, EventSigningArguments, FormattedEvent, HttpRequest, MessageSigner, RequestPresigner, RequestPresigningArguments, RequestSigner, RequestSigningArguments, SignableMessage, SignedMessage, SigningArguments, StringSigner } from "@smithy/types";
|
|
2
|
-
import type
|
|
3
|
-
import { SignatureV4Base } from "./SignatureV4Base";
|
|
1
|
+
import type { EventSigner, EventSigningArguments, FormattedEvent, HttpRequest, MessageSigner, MessageSigningArguments, RequestPresigner, RequestPresigningArguments, RequestSigner, RequestSigningArguments, SignableMessage, SignedMessage, SigningArguments, StringSigner } from "@smithy/types";
|
|
2
|
+
import { SignatureV4Base, type SignatureV4CryptoInit, type SignatureV4Init } from "./SignatureV4Base";
|
|
4
3
|
/**
|
|
5
4
|
* @public
|
|
6
5
|
*/
|
|
@@ -10,10 +9,10 @@ export declare class SignatureV4 extends SignatureV4Base implements RequestPresi
|
|
|
10
9
|
presign(originalRequest: HttpRequest, options?: RequestPresigningArguments): Promise<HttpRequest>;
|
|
11
10
|
sign(stringToSign: string, options?: SigningArguments): Promise<string>;
|
|
12
11
|
sign(event: FormattedEvent, options: EventSigningArguments): Promise<string>;
|
|
13
|
-
sign(event: SignableMessage, options:
|
|
12
|
+
sign(event: SignableMessage, options: MessageSigningArguments): Promise<SignedMessage>;
|
|
14
13
|
sign(requestToSign: HttpRequest, options?: RequestSigningArguments): Promise<HttpRequest>;
|
|
15
14
|
private signEvent;
|
|
16
|
-
signMessage(signableMessage: SignableMessage, { signingDate, signingRegion, signingService }:
|
|
15
|
+
signMessage(signableMessage: SignableMessage, { signingDate, signingRegion, signingService, eventStreamCredentials }: MessageSigningArguments): Promise<SignedMessage>;
|
|
17
16
|
private signString;
|
|
18
17
|
private signRequest;
|
|
19
18
|
private getSignature;
|
package/dist-types/index.d.ts
CHANGED
|
@@ -6,6 +6,6 @@ export { getPayloadHash } from "./getPayloadHash";
|
|
|
6
6
|
export { moveHeadersToQuery } from "./moveHeadersToQuery";
|
|
7
7
|
export { prepareRequest } from "./prepareRequest";
|
|
8
8
|
export * from "./credentialDerivation";
|
|
9
|
-
export { SignatureV4Init, SignatureV4CryptoInit
|
|
9
|
+
export { SignatureV4Base, type SignatureV4Init, type SignatureV4CryptoInit } from "./SignatureV4Base";
|
|
10
10
|
export { hasHeader } from "./headerUtil";
|
|
11
11
|
export * from "./signature-v4a-container";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smithy/signature-v4",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"description": "A standalone implementation of the AWS Signature V4 request signing algorithm",
|
|
5
5
|
"main": "./dist-cjs/index.js",
|
|
6
6
|
"module": "./dist-es/index.js",
|
|
@@ -25,13 +25,8 @@
|
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"sideEffects": false,
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@smithy/
|
|
29
|
-
"@smithy/
|
|
30
|
-
"@smithy/types": "^4.14.0",
|
|
31
|
-
"@smithy/util-hex-encoding": "^4.2.2",
|
|
32
|
-
"@smithy/util-middleware": "^4.2.13",
|
|
33
|
-
"@smithy/util-uri-escape": "^4.2.2",
|
|
34
|
-
"@smithy/util-utf8": "^4.2.2",
|
|
28
|
+
"@smithy/core": "^3.24.0",
|
|
29
|
+
"@smithy/types": "^4.14.1",
|
|
35
30
|
"tslib": "^2.6.2"
|
|
36
31
|
},
|
|
37
32
|
"devDependencies": {
|