• No results found

6-3 Verifying File Integrity with Hashes Problem

In document Node js Recipes Cory Gackenheimer pdf (Page 141-144)

You need to utilize a cryptographic hash algorithm to validate the integrity of files utilized in your Node.js application.

Solution

You may often encounter a situation where you need to check whether the content of your file or files that you access in your Node.js application has changed from a previous version. You can do this with the Node.js crypto module by generating a hash of the file’s content.

In this solution you will create an application that demonstrates the abilities of four hashing algorithms to handle the task of reading the content of a file. In Listing 6-6, you will pass in the file you wish to hash, and then your application will read the file stream, updating the message as the stream is read, then log the resultant hash for each algorithm.

Listing 6-6. Checking File Integrity /**

* Checking File Integrity */

var fs = require('fs'),

args = process.argv.splice('2'), crypto = require('crypto');

var algorithm = ['md5', 'sha1', 'sha256', 'sha512']; algorithm.forEach(function(algo) {

var hash = crypto.createHash(algo); var fileStream = fs.ReadStream(args[0]); fileStream.on('data', function(data) { hash.update(data); }); fileStream.on('end', function() { console.log(algo); console.log(hash.digest('hex')); }); });

You can imagine building a deploy process in Node.js where you are sending or retrieving files from a remote server and you want to ensure that these files match the expected hash of the content from where they came.

You might also need to download a file. Once you download the file, you might need to check the integrity of this file to verify it against the value that you know to be accurate. In Listing 6-7 you download the node executable for version 0.10.10 for Windows and check the shasum against the known value of this hash.

Chapter 6 ■ ImplementIng SeCurIty and Cryptography

Listing 6-7. Downloading a File and Checking shasum /**

* Verifying file integrity */

var http = require('http'), fs = require('fs'),

crypto = require('crypto');

var node_exe = fs.createWriteStream('node.exe');

var req = http.get('http://nodejs.org/dist/v0.10.10/node.exe', function(res) { res.pipe(node_exe);

res.on('end', function() {

var hash = crypto.createHash('sha1'); readr = fs.ReadStream('node.exe'); readr.on('data', function(data) { hash.update(data);

});

readr.on('end', function() {

// Should match 419fc85e5e16139260f7b2080ffbb66550fbe93f node.exe // from http://nodejs.org/dist/v0.10.10/SHASUMS.txt

var dig = hash.digest('hex');

if (dig === '419fc85e5e16139260f7b2080ffbb66550fbe93f') { console.log('match'); } else { console.log('no match'); } console.log(dig); }); }); });

How It Works

The solution in Listing 6-6 begins by requiring the crypto and the file-system modules, both needed for this implementation. You then create an array of different algorithms to use for your hashing. As you saw in the previous sections, the two most commonly used are MD5 and SHA-1, but the variants of SHA-2 are gaining popularity as well.

As you loop through each of the algorithms, you then create a new hash by using crypto.getHash, passing the algorithm to use. You then create a file stream using fs.ReadStream, passing in a file name you provided as an argument on the command line. You could just as easily pass any file name to be read from your application. As the file is read by Node.js, the data event is emitted.

Within the callback to the data event listener, you begin to process the message portion of your hash. This is done by passing the data directly to the hash’s update() function. After the file is finished reading, the ‘end’ event is emitted. Within this callback you will actually generate the hash digest and log the result to the console.

Chapter 6 ■ ImplementIng SeCurIty and Cryptography

When you are hashing files, it is easy to see how slight variations in content will result in a different hash. For example, a file that contains only the string ‘This is text.’ will generate an shasum, which is drastically independent from the shasum of a similar file containing the string ‘This is test.’

In the second example, Listing 6-7, you created a very practical solution that checks for the integrity of a file once it has been downloaded to your server using an shasum. To do this you need to import the http, file system, and crypto modules. This implementation begins by creating a file on your file system that is writable via fs.createWriteStream. Next you make an HTTP GET request to the file source; in this case you retrieve the Node.js executable for Windows, version 0.10.10. You know the correct shasum that the file should match because it is freely available from the download page for this version.

The response from this GET request is then piped into the file you created using response.pipe(file). Once the response is complete, signified by the ‘end’ event, you are able to read the file from your file system. Just as in the previous example you create a hash with the given algorithm, which in this case is SHA-1, and update the message on the ‘data’ event of the file reader stream. Once the read is completed, you are able to generate the hash by calling the digest(‘hex’) method on the hash. You now have the shasum of the file you downloaded and you can compare this to the expected value to ensure that the download is complete and not corrupted.

Checking the integrity of the file on your system is critical, but if you just want to get the hash of a remote file, you are able to generate the shasum of the file by hashing the response stream directly, as shown in Listing 6-8.

Listing 6-8. Hashing the HTTP Response Stream /**

* Verifying file integrity */

var http = require('http'), fs = require('fs'),

crypto = require('crypto');

var req = http.get('http://nodejs.org/dist/v0.10.10/node.exe', function(res) { var hash = crypto.createHash('sha1');

res.on('data', function(data) { hash.update(data); }); res.on('end', function() { console.log(hash.digest('hex')); }); });

This eliminates the file writing and simply updates the hash when the response stream emits the ‘data’ event, finally generating the digest when the response ends.

Chapter 6 ■ ImplementIng SeCurIty and Cryptography

6-4. Using an HMAC to Verify and Authenticate Messages

In document Node js Recipes Cory Gackenheimer pdf (Page 141-144)