Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

HMAC request validation

Not applicable

Hi,

Is it possible to use HMAC (or alternative hash) to validate the request has not been tampered with?

Some of our requests are based on the post payload so I would like to be able to hash the payload with a provided secret and confirm that within apigee when the request is received. Is this possible?

Thanks

Carl

Solved Solved
2 24 6,044
1 ACCEPTED SOLUTION

Not applicable

Implementation that uses - https://crypto.stanford.edu/sjcl/

string to Sign is defined at the top and can be changed based upon agreement between client and server. Variable extraction and key verification needs to be done prior to this script

function validDate(){
    context.setVariable("Auth.stringToSign", "Auth.dateSigned,Auth.apikey,Auth.nonce,Auth.salt,request.content");


    var validMilliseconds = 300000;
    var dtstr = context.getVariable("Auth.dateSigned"); // format yyyyMMddHHmmss UTC
    var yy = parseInt(dtstr.substr(0,4));
    var MM = parseInt(dtstr.substr(4,2))-1;
    var dd = parseInt(dtstr.substr(6,2));
    var HH = parseInt(dtstr.substr(8,2));
    var mm = parseInt(dtstr.substr(10,2));
    var ss = parseInt(dtstr.substr(12,2));


    var dt = new Date(Date.UTC(yy,MM,dd,HH,mm,ss));
    var dtnow = new Date();
    return ((Math.abs(dtnow - dt)) < validMilliseconds);
}


(function validate(validDate) {
    var stringToSign = "";
    var computedSig = "";
    var signatureMatch = false;


    if (validDate)
    {
        var contextVars = context.getVariable("Auth.stringToSign").split(",");


        var i = 0;
        for (i = 0; i < contextVars.length; i++) {
            var str = context.getVariable(contextVars[i]);
            if ( str !== null ) {
                stringToSign += str;
            }
        }


        var key = context.getVariable("verifyapikey.verifyApiKey.client_secret");
        var keyBits = sjcl.codec.utf8String.toBits(key);
        var out = (new sjcl.misc.hmac(keyBits, sjcl.hash.sha256)).mac(stringToSign);
        computedSig = sjcl.codec.hex.fromBits(out);
    }


    if (computedSig !== null && computedSig.length > 0)
    {
        var requestSig = context.getVariable("Auth.signature");
        // modified base64 i.e. + -> - , / -> _, remove trailing pad
        computedSig = computedSig.replace("+","-");
        computedSig = computedSig.replace("/","_");
        computedSig = computedSig.replace(/(=+$)/g, "");


        signatureMatch = (computedSig.valueOf() === requestSig.valueOf());
    }


    context.setVariable("hmacjs.signatureMatch", signatureMatch);


})(validDate());


View solution in original post

24 REPLIES 24
Top Solution Authors