Stefan
Stefan

Reputation: 1294

Using the built in dynamic values

I have written an extension to generate a custom authentication string (getting it to actually work would improve our team's performance significantly).

The issue: our custom authentication string requires a HMAC to be computed, which also requires an MD5 hash. I tried requiring modules in a Nodejs fashion but it does not work. I noticed that the HMAC and MD5 functions I need are already built-in in the application.

The question: Is there any way to re-use the built in functions in custom extensions? - Having this possibility would make the whole process so much easier.

If the above is not possible; how could I do something like: var crypto = require('crypto'); in order to use Nodejs' default cryptography module?

Any feedback would be highly appreciated.

Upvotes: 1

Views: 240

Answers (2)

Micha Mazaheri
Micha Mazaheri

Reputation: 3481

Yeah there's a way to create and compute dynamic values from the JavaScript code, but it isn't documented yet. Here are the 2 functions you need implemented using dynamic values:

function hmac(key, input){
  return DynamicValue('com.luckymarmot.HMACDynamicValue', {
    algorithm: 0, // for HMAC-MD5
    input: input,
    key: key
  }).getEvaluatedString();
};

function md5(input){
  return DynamicValue('com.luckymarmot.HashDynamicValue', {
    hashType: 2, // for MD5
    input: input
  }).getEvaluatedString();
};

And and example of use in a custom dynamic value:

function evaluate(context){
  var a = md5("MyStringToHash");
  var b = hmac("MyHMACKey", "String to sign");
  return a + ':' + b;
};

Upvotes: 1

Stefan
Stefan

Reputation: 1294

For the time being, I managed to decode the base64 and re-encode it to hex, this is not the cleanest way of doing this, but until extra features are made available this might help people with similar issues. The AuthenticationHeaderDynamicValue function can be adjusted to do whatever you need it to do.

(function() {

var request,
    url,
    md5 = function (input) {
        return DynamicValue('com.luckymarmot.HashDynamicValue', {
            hashType: 2,
            input: input
        }).getEvaluatedString();
    },
    hmac = function (key, input) {
        return DynamicValue('com.luckymarmot.HMACDynamicValue', {
            algorithm: 3,
            input: input,
            key: key
        }).getEvaluatedString();
    },
    base64Decode = function (input) {
        var a,
            b = 0,
            c,
            e = {},
            loop = 0,
            result = '';

        for (var i = 0; i < 64; i++) {
            e['ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.charAt(i)] = i;
        }

        for (var x = 0; x < input.length; x++) {
            c = e[input.charAt(x)];
            b = (b << 6) + c;
            loop += 6;

            while (loop >= 8) {
                (( a = (b >>> (loop -= 8)) &0xff ) || ( x < (input.length - 2))) && ( result += String.fromCharCode(a));
            }
        }

        return result;
    },
    recode = function (input) {

        var decodedString = base64Decode(input),
            recodedString = '';

        // Encode binary to hex
        for (var i = 0; i < decodedString.length; i++) {
            var hex = decodedString.charCodeAt(i).toString(16);
            recodedString += ('000' + hex).slice(-2);
        }

        return recodedString;
    },
    AuthenticationHeaderDynamicValue = function () {
        this.computeString = function (context) {
            request = context.getCurrentRequest();
            url = request.getUrl(true).components[1];

            var time = Math.round(+new Date() / 1000),
                md5Checksum = md5(request.jsonBody ? JSON.stringify(request.jsonBody) : url),
                signature = hmac(this.secretKey, md5Checksum);

            return recode(signature);
        };

        this.evaluate = function(context) {
            if (this.secretKey) {
                return this.computeString(context);
            }
        };

        this.title = function() {
            return "Authentication header";
        };

        this.text = function() {
            return;
        };
    };

AuthenticationHeaderDynamicValue.identifier = "com.test.PawExtensions.AuthenticationHeaderDynamicValue";
AuthenticationHeaderDynamicValue.title = "AuthenticationHeader";
AuthenticationHeaderDynamicValue.inputs = [
    DynamicValueInput("publicKey", "Public key", "String"),
    DynamicValueInput("secretKey", "Secret key", "String")
];

registerDynamicValueClass(AuthenticationHeaderDynamicValue);

}).call(this);

Upvotes: 1

Related Questions