192 lines
5.9 KiB
Markdown
192 lines
5.9 KiB
Markdown
# SparkMD5
|
|
|
|
SparkMD5 is a fast md5 implementation of the MD5 algorithm.
|
|
This script is based in the JKM md5 library which is the [fastest](http://jsperf.com/md5-shootout/7) algorithm around. This is most suitable for browser usage, because `nodejs` version might be faster.
|
|
|
|
NOTE: Please disable Firebug while performing the test!
|
|
Firebug consumes a lot of memory and CPU and slows the test by a great margin.
|
|
|
|
|
|
**[Demo](http://9px.ir/demo/incremental-md5.html)**
|
|
|
|
## Install
|
|
|
|
```sh
|
|
npm install --save spark-md5
|
|
```
|
|
|
|
## Improvements over the JKM md5 library
|
|
|
|
* Strings are converted to utf8, like most server side algorithms
|
|
* Fix computation for large amounts of data (overflow)
|
|
* Incremental md5 (see below)
|
|
* Support for array buffers (typed arrays)
|
|
* Functionality wrapped in a closure, to avoid global assignments
|
|
* Object oriented library
|
|
* CommonJS (it can be used in node) and AMD integration
|
|
* Code passed through JSHint and JSCS
|
|
|
|
|
|
Incremental md5 performs a lot better for hashing large amounts of data, such as
|
|
files. One could read files in chunks, using the FileReader & Blob's, and append
|
|
each chunk for md5 hashing while keeping memory usage low. See example below.
|
|
|
|
|
|
## Usage
|
|
|
|
### Normal usage
|
|
|
|
```js
|
|
var hexHash = SparkMD5.hash('Hi there'); // hex hash
|
|
var rawHash = SparkMD5.hash('Hi there', true); // OR raw hash (binary string)
|
|
```
|
|
|
|
### Incremental usage
|
|
|
|
```js
|
|
var spark = new SparkMD5();
|
|
spark.append('Hi');
|
|
spark.append(' there');
|
|
var hexHash = spark.end(); // hex hash
|
|
var rawHash = spark.end(true); // OR raw hash (binary string)
|
|
```
|
|
|
|
### Hash a file incrementally
|
|
|
|
NOTE: If you test the code bellow using the file:// protocol in chrome you must start the browser with -allow-file-access-from-files argument.
|
|
Please see: http://code.google.com/p/chromium/issues/detail?id=60889
|
|
|
|
```js
|
|
document.getElementById('file').addEventListener('change', function () {
|
|
var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
|
|
file = this.files[0],
|
|
chunkSize = 2097152, // Read in chunks of 2MB
|
|
chunks = Math.ceil(file.size / chunkSize),
|
|
currentChunk = 0,
|
|
spark = new SparkMD5.ArrayBuffer(),
|
|
fileReader = new FileReader();
|
|
|
|
fileReader.onload = function (e) {
|
|
console.log('read chunk nr', currentChunk + 1, 'of', chunks);
|
|
spark.append(e.target.result); // Append array buffer
|
|
currentChunk++;
|
|
|
|
if (currentChunk < chunks) {
|
|
loadNext();
|
|
} else {
|
|
console.log('finished loading');
|
|
console.info('computed hash', spark.end()); // Compute hash
|
|
}
|
|
};
|
|
|
|
fileReader.onerror = function () {
|
|
console.warn('oops, something went wrong.');
|
|
};
|
|
|
|
function loadNext() {
|
|
var start = currentChunk * chunkSize,
|
|
end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
|
|
|
|
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
|
|
}
|
|
|
|
loadNext();
|
|
});
|
|
```
|
|
|
|
You can see some more examples in the test folder.
|
|
|
|
## Documentation
|
|
|
|
|
|
### SparkMD5 class
|
|
|
|
#### SparkMD5#append(str)
|
|
|
|
Appends a string, encoding it to UTF8 if necessary.
|
|
|
|
#### SparkMD5#appendBinary(str)
|
|
|
|
Appends a binary string (e.g.: string returned from the deprecated [readAsBinaryString](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsBinaryString)).
|
|
|
|
#### SparkMD5#end(raw)
|
|
|
|
Finishes the computation of the md5, returning the hex result.
|
|
If `raw` is true, the result as a binary string will be returned instead.
|
|
|
|
#### SparkMD5#reset()
|
|
|
|
Resets the internal state of the computation.
|
|
|
|
#### SparkMD5#getState()
|
|
|
|
Returns an object representing the internal computation state.
|
|
You can pass this state to setState(). This feature is useful to resume an incremental md5.
|
|
|
|
#### SparkMD5#setState(state)
|
|
|
|
Sets the internal computation state. See: getState().
|
|
|
|
#### SparkMD5#destroy()
|
|
|
|
Releases memory used by the incremental buffer and other additional resources.
|
|
|
|
#### SparkMD5.hash(str, raw)
|
|
|
|
Hashes a string directly, returning the hex result.
|
|
If `raw` is true, the result as a binary string will be returned instead.
|
|
Note that this function is `static`.
|
|
|
|
#### SparkMD5.hashBinary(str, raw)
|
|
|
|
Hashes a binary string directly (e.g.: string returned from the deprecated [readAsBinaryString](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsBinaryString)), returning the hex result.
|
|
If `raw` is true, the result as a binary string will be returned instead.
|
|
Note that this function is `static`.
|
|
|
|
|
|
### SparkMD5.ArrayBuffer class
|
|
|
|
#### SparkMD5.ArrayBuffer#append(arr)
|
|
|
|
Appends an array buffer.
|
|
|
|
#### SparkMD5.ArrayBuffer#end(raw)
|
|
|
|
Finishes the computation of the md5, returning the hex result.
|
|
If `raw` is true, the result as a binary string will be returned instead.
|
|
|
|
#### SparkMD5.ArrayBuffer#reset()
|
|
|
|
Resets the internal state of the computation.
|
|
|
|
#### SparkMD5.ArrayBuffer#destroy()
|
|
|
|
Releases memory used by the incremental buffer and other additional resources.
|
|
|
|
#### SparkMD5.ArrayBuffer#getState()
|
|
|
|
Returns an object representing the internal computation state.
|
|
You can pass this state to setState(). This feature is useful to resume an incremental md5.
|
|
|
|
#### SparkMD5.ArrayBuffer#setState(state)
|
|
|
|
Sets the internal computation state. See: getState().
|
|
|
|
#### SparkMD5.ArrayBuffer.hash(arr, raw)
|
|
|
|
Hashes an array buffer directly, returning the hex result.
|
|
If `raw` is true, the result as a binary string will be returned instead.
|
|
Note that this function is `static`.
|
|
|
|
|
|
## License
|
|
|
|
The project is double licensed, being [WTF2](./LICENSE) the master license and [MIT](./LICENSE2) the alternative license.
|
|
The reason to have two licenses is that some entities refuse to use the master license (WTF2) due to
|
|
bad language. If that's also your case, you can choose the alternative license.
|
|
|
|
|
|
## Credits
|
|
|
|
[Joseph Myers](http://www.myersdaily.org/joseph/javascript/md5-text.html)
|