如何在Google表格中仅用一个公式计算MD5哈希值?

编程语言 2026-07-11

是否可以仅使用原生Google表格公式实现真正完整的MD5哈希?尤其是因为没有像这样的原生函数:

=MD5("text")

=ARRAYFORMULA(MD5(A2:A5))

我在寻找一个纯GS公式解决方案,能够对字符串数组进行MD5校验,可靠、快速且高效地运行。对于长度高达50,000个字符的字符串也欢迎支持。请注意:

  • 使用 Apps Script / 宏
  • 插件 / 扩展 / 库

输入/输出示例:

文本 MD5值
Nyuu a05b9e2769d3e36f9ed2df205a1aa241
测试字符串 6f8db599de986fab7a21625b7916589c
测试2 38b0d2ff1c03df82aea67222983d337e

我没有找到可借鉴的现成工作,因此我从头开始实现了这个fx,因为在电子表格中将这些操作镜像出来相对容易:

=INDEX(LET(BITNOT32, LAMBDA(x, 4294967295-x),
           ADDD32, LAMBDA(x, y, MOD(x+y, 4294967296)),
           ROTL32, LAMBDA(x, s, MOD(x*2^s, 4294967296)+INT(x/2^(32-s))),
           MD5_F, LAMBDA(b, c, d, BITOR(BITAND(b, c), BITAND(BITNOT32(b), d))),
           MD5_G, LAMBDA(b, c, d, BITOR(BITAND(b, d), BITAND(c, BITNOT32(d)))),
           MD5_H, LAMBDA(b, c, d, BITXOR(BITXOR(b, c), d)),
           MD5_I, LAMBDA(b, c, d, BITXOR(c, BITOR(b, BITNOT32(d)))),
           T, LAMBDA(i, MOD(FLOOR(ABS(SIN(i))*4294967296), 4294967296)),
           S, LAMBDA(i, INDEX({7, 12, 17, 22; 5, 9, 14, 20; 4, 11, 16, 23; 6, 10, 15, 21}, INT((i-1)/16)+1, MOD(i-1, 4)+1)),
           BYTES, LAMBDA(str, MAKEARRAY(LEN(str), 1, LAMBDA(i, j, CODE(MID(str, i, 1))))),
           PAD, LAMBDA(str, LET(n, LEN(str), VSTACK(BYTES(str), 128, SEQUENCE(MOD(55-n, 64))*0, MOD(INT(n*8/256^(SEQUENCE(8)-1)), 256)))),
           WORDS, LAMBDA(p, MMULT(WRAPROWS(p, 4), {1; 256; 65536; 16777216})),
           _ROUND, LAMBDA(st, w, LET(r, REDUCE(st, SEQUENCE(64), LAMBDA(acc, i,
                   LET(a, INDEX(acc, 1),
                       b, INDEX(acc, 2),
                       c, INDEX(acc, 3),
                       d, INDEX(acc, 4),
                       rnd, INT((i-1)/16),
                       g, MOD(INDEX({1; 5; 3; 7}, rnd+1)*(i-1)+INDEX({0; 1; 5; 0}, rnd+1), 16)+1,
                       f, IFS(rnd=0, MD5_F(b, c, d), rnd=1, MD5_G(b, c, d), rnd=2, MD5_H(b, c, d), TRUE, MD5_I(b, c, d)),
                       t, ADDD32(ADDD32(ADDD32(a, f), T(i)), INDEX(w, g)), {d; ADDD32(b, ROTL32(t, S(i))); b; c}))), MAKEARRAY(4, 1, LAMBDA(i, j, ADDD32(INDEX(r, i), INDEX(st, i)))))),
                       padded, PAD(A2),
                       res, REDUCE({1732584193; 4023233417; 2562383102; 271733878}, SEQUENCE(ROWS(padded)/64), LAMBDA(st, blk, _ROUND(st, WORDS(CHOOSEROWS(padded, SEQUENCE(64, 1, (blk-1)*64+1)))))),
 LOWER(TEXTJOIN(, 1, MAP(SEQUENCE(4), LAMBDA(i,  LET(n, INDEX(res, i),
       TEXTJOIN(, 1, MAP(SEQUENCE(4), LAMBDA(j,  TEXT(DEC2HEX(MOD(INT(n/256^(j-1)), 256), 2), "00")))))))))))

该公式的问题包括:

  • 太长(1519个字符)
  • 性能较差
  • 运行十分缓慢
  • 最大字符串长度仅为9462个字符
  • #NUM! 在9463个字符处出现错误

    函数SEQUENCE的参数1 的值为0。它应大于或等于1。

  • #ERROR! 在9464个字符处出现错误

    在尝试计算此公式时达到了计算限制。

我不确定为什么会失败,或实现MD5校验和时存在哪些限制(例如整数精度、缺失的运算、栈溢出、计算上限等)。

解决方案

在尝试计算此公式时达到了计算限制。

这直接由 LAMBDA MINIONS 导致,表现为在LAMBDA内使用不必要的全局变量和/或使用重量级函数或/和运算,从而消耗有限的开销。在这种情形下进行优化以发挥最大潜力非常有必要。下面给出两种可能的解决方案:

你可以选择将其外包:

  • 相当快
  • 133个字符长
  • 轻量级
  • 最大字符串长度为1500个字符
=BYROW(A2:A, LAMBDA(x, HA(x="",,REGEXEXTRACT(INDEX(IMPORTDATA(
 "https://api.hashify.net/hash/md5/hex?value="&URLKODLA(x), ":"),,2), "(.*),")

enter image description here



或者你可以(重新)构建它:

  • 相对较快
  • 1046个字符长
  • 支持动态数组
  • 在本地运行(完全内部实现)
  • 最大字符串长度为 24823 个字符
=BYROW(A2:İNDİS(A:A; XMATCH(;-(A:A="");;-1)); LAMBDA(Ξ; HA(Ξ="";;İNDİS(LET(Џ; 2^32; А; LIN($1:$64);
 Б; ENT(ASS(SEN(А))*Џ); В; TETO(А/16); Г; {1;256;2^16;2^24}; Д; LIN($1:$16)-1; Е; 
 {Д+1;MOD(Д*5+1;16)+1;MOD(Д*3+5;16)+1;MOD(Д*7;16)+1}; Ж; TOCOL(REDUCE(TOROW(;1); LIN($1:$4); 
 LAMBDA(Л; И; HSTACK(Л; MTRANS(HSTACK({7;12;17;22};{5;9;14;20};{4;11;16;23};{6;10;15;21})))))); З; 2^Ж;
 И; LAMBDA(Й; К; MOD(REDUCE(Й; А; LAMBDA(Л; М; LET(Н; İNDİS(Л; 2); О; İNDİS(Л; 3); П; İNDİS(Л; 4); 
 Р; İNDİS(В; М); С; MOD(İNDİS(Л; 1)+VELG(Р; BITXOR(П; BİTVE(Н; BITXOR(О; П))); BITXOR(О; 
 BİTVE(П; BITXOR(Н; О))); BITXOR(BITXOR(Н; О); П); BITXOR(О; BITOR(Н; Џ-1-П)))+İNDİS(Б; М)+
 İNDİS(К; İNDİS(Е; М)); Џ); Т; С*İNDİS(З; М); {П;MOD(Н+BITOR(MOD(Т;Џ); ENT(Т/Џ)); Џ);Н;О})))+Й; 
 Џ)); У; DŁ(Ξ); Ф; MOD(55-У; 64); Х; DÇARP(WRAPROWS(TOCOL(VSTACK(KOD(MID(Ξ; SEQUENCE(У); 1)); 128; 
 HA(Ф=0;;SEQUENCE(Ф;1;;)); MOD(ENT(У*8/256^(LIN($1:$8)-1)); 256)); 1); 4); Г); Ц; REDUCE(
 {1732584193;4023233417;2562383102;271733878}; SEQUENCE(LINS(Х)/16); LAMBDA(Ч; Ш; И(Ч; CHOOSEROWS(Х;
 SEQUENCE(16; 1; Ш*16-15))))); SMÅ(JOIN(; MAP(Д+1; LAMBDA(Щ; DECHEX(MOD(ENT(İNDİS(Ц; TETO(Щ/4))
 /İNDİS(Г; MOD(Щ-1; 4)+1)); 256); 2)

enter image description here



额外内容:

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章