Skip to content

Instantly share code, notes, and snippets.

@mrpinghe
Last active August 23, 2023 21:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mrpinghe/f44479f2270ea36bf3b7cc958cc76cc0 to your computer and use it in GitHub Desktop.
Save mrpinghe/f44479f2270ea36bf3b7cc958cc76cc0 to your computer and use it in GitHub Desktop.
Veracode custom HMAC request signing algorithm (used for API authorization)
var crypto = require('crypto');
const id = process.env.API_ID; // your API ID, reading from environment variable
const key = process.env.KEY; // your API key, reading from environment variable
const preFix = "VERACODE-HMAC-SHA-256";
const verStr = "vcode_request_version_1";
var resthost = "api.veracode.com"; // rest host
var xmlhost = "analysiscenter.veracode.com"; // xml host
var hmac256 = (data, key, format) => {
var hash = crypto.createHmac('sha256', key).update(data);
// no format = Buffer / byte array
return hash.digest(format);
}
var getByteArray = (hex) => {
var bytes = [];
for(var i = 0; i < hex.length-1; i+=2){
bytes.push(parseInt(hex.substr(i, 2), 16));
}
// signed 8-bit integer array (byte array)
return Int8Array.from(bytes);
}
var getHost = (xml) => {
if (xml) {
return xmlhost;
}
return resthost;
}
var generateHeader = (url, method, xml) => {
var host = getHost(xml);
var data = `id=${id}&host=${host}&url=${url}&method=${method}`;
var timestamp = (new Date().getTime()).toString();
var nonce = crypto.randomBytes(16).toString("hex");
// calculate signature
var hashedNonce = hmac256(getByteArray(nonce), getByteArray(key));
var hashedTimestamp = hmac256(timestamp, hashedNonce);
var hashedVerStr = hmac256(verStr, hashedTimestamp);
var signature = hmac256(data, hashedVerStr, 'hex');
return `${preFix} id=${id},ts=${timestamp},nonce=${nonce},sig=${signature}`;
}
module.exports = {
getHost,
generateHeader
}
@mrpinghe
Copy link
Author

mrpinghe commented Nov 6, 2018

sample usage

// test.js

const https = require("https");
const auth = require("./auth");

var options = {
    host: auth.getHost(),
    path: "/appsec/v1/applications?size=100&page=0",
    method: "GET"
}

/* xml api

var options = {
    host: auth.getHost("xml"),
    path: "/api/5.0/getapplist.do",
    method: "GET"
}

*/

options.headers = {
    "Authorization": auth.generateHeader(options.path, options.method)
    // xml api
    // "Authorization": auth.generateHeader(options.path, options.method, "xml")
}


var req = https.request(options, (resp) => {
    var body = "";

    resp.on("data", (chunk) => {
        body += chunk;
    });

    resp.on("end", () => {
        console.log(body);
    });
})


req.on("error", (err) => {
    console.error(err);
});

req.end();

Then in command line

$ export API_ID=YOUR_API_ID_VALUE && export KEY=YOUR_KEY_VALUE && node test.js

@pillamarip
Copy link

Does this script need any changes? I get "message":"Request failed with status code 401","name":"Error","stack":"Error: Request failed with status code 401\n". Need some help

@mrpinghe
Copy link
Author

This still works as of yesterday.
A few things to check

  1. Is your ID and API key still valid?
  2. Did you generate a token for every request?
  3. Is your account authorized to call the API endpoint you are trying to access ?

If you are sure none of them is the issue, you probably need to post your code for me to help you

@pillamarip
Copy link

Thank you for reaching back. It worked as is. Thank you!

@mrpinghe
Copy link
Author

Ah glad to see it worked out!

@falcond20
Copy link

Hi @mrpinghe Im trying to use this and kinda confused on
"Then in command line

$ export API_ID=YOUR_API_ID_VALUE && export KEY=YOUR_KEY_VALUE && node test.js"

I cant seem to get it to work as i paste it in my terminal and get this error Uncaught SyntaxError: Unexpected token 'export'

$ export
$ export

What am I doing wrong?

@mrpinghe
Copy link
Author

mrpinghe commented Mar 4, 2023

@falcond20 could you paste a screenshot of your terminal showing how you ran the command and the output, with your ID and Key values redacted?

@falcond20
Copy link

falcond20 commented Mar 5, 2023

Here is the screenshot @mrpinghe
978CDD2C-2823-431E-9577-8271DF2FE377

@mrpinghe
Copy link
Author

mrpinghe commented Mar 5, 2023

Ah PowerShell. You want to use Set-Variable to set those variables I believe (I'm not too familiar with PowerShell) https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/set-variable?view=powershell-7.3

@ThibaudLopez
Copy link

FYI - For those interested in using the Web Crypto API (e.g. browser) instead of the Node.js Crypto module, https://gist.github.com/ThibaudLopez/fe1baeaa4461cbf0bfa8fd258ff43243 (based on @mrpinghe work here)

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