SHA-256 對於任何輸入都會產生固定長度 256 位元(32 位元組)的摘要,無論原始訊息的大小為何,皆會以 64 個小寫十六進位字元或標準填補式 Base64 顯示。同樣的 UTF-8 文字或同樣的檔案位元組,在每個符合規範的實作上都會產生相同的摘要,因為 SHA-256 是由 NIST FIPS 180-4 逐位元指定的。在 JavaScript 中,產生該摘要主要有三種實務做法:透過 SubtleCrypto.digest 並使用演算法字串 "SHA-256" 呼叫平台 Web Crypto API;匯入一個在使用者空間中重新實作壓縮函式的第三方純 JavaScript 函式庫;或是將精確的位元組交給本機瀏覽器工具後複製結果。這三種方式對於「什麼算作輸入」必須有共識:一串字元並不等於一段位元組序列,任何一個多餘的換行、表情符號或 Unicode 標準化差異,都會產生不同的摘要。以下章節將說明 SHA-256 實際計算的內容、三種 JavaScript 途徑的差異、如何透過 SHA256 雜湊產生器 執行摘要運算,以及最常導致「我的雜湊對不上」回報的位元組層級陷阱。

SHA-256 實際計算的內容
SHA-256 屬於 SHA-2 家族的雜湊函式,完整演算法發布於 NIST FIPS 180-4。其中「256」指的是以位元為單位的摘要長度,因此每個輸出都恰好是 32 個位元組;32 個位元組以十六進位表示即為 64 個字元,以標準 Base64 表示則為 44 個填補字元。此函式具有確定性:相同的輸入位元組在每個符合規範的實作上都會產生相同的輸出位元組,而原始演算法中並不包含金鑰、鹽值或隨機元素。
在內部,演算法會將訊息填補至 512 位元的倍數,將填補後的位元組切分為 512 位元的區塊,然後透過 64 輪運算處理每個區塊,更新八個 32 位元的工作變數。當所有區塊處理完畢後,這八個工作變數會被串接起來,形成最終的 256 位元摘要。每一輪的常數與初始值均由標準固定,這也是為什麼空位元組字串必定產生精確的摘要 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855。任何符合規範的實作都不允許對該輸入產生其他不同的值,且測試向量會與 NIST CAVP Secure Hashing 套件獨立比對。
在 JavaScript 中產生 SHA-256 的三種方式
現代 JavaScript 環境透過 Web Crypto API 公開摘要運算,並將底層數學運算委派給底層平台。標準呼叫為非同步,並回傳 ArrayBuffer:
// Web Crypto API(瀏覽器與具備 globalThis.crypto 的現代 Node.js)const bytes = new TextEncoder().encode(value);const digest = await crypto.subtle.digest('SHA-256', bytes);// digest 為恰好 32 位元組的 ArrayBuffer
只要可行,這就是建議採用的途徑,因為底層實作與作業系統共用,並已根據公開的測試向量進行驗證。第二種途徑是使用第三方 JavaScript 函式庫,例如 js-sha256、hash-wasm 或自行撰寫的實作;這些會在純使用者空間中執行,適用於沒有 SubtleCrypto 的環境,或需要 SHA-256 轉換在主執行緒上同步執行的情境。第三種途徑是將位元組交給像 SHA256 雜湊產生器這類的本機瀏覽器工具,它會對精確的 UTF-8 文字或所選的檔案位元組執行相同的 SubtleCrypto 呼叫,並同時顯示 64 字元的十六進位與標準填補式 Base64。
| 方法 | 執行位置 | 回傳內容 | 適用情境 |
|---|---|---|---|
| Web Crypto SubtleCrypto.digest | 瀏覽器分頁/現代 Node | 32 位元組的 ArrayBuffer | 正式程式碼、測試、已簽署的發行版本 |
| 純 JS 函式庫(js-sha256、hash-wasm) | 使用者空間 JavaScript | 十六進位字串或位元組陣列 | 舊版瀏覽器、同步程式碼、嵌入式 JS |
| SHA256 雜湊產生器工具 | 瀏覽器分頁 | 十六進位與 Base64 字串 | 人工驗證、一次性檢查碼 |
三者在相同的輸入位元組下皆為正確;選擇取決於你需要在腳本、建置流程還是人為檢查中取得結果。沒有任何一者應被宣稱比其他「更安全」,因為 SHA-256 在各種情況下都是相同的演算法。
透過本機工具產生 SHA-256 雜湊
當你需要為一段文字或下載的檔案取得精確的 SHA-256 摘要時,最快速的途徑是將位元組送入 SHA256 雜湊產生器並複製結果。該工具公開的摘要運算與你自行撰寫的程式碼中 SubtleCrypto 執行的完全相同,輸入控制項僅限於文字或檔案。
- 在瀏覽器分頁中開啟 SHA256 雜湊產生器。
- 針對 UTF-8 輸入選擇文字模式,或針對原始位元組選擇檔案模式,然後輸入或選取你要驗證的精確內容。該工具在雜湊前會以 UTF-8 編碼文字,因此帶有腔調字元、表情符號與非 ASCII 文字的內容會以其完整的多位元組 UTF-8 表示方式參與計算。
- 點擊產生動作。摘要會以 64 個小寫十六進位字元與標準填補式 Base64 顯示;兩種表示方式描述的是相同的 32 個結果位元組。
- 複製你所驗證的系統所期望的表示形式。十六進位字母的大小寫僅為呈現選擇,並不會改變底層位元組;以小寫十六進位比對大寫十六進位,兩者仍描述相同的摘要。
- 比對完整輸出而非前綴,並與參考值進行比較。任何單一字元差異即代表輸入位元組不同;完全相符則代表位元組完全相同。
空字串是合法的輸入,會產生著名的 SHA-256 摘要,開頭為 e3b0c442,這是確認該工具已連接至與你的 SubtleCrypto 呼叫相同的 FIPS 180-4 演算法的快速方法。檔案大小上限為 100 MB,因為 Web Cryptography 摘要介面接收的是完整位元組緩衝,而非串流;針對更大的檔案,請改用支援串流的命令列工具在本機進行雜湊,避免耗盡瀏覽器記憶體。
為何位元組表示方式如此重要
SHA-256 處理的是位元組而非字元。當你在文字欄位中輸入「héllo」並產生摘要時,工具會先將這些字元以 UTF-8 編碼,針對可見字詞產生五個位元組,帶腔調的 é 再多一個位元組,接著對這六個位元組計算摘要。同樣的字詞若貼到將輸入解讀為 Latin-1 的工具中,則只會對五個位元組計算摘要而回傳不同的值。檔案模式則完全避免此類模糊性:它會跳過文字解碼,直接對所有選取的位元組進行雜湊,包括隱藏的標頭位元組、嵌入的中繼資料,以及檔案實際包含的精確行結尾位元組(CR、LF 或 CRLF)。
在 JavaScript 專案中,數個細微的來源差異會反覆出現:
- 結尾換行。像是 echo "abc" 的 shell 指令通常會附加換行後再串接給雜湊工具,而貼上的字串通常不會。兩者摘要相差一個位元組。
- Unicode 標準化。部分字元具有多種有效的 UTF-8 序列。「é」的合成(NFC)與分解(NFD)形式會產生不同的位元組序列,因此摘要也不同。
- 編碼不一致。儲存為 Windows-1252 或 UTF-16 的檔案,相較於以 UTF-8 編碼的相同文字會包含不同的位元組。以錯誤的編碼進行雜湊,將產生與 UTF-8 參考值不同的結果。
- 位元組順序標記。檔案開頭的 UTF-8 BOM(EF BB BF)是一個真實的位元組。移除或保留它會改變摘要。
規則很簡單:保留精確的位元組,然後進行雜湊。若存在參考值,請從已知乾淨的輸入產生,或使用能同時回報位元組計數與摘要的工具將位元組從檔案中取出。空格、 carriage returns 以及最終的換行也是位元組,同樣會影響結果,請將空白字元視為有意義的內容。
安全地驗證摘要
相符的 SHA-256 摘要只有在期望值本身為可信來源時才具有意義。若攻擊者能同時替換下載的檔案與其旁顯示的檢查碼,重新計算 SHA-256 僅會確認攻擊者的那一對結果。請透過 HTTPS 從軟體擁有者、透過已簽署的發行清單,或透過其他適用於該風險層級且經驗證的管道取得參考雜湊,並在任何儲存的摘要旁一併記錄演算法名稱,避免日後將 64 字元的 SHA-256 值與其他格式或未記載的檢查碼混淆。
SHA-256 同樣無法驗證輸入的建立者身分。若兩個系統共享秘密並需要訊息驗證,正確的工具是 HMAC-SHA256,它會將秘密混入壓縮函式並能抵擋長度延伸攻擊。當驗證者必須使用公開金鑰確定來源時,則適合採用數位簽章。單純的 SHA-256 適用於完整性檢查、去重複化與建置流程檢查碼,但不適用於證明作者身分。
SHA-256 不是加密,也不是密碼雜湊
SHA-256 是一種單向函式:它不具備金鑰,也沒有支援的反向運算,因此無法還原原始輸入。它的執行速度也過快,不適合用於密碼儲存。這樣的速度正是它在完整性檢查時實用的原因,卻也讓攻擊者能在竊得的資料庫上每秒測試數十億組密碼猜測。帳號系統應為每位使用者使用唯一的隨機鹽值,並搭配經過校正記憶體與時間成本的專用密碼雜湊函式,例如 Argon2id、scrypt 或 bcrypt。若一開始就必須產生密碼,請使用由密碼學安全 RNG 支援的 密碼產生器,並將產生的結果與 密碼強度檢查工具 進行比對,而非以其 SHA-256 摘要的長度作為判斷依據。
如果你正在權衡各種選項,如何從文字或檔案建立 SHA-512 雜湊 一文有詳細說明。
<