Problems with cross-language HMAC / SHA256 / Base64 - javascript

I'm using a node.js script to create a signature for azure documentDB - the simplified version is (result at the bottom):-
var crypto = require("crypto");
var masterKey = "ABCDE"
var key = new Buffer(masterKey, "base64");
var signature = crypto.createHmac("sha256", key).update("FGHIJ").digest("base64");
console.log("\n\n"+signature)
// RNkID54/1h1H9p3NWPeRA0mOW2L0c0HUJGTTY2GPbDo=
This works, and does what I need it to. I'm trying to do the same thing in Swift with CommonCrypto
let keyString = "ABCDE"
let body = "FGHIJ"
let utf8data = keyString.dataUsingEncoding(NSUTF8StringEncoding)
let key = utf8data!.base64EncodedDataWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
let str = body.cStringUsingEncoding(NSUTF8StringEncoding)
let strLen = body.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
let digestLen = Int(CC_SHA256_DIGEST_LENGTH)
let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen)
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), key.bytes, key.length, str!, strLen, result);
var hmacData = NSData(bytes: result, length: digestLen)
var hmacBase64 = hmacData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
result.dealloc(digestLen)
let signature = String(hmacBase64)
let test = "RNkID54/1h1H9p3NWPeRA0mOW2L0c0HUJGTTY2GPbDo="
XCTAssert(test == signature, "Pass")
But it returns a completely different result. If I pass the masterKey directly into the javascript hmac, and pass it in as a string into the CCHmac method in Swift, it all works; so it seems to be something to do with finding the equivalent to this:-
var key = new Buffer(masterKey, "base64");
Thoughts?
More information - this:-
let keyString = "ABCDE"
let body = "FGHIJ"
let keyData = keyString.dataUsingEncoding(NSUTF8StringEncoding)! // .base64EncodedDataWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
let bodyData = body.dataUsingEncoding(NSUTF8StringEncoding)!
let digestLen = Int(CC_SHA256_DIGEST_LENGTH)
let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen)
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), keyData.bytes, keyData.length, bodyData.bytes, bodyData.length, result);
var hmacData = NSData(bytes: result, length: digestLen)
var hmacBase64 = hmacData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
result.dealloc(digestLen)
let signature = String(hmacBase64)
let test = "FA372zbobgpTLI5cQWh5YFiFwkNhMI8womX4Cvw68YE=" // "RNkID54/1h1H9p3NWPeRA0mOW2L0c0HUJGTTY2GPbDo="
XCTAssert(test == signature, "Pass")
Produces the same result as this:-
var crypto = require("crypto");
var masterKey = "ABCDE"
var signature = crypto.createHmac("sha256", masterKey).update("FGHIJ").digest("base64");
console.log("\n\n"+signature)
// FA372zbobgpTLI5cQWh5YFiFwkNhMI8womX4Cvw68YE=

Related

Count the number of items in Array in nodejs

I have big file almost 2GB and text also includes so many countries, sometimes twise and more. I should create script what will write to stdout all countries from the file and also will show how many times the country name was used. for example if there is germany five times in file code Should show us: Germany: 5 (something like that)
const fs = require("fs");
readline = require("readline");
stream = require("stream");
const filename = process.argv[2];
const instream = fs.createReadStream(filename);
const outstream = new stream();
outstream.readable = true;
outstream.writable = true;
const rl = readline.createInterface({
input: instream,
output: outstream,
terminal: false,
});
rl.on("line", function (line) {
const [country] = line.split(",", 1);
Str = country;
var obj = new Object();
for (var i = 0; i < Str.length; i++) {
if (obj[Str] != null) {
obj[Str] += 1;
} else {
obj[Str] = 1;
}
}
console.log(obj);
});
I wrote this but it shows the number of letters in word.
Thank you (link for download file is in comments)
Here is a part of text:
united
states,2001,dinner-and-a-murder-mystery-games,retail,linkedin.com/company/dinner-and-a-murder-mystery-games,"",dinner
and a murder mystery games,tennessee,1-10,dinnerandamurder.com
netherlands,2013,jennifer-campbell,management
consulting,linkedin.com/company/jennifer-campbell,houten,jennifer
campbell,utrecht,1-10,jennifercampbell.com united
states,"",imtec-corp,marketing and
advertising,linkedin.com/company/imtec-corp,ardmore,imtec corp
italy,1977,bo.ma-s.r.l.,research,linkedin.com/company/bo.ma-s.r.l.
Your problem is probably, that you have a variable "country" that contains the country as string and then you store it to Str and do:
"for (var i = 0; i < Str.length; i++) {
this loops over every char in the stream.
Also you need to define the "obj" outside of the callback otherwise it gets recreated for every line.
Just try:
var obj = {};
rl.on("line", function (line) {
const [country] = line.split(",", 1);
if (obj[country]) {
obj[country]++;
} else {
obj[country] = 1;
}
console.log(obj);
});

Getting the last segment of an URL

Let's say that this is my URL/Link that i have written in an input
https://www.instagram.com/p/CBt-W4jHZjH/
How can I get the "CBt-W4jHZjH" part?
var link = ?????
var a = link.val().trim();
var regex = new RegExp(/^(?!.*\.\.)(?!.*\.$)[^\W][\w.]{0,29}$/);
var validation = regex.test(a);
https://developer.mozilla.org/en-US/docs/Web/API/URL
const getLastPath = (url) => {
url = new URL(url);
const pathname = url.pathname;
const paths = pathname.split("/");
return paths.pop() || paths.pop();
}
console.log(getLastPath("https://www.instagram.com/p/CBt-W4jHZjH/")); // "CBt-W4jHZjH"
console.log(getLastPath("https://www.instagram.com/p/CBt-W4jHZjH")); // "CBt-W4jHZjH"
Many ways to do it. One way is to look for / any character but / ending with / end of line.
var url = 'https://www.instagram.com/p/CBt-W4jHZjH/'
var x = new URL(url);
console.log(x.pathname.match(/\/([^\/]+)\/?$/)[1])
Could be done with split. The filter removes the empty string caused by the trailing /.
var url = 'https://www.instagram.com/p/CBt-W4jHZjH/'
var x = new URL(url);
console.log(x.pathname.split('/').filter(x=>x).pop());

jsSha HMAC not match with crypto - OTP algorithm

This 2 codes doesn't return the same. Sorry I am no expert of both library.
const jsSHA = require("jssha");
const time = "00000000030f7141"
const key = "101010"
var shaObj = new jsSHA("SHA-1", "HEX");
shaObj.setHMACKey(key, "HEX");
shaObj.update(time);
const hmac = shaObj.getHMAC("HEX");
console.log(hmac)
// returns '536d6eed86796085f8ec2ead742c52fd73995f27'
---------------
const crypto = require('crypto')
const time = "00000000030f7141"
const key = "101010"
crypto.createHmac('sha1', new Buffer(key,
'HEX')).update(time).digest('HEX')
// returns '8a3df92d2a68b32b2b571a1b71bfea03556e0df4'
My point is to avoid to use an external lib for using OTP with Google Authenticator.
Best,
your nodejs update() is no different. you need to use hex there also.
Attached a sample code
const jsSHA = require("jssha");
const time = "00000000030f7141"
const key = "101010"
var shaObj = new jsSHA("SHA-1", "HEX");
shaObj.setHMACKey(key, "HEX");
shaObj.update(time);
const hmac = shaObj.getHMAC("HEX");
console.log(hmac)
// returns '536d6eed86796085f8ec2ead742c52fd73995f27'
const crypto = require('crypto')
let out = crypto.createHmac('sha1', new Buffer(key, 'hex')).update(new Buffer(time,'hex')).digest('hex')
// returns '536d6eed86796085f8ec2ead742c52fd73995f27'
console.log(out)

Separate string into multiple variables with JavaScript

Using JavaScript I want to take a string like this var hashStr = 'modal-123456' and assign the string left of the - to a variable and the string right of the - to another variable.
If the string does not contain a - then ignore it.
How can I best achieve this?
var hashStr = location.hash.replace('#', '');
// hashStr now === 'modal-123456'
var firstHalf = // modal
var secondHalf = // '123456'
You can use split API.
var hashStr = 'modal-123456'
var splitStr = hashStr.split('-');
console.log(splitStr[0])
console.log(splitStr[1])
Just use split.
var hashStr = 'modal-123456';
var [firstHalf, secondHalf] = hashStr.split("-");
console.log("first half:", firstHalf);
console.log("second half:", secondHalf);
Simply
var hashStr = location.hash.replace('#', '');
var firstHalf = hashStr.split("-")[0];
var secondHalf = hashStr.split("-")[1];
or
var hashStr = location.hash.replace('#', '').split("-");
var firstHalf = hashStr[0];
var secondHalf = hashStr[1];

how to recreate the .net membership hmacsha1 hash in javascript

I'm trying to reproduce the same hmacsha1 hash and base64 encoding from .net membership provider in a javascript function. I've tried using crypto-js and am getting different results. The .net code will hash "test" into "W477AMlLwwJQeAGlPZKiEILr8TA="
Here's the .net code
string password = "test";
HMACSHA1 hash = new HMACSHA1();
hash.Key = Encoding.Unicode.GetBytes(password);
string encodedPassword = Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password)));
And here's the javascript method I tried using crypto-js that does not produce the same output
var hash = CryptoJS.HmacSHA1("test", "");
var encodedPassword = CryptoJS.enc.Base64.stringify(hash);
How can I get my javascript hash to match the hash being generated from .net.
//not sure why crypt-js's utf16LE function doesn't give the same result
//words = CryptoJS.enc.Utf16LE.parse("test");
//utf16 = CryptoJS.enc.Utf16LE.stringify("test");
function str2rstr_utf16le(input) {
var output = [],
i = 0,
l = input.length;
for (; l > i; ++i) {
output[i] = String.fromCharCode(
input.charCodeAt(i) & 0xFF,
(input.charCodeAt(i) >>> 8) & 0xFF
);
}
return output.join('');
}
var pwd = str2rstr_utf16le("test");
var hash = CryptoJS.HmacSHA1(pwd, pwd);
var encodedPassword = CryptoJS.enc.Base64.stringify(hash);
alert(encodedPassword);
You don't specify a key in .NET:
var secretKey = "";
var password = "test";
var enc = Encoding.ASCII;
System.Security.Cryptography.HMACSHA1 hmac = new System.Security.Cryptography.HMACSHA1(enc.GetBytes(secretKey));
hmac.Initialize();
byte[] buffer = enc.GetBytes(password);
var encodedPassword = Convert.ToBase64String(hmac.ComputeHash(buffer));
Edit: as #Andreas mentioned, your problem is the encoding. So you just need to replace UTF by ANSI in your own code:
string password = "test";
System.Security.Cryptography.HMACSHA1 hash = new System.Security.Cryptography.HMACSHA1();
hash.Key = Encoding.ASCII.GetBytes("");
string encodedPassword = Convert.ToBase64String(hash.ComputeHash(Encoding.ASCII.GetBytes(password)));

Categories