<script>
function md5(str) {
const encoder = new TextEncoder();
const data = Array.from(encoder.encode(str));
let len = data.length;
const bits = len * 8;
// 填充数据
data.push(0x80);
while ((data.length * 8) % 512 !== 448) {
data.push(0x00);
}
// 添加小端序的长度
const lenLow = bits >>> 0;
const lenHigh = Math.floor(bits / 0x100000000) >>> 0;
for (let i = 0; i < 4; i++) {
data.push((lenLow >>> (i * 8)) & 0xff);
}
for (let i = 0; i < 4; i++) {
data.push((lenHigh >>> (i * 8)) & 0xff);
}
// 初始化哈希值
let h0 = 0x67452301;
let h1 = 0xefcdab89;
let h2 = 0x98badcfe;
let h3 = 0x10325476;
// 处理每个512位块
for (let i = 0; i < data.length; i += 64) {
const chunk = data.slice(i, i + 64);
const X = new Array(16);
for (let j = 0; j < 16; j++) {
X[j] = (
chunk[j * 4] |
chunk[j * 4 + 1] << 8 |
chunk[j * 4 + 2] << 16 |
chunk[j * 4 + 3] << 24
) >>> 0;
}
let [a, b, c, d] = [h0, h1, h2, h3];
// 定义轮次参数
const K = Array.from({ length: 64 }, (_, i) => {
return Math.floor(Math.abs(Math.sin(i + 1)) * 0x100000000) >>> 0;
});
const r = [
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
];
for (let i = 0; i < 64; i++) {
let f, g;
if (i < 16) {
f = (b & c) | (~b & d);
g = i;
} else if (i < 32) {
f = (d & b) | (~d & c);
g = (5 * i + 1) % 16;
} else if (i < 48) {
f = b ^ c ^ d;
g = (3 * i + 5) % 16;
} else {
f = c ^ (b | ~d);
g = (7 * i) % 16;
}
f = (f + a + K[i] + X[g]) >>> 0;
f = ((f << r[i]) | (f >>> (32 - r[i]))) >>> 0;
f = (f + b) >>> 0;
// 轮换变量
[a, b, c, d] = [d, f, b, c];
}
// 更新哈希值
h0 = (h0 + a) >>> 0;
h1 = (h1 + b) >>> 0;
h2 = (h2 + c) >>> 0;
h3 = (h3 + d) >>> 0;
}
// 转换为小端序的十六进制字符串
const result = new Uint8Array(16);
const view = new DataView(result.buffer);
view.setUint32(0, h0, true);
view.setUint32(4, h1, true);
view.setUint32(8, h2, true);
view.setUint32(12, h3, true);
return Array.from(result).map(b => b.toString(16).padStart(2, '0')).join('');
}
</script>