0

The goal is to output both the base64 and hex encodings of a file's MD5 hash without relying on deprecated node.js features. This means using Hash.read() instead of Hash.digest(), and using Buffer instances instead of "binary"-encoded strings. From the docs:

Once the writable side of the [Hash] stream is ended, use the read() method to get the computed hash digest. The legacy update and digest methods are also supported.

and

[The "binary"] encoding method is deprecated and should be avoided in favor of Buffer objects where possible. This encoding will be removed in future versions of Node.

So far, I cannot see how computing multiple hash encodings is possible in 0.10.22 without using these deprecated features. (Technically, hash.digest() is not deprecated, but I'm wary to use anything labeled legacy).

The best I've found still relies on "binary"-encoded strings:

var fs = require("fs"), crypto = require("crypto");

var input = fs.createReadStream("test.txt");
var hash = crypto.createHash("md5");

hash.setEncoding("binary");

input.pipe(hash).on("finish", function() {
    var buffer = new Buffer(hash.read(), "binary");
    console.log(buffer.toString("hex"));
    console.log(buffer.toString("base64"));
});

If the call to hash.setEncoding is removed, then the subsequent hash.read() method returns null. Perhaps this is a bug? Kinda expected an instance of Buffer...

Any ideas on how to avoid the above deprecated features?

(For reference, this question covers how to compute one hash encoding, not multiple encodings.)

Community
  • 1
  • 1
cambecc
  • 4,083
  • 1
  • 23
  • 24

1 Answers1

0

The problem is that the "finish" event is triggered when the input has finished piping to the hash object, not when the hash is ready to be read. Setting the encoding must change the path that is followed somehow to make 'finish' fire late enough that your example works.

The 'readable' event will trigger when there is data to be read, and then you can read from hash to accumulate all of the hash chunks to make a single buffer.

You can use a module like accum or you can bind the listeners yourself:

var input = fs.createReadStream("test.txt");
var hash = input.pipe(crypto.createHash("md5"));

var chunks = [];
hash.on('readable', function() {
    var chunk;
    while ((chunk = hash.read()) !== null){
        chunks.push(chunk);
    }
});
hash.on('end', function(){
    var buffer = Buffer.concat(chunks);

    console.log(buffer.toString("hex"));
    console.log(buffer.toString("base64"));
});
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251