Generate a Hash from string in Javascript

前端 未结 22 1419
不知归路
不知归路 2020-11-22 03:34

I need to convert strings to some form of hash. Is this possible in JavaScript?

I\'m not utilizing a server-side language so I can\'t do it that way.

22条回答
  •  情书的邮戳
    2020-11-22 04:12

    This should be a bit more secure hash than some other answers, but in a function, without any preloaded source

    I created basicly a minified simplified version of sha1.
    You take the bytes of the string and group them by 4 to 32bit "words"
    Then we extend every 8 words to 40 words (for bigger impact on the result).
    This goes to the hashing function (the last reduce) where we do some maths with the current state and the input. We always get 4 words out.
    This is almost a one-command/one-line version using map,reduce... instead of loops, but it is still pretty fast

    String.prototype.hash = function(){
        var rot = (word, shift) => word << shift | word >>> (32 - shift);
        return unescape(encodeURIComponent(this.valueOf())).split("").map(char =>
                char.charCodeAt(0)
            ).reduce((done, byte, idx, arr) =>
                idx % 4 == 0 ? [...done, arr.slice(idx, idx + 4)] : done
            , []).reduce((done, group) =>
                [...done, group[0] << 24 | group[1] << 16 | group[2] << 8 | group[3]]
            , []).reduce((done, word, idx, arr) =>
                idx % 8 == 0 ? [...done, arr.slice(idx, idx + 8)] : done
            , []).map(group => {
                while(group.length < 40)
                    group.push(rot(group[group.length - 2] ^ group[group.length - 5] ^ group[group.length - 8], 3));
                return group;
            }).flat().reduce((state, word, idx, arr) => {
                var temp = ((state[0] + rot(state[1], 5) + word + idx + state[3]) & 0xffffffff) ^ state[idx % 2 == 0 ? 4 : 5](state[0], state[1], state[2]);
                state[0] = rot(state[1] ^ state[2], 11);
                state[1] = ~state[2] ^ rot(~state[3], 19);
                state[2] = rot(~state[3], 11);
                state[3] = temp;
                return state;
            }, [0xbd173622, 0x96d8975c, 0x3a6d1a23, 0xe5843775,
                (w1, w2, w3) => (w1 & rot(w2, 5)) | (~rot(w1, 11) & w3),
                (w1, w2, w3) => w1 ^ rot(w2, 5) ^ rot(w3, 11)]
            ).slice(0, 4).map(p =>
                p >>> 0
            ).map(word =>
                ("0000000" + word.toString(16)).slice(-8)
            ).join("");
    };
    

    we also convert the output to hex to get a string instead of word array.
    Usage is simple. for expample "a string".hash() will return "88a09e8f9cc6f8c71c4497fbb36f84cd"

    String.prototype.hash = function(){
    	var rot = (word, shift) => word << shift | word >>> (32 - shift);
    	return unescape(encodeURIComponent(this.valueOf())).split("").map(char =>
    			char.charCodeAt(0)
    		).reduce((done, byte, idx, arr) =>
    			idx % 4 == 0 ? [...done, arr.slice(idx, idx + 4)] : done
    		, []).reduce((done, group) =>
    			[...done, group[0] << 24 | group[1] << 16 | group[2] << 8 | group[3]]
    		, []).reduce((done, word, idx, arr) =>
    			idx % 8 == 0 ? [...done, arr.slice(idx, idx + 8)] : done
    		, []).map(group => {
    			while(group.length < 40)
    				group.push(rot(group[group.length - 2] ^ group[group.length - 5] ^ group[group.length - 8], 3));
    			return group;
    		}).flat().reduce((state, word, idx, arr) => {
    			var temp = ((state[0] + rot(state[1], 5) + word + idx + state[3]) & 0xffffffff) ^ state[idx % 2 == 0 ? 4 : 5](state[0], state[1], state[2]);
    			state[0] = rot(state[1] ^ state[2], 11);
    			state[1] = ~state[2] ^ rot(~state[3], 19);
    			state[2] = rot(~state[3], 11);
    			state[3] = temp;
    			return state;
    		}, [0xbd173622, 0x96d8975c, 0x3a6d1a23, 0xe5843775,
    			(w1, w2, w3) => (w1 & rot(w2, 5)) | (~rot(w1, 11) & w3),
    			(w1, w2, w3) => w1 ^ rot(w2, 5) ^ rot(w3, 11)]
    		).slice(0, 4).map(p =>
    			p >>> 0
    		).map(word =>
    			("0000000" + word.toString(16)).slice(-8)
    		).join("");
    };
    let str = "the string could even by empty";
    console.log(str.hash())//9f9aeca899367572b875b51be0d566b5

提交回复
热议问题