import { createHash, createHmac } from '../node-singletons/crypto.js';
export const AwsSigV4 = Object.freeze({
    sha256Hex(data) {
        return createHash('sha256').update(data).digest('hex');
    },
    hmacSha256(key, data) {
        return createHmac('sha256', key).update(data).digest();
    },
    toAmzDate(date) {
        const yyyy = String(date.getUTCFullYear());
        const mm = String(date.getUTCMonth() + 1).padStart(2, '0');
        const dd = String(date.getUTCDate()).padStart(2, '0');
        const hh = String(date.getUTCHours()).padStart(2, '0');
        const mi = String(date.getUTCMinutes()).padStart(2, '0');
        const ss = String(date.getUTCSeconds()).padStart(2, '0');
        const dateStamp = `${yyyy}${mm}${dd}`;
        const amzDate = `${dateStamp}T${hh}${mi}${ss}Z`;
        return { amzDate, dateStamp };
    },
    deriveSigningKey(params) {
        const kDate = this.hmacSha256(`AWS4${params.secretAccessKey}`, params.dateStamp);
        const kRegion = this.hmacSha256(kDate, params.region);
        const kService = this.hmacSha256(kRegion, params.service);
        return this.hmacSha256(kService, 'aws4_request');
    },
    canonicalizeHeaders(headers) {
        const sortedHeaderKeys = Object.keys(headers).sort((a, b) => a.localeCompare(b));
        const canonicalHeaders = sortedHeaderKeys
            .map((k) => `${k}:${String(headers[k]).trim().replaceAll(/\s+/g, ' ')}`)
            .join('\n');
        const signedHeaders = sortedHeaderKeys.join(';');
        return { canonicalHeaders, signedHeaders };
    },
    buildAuthorization(params) {
        const sessionToken = params.credentials.sessionToken;
        if (typeof sessionToken === 'string' &&
            sessionToken.trim() !== '' &&
            params.headers['x-amz-security-token'] === undefined) {
            params.headers['x-amz-security-token'] = sessionToken;
        }
        const { canonicalHeaders, signedHeaders } = this.canonicalizeHeaders(params.headers);
        const canonicalRequest = [
            params.method,
            params.canonicalUri,
            params.canonicalQueryString,
            `${canonicalHeaders}\n`,
            signedHeaders,
            params.payloadHash,
        ].join('\n');
        const algorithm = 'AWS4-HMAC-SHA256';
        const credentialScope = `${params.dateStamp}/${params.region}/${params.service}/aws4_request`;
        const stringToSign = [
            algorithm,
            params.amzDate,
            credentialScope,
            this.sha256Hex(canonicalRequest),
        ].join('\n');
        const signingKey = this.deriveSigningKey({
            secretAccessKey: params.credentials.secretAccessKey,
            dateStamp: params.dateStamp,
            region: params.region,
            service: params.service,
        });
        const signature = createHmac('sha256', signingKey).update(stringToSign).digest('hex');
        const authorization = `${algorithm} Credential=${params.credentials.accessKeyId}/${credentialScope}, ` +
            `SignedHeaders=${signedHeaders}, Signature=${signature}`;
        return { authorization, signedHeaders };
    },
});
