Visit Mozilla.org

nsICryptoHash

From MDC

Contents

[edit] Introduction

nsICryptoHash can be used to compute a cryptographic hash function of some data. You can, for example, calculate the MD5 hash of a file to determine if it contains the data you think it does. The hash algorithms supported are MD2, MD5, SHA-1, SHA-256, SHA-384, and SHA-512. This interface is only available in Firefox 1.5 or newer.

nsICryptoHash is defined in netwerk/base/public/nsICryptoHash.idl. It is scriptable and unfrozen (hasn't changed since Mozilla 1.8).

[edit] Constants

[edit] Hash Algorithms

These constants represent the hash algorithms supported by this interface. The available values are:

  • MD2
  • MD5
  • SHA1
  • SHA512
  • SHA256
  • SHA384

[edit] Methods

[edit] init

void init(in unsigned long aAlgorithm);

init() initializes the object, indicating which hash algorithm to use by specifying one of the constants defined on the interface. You must call either this method or initWithString() before updating the object with any data.

[edit] Parameters

aAlgorithm

The hash algorithm to use. Must be one of the constants defined on the interface.

[edit] Exceptions

NS_ERROR_INVALID_ARG

Indicates that an unsupported algorithm type was passed

[edit] initWithString

void initWithString(in ACString aAlgorithm);

initWithString() initializes the object, indicating which hash algorithm to use by specifying the name of the algorithm as a string, such as "MD5". You must call either this method or init() before updating the object with any data.

[edit] Parameters

aAlgorithm

The hash algorithm to use

[edit] Exceptions

NS_ERROR_INVALID_ARG

Indicates that an unsupported algorithm type was passed

[edit] update

void update([const, array, size_is(aLen)] in octet aData, in unsigned long aLen);

update() adds an array of data to be hashed to the object. See Computing the Hash of a String for an example of using this method.

[edit] Parameters

aData

A buffer to calculate the hash over

aLen

The length of the buffer aData

[edit] Exceptions

NS_ERROR_NOT_INITIALIZED

Indicates that init() or initWithString() was not called

[edit] updateFromStream

void updateFromStream(in nsIInputStream aStream, in unsigned long aLen);

updateFromStream() adds data to be hashed from an nsIInputStream. See Computing the Hash of a File for an example of using this method.

[edit] Parameters

aStream

An input stream to read from

aLen

How much to read from the given aStream. Passing PR_UINT32_MAX indicates that all data available will be used to update the hash.

[edit] Exceptions

NS_ERROR_NOT_INITIALIZED

Indicates that init() or initWithString() was not called.

NS_ERROR_NOT_AVAILABLE

Indicates that the requested amount of data to be calculated into the hash is not available.

[edit] finish

ACString finish(in PRBool aASCII);

finish() completes the hash object and produces the actual hash data.

[edit] Parameters

aASCII

If true then the returned value is a base-64 encoded string. If false, then the returned value is binary data.

[edit] Return Values

This method returns a hash of the data that was read by this object. This can be either binary data or a base-64 encoded string.

[edit] Exceptions

NS_ERROR_NOT_INITIALIZED

Indicates that init() or initWithString() was not called
Note: This method may be called any time after init() is called. This call resets the object to its pre-init state.

[edit] Example Code

Note: The examples below use features of JavaScript 1.7, implemented in Firefox 2. To use the examples in Firefox 1.5, replace the array comprehension with a loop.

[edit] Computing the Hash of a File

You can easily compute the hash of a file using nsICryptoHash. You will need to create an instance of nsICryptoHash, open an input stream from a file, and then update the hash with the file. The following example shows how to compute the MD5 hash of a file:

// hardcoded here for convenience
var path = "c:\\windows\\notepad.exe";
var f = Components.classes["@mozilla.org/file/local;1"]
                  .createInstance(Components.interfaces.nsILocalFile);
f.initWithPath(path);
var istream = Components.classes["@mozilla.org/network/file-input-stream;1"]           
                        .createInstance(Components.interfaces.nsIFileInputStream);
// open for reading
istream.init(f, 0x01, 0444, 0);
var ch = Components.classes["@mozilla.org/security/hash;1"]
                   .createInstance(Components.interfaces.nsICryptoHash);
// we want to use the MD5 algorithm
ch.init(ch.MD5);
// this tells updateFromStream to read the entire file
const PR_UINT32_MAX = 0xffffffff;
ch.updateFromStream(istream, PR_UINT32_MAX);
// pass false here to get binary data back
var hash = ch.finish(false);

// return the two-digit hexadecimal code for a byte
function toHexString(charCode)
{
  return ("0" + charCode.toString(16)).slice(-2);
}

// convert the binary hash data to a hex string.
var s = [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
// s now contains your hash in hex

This gives 5eb63bbbe01eeed093cb22bb8f5acdc3 for the hash value. This example, while simple, shows most of the functionality of the interface.

The first thing to note is that when you call the init() method you must specify the hash algorithm to use. All of the available algorithms are specified as constants on the interface.

Also note that when you call the updateFromStream() method, the second parameter is the number of bytes to read. Passing PR_UINT32_MAX here indicates that you want the entire file read.

Finally, note that calling the finish() method produces the hash value. The single parameter to this method is false in this example to return binary data. Passing true returns the hash as a base 64 encoded string. In this example we take the binary data and produce a hexadecimal string of the result, as is commonly output by hashing programs.

[edit] Computing the Hash of a String

Another common operation is computing the hash value of a string. Since hash functions are computed over bytes, you will first need to convert the string to a series of bytes using nsIScriptableUnicodeConverter and a Unicode encoding that you specify.

Note: Different encodings will produce different hash values! You should always use the same encoding if you intend to compare results.

The example below shows how to convert a string to bytes in the UTF-8 encoding, and then compute the MD5 hash of it. The result is computed as a hex string as in the previous example.

var str = "hello world";
var converter =
  Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].
    createInstance(Components.interfaces.nsIScriptableUnicodeConverter);

// we use UTF-8 here, you can choose other encodings.
converter.charset = "UTF-8";
// result is an out parameter,
// result.value will contain the array length
var result = {};
// data is an array of bytes
var data = converter.convertToByteArray(str, result);
var ch = Components.classes["@mozilla.org/security/hash;1"]
                   .createInstance(Components.interfaces.nsICryptoHash);
ch.init(ch.MD5);
ch.update(data, data.length);
var hash = ch.finish(false);

// return the two-digit hexadecimal code for a byte
function toHexString(charCode)
{
  return ("0" + charCode.toString(16)).slice(-2);
}

// convert the binary hash data to a hex string.
var s = [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
// s now contains your hash in hex: should be
// 5eb63bbbe01eeed093cb22bb8f5acdc3

In this example, we use the update() method to pass an array of bytes to be hashed. As in the previous example, we convert the binary result to a hex string.