Reputation: 1294
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
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
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