雜記 › 技術筆記 › 改了鹽值不點按鈕,四個框一動不動:MD5 頁的三段拼接與多行輸入實測

改了鹽值不點按鈕,四個框一動不動:MD5 頁的三段拼接與多行輸入實測

三段拼接順序與四組鹽填法實測互不相同,鹽與原字串的邊界平移要拼成同一條字串才同值;textarea 從不按行拆分,多行只出 1 條雜湊;空輸入走守衛,四個框留著上一次的值。

四個框的不同填法:同一句 hello 送進去是四條字串

這頁的腳本段我逐字切出來在 Node 裡原樣跑,雜湊庫那一步換成內建 crypto 對 UTF-8 位元組算 MD5,拼接與切片一行未動。要量的只有一行:const text = pre + raw + suf;。模板實測 3635 位元組、84 行行行 CRLF。

原字串固定填 hello,四組填法捕捉到的送雜湊字串逐字是 hello、salt1hello、hellosalt2、salt1hellosalt2:三段之間沒有分隔符也不做 trim。

前置鹽後置鹽送進雜湊的字串32 位小寫
空空hello5d41402abc4b2a76b9719d911017c592
salt1空salt1hello95a2e8514b40b95ef41fb464a6e382ee
空salt2hellosalt2d25f7bdb12f78be4238273d49591f882
salt1salt2salt1hellosalt27be7c42377de79b9012a2fba496208c6

去重計數實測 4/4 互不相同;兩組鹽對調拼出 salt2hellosalt1,實測結果與都填那條也不同——順序一變字串就變。這頁 文本 MD5 線上工具 的雜湊呼叫點只有 calcMd5() 一處。

三段順序固定:前置鹽 + 原字串 + 後置鹽,拼成一條字串再雜湊 pre 前置鹽 + raw 原字串 + suf 後置鹽 = 一條 text 原字串填 hello:四組填法捕捉 4 條字串,32 位結果去重 4 對 4 兩鹽對調是第五條字串,結果不同 邊界 5 種切法都拼成 abc:同一條字串、同一個結果 測試|文|一下 與 測|試文|一下 都是 測試文一下:5 碼元 15 位元組 函數只看拼完的那條字串

圖 1:三段拼接的順序,與兩類同值的來路

邊界平移:拼出來是同一條字串

前中後三格按 ab|c|、a|bc|、|abc| 等五種切法填,捕捉值五條逐一都是 abc,32 位結果全等於 900150983cd24fb0d6963f7d28e17f72。中文同型一組 測試|文|一下 與 測|試文|一下 都拼成 測試文一下,兩條同為 8f76011a697386edf2f3132d4e4f57de。函數只看拼完的那條字串,邊界切在哪不算它的口徑;上面的兩鹽對調換的是字串本身,所以換的是結果。

textarea 從不按行拆分

函數體沒有 split、也沒有按行的迴圈,換行只是字串裡一個普通碼元:

輸入(JSON 轉義寫法)碼元換行碼元32 位小寫
"alpha\nbeta\ngamma"162b81e722771977ee32a6822155f761acd
"alphabetagamma"14011db5b10e1c21d2e7e4dfa597552e331
"alpha\nbeta"1016d76416219367970d143155ecd77d609
"alpha\r\nbeta"多一枚 \r10ff5fc67c03065f1c72d4ac72aeefdbf

1 到 6 行的樣本字串長 5、10、16、22、30、35 碼元、換行碼元從 0 到 5,而每一次的雜湊呼叫都是 1 次、結果 1 條。intro 那句「批量處理:支持多行文本批量生成MD5」判 [衝突]:輸出只有 4 個單值唯讀框。

監聽器 1 對 0 對 0

#md5-input 上掛著 1 個 input 監聽,兩個鹽框各 0 個;監聽體逐字是 if (this.value) calcMd5();。從空態逐字元敲入 hello 觸發 5 次,捕捉的字串依次是 h、he、hel、hell、hello;再逐字元退格觸發 4 次,刪到空那一步 0 次呼叫、0 次提示,畫面停在 h 的 2510c39011c5be704182423e3a695e91 上,總計數 9 = 5 + 4。

input 監聽只在原字串非空時整算一遍 h he hel hell hello 退格 4 步 刪空不觸發 總計數 9 = 5 + 4,刪到空呼叫 0 次、提示 0 次 兩個鹽框監聽 0 個:改前鹽不點按鈕,輸出逐字元不變 點一下才把新鹽拼進字串,salt9hello 另得一條結果

圖 2:input 監聽的觸發計數

空輸入被守衛擋下,框裡留著上一次的值

守衛逐字是 if (!raw) { UU.toast('请输入要加密的文本', 'error'); return; }:鹽框填什麼都攔,鹽框留空則以空段參與拼接。三影格實測——影格 A 預填 ab、hello、cd,捕捉 abhellocd,32 位小寫 07663b565bdbcf17432e20d56eb1a51b,結果容器轉為顯示;影格 B 打字清空輸入,監聽判空不呼叫、連提示都不彈;影格 C 點按鈕,提示計數 +1,return 之後的賦值一條沒執行,四個唯讀框與容器狀態和影格 A 逐字元相同。d41d8cd98f00b204e9800998ecf8427e 確是空字串的 MD5、與 intro 那則例常量逐字元 0 處差異,但本頁的空輸入進不到雜湊呼叫點,這則例值沒有任何路徑能重現。清空按鈕走另一條:一次抹掉 7 個 id 的值。

中文與 emoji 依 UTF-8 位元組進雜湊

中 是 1 碼元 / 3 位元組(e4b8ad),测试文本 是 4 碼元 / 12 位元組(e6b58be8af95e69687e69cac),一枚 U+1F600 的 emoji 與 U+20000 那個輔助平面漢字都是 2 碼元 / 4 位元組。兩條路徑在 6 則樣本上 6/6 一致,RFC 1321 的 5 則向量 5/5 命中——進雜湊的始終是位元組,不是螢幕上的字數。

對著 intro 只登記三句

  • 「大小寫切換」:沒有可切的動作,兩個大寫值與兩個小寫值在同一次點擊裡同時寫進 4 個框。[部分一致]
  • 「16 位是取中間 16 個字元」:substring(8, 24) 取到 1 基第 9 到第 24 個字元、長度 16,6 條輸入上它與 32 位串同區間逐位相同 6/6。這句SHA-256 與 MD5 對比舊文寫過,不展開。[一致]
  • 「批量」見上面的換行表,[衝突]。intro 的安全提示區塊與加鹽條目的評語句只登記、不評價;檔案那一頁(檔案 MD5 計算)本篇沒測,也不外推別的雜湊頁。

FAQ

Q:鹽放前邊還是後邊,結果一樣嗎?

看拼出來的那條字串:只填前鹽是 salt1hello、只填後鹽是 hellosalt2,兩條兩個結果。平移只在拼完是同一條字串時同值;兩鹽對調拼的不是同一條,結果也不同。

Q:貼 3 行能得到 3 個雜湊嗎?

不能,實測 1 次呼叫、1 條結果。刪掉換行實測會讓結果換一條,CRLF 與 LF 也是兩條字串。

Q:改了鹽值結果沒動,是沒算嗎?

鹽框沒有監聽,改完不點按鈕就不算;空輸入被守衛擋下時只彈提示,四個框仍保持上一次的值。

📎 相關文章

取色器的解析門只收六位十六進位:三位短寫摘出能算、頁面永遠走不到 2026-11-08 60 位時間戳在這一頁只剩 28 個位置:UUID 產生器 v1 分支的移位與掩碼逐毫秒實測 2026-11-08 替換次數報 5 還是報 1:批次尋找替換的三個開關與零寬匹配實測 2026-11-07 空一個框就 0 張卡:分數通分頁的靜默失敗、跳號的「分數N」與 990 行不約分 2026-11-07 刪右側給空串、截右側還整行:text-line-ops 的碼元口徑與越界不對稱實測 2026-11-07