可信源码风险提示:保存或下载前请阅读源码和权限声明。
/**
Author: Drific && DeepSeek-V4.1-Flash
Email: Drific_pl@163.com
声明:部分注释和代码由AI生成,可能包含不实信息
*/
// ====================================================
// SHA-3 (Keccak) 纯 JS 实现 —— ES5 兼容版,适用 Vela / QuickJS
// ====================================================
var RC_LO = new Uint32Array([
0x00000001, 0x00008082, 0x0000808A, 0x80008000,
0x0000808B, 0x80000001, 0x80008081, 0x00008009,
0x0000008A, 0x00000088, 0x80008009, 0x8000000A,
0x8000808B, 0x0000008B, 0x00008089, 0x00008003,
0x00008002, 0x00000080, 0x0000800A, 0x8000000A,
0x80008081, 0x00008080, 0x80000001, 0x80008008
]);
var RC_HI = new Uint32Array([
0x00000000, 0x00000000, 0x80000000, 0x80000000,
0x00000000, 0x00000000, 0x80000000, 0x80000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x80000000, 0x80000000, 0x80000000,
0x80000000, 0x80000000, 0x00000000, 0x80000000,
0x80000000, 0x80000000, 0x00000000, 0x80000000
]);
var RHO = new Uint8Array([
0, 1, 62, 28, 27,
36, 44, 6, 55, 20,
3, 10, 43, 25, 39,
41, 45, 15, 21, 8,
18, 2, 61, 56, 14
]);
var _C = new Uint32Array(10);
var _D = new Uint32Array(10);
var _B = new Uint32Array(50);
function keccakF(state) {
var x, y, round, idx, i1, i2;
var lo, hi, cPrevLo, cPrevHi, cNextLo, cNextHi;
var rotLo, rotHi, r, r2, newX, newY, dstIdx;
var b0lo, b0hi, b1lo, b1hi, b2lo, b2hi;
for (round = 0; round < 24; round++) {
// Theta
for (x = 0; x < 5; x++) {
lo = 0; hi = 0;
for (y = 0; y < 5; y++) {
idx = 2 * (x + 5 * y);
lo ^= state[idx];
hi ^= state[idx + 1];
}
_C[2 * x] = lo >>> 0;
_C[2 * x + 1] = hi >>> 0;
}
for (x = 0; x < 5; x++) {
cPrevLo = _C[2 * ((x + 4) % 5)];
cPrevHi = _C[2 * ((x + 4) % 5) + 1];
cNextLo = _C[2 * ((x + 1) % 5)];
cNextHi = _C[2 * ((x + 1) % 5) + 1];
rotLo = ((cNextLo << 1) | (cNextHi >>> 31)) >>> 0;
rotHi = ((cNextHi << 1) | (cNextLo >>> 31)) >>> 0;
_D[2 * x] = (cPrevLo ^ rotLo) >>> 0;
_D[2 * x + 1] = (cPrevHi ^ rotHi) >>> 0;
}
for (x = 0; x < 5; x++) {
for (y = 0; y < 5; y++) {
idx = 2 * (x + 5 * y);
state[idx] = (state[idx] ^ _D[2 * x]) >>> 0;
state[idx + 1] = (state[idx + 1] ^ _D[2 * x + 1]) >>> 0;
}
}
// Rho + Pi
for (x = 0; x < 5; x++) {
for (y = 0; y < 5; y++) {
idx = 2 * (x + 5 * y);
r = RHO[x + 5 * y];
lo = state[idx];
hi = state[idx + 1];
if (r === 0) {
rotLo = lo; rotHi = hi;
} else if (r === 32) {
rotLo = hi; rotHi = lo;
} else if (r < 32) {
rotLo = ((lo << r) | (hi >>> (32 - r))) >>> 0;
rotHi = ((hi << r) | (lo >>> (32 - r))) >>> 0;
} else {
r2 = r - 32;
rotLo = ((hi << r2) | (lo >>> (32 - r2))) >>> 0;
rotHi = ((lo << r2) | (hi >>> (32 - r2))) >>> 0;
}
newX = y;
newY = (2 * x + 3 * y) % 5;
dstIdx = 2 * (newX + 5 * newY);
_B[dstIdx] = rotLo;
_B[dstIdx + 1] = rotHi;
}
}
// Chi
for (x = 0; x < 5; x++) {
for (y = 0; y < 5; y++) {
idx = 2 * (x + 5 * y);
i1 = 2 * (((x + 1) % 5) + 5 * y);
i2 = 2 * (((x + 2) % 5) + 5 * y);
b0lo = _B[idx]; b0hi = _B[idx + 1];
b1lo = _B[i1]; b1hi = _B[i1 + 1];
b2lo = _B[i2]; b2hi = _B[i2 + 1];
state[idx] = (b0lo ^ ((~b1lo) & b2lo)) >>> 0;
state[idx + 1] = (b0hi ^ ((~b1hi) & b2hi)) >>> 0;
}
}
// Iota
state[0] = (state[0] ^ RC_LO[round]) >>> 0;
state[1] = (state[1] ^ RC_HI[round]) >>> 0;
}
}
function absorbBlock(state, bytes, offset, rate) {
var i, laneIdx, byteInLane, b, shift;
for (i = 0; i < rate; i++) {
laneIdx = (i / 8) | 0;
byteInLane = i % 8;
b = bytes[offset + i];
if (byteInLane < 4) {
shift = 8 * byteInLane;
state[2 * laneIdx] = (state[2 * laneIdx] ^ (b << shift)) >>> 0;
} else {
shift = 8 * (byteInLane - 4);
state[2 * laneIdx + 1] = (state[2 * laneIdx + 1] ^ (b << shift)) >>> 0;
}
}
}
function utf8Encode(str) {
// Vela 的 QuickJS 部分版本没有 TextEncoder,走纯 JS
if (typeof TextEncoder !== 'undefined') {
return new TextEncoder().encode(str);
}
var bytes = [];
for (var i = 0; i < str.length; i++) {
var c = str.charCodeAt(i);
if (c < 0x80) bytes.push(c);
else if (c < 0x800) {
bytes.push(0xc0 | (c >> 6));
bytes.push(0x80 | (c & 0x3f));
} else if (c < 0xd800 || c >= 0xe000) {
bytes.push(0xe0 | (c >> 12));
bytes.push(0x80 | ((c >> 6) & 0x3f));
bytes.push(0x80 | (c & 0x3f));
} else {
i++;
var c2 = str.charCodeAt(i);
var cp = 0x10000 + (((c & 0x3ff) << 10) | (c2 & 0x3ff));
bytes.push(0xf0 | (cp >> 18));
bytes.push(0x80 | ((cp >> 12) & 0x3f));
bytes.push(0x80 | ((cp >> 6) & 0x3f));
bytes.push(0x80 | (cp & 0x3f));
}
}
return new Uint8Array(bytes);
}
function sha3(message, bits) {
var rate, outputLen;
if (bits === 224) { rate = 144; outputLen = 28; }
else if (bits === 256) { rate = 136; outputLen = 32; }
else if (bits === 384) { rate = 104; outputLen = 48; }
else if (bits === 512) { rate = 72; outputLen = 64; }
else throw new Error('Unsupported SHA-3 variant: ' + bits);
var msg;
if (typeof message === 'string') msg = utf8Encode(message);
else if (message instanceof Uint8Array) msg = message;
else if (message instanceof ArrayBuffer) msg = new Uint8Array(message);
else throw new Error('Unsupported message type');
var state = new Uint32Array(50);
var offset = 0;
var len = msg.length;
while (len - offset >= rate) {
absorbBlock(state, msg, offset, rate);
keccakF(state);
offset += rate;
}
var lastBlock = new Uint8Array(rate);
var remaining = len - offset;
for (var i = 0; i < remaining; i++) lastBlock[i] = msg[offset + i];
lastBlock[remaining] = 0x06;
lastBlock[rate - 1] |= 0x80;
absorbBlock(state, lastBlock, 0, rate);
keccakF(state);
var output = new Uint8Array(outputLen);
for (var j = 0; j < outputLen; j++) {
var laneIdx = (j / 8) | 0;
var byteInLane = j % 8;
if (byteInLane < 4) {
output[j] = (state[2 * laneIdx] >>> (8 * byteInLane)) & 0xff;
} else {
output[j] = (state[2 * laneIdx + 1] >>> (8 * (byteInLane - 4))) & 0xff;
}
}
return output;
}
function toHex(bytes) {
var s = '';
for (var i = 0; i < bytes.length; i++) {
var h = bytes[i].toString(16);
s += h.length === 1 ? '0' + h : h;
}
return s;
}
function sha3_224(message){return toHex(sha3(message, 224));}
function sha3_256(message){return toHex(sha3(message, 256));}
function sha3_384(message){return toHex(sha3(message, 384));}
function sha3_512(message){return toHex(sha3(message, 512));}
const text = 'abcde'
console.log(`sha_224('${text}') = ${sha3_224(text)}`)
console.log(`sha_256('${text}') = ${sha3_256(text)}`)
console.log(`sha_384('${text}') = ${sha3_384(text)}`)
console.log(`sha_512('${text}') = ${sha3_512(text)}`)