1- import { BSON } from './bson' ;
2- import { type AWSCredentials } from './deps' ;
1+ import { BSON } from '../.. /bson' ;
2+ import { type AWSCredentials } from '../.. /deps' ;
33
44export type Options = {
55 path : '/' ;
@@ -14,7 +14,7 @@ export type Options = {
1414 } ;
1515 service : string ;
1616 region : string ;
17- date ? : Date ;
17+ date : Date ;
1818} ;
1919
2020export type SignedHeaders = {
@@ -24,13 +24,26 @@ export type SignedHeaders = {
2424 } ;
2525} ;
2626
27+ /**
28+ * Calculates the SHA-256 hash of a string.
29+ *
30+ * @param str - String to hash.
31+ * @returns Hexadecimal representation of the hash.
32+ */
2733const getHash = async ( str : string ) : Promise < string > => {
2834 const data = new Uint8Array ( BSON . onDemand . ByteUtils . utf8ByteLength ( str ) ) ;
2935 BSON . onDemand . ByteUtils . encodeUTF8Into ( data , str , 0 ) ;
3036 const hashBuffer = await crypto . subtle . digest ( 'SHA-256' , data ) ;
3137 const hashHex = BSON . onDemand . ByteUtils . toHex ( new Uint8Array ( hashBuffer ) ) ;
3238 return hashHex ;
3339} ;
40+
41+ /**
42+ * Calculates the HMAC-SHA256 of a string using the provided key.
43+ * @param key - Key to use for HMAC calculation. Can be a string or Uint8Array.
44+ * @param str - String to calculate HMAC for.
45+ * @returns Uint8Array containing the HMAC-SHA256 digest.
46+ */
3447const getHmacBuffer = async ( key : string | Uint8Array , str : string ) : Promise < Uint8Array > => {
3548 let keyData : Uint8Array ;
3649 if ( typeof key === 'string' ) {
@@ -53,12 +66,16 @@ const getHmacBuffer = async (key: string | Uint8Array, str: string): Promise<Uin
5366 const digest = new Uint8Array ( signature ) ;
5467 return digest ;
5568} ;
56- const getHmacString = async ( key : Uint8Array , str : string ) : Promise < string > => {
57- const hmacBuffer = await getHmacBuffer ( key , str ) ;
58- const hashHex = BSON . onDemand . ByteUtils . toHex ( hmacBuffer ) ;
59- return hashHex ;
60- } ;
6169
70+ /**
71+ * Converts header values according to AWS requirements,
72+ * From https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html#create-canonical-request
73+ * For values, you must:
74+ - trim any leading or trailing spaces.
75+ - convert sequential spaces to a single space.
76+ * @param value - Header value to convert.
77+ * @returns - Converted header value.
78+ */
6279const convertHeaderValue = ( value : string | number ) => {
6380 return value . toString ( ) . trim ( ) . replace ( / \s + / g, ' ' ) ;
6481} ;
@@ -91,8 +108,8 @@ export async function aws4Sign(
91108
92109 // 1: Create a canonical request
93110
94- // Date – The date and time used to sign the request. If not provided, use the current date.
95- const date = options . date || new Date ( ) ;
111+ // Date – The date and time used to sign the request.
112+ const date = options . date ;
96113 // RequestDateTime – The date and time used in the credential scope. This value is the current UTC time in ISO 8601 format (for example, 20130524T000000Z).
97114 const requestDateTime = date . toISOString ( ) . replace ( / [: -] | \. \d { 3 } / g, '' ) ;
98115 // RequestDate – The date used in the credential scope. This value is the current UTC date in YYYYMMDD format (for example, 20130524).
@@ -164,7 +181,8 @@ export async function aws4Sign(
164181 const signingKey = await getHmacBuffer ( dateRegionServiceKey , 'aws4_request' ) ;
165182
166183 // 5. Calculate the signature
167- const signature = await getHmacString ( signingKey , stringToSign ) ;
184+ const signatureBuffer = await getHmacBuffer ( signingKey , stringToSign ) ;
185+ const signature = BSON . onDemand . ByteUtils . toHex ( signatureBuffer ) ;
168186
169187 // 6. Add the signature to the request
170188 // Calculate the Authorization header
0 commit comments