All is ok, when I call the tool with the text file. But results always are different, when I pass the binary one.
I have to use some js library, like jssha, because my code should be run under several platforms and etc. Binary files processing is the mandatory requirement.
Where is the mistake ?
Node
var crypto = require('crypto')
, shasum = crypto.createHash('sha1');
var fs = require('fs');
var args = process.argv.slice(2);
console.time('readFile');
var data = fs.readFileSync(args[0],'utf8').toString();
console.timeEnd('readFile');
console.time('sha1');
shasum.update(data);
var hash = shasum.digest('base64');
console.timeEnd('sha1');
console.log(hash);
jssha
var jsSHA = require('jssha')
var fs = require('fs');
var args = process.argv.slice(2);
console.time('readFile');
var data = fs.readFileSync(args[0],'utf8').toString();
console.timeEnd('readFile');
console.time('sha1');
var shaObj = new jsSHA(data, "TEXT");
var hash = shaObj.getHash("SHA-1", "B64");
console.timeEnd('sha1');
console.log(hash);
Update
The solution for Node and jsSha is my answer below. Looks like all JS-implementations of SHA-1 work a bit different with binary data.
I've found the solution for Node and jsSHA.
Node
var crypto = require('crypto')
, shasum = crypto.createHash('sha1');
var fs = require('fs');
var args = process.argv.slice(2);
console.time('readFile');
var data = fs.readFileSync(args[0]);
console.timeEnd('readFile');
console.time('sha1');
shasum.update(data);
var hash = shasum.digest('base64');
console.timeEnd('sha1');
console.log(hash);
jsSHA
var jsSHA = require('jssha')
var fs = require('fs');
var args = process.argv.slice(2);
console.time('readFile');
var data = fs.readFileSync(args[0]).toString('hex');
console.timeEnd('readFile');
console.time('sha1');
var shaObj = new jsSHA(data, "HEX");
var hash = shaObj.getHash("SHA-1", "B64");
console.timeEnd('sha1');
console.log(hash);
Related
I'd like to run an SVG-PDF-converter, which processes all files in a folder and creates the PDF output files with the corresponding file names:
var fs = require('fs'),
PDFDocument = require('pdfkit'),
SVGtoPDF = require('svg-to-pdfkit'),
glob = require("glob"),
inputFiles = glob.sync('./input/**/*.svg');
for (let i = 0; i < inputFiles.length; i++) {
var doc = new PDFDocument(),
stream = fs.createWriteStream('./output/' + inputFiles[i] + '.pdf'),
svg = fs.readFileSync(inputFiles[i], 'utf-8');
SVGtoPDF(doc, svg, 0, 0);
doc.pipe(stream);
doc.end();
};
Obviously it doesn't work that way...
How can I use variable file names in createWriteStream?
Short answer: Use backquote like this
fs.createWriteStream(`./somefolder/${fileName}.pdf`)
var fileName = String(inputFiles[i]),
outputString = fileName.replace("input", "output"),
outputStringComplete = outputString.replace("svg", "pdf"),
stream = fs.createWriteStream(outputStringComplete);
You can do something like this to actually fetch the filename using regex. You will get the filenames then you can use this filename to create new file.
const fileDetails = glob.sync('yourpathtodir');
const regex = new RegExp(/[^\\\/]+(?=\.[\w]+$)|[^\\\/]+$/);
const fileNames = [];
fileDetails.forEach(el => fileNames.push(regex.exec(el)[0]));
console.log(fileNames);
for (let i = 0; i < fileNames.length; i++) {
var doc = new PDFDocument(),
stream = fs.createWriteStream(`./output/${fileNames[i]}.pdf`),
svg = fs.readFileSync(`${fileNames[i]}.svg`, 'utf-8'); // you might need to provide full name for file
SVGtoPDF(doc, svg, 0, 0);
doc.pipe(stream);
doc.end();
};
//I can split a string in the following way without problem
var string1 = "abc def ghi";
var res = string1.split(" ");
var split1 = res[1]; // abc
var split2 = res[2]; // def
var split3 = res[3]; // ghi
//But my string that has to be split is coming from reading a textfile (text)
//Unfortunately this is not working
var fs = require("fs");
fs.readFile("./mytext.txt", function(text){
var textByLine = text.split("\n")
});
var res = text.split(" ");
var split1 = res[1];
var split2 = res[2];
var split3 = res[3];
Assuming this is Javascript and not Java code, the problem is that you're trying to access the text variable outside of the callback function. The value from the readFile will only be available inside of its callback function.
You should use fs.readFileSync to get the value directly and work with it. See documentation for more details on using the function, but this should work:
var fs = require("fs")
var text = fs.readFileSync("./mytext.txt")
var textByLine = text.split("\n")
console.log("first line:",textByLine[0])
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)
How is it possible in javascript to obtain the b Buffer in a way simpler than the following?
var num=6553599
var a = new Buffer(4);
a.writeInt32LE(num);
var up=a.readUInt8(2);
var mid=a.readUInt8(1);
var low=a.readUInt8(0);
var b=new Buffer(6);
b.writeUInt8('T'.charCodeAt(0),0);
b.writeUInt8(up ,1);
b.writeUInt8(mid ,2);
b.writeUInt8(low ,3);
b.writeUInt8(0 ,4);
b.writeUInt8(1 ,5);
If performance is not an issue you can use the string representation of buffers to work with them more easily.
Usually I prefer the hex representation of buffers since they're easier to read and it is easy to count bytes this way.
var bConcat = (a, b) => new Buffer(a.toString("hex") + b.toString("hex"), "hex");
var reducer = (acc, current)=> bConcat(acc, current);
var num=6553599
var a = new Buffer(4);
var t = 'T'.charCodeAt(0);
a.writeInt32LE(num);
var head = new Buffer(t.toString(16), "hex");
var tail = new Buffer("0001", "hex");
var b = [head, a.slice(0,3).reverse(), tail].reduce(reducer);
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=