Skip to content

Instantly share code, notes, and snippets.

@DinoChiesa
Created January 26, 2016 23:18
Show Gist options
  • Star 49 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save DinoChiesa/75796b27828cf8e15c91 to your computer and use it in GitHub Desktop.
Save DinoChiesa/75796b27828cf8e15c91 to your computer and use it in GitHub Desktop.
pre-request script for Postman, to perform HttpSignature calculation. Also SHA-256 message digest.
function computeHttpSignature(config, headerHash) {
var template = 'keyId="${keyId}",algorithm="${algorithm}",headers="${headers}",signature="${signature}"',
sig = template;
// compute sig here
var signingBase = '';
config.headers.forEach(function(h){
if (signingBase !== '') { signingBase += '\n'; }
signingBase += h.toLowerCase() + ": " + headerHash[h];
});
var hashf = (function() {
switch (config.algorithm) {
case 'hmac-sha1': return CryptoJS.HmacSHA1;
case 'hmac-sha256': return CryptoJS.HmacSHA256;
case 'hmac-sha512': return CryptoJS.HmacSHA512;
default : return null;
}
}());
var hash = hashf(signingBase, config.secretkey);
var signatureOptions = {
keyId : config.keyId,
algorithm: config.algorithm,
headers: config.headers,
signature : CryptoJS.enc.Base64.stringify(hash)
};
// build sig string here
Object.keys(signatureOptions).forEach(function(key) {
var pattern = "${" + key + "}",
value = (typeof signatureOptions[key] != 'string') ? signatureOptions[key].join(' ') : signatureOptions[key];
sig = sig.replace(pattern, value);
});
return sig;
}
var curDate = new Date().toGMTString();
var targetUrl = request.url.trim(); // there may be surrounding ws
targetUrl = targetUrl.replace(new RegExp('^https?://[^/]+/'),'/'); // strip hostname
var method = request.method.toLowerCase();
var sha256digest = CryptoJS.SHA256(request.data);
var base64sha256 = CryptoJS.enc.Base64.stringify(sha256digest);
var computedDigest = 'sha-256=' + base64sha256;
var headerHash = {
date : curDate,
digest : computedDigest,
'(request-target)' : method + ' ' + targetUrl
};
var config = {
algorithm : 'hmac-sha256',
keyId : environment['key-id'],
secretkey : environment['shared-secret'],
headers : [ '(request-target)', 'date', 'digest' ]
};
var sig = computeHttpSignature(config, headerHash);
postman.setEnvironmentVariable('httpsig', sig);
postman.setEnvironmentVariable('computed-digest', computedDigest);
postman.setEnvironmentVariable("current-date", curDate);
postman.setEnvironmentVariable("target-url", targetUrl);
@iamlothian
Copy link

👍 Very handy. Nice work.

@SofHad
Copy link

SofHad commented Dec 10, 2018

Good, thanks 👍

@idontusenumbers
Copy link

idontusenumbers commented Oct 8, 2019

Thanks for the head start on this; I was able to adapt to our use.

Some suggestions:

  • Base64 decode the secretKey before use
  • change headerHash to also pull from the request:
var headerHash = Object.assign(Object.assign({},pm.request.headers.toObject(true)),  {
      date : curDate,
      digest : computedDigest,
      '(request-target)' : method + ' ' + targetUrl
    });
  • Parameterize or at least call out the hash algorithm name might need adjusting (it did in my case)

@SecOpsWarrior
Copy link

Trying to get this to work...getting:

"TypeError: Cannot read property 'sigBytes' of undefined"

In the postman GUI. Any ideas where to start? What variables should be defined to start with? I have defined:

keyId
shared-secret

with values in the environment settings.

@iteratelance
Copy link

@SecOpsWarrior

I think it's because you need to add variables to the environment with a different syntax

notice pm.environment.get("signature_key_id") and pm.environment.get("signature_key")

var config = {
      algorithm : 'hmac-sha256',
      keyId : pm.environment.get("signature_key_id"),
      secretkey : pm.environment.get("signature_key"),
      headers : [ '(request-target)', 'digest', 'date']
    };

@mquarters
Copy link

Thanks for the head start on this; I was able to adapt to our use.

Some suggestions:

* Base64 decode the `secretKey` before use

* change `headerHash` to also pull from the request:
var headerHash = Object.assign(Object.assign({},pm.request.headers.toObject(true)),  {
      date : curDate,
      digest : computedDigest,
      '(request-target)' : method + ' ' + targetUrl
    });
* Parameterize or at least call out the hash algorithm name might need adjusting (it did in my case)

Specifically you need to Base64 decode with

CryptoJS.enc.Base64.parse('your-secret-key')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment