Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving CryptoJS's CryptoMD5 state as a string and restoring it later

I gradually compute the MD5 hash of a large file, during an upload, then at some point I want to save to HTML5 localStorage what I have calculated so far, to be able to resume later.

From what I know, localStorage can store strings, so I have to store the progressive MD5 value as a string and then restore them, when the user opens the browser at a later time.

Basically my code looks like this:

var md5_full = CryptoJS.algo.MD5.create();

var wordArray = CryptoJS.lib.WordArray.create(chunk);

md5_full.update(wordArray);

At this point, I want to convert md5_full to a string, to be able to save to localStorage. And then, at a later time, when the user wants to resume the upload, to be able to retrieve the md5_full from localStorage, unstringify, and continue to update it with chunks.

In the end I should be able to call md5_full.finalize(); to get the final full MD5 hash digest.

like image 391
StefanH Avatar asked Oct 05 '22 01:10

StefanH


1 Answers

I think the problem may be with function serialization - CryoJS apparently attempts to serialize functions but it may not restore references correctly (the scope is lost).

The code below circumvents this problem by restoring only data, not functions. JSFiddle.

(De)serialization functions:

/** Serialize MD5 object. */
function stringify_md5(md5) {
    return JSON.stringify(md5);
}

/** Deserialize MD5 object. */
function parse_md5(serialized_md5) {
    var md5 = CryptoJS.algo.MD5.create();
    restore_data(JSON.parse(serialized_md5), md5);
    return md5;    
}

/** Recursively copy properties from object source to object target. */
function restore_data(source, target) {
    for (var prop in source) {
        var value = source[prop];
        if (typeof value == "object") {
            if (typeof target[prop] != "object") {
                target[prop] = {};
            }
            restore_data(source[prop], target[prop]);
        } else {
            target[prop] = source[prop];
        }
    }
}

Example of usage:

var chunk1 = "abc", chunk2 = "def";

// The correct hash:
var md5_full_1 = CryptoJS.algo.MD5.create();
md5_full_1.update(chunk1);
md5_full_1.update(chunk2);
var correct_hash = md5_full_1.finalize();

// Using stringify/parse
var md5_full_2 = CryptoJS.algo.MD5.create();
md5_full_2.update(chunk1);
var md5_serialized = stringify_md5(md5_full_2); // serialize
md5_full_2 = parse_md5(md5_serialized);  // deserialize
md5_full_2.update(chunk2);
var result_hash = md5_full_2.finalize();

alert(correct_hash.toString() == result_hash.toString()); // true

(Using WordArray threw me an error in CryptoJS for some reason)

like image 58
Mifeet Avatar answered Oct 26 '22 22:10

Mifeet