md5.js/md5.js

141 lines
4.2 KiB
JavaScript

/*
* This file is part of md5.js.
*
* md5.js is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* md5.js is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with md5.js. If not, see <https://www.gnu.org/licenses/>.
*/
function md5(str)
{
// Convert string to bytes
var data = new TextEncoder("utf-8").encode(str);
// Constants
var s = new Uint32Array([
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
]);
var K = new Uint32Array([
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
]);
// Initialize hash
var hash = new Uint32Array([0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]);
// Apply padding
var padLength = data.length + 1;
while (padLength % 64 != 56)
padLength++;
padLength += 8;
var padData = new Uint8Array(padLength);
for (var i = 0; i < data.length; i++)
padData[i] = data[i];
for (var i = data.length; i < padLength; i++)
padData[i] = 0x0;
// Append 1 bit
padData[data.length] = 0x80;
// Append original length
var bits = data.length * 8;
var upperLen = parseInt(bits.toString(16).slice(0, -8), 16);
if (isNaN(upperLen))
upperLen = 0;
padData[padLength-8] = bits;
padData[padLength-7] = bits >>> 8;
padData[padLength-6] = bits >>> 16;
padData[padLength-5] = bits >>> 24;
padData[padLength-4] = upperLen;
padData[padLength-3] = upperLen >>> 8;
padData[padLength-2] = upperLen >>> 16;
padData[padLength-1] = upperLen >>> 24;
// Process the data in 64-byte chunks
for (var i = 0; i < padLength; i += 64) {
var M = new Uint32Array(16);
for (var j = 0, offset = i; j < 16; j++, offset += 4)
M[j] = padData[offset] + (padData[offset+1] << 8) + (padData[offset+2] << 16) + (padData[offset+3] << 24);
// Main loop
var chunk = new Uint32Array(hash);
for (var j = 0; j < 64; j++) {
var locals = new Uint32Array(2);
if (j <= 15) {
locals[0] = (chunk[1] & chunk[2]) | ((~chunk[1]) & chunk[3]);
locals[1] = j;
} else if (j <= 31) {
locals[0] = (chunk[3] & chunk[1]) | ((~chunk[3]) & chunk[2]);
locals[1] = (5 * j + 1) % 16;
} else if (j <= 47) {
locals[0] = chunk[1] ^ chunk[2] ^ chunk[3];
locals[1] = (3 * j + 5) % 16;
} else {
locals[0] = chunk[2] ^ (chunk[1] | (~chunk[3]));
locals[1] = (7 * j) % 16;
}
locals[0] += chunk[0] + K[j] + M[locals[1]];
chunk[0] = chunk[3];
chunk[3] = chunk[2];
chunk[2] = chunk[1];
chunk[1] += rotl(locals[0], s[j]);
}
// Add this chunk's hash to the main hash
hash[0] += chunk[0];
hash[1] += chunk[1];
hash[2] += chunk[2];
hash[3] += chunk[3];
}
// Convert to string
var md5Str = "";
for (var i = 0; i < 4; i++) {
var bytes = new Uint8Array([hash[i], hash[i] >> 8, hash[i] >> 16, hash[i] >> 24]);
for (var j = 0; j < 4; j++) {
if (bytes[j] < 0x10)
md5Str += "0";
md5Str += bytes[j].toString(16);
}
}
return md5Str;
}
// Bitwise left-rotate
function rotl(val, sft)
{
return (val << sft) | (val >>> (32 - sft));
}
export { md5 };