Kyba1985
10/21/2019 - 2:56 PM

typescript function to validate signature api request, reference: https://tools.ietf.org/html/draft-cavage-http-signatures-11

typescript function to validate signature api request, reference: https://tools.ietf.org/html/draft-cavage-http-signatures-11

import * as crypto from 'crypto';
import Base64 from 'crypto-js/enc-base64';
import UTF8 from 'crypto-js/enc-utf8';
import * as cryptoJS from 'crypto-js';

export async function validateSignatureRequest(event: APIGatewayEvent): Promise<boolean> {
    //1 ricerca header signature
    try {
        let headerSignature = event.headers["x-is-signature"];
        let digest = event.headers["digest"];
        if (headerSignature === undefined) return false;
        if (digest === undefined) return false;

        let regex = /(?<key>created|signature)=(?<value>[^ ]*)/gm;
        let str = headerSignature;
        let m;
        let ret: regExWrapper = {};
        while ((m = regex.exec(str)) !== null) {
            // This is necessary to avoid infinite loops with zero-width matches
            if (m.index === regex.lastIndex) {
                regex.lastIndex++;
            }
            ret[m.groups['key']] = m.groups['value'];
        }
        regex.lastIndex = 0;

        let created = ret["created"];
        let signature = ret["signature"];
        if (created === undefined || signature === undefined) return false;

        let body = event.body;
        
        if (body !== null) {
            const hash = crypto.createHash('sha256');
            let digestBodyCalculated = `SHA-256=${hash.update(body, 'utf8').digest('base64')}`
            console.log("SHA BODY calcualted: " + digestBodyCalculated);
            if (digest !== digestBodyCalculated) return false;
        }

        let methodAndPath = event.httpMethod.toLowerCase() + ' ' + event.path;
        let signatureString = "(request-target): " + methodAndPath + "\n";
        signatureString += "(created): " + created + "\n";
        signatureString += "digest: " + digest;
        console.log(signatureString);

        var secretKeyBytes = Base64.parse("sampleKEYTOUPDATE");
        var payloadBytes = UTF8.parse(signatureString);
        var signatureBytes = cryptoJS.HmacSHA256(payloadBytes, secretKeyBytes);
        var signatureBase64String = Base64.stringify(signatureBytes);
        if (signatureBase64String !== signature) return false;
        return true;
    }
    catch (exception) {
        return false;
    }
}