加密哈希 #
什么是哈希算法? #
哈希算法(Hash Algorithm)是一种将任意长度的数据映射为固定长度哈希值的算法。
text
┌─────────────────────────────────────────────────────────────┐
│ 哈希算法原理 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 输入数据(任意长度) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Hello, World! 这是一个测试字符串... │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ 哈希算法 │ │
│ └──────────────┘ │
│ │ │
│ ▼ │
│ 输出哈希值(固定长度) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
哈希算法特点 #
text
┌─────────────────────────────────────────────────────────────┐
│ 哈希算法特点 │
├─────────────────────────────────────────────────────────────┤
│ ✅ 确定性:相同输入产生相同输出 │
│ ✅ 快速计算:能够快速生成哈希值 │
│ ✅ 雪崩效应:输入微小变化导致输出巨大变化 │
│ ✅ 不可逆:无法从哈希值反推原始数据 │
│ ✅ 抗碰撞:难以找到产生相同哈希值的不同输入 │
└─────────────────────────────────────────────────────────────┘
MD5 哈希 #
MD5 简介 #
MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希算法,产生 128 位(16 字节)的哈希值。
javascript
import md5 from './utils/md5';
const hash = md5('hello world');
console.log(hash);
MD5 特点 #
| 特性 | 描述 |
|---|---|
| 输出长度 | 128 位(32 个十六进制字符) |
| 分组大小 | 512 位 |
| 安全性 | 已被破解,不推荐用于安全场景 |
| 速度 | 快 |
| 应用场景 | 文件校验、数据指纹、非安全哈希 |
MD5 使用示例 #
javascript
import md5 from './utils/md5';
console.log(md5(''));
console.log(md5('hello'));
console.log(md5('hello world'));
console.log(md5('Hello World'));
const longText = '这是一个很长的文本内容...'.repeat(100);
console.log(md5(longText));
MD5 应用场景 #
1. 文件完整性校验 #
javascript
const calculateFileMD5 = async (file) => {
const buffer = await file.arrayBuffer();
const hash = md5(new Uint8Array(buffer));
return hash;
};
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async (e) => {
const file = e.target.files[0];
const hash = await calculateFileMD5(file);
console.log(`文件 ${file.name} 的 MD5: ${hash}`);
});
2. 数据缓存键 #
javascript
const getCacheKey = (params) => {
const str = JSON.stringify(params);
return md5(str);
};
const cache = new Map();
const fetchData = async (params) => {
const key = getCacheKey(params);
if (cache.has(key)) {
return cache.get(key);
}
const data = await fetch('/api/data', {
method: 'POST',
body: JSON.stringify(params)
}).then(r => r.json());
cache.set(key, data);
return data;
};
3. 密码存储(不推荐) #
javascript
import md5 from './utils/md5';
const hashPassword = (password, salt) => {
return md5(password + salt);
};
const salt = 'random-salt-value';
const hashedPassword = hashPassword('user-password', salt);
console.log(hashedPassword);
MD6 哈希 #
MD6 简介 #
MD6 是一种可变输出长度的哈希函数,支持从 1 到 512 位的输出。
javascript
import md6 from './utils/md6';
const hash128 = md6.hash128('hello world');
const hash256 = md6.hash256('hello world');
const hash512 = md6.hash512('hello world');
console.log(hash128.toString());
console.log(hash256.toString());
console.log(hash512.toString());
MD6 实现原理 #
javascript
const MD6 = (function() {
const w = 64;
const c = 64;
const n = 89;
const r = 80;
const K = [
0x7311c2812425cfa0n, 0x6432286434158a08n,
0xb60450e9ef68b7c1n, 0xe8fb23908d9f06f1n,
];
function compress(data, outputLen) {
const input = typeof data === 'string'
? new TextEncoder().encode(data)
: data;
const blockSize = 128;
const padLen = (blockSize - (input.length + 17) % blockSize) % blockSize;
const padded = new Uint8Array(input.length + 1 + padLen + 16);
padded.set(input);
padded[input.length] = 0x80;
const view = new DataView(padded.buffer);
view.setBigUint64(padded.length - 8, BigInt(outputLen), true);
let state = new BigUint64Array(8);
for (let i = 0; i < 8; i++) {
state[i] = K[i % K.length];
}
for (let i = 0; i < padded.length; i += blockSize) {
const block = new BigUint64Array(16);
for (let j = 0; j < 16 && i + j * 8 < padded.length; j++) {
block[j] = view.getBigUint64(i + j * 8, true) || 0n;
}
for (let round = 0; round < 16; round++) {
for (let j = 0; j < 8; j++) {
state[j] ^= block[(round + j) % 16];
state[j] = BigInt.asUintN(64, state[j] * 0x5bd1e995n);
state[j] ^= (state[(j + 1) % 8] >> 17n);
}
}
}
const outputBytes = Math.ceil(outputLen / 8);
const result = new Uint8Array(outputBytes);
const resultView = new DataView(result.buffer);
for (let i = 0; i < Math.min(8, Math.ceil(outputBytes / 8)); i++) {
if (i * 8 + 8 <= outputBytes) {
resultView.setBigUint64(i * 8, state[i], true);
} else {
const remaining = outputBytes - i * 8;
for (let j = 0; j < remaining; j++) {
result[i * 8 + j] = Number((state[i] >> BigInt(j * 8)) & 0xffn);
}
}
}
return result;
}
function hash(message, outputBits = 256) {
const result = compress(message, outputBits);
return {
toString: function() {
return Array.from(result)
.map(b => b.toString(16).padStart(2, '0'))
.join('');
},
toBytes: function() {
return result;
}
};
}
return {
hash: hash,
hash128: (message) => hash(message, 128),
hash224: (message) => hash(message, 224),
hash256: (message) => hash(message, 256),
hash384: (message) => hash(message, 384),
hash512: (message) => hash(message, 512)
};
})();
export default MD6;
MD6 使用示例 #
javascript
import md6 from './utils/md6';
const message = 'hello world';
console.log('MD6-128:', md6.hash128(message).toString());
console.log('MD6-224:', md6.hash224(message).toString());
console.log('MD6-256:', md6.hash256(message).toString());
console.log('MD6-384:', md6.hash384(message).toString());
console.log('MD6-512:', md6.hash512(message).toString());
const customHash = md6.hash(message, 200);
console.log('MD6-200:', customHash.toString());
哈希算法对比 #
| 特性 | MD5 | SHA-1 | SHA-256 | MD6 |
|---|---|---|---|---|
| 输出长度 | 128位 | 160位 | 256位 | 可变(1-512位) |
| 安全性 | 已破解 | 已破解 | 安全 | 安全 |
| 速度 | 快 | 中等 | 较慢 | 中等 |
| 应用场景 | 校验、指纹 | 已不推荐 | 安全场景 | 灵活场景 |
实际应用场景 #
1. 数据去重 #
javascript
import md5 from './utils/md5';
class Deduplication {
constructor() {
this.hashes = new Set();
}
add(data) {
const hash = md5(JSON.stringify(data));
if (this.hashes.has(hash)) {
return false;
}
this.hashes.add(hash);
return true;
}
has(data) {
const hash = md5(JSON.stringify(data));
return this.hashes.has(hash);
}
}
const dedup = new Deduplication();
console.log(dedup.add({ id: 1, name: 'John' }));
console.log(dedup.add({ id: 1, name: 'John' }));
console.log(dedup.add({ id: 2, name: 'Jane' }));
2. 版本控制 #
javascript
import md5 from './utils/md5';
const getVersionHash = (content) => {
return md5(content).slice(0, 8);
};
const versions = new Map();
const saveVersion = (documentId, content) => {
const version = getVersionHash(content);
versions.set(`${documentId}:${version}`, {
content,
timestamp: Date.now()
});
return version;
};
const version1 = saveVersion('doc1', '第一版内容');
const version2 = saveVersion('doc1', '第二版内容');
console.log('版本1:', version1);
console.log('版本2:', version2);
3. 负载均衡 #
javascript
import md5 from './utils/md5';
class ConsistentHash {
constructor(nodes = []) {
this.ring = new Map();
nodes.forEach(node => this.addNode(node));
}
addNode(node) {
const hash = parseInt(md5(node).slice(0, 8), 16);
this.ring.set(hash, node);
}
getNode(key) {
const hash = parseInt(md5(key).slice(0, 8), 16);
const sortedHashes = [...this.ring.keys()].sort((a, b) => a - b);
for (const nodeHash of sortedHashes) {
if (hash <= nodeHash) {
return this.ring.get(nodeHash);
}
}
return this.ring.get(sortedHashes[0]);
}
}
const ch = new ConsistentHash(['node1', 'node2', 'node3']);
console.log(ch.getNode('user:1'));
console.log(ch.getNode('user:2'));
console.log(ch.getNode('user:3'));
安全注意事项 #
1. 不要用于密码存储 #
javascript
import md5 from './utils/md5';
const insecureHash = (password) => md5(password);
const secureHash = async (password, salt) => {
const encoder = new TextEncoder();
const data = encoder.encode(password + salt);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
};
2. 使用 Web Crypto API #
javascript
const secureHash = async (message, algorithm = 'SHA-256') => {
const encoder = new TextEncoder();
const data = encoder.encode(message);
const hashBuffer = await crypto.subtle.digest(algorithm, data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
};
await secureHash('hello world', 'SHA-256');
await secureHash('hello world', 'SHA-384');
await secureHash('hello world', 'SHA-512');
下一步 #
现在你已经掌握了加密哈希,接下来学习 高级用法,了解深拷贝、深合并等高级技巧!
最后更新:2026-04-04