Hash 的妙用
問題與答案 (FAQ)
Q&A 類別 A: 概念理解類
Q1: 什麼是雜湊(Hash)演算法?
- A簡: 將任意長度資料映射為固定長度摘要的單向函數。具決定性、固定長度、難逆向與抗碰撞等特性,常用於驗證、簽章與索引。
- A詳: 雜湊演算法是把任意長度輸入資料,經過數學運算,輸出固定長度的摘要(digest)。理想的特性包含:同樣輸入得到同樣輸出(決定性)、輸出長度固定、很難由輸出推回輸入(單向性)、難以找到不同輸入卻輸出相同值(碰撞困難),以及微小變動造成巨變輸出(雪崩效應)。應用於密碼儲存、檔案比對、數位簽章與資料防竄改等。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q2, A-Q4, B-Q1
Q2: 雜湊的核心特性有哪些?
- A簡: 決定性、固定長度、單向性、碰撞困難、雪崩效應。密碼學雜湊更要求前像與次前像抗性及抗碰撞強度。
- A詳: 核心特性包括:決定性(相同輸入得相同輸出)、固定長度(無論輸入多大,摘要長度不變)、單向性(無法有效由摘要還原原文)、碰撞困難(難找不同輸入同摘要)、雪崩效應(輸入微調導致輸出大變)。密碼學雜湊另要求前像抗性(給定摘要難找到原文)與次前像抗性(給定原文難找同摘要他文)。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q1, A-Q7, A-Q8
Q3: 為什麼需要雜湊演算法?
- A簡: 提供高效驗證與完整性保護:密碼儲存、檔案比對、數位簽章、訊息防竄改、去重索引等。
- A詳: 雜湊的固定長度與單向性,讓我們能安全地儲存密碼(存雜湊而非明文),快速判斷檔案是否相同(比對摘要),建立數位簽章的完整性基礎(先雜湊再簽),以及替對外暴露資訊加上防竄改保護(如 Cookie、URL 簽名)。在海量資料環境,雜湊也常用來建立索引與去重,降低儲存與比對成本。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q18, A-Q19, B-Q8
Q4: 雜湊與加密有何差異?
- A簡: 加密可逆需金鑰,雜湊不可逆無金鑰。加密確保機密性,雜湊確保完整性與身份驗證(配合 HMAC/簽章)。
- A詳: 加密透過金鑰把明文轉密文,授權者可用金鑰還原,目的在保密。雜湊將資料映射為固定長度摘要,過程不可逆,因此不能還原原文,主要用途是驗證內容是否被改、資料身份與一致性。當雜湊與祕密金鑰結合(HMAC)或與非對稱簽章結合,就能達成防竄改與身份驗證。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q16, A-Q17, B-Q19
Q5: 雜湊與檢查碼(CRC)差異是什麼?
- A簡: CRC偵測偶發錯誤,非對抗性;雜湊(密碼學)抵禦惡意偽造。安全需求用雜湊或 HMAC,不用 CRC。
- A詳: CRC 是線性演算法,擅長偵測傳輸或儲存中的偶發錯誤(位翻轉),但對攻擊者可被蓄意構造繞過。密碼學雜湊具抗碰撞與單向性,能抵禦刻意偽造與差異構造攻擊,適合安全用途。若需驗證訊息與身份,應用 HMAC 或數位簽章,而不是單純 CRC。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q1, A-Q16, B-Q14
Q6: 什麼是訊息摘要(Message Digest)?
- A簡: 訊息摘要即雜湊輸出,為固定長度字串,用來代表原始資料以進行比對與驗證。
- A詳: 訊息摘要是對資料套用雜湊演算法後得到的固定長度結果,又稱雜湊值、指紋。它壓縮資訊而保留完整性判斷能力,適用於檔案相等性比對、傳輸後驗證、簽章流程中的待簽內容等。常以十六進位或 Base64 編碼儲存或展示,便於人讀與傳輸。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q10, B-Q13, C-Q3
Q7: 什麼是碰撞(Collision)?
- A簡: 不同輸入產生相同雜湊值的情況。理想密碼學雜湊令刻意製造碰撞在計算上不可行。
- A詳: 因輸出長度固定、輸入無限,碰撞必然存在。安全重點在「計算困難度」:攻擊者不應能在合理時間內找到兩個不同輸入卻共享同一摘要。若碰撞易找,則可偽造文件或繞過相等性檢查,危及簽章與完整性機制。MD5、SHA-1 已不具足夠抗碰撞性。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q11, B-Q11, B-Q10
Q8: 什麼是前像抗性與次前像抗性?
- A簡: 前像抗性:難從摘要找原文。次前像抗性:難找與指定原文同摘要的另一輸入。
- A詳: 前像抗性(Preimage Resistance)確保給定摘要時,無法有效倒推出任何生成該摘要的原文。次前像抗性(Second Preimage)則是已知某原文時,難找到另一不同輸入卻有相同摘要。這兩者與抗碰撞性共同構成密碼學雜湊的三大安全性目標,支撐密碼儲存、簽章與防竄改方案。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q2, A-Q7, A-Q16
Q9: 什麼是雪崩效應(Avalanche effect)?
- A簡: 輸入一位微小變動,輸出摘要應有約半數位元翻轉,呈現高度不可預測。
- A詳: 雪崩效應保證雜湊對輸入變化高度敏感,避免攻擊者藉由輸出變化推測輸入結構。良好的雪崩效應帶來「看似隨機」的輸出分佈,有助均衡桶分佈、降低聚集。若雪崩表現差,容易出現偏差與結構性弱點,影響碰撞安全與索引品質。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q2, B-Q1, B-Q14
Q10: 常見雜湊演算法有哪些?
- A簡: MD5、SHA-1(過時)、SHA-2(SHA-256/512)、SHA-3(Keccak)。安全用途建議選 SHA-2/3。
- A詳: 歷史上常用 MD5、SHA-1,如今已被證實碰撞脆弱,不建議安全用途。現行主流為 SHA-2 家族(SHA-256、SHA-512 等)與標準化的 SHA-3(基於 Keccak 海綿結構)。選擇時考量安全等級、效能與硬體支援(如 SHA-NI),並依場景採 HMAC、Argon2、PBKDF2 等結合。
- 難度: 初級
- 學習階段: 核心
- 關聯概念: A-Q11, B-Q2, B-Q3
Q11: MD5 與 SHA-1 還能用嗎?
- A簡: 不適合安全敏感用途。僅可用於非對抗性場景(如重複檔案初篩),安全應換 SHA-256/HMAC。
- A詳: MD5、SHA-1 已有實用碰撞攻擊,能被刻意構造相同摘要,危及簽章、驗證與信任鏈。不建議用於任何需抗對手的完整性或身份檢驗。可在去重初步比對使用,但務必搭配更強雜湊或二次比對。安全場景改用 SHA-256/512 或 SHA-3,並配合 HMAC 或簽章。
- 難度: 初級
- 學習階段: 核心
- 關聯概念: A-Q7, A-Q10, B-Q11
Q12: SHA-256 與 SHA-512 有何差異?
- A簡: 摘要長度與安全邊際不同,SHA-512 在 64 位元硬體常更快;選擇依平台與需求。
- A詳: SHA-256 輸出 256 位元,碰撞安全邊際約 128 位;SHA-512 輸出 512 位元,碰撞邊際約 256 位。在 64 位元 CPU,SHA-512 常有更佳效能;在受限平台或相容需求,SHA-256 更通用。多數應用兩者皆足夠,重點在正確實作與 HMAC/簽章搭配。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q10, B-Q16, C-Q3
Q13: 什麼是鹽(Salt),為何要用在密碼雜湊?
- A簡: Salt 是每筆獨立隨機值,與密碼一起雜湊,防止彩虹表與同值密碼產生相同摘要。
- A詳: 使用者常重複密碼,單純雜湊易被彩虹表或事前計算攻擊破解。對每筆密碼加入獨立高熵隨機 salt(且儲存於資料庫),可破壞預計算攻擊,讓相同密碼因 salt 不同而產生不同摘要。配合延展演算法(如 PBKDF2、bcrypt、scrypt、Argon2)可顯著提高爆破成本。
- 難度: 初級
- 學習階段: 核心
- 關聯概念: A-Q15, C-Q4, C-Q5
Q14: 什麼是胡椒(Pepper),與 Salt 有何不同?
- A簡: Pepper 是服務端共用祕密,與 Salt 不同,Pepper 不存於資料庫而放於安全配置。
- A詳: Salt 是公開、每筆獨立的隨機值,阻擋預計算攻擊;Pepper 則是應用層的共用祕密,與密碼一起參與雜湊或 HMAC,增加攻擊者在獲得資料庫後仍需取得的材料。Pepper 應存於 HSM、環境變數或安全金鑰管理系統,並具輪替機制,防止資料洩露時全軍覆沒。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q13, C-Q9, B-Q19
Q15: 什麼是金鑰延展(Key Stretching)?
- A簡: 透過計算昂貴演算法(PBKDF2、bcrypt、scrypt、Argon2),放大密碼猜測成本,抵抗爆破。
- A詳: 使用者密碼熵低,攻擊者可用 GPU/ASIC 暴力破解。Key Stretching 將雜湊重複多輪或採記憶體硬成本計算,使每次猜測變慢變貴。PBKDF2 可調迭代次數;bcrypt 引入 cost 參數;scrypt、Argon2 增加記憶體需求,有效對抗並行化硬體。建議選 Argon2id 或 PBKDF2-SHA256。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q13, C-Q4, C-Q5
Q16: 什麼是 HMAC?為何比單純雜湊更安全?
- A簡: HMAC 用祕密金鑰與雜湊結合驗證訊息,能防竄改與偽造;單純雜湊無法驗證身份。
- A詳: HMAC(Keyed-Hash Message Authentication Code)將資料與金鑰經由內外層雜湊(ipad/opad)組合,產生驗證碼。接收端用同金鑰可重算比對,確保資料未被竄改且由持鍵者產生。與純雜湊不同,攻擊者不知道金鑰無法偽造同值。常用於 Cookie/URL 簽名與微服務請求驗證。
- 難度: 初級
- 學習階段: 核心
- 關聯概念: A-Q4, B-Q4, C-Q2
Q17: 數位簽章與雜湊的關係是什麼?
- A簡: 簽章先雜湊資料,再用私鑰簽摘要;驗章用公鑰驗證,確保完整性與不可否認。
- A詳: 直接簽整份資料成本高且脆弱,因此慣例先計算資料摘要,再用私鑰(RSA/ECDSA/EdDSA)對摘要簽章。驗證時,重算摘要並用公鑰驗章比對。雜湊提供完整性與固定長度,簽章提供來源認證與不可否認,是公鑰基礎設施(PKI)與檔案分發的關鍵組合。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q8, C-Q7, C-Q6
Q18: 如何用雜湊比對兩份檔案?
- A簡: 計算各自摘要(如 SHA-256),值相同高度可能相同;安全場景再做二次確認或用簽章。
- A詳: 以流式方式計算兩檔摘要,若雜湊相同,表示極高機率內容相同。實務中可先用速度較快的雜湊初篩,再以強雜湊或二進位逐位比對確認,避免碰撞風險。在非對抗性場景(去重、快取)足夠;若牽涉安全與信任,應搭配簽章或受信通道分發摘要。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: C-Q3, C-Q8, B-Q6
Q19: 如何用雜湊保護 Cookie 或 URL 不被竄改?
- A簡: 使用 HMAC 對資料與到期時間簽名,伺服端驗證簽章即可偵測竄改與控制有效期。
- A詳: 構造待簽字串(包含重要欄位與截止時間),以 HMAC-SHA256 搭配伺服端祕密金鑰產生簽名,附於 Cookie 或 URL。伺服端收到後重算簽名並檢查時戳與逾時。透過正規化參數順序、使用 URL-safe 編碼與常數時間比較,可抵禦竄改與時序攻擊。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q16, B-Q9, C-Q2
Q20: 身分證最後一碼檢查碼算是雜湊嗎?
- A簡: 它類似簡化檢查碼機制,可用作格式與錯誤檢查,但不具密碼學強度。
- A詳: 身分證檢查碼由前面字母與數字依規則計算,能偵測輸入錯誤或亂填,性質近似校驗碼或弱雜湊。它缺乏單向性與抗碰撞保障,容易被反推或偽造,因此不可用於安全敏感的完整性或身份驗證,僅適合基本格式校驗用途。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q5, A-Q1, B-Q14
Q&A 類別 B: 技術原理類
Q1: 雜湊函數高階運作原理是什麼?
- A簡: 將輸入分塊後經壓縮函數迭代處理與填充,最終產生固定長度摘要。需具單向與抗碰撞特性。
- A詳: 多數雜湊採分塊與迭代設計。流程:1) 對輸入做填充(含長度資訊);2) 以固定大小區塊餵入;3) 透過壓縮函數與內部狀態累積;4) 最終輸出固定長度摘要。經典架構如 Merkle–Damgård(SHA-2)與海綿結構(SHA-3)。核心組件包含:填充策略、常數表、輪函數與非線性混合。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q1, B-Q2, B-Q3
Q2: SHA-256 的執行流程為何?
- A簡: 將訊息填充成 512 位元塊,經 64 輪壓縮函數與訊息排程更新狀態,輸出 256 位元摘要。
- A詳: 流程:1) 附加 1 與 0 填充並附加長度;2) 分 512-bit 區塊;3) 為每塊建立 64 個 32-bit 字的訊息排程;4) 初始化 8 個工作變數;5) 進行 64 輪非線性混合(Ch、Maj、Σ 等)與常數加總;6) 將結果累加至鏈結狀態;7) 最終拼接輸出。核心組件:壓縮函數、常數表 K、初始向量 IV。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q12, B-Q10, C-Q3
Q3: SHA-3(Keccak)的海綿結構如何運作?
- A簡: 海綿結構交替吸收與擠出,內部以置換與非線性操作混合狀態,彈性輸出長度。
- A詳: Keccak 使用「海綿」架構:1) 吸收(Absorb):將輸入分塊 XOR 進狀態;2) 置換(Permute):多輪非線性轉換;3) 擠出(Squeeze):從狀態讀出輸出,必要時重複置換以延伸輸出。核心組件:狀態寬度、速率/容量參數、置換輪。其安全性取決於容量大小與置換設計。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: B-Q1, A-Q10, B-Q10
Q4: HMAC 的機制與步驟是什麼?
- A簡: 以金鑰與資料分別與 ipad/opad 混合,做內外層雜湊,產生驗證碼供接收端比對。
- A詳: 步驟:1) 規範化金鑰長度(過長先雜湊);2) k ⊕ ipad 與訊息串接做內層雜湊;3) k ⊕ opad 與內層結果串接做外層雜湊;4) 得到 HMAC。核心組件:底層雜湊(SHA-256/512)、ipad/opad 常數、共享祕鑰。設計可抵長度延展攻擊,適合訊息驗證與完整性保護。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q16, C-Q2, B-Q19
Q5: 密碼雜湊(含 Salt 與延展)的流程如何設計?
- A簡: 生成隨機 salt,使用 PBKDF2/bcrypt/scrypt/Argon2 以設定成本參數計算雜湊,保存參數+salt+雜湊。
- A詳: 步驟:1) 產生高熵 salt;2) 選擇演算法與成本(迭代數、記憶體、平行度);3) 雜湊密碼+salt(可含 pepper);4) 儲存格式化字串(版本、演算法、成本、salt、雜湊);5) 驗證時重建參數重算比較。核心組件:KDF(PBKDF2/Argon2)、CSPRNG、金鑰管理(pepper)。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q13, A-Q15, C-Q4
Q6: 檔案雜湊的串流與增量計算原理?
- A簡: 以固定大小緩衝逐塊讀取並更新雜湊狀態,節省記憶體並支援超大檔案。
- A詳: 雜湊 API 通常提供 update 接口,可反覆餵入資料塊。流程:1) 開檔;2) 以 64KB~1MB 讀取;3) 每塊呼叫 update;4) 完成後 digest。核心組件:緩衝大小、I/O 模式、雜湊上下文。增量計算可在資料流傳輸中並行驗證,避免一次載入全部檔案造成記憶體壓力。
- 難度: 初級
- 學習階段: 核心
- 關聯概念: C-Q1, C-Q3, C-Q8
Q7: 去重系統基於雜湊的架構如何設計?
- A簡: 建索引(hash→位置/Meta),命中後二次驗證,處理碰撞與版本,支援批量掃描與壓縮。
- A詳: 架構:1) 掃描檔案計算強雜湊(SHA-256);2) 在資料庫建立索引(hash→檔案清單/位置);3) 命中後進行二進位比對或第二雜湊確認;4) 併發處理與分段掃描;5) 碰撞風險管理與版本標記。核心組件:雜湊引擎、索引存儲、重複決策策略、任務排程。
- 難度: 中級
- 學習階段: 進階
- 關聯概念: A-Q18, C-Q8, D-Q9
Q8: 數位簽章(RSA/ECDSA)與雜湊的技術流程?
- A簡: 先雜湊,再用私鑰簽摘要;驗證端重算摘要用公鑰驗章,比對成功視為可信。
- A詳: 流程:1) Canonicalize 資料;2) 計算雜湊(SHA-256);3) 私鑰簽章(RSA-PSS/ECDSA);4) 傳遞資料+簽章;5) 驗證端重算雜湊並用公鑰驗章。核心組件:金鑰對、簽章演算法與填充、雜湊函數、時間戳。避免直接簽原文或混用演算法,以免驗證失敗。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q17, C-Q7, D-Q7
Q9: 用雜湊保護 Cookie/URL 的技術設計?
- A簡: 以 HMAC 對規範化的資料與到期時間簽名,伺服端用相同金鑰驗證,防竄改/重放。
- A詳: 重要步驟:1) 排序/正規化參數(避免等價不同字串);2) 加入到期時間與 nonce;3) HMAC-SHA256 生成簽名;4) 使用 URL-safe Base64;5) 驗證簽章、時間窗與重放。核心組件:金鑰管理、時間同步、常數時間比較、權限綁定(IP/UA)。避免使用裸雜湊或可被長度延展攻擊。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q19, C-Q2, D-Q4
Q10: 雜湊長度與安全位元的關係是?
- A簡: n 位元雜湊的碰撞安全約為 n/2 位元(生日界),前像安全約為 n 位元。
- A詳: 例如 SHA-256 的碰撞複雜度約 2^128,前像複雜度約 2^256。選擇摘要長度時,需滿足應用的安全壽命與攻擊者資源評估。對長期信任或高價值資產,選擇更長摘要(SHA-512/384)可提供更寬裕安全邊際,但也要兼顧效能與相容性。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q12, B-Q11, B-Q16
Q11: 生日攻擊如何影響碰撞安全?
- A簡: 生日悖論使得找到任意碰撞的期望成本為 2^(n/2),遠低於 2^n 的直覺。
- A詳: 在 n 位元雜湊,任意兩者碰撞的機率成對數成長。攻擊者可透過大量嘗試集合,期望於約 2^(n/2) 次試驗找到碰撞。這就是為何碰撞安全位元僅為摘要長度的一半。設計時需考慮此界限,避免選擇過短雜湊或在多方交互中累積風險。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: B-Q10, A-Q7, A-Q10
Q12: 為何雜湊前需資料正規化(Canonicalization)?
- A簡: 確保等價資料產生同一字串再雜湊,避免排序、空白、編碼差異導致驗證失敗。
- A詳: 輸入不同表示法(參數順序、大小寫、空白、Unicode 正規化、換行)會造成不同摘要。正規化把等價資料轉換為唯一表示:排序鍵值、修剪空白、規範大小寫、固定編碼(UTF-8)、一致換行(LF)、固定序列化(JSON Canonical Form)。這對 URL 簽名與跨語言一致性至關重要。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: C-Q2, D-Q1, D-Q4
Q13: 雜湊輸出常用編碼(Hex/Base64)差異?
- A簡: Hex 可讀性高但較長;Base64 較短但需小心 URL 安全版本。皆為表示法,非安全強度差異。
- A詳: 摘要本質為位元序列。十六進位每位代表 4 位元,易閱讀與比對;Base64 每字元 6 位元,較短更省空間。URL 場景常用 Base64URL(-_/不含=),跨語言需注意填充與大小寫。選擇編碼不改變雜湊安全強度,僅影響傳輸與相容性。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: C-Q2, C-Q3, D-Q8
Q14: 非密碼學雜湊(如 MurmurHash)適用在哪?
- A簡: 適合雜湊表分佈、分片與指紋初篩,不適合安全用途。抗碰撞不足。
- A詳: MurmurHash、xxHash 等追求速度與分佈,適用於資料結構(HashMap)、分散式分片、一致性哈希與去重初篩。它們缺乏密碼學強度,容易被惡意構造碰撞,導致 DOS 或安全繞過。安全場景應使用 HMAC 或 SHA-2/3。選擇依威脅模型決定。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q5, B-Q1, D-Q6
Q15: 什麼是滾動雜湊(Rolling Hash)?
- A簡: 可快速更新視窗雜湊值的演算法,用於字串搜尋、差異同步與內容定界。
- A詳: 滾動雜湊能在移動視窗時以 O(1) 更新,例如 Rabin-Karp 比對透過刪除舊字元貢獻、加入新字元計算新值。應用於 rsync、內容定界去重(CDC)。但它不具密碼學安全,僅適合演算法加速與資料處理,安全驗證需另用強雜湊或 HMAC。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: B-Q6, B-Q7, A-Q5
Q16: 如何選擇 SHA-256 或 SHA-512?
- A簡: 依平台與安全邊際。64 位元平台常 SHA-512 較快;相容性與通用性多選 SHA-256。
- A詳: 若目標平台有 SHA-NI/64 位元優化,SHA-512 在吞吐與能效上可能佔優;行動或嵌入式平台則視硬體而定。安全需求多數場景兩者足夠,關鍵在正確設計(HMAC、正規化、常數時間比較)與端到端部署。也可選 SHA-512/256 取得較短輸出與 512 內核效益。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q12, B-Q10, C-Q3
Q17: 雜湊的效能優化與硬體加速有哪些?
- A簡: 使用最佳化函式庫(OpenSSL、libsodium)、CPU 指令(SHA-NI)、並行與零拷貝 I/O。
- A詳: 選擇經過硬體優化的實作(OpenSSL、BoringSSL、libsodium),利用 CPU 指令集(SHA-NI、ARMv8 SHA),並行處理多檔案、採流式與大緩衝讀取,減少系統呼叫。對 GPU/FPGA/ASIC 的支援則多用於研究或密碼猜測,安全系統應提升 KDF 成本抵抗此類加速。
- 難度: 中級
- 學習階段: 進階
- 關聯概念: B-Q6, D-Q6, C-Q8
Q18: Unicode 與換行符如何影響雜湊一致性?
- A簡: 編碼、正規化(NFC/NFD)、BOM 與 CRLF/LF 差異會導致不同摘要,需要規範。
- A詳: 同樣文字在不同平台/語言可能採不同 Unicode 正規化或含 BOM,文字檔換行有 CRLF(Windows)與 LF(Unix)差異。雜湊前應明確規範:採 UTF-8、移除 BOM、Normalize 至 NFC、統一 LF、固定序列化。跨語言處理時,避免隱式字串→位元組轉換。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q12, D-Q1, C-Q1
Q19: Hash、HMAC 與簽章在安全性上的界線?
- A簡: Hash 確認完整性;HMAC 驗證完整性與共享祕密身份;簽章提供公鑰身份與不可否認。
- A詳: 單純雜湊只能驗證資料是否改變,無法驗證誰產生。HMAC 在共享祕鑰模式下抵禦竄改與偽造,但無法區分雙方。數位簽章使用非對稱金鑰,第三方可驗證來源與不可否認。選擇取決於信任模型:同組織內服務間建議 HMAC,跨組織或公開驗證需簽章。
- 難度: 初級
- 學習階段: 核心
- 關聯概念: A-Q4, A-Q16, A-Q17
Q20: URL 簽名的時間窗與防重放如何設計?
- A簡: 簽名中加入到期時間與 nonce,伺服端檢查時間窗並記錄已用 nonce 拒絕重放。
- A詳: 設計要點:1) 字串含 expires(Unix time)與 nonce;2) 短時間窗(如 5 分鐘);3) 伺服端保存近期 nonce(LRU/布隆過濾器);4) 檢查時間偏移與時鐘同步;5) 綁定重要欄位(方法、路徑、身分)。這樣可有效降低截獲重放與長期有效風險。
- 難度: 中級
- 學習階段: 進階
- 關聯概念: B-Q9, D-Q10, C-Q10
Q&A 類別 C: 實作應用類(10題)
Q1: 如何用 Python 計算字串與檔案的 SHA-256?
- A簡: 使用 hashlib 計算字串/串流檔案雜湊。注意統一編碼與分塊讀取大檔。
- A詳:
- 實作步驟: 安裝 Python3;對字串使用 UTF-8 編碼;對檔案以 1MB 分塊讀取更新雜湊。
- 程式碼:
- 字串: import hashlib; hashlib.sha256(“msg”.encode(“utf-8”)).hexdigest()
- 檔案: import hashlib h=hashlib.sha256() with open(“file”,”rb”) as f: for b in iter(lambda:f.read(1«20), b””): h.update(b) print(h.hexdigest())
- 注意事項: 固定編碼 UTF-8;避免一次載入大檔;比對用常數時間比較;必要時用 SHA-512。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q6, D-Q1, C-Q3
Q2: 如何在 Node.js 產生並驗證 URL 的 HMAC-SHA256 簽名?
- A簡: 以金鑰對正規化字串簽名並附加到期時間;伺服端重算 HMAC 驗證與檢查時間窗。
- A詳:
- 步驟: 1) 排序查詢參數;2) 串接方法/路徑/參數/expires;3) crypto.createHmac(“sha256”, key).update(str).digest(“base64url”);4) 驗證端重算比對與檢查 expires。
- 程式碼: const crypto=require(“crypto”); function sign(method,path,params,exp,key){ const q=new URLSearchParams(params); q.sort(); const s=[method.toUpperCase(),path,q.toString(),exp].join(“\n”); return crypto.createHmac(“sha256”,key).update(s).digest(“base64url”); }
- 注意: 使用 Base64URL;常數時間比較;伺服端與客戶端時鐘同步;加上 nonce 防重放。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q9, B-Q12, D-Q4
Q3: 如何用命令列計算並驗證檔案雜湊?
- A簡: 使用 sha256sum 或 openssl dgst 產生與比對摘要;發布時附檔名 .sha256 檔。
- A詳:
- 步驟: 1) 產生: sha256sum file > file.sha256;2) 驗證: sha256sum -c file.sha256;或 openssl dgst -sha256 file。
- 範例: 產生: sha256sum my.iso > my.iso.sha256 驗證: sha256sum -c my.iso.sha256
- 注意: 保護 .sha256 檔取得管道(TLS/簽章);Windows 可用 CertUtil 或 PowerShell Get-FileHash;發布關鍵檔案建議同時提供簽章(.sig)。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q6, C-Q6, D-Q9
Q4: 如何用 Python Argon2 安全儲存與驗證密碼?
- A簡: 使用 argon2-cffi 生成含參數的雜湊字串,驗證時用 verify 比對。調整記憶體/迭代成本。
- A詳:
- 步驟: pip install argon2-cffi;使用 PasswordHasher 設定 time_cost、memory_cost、parallelism;儲存回傳的雜湊字串。
- 程式碼: from argon2 import PasswordHasher ph=PasswordHasher(time_cost=3, memory_cost=65536, parallelism=2) h=ph.hash(“P@ssw0rd!”) ph.verify(h, “P@ssw0rd!”)
- 注意: 捕捉 VerifyMismatchError;定期調升成本;加入伺服端 pepper(不入庫);禁止自訂鹽來源,交由庫生成。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q13, A-Q15, D-Q2
Q5: 如何用 Node.js PBKDF2-SHA256 雜湊與驗證密碼?
- A簡: 以隨機 salt 與足夠迭代數產生雜湊,存格式化字串;驗證時重建參數重算比對。
- A詳:
- 程式碼:
const crypto=require(“crypto”);
function hash(pw){
const salt=crypto.randomBytes(16);
const it=200000, dk=32;
const h=crypto.pbkdf2Sync(pw,salt,it,”sha256”,dk);
return
pbkdf2$sha256$${it}$${salt.toString("hex")}$${h.toString("hex")}; } function verify(pw, rec){ const [, , algo, it, s, d]=rec.split(“$”); const salt=Buffer.from(s,”hex”); const h=crypto.pbkdf2Sync(pw,salt,parseInt(it),”sha256”,32); return crypto.timingSafeEqual(h, Buffer.from(d,”hex”)); } - 注意: 迭代數≥100k 依硬體調整;常數時間比較;儲存版本欄位便於日後升級。
- 程式碼:
const crypto=require(“crypto”);
function hash(pw){
const salt=crypto.randomBytes(16);
const it=200000, dk=32;
const h=crypto.pbkdf2Sync(pw,salt,it,”sha256”,dk);
return
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q15, D-Q2, C-Q9
Q6: 如何建立檔案下載的完整性驗證(雜湊+簽章)?
- A簡: 發布 SHA-256 清單並用私鑰簽章;客戶端先驗簽清單,再檢查檔案雜湊。
- A詳:
- 步驟: 1) 產生 hashes.txt(檔名=摘要);2) 用 GPG/RSA 對清單簽章生成 .sig;3) 客戶端下載清單與簽章,先驗簽,再核對檔案摘要。
- 指令: sha256sum *.tar.gz > hashes.txt;gpg –sign hashes.txt
- 注意: 僅有雜湊不足,需信任來源;簽章公鑰需透過可信通道分發;處理鏡像站同步延遲。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q17, C-Q3, D-Q9
Q7: 如何用 Python cryptography 實作 RSA 簽章與驗證?
- A簡: 對資料雜湊並用私鑰 RSA-PSS 簽章,公鑰驗證。注意填充與雜湊一致。
- A詳:
- 程式碼: from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding sig=priv.sign(data, padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH), hashes.SHA256()) pub.verify(sig, data, padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH), hashes.SHA256())
- 步驟: 載入金鑰、規範化資料、選 SHA-256、簽章/驗章。
- 注意: 不混用 PSS 與 PKCS#1 v1.5;資料要一致序列化;處理例外並回報。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q8, D-Q7, C-Q6
Q8: 如何寫一個檔案去重小工具(Python)?
- A簡: 掃描檔案計算 SHA-256,命中雜湊再做位元比對確認,輸出重複組。
- A詳:
- 程式碼概要: import os,hashlib,filecmp m={} for root,_,files in os.walk(“root”): for fn in files: p=os.path.join(root,fn); h=hashlib.sha256(open(p,”rb”).read()).hexdigest() m.setdefault(h,[]).append(p) for k,v in m.items(): if len(v)>1: g=[v[0]]+[p for p in v[1:] if filecmp.cmp(v[0],p,shallow=False)] if len(g)>1: print(“dup:”,g)
- 注意: 大檔用串流;可先用檔案大小初篩;命中後必做二進位比對以防碰撞;多執行緒提升效能。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q7, D-Q3, D-Q6
Q9: 如何實作防竄改 Cookie(HMAC + 過期)?
- A簡: 將資料與 expires 序列化後以 HMAC 簽名,Set-Cookie 時一併附上;驗證時重算比對。
- A詳:
- Node/Express 範例:
const val=JSON.stringify({uid:123,exp:Date.now()+300000});
const sig=crypto.createHmac(“sha256”,key).update(val).digest(“base64url”);
res.cookie(“sess”,
${val}.${sig}, { httpOnly:true, secure:true, sameSite:”Lax” }); - 驗證: 拆分 val 與 sig,重算 HMAC,檢查 exp。
- 注意: 使用 httpOnly/secure;資料最小化;簽名先於加密(若有);金鑰輪替機制。
- Node/Express 範例:
const val=JSON.stringify({uid:123,exp:Date.now()+300000});
const sig=crypto.createHmac(“sha256”,key).update(val).digest(“base64url”);
res.cookie(“sess”,
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q19, B-Q9, D-Q5
Q10: 如何為微服務請求加上簽名(HMAC + 時戳 + Nonce)?
- A簡: 客戶端在標頭附上 keyId、ts、nonce 與簽名;伺服端重算並檢查時間窗與重放。
- A詳:
- 共同字串: METHOD\nPATH\nQuery\nBodyHash\nkeyId\nts\nnonce
- 產生簽名: HMAC-SHA256(Base64URL)
- 伺服端: 取出 keyId 取得金鑰→重算→常數時間比較→檢查 ts 在 300 秒內→nonce 未用過。
- 注意: 正規化 Body(JSON Canonical);金鑰管理與輪替;記錄 nonce(短期 TTL)。
- 難度: 中級
- 學習階段: 進階
- 關聯概念: B-Q20, D-Q10, B-Q12
Q&A 類別 D: 問題解決類(10題)
Q1: 計算雜湊在不同環境結果不一致怎麼辦?
- A簡: 檢查編碼、換行、BOM 與序列化差異;統一 UTF-8、LF 與 Canonical JSON 後重算。
- A詳:
- 症狀: 相同資料跨語言/平台雜湊不同。
- 可能原因: 字串編碼不同、Unicode 正規化差異、CRLF/LF、BOM、參數排序不同。
- 解決步驟: 固定 UTF-8;Normalize=NFC;換行統一 LF;去 BOM;參數排序;固定序列化。
- 預防: 訂定跨服務 canonical 規範,寫入測試與工具檢查。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q12, B-Q18, C-Q2
Q2: 密碼驗證總是失敗如何診斷?
- A簡: 確認保存了 salt 與參數,驗證重建相同 KDF,避免不同編碼或剪裁雜湊值。
- A詳:
- 症狀: 使用者輸入正確密碼卻無法登入。
- 原因: 遺失 salt/迭代數、字串編碼不符、使用不同 KDF、十六進位/Base64 混用。
- 解法: 儲存格式化紀錄(演算法、成本、salt、hash);驗證時重建;統一編碼;常數時間比較。
- 預防: 採用成熟庫(Argon2/PBKDF2)與版本欄位;寫整合測試。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: C-Q4, C-Q5, A-Q13
Q3: 使用 MD5 導致資料被偽造或誤判相同怎麼辦?
- A簡: 立即改用 SHA-256/HMAC;對舊資料復核並加入二次比對或重新雜湊。
- A詳:
- 症狀: 發現碰撞案例或重複檔案誤判。
- 原因: MD5 抗碰撞不足,可被構造同摘要。
- 解法: 轉換至 SHA-256/512;去重系統命中後做位元比對;安全驗證改 HMAC/簽章。
- 預防: 安全場景禁用 MD5/SHA-1;定期安全審查與相依庫檢測。
- 難度: 初級
- 學習階段: 核心
- 關聯概念: A-Q11, B-Q11, C-Q8
Q4: URL 簽名偶發驗證失敗怎處理?
- A簡: 檢查參數排序、編碼、空白與時鐘;統一 canonical 字串並設置合理時間窗。
- A詳:
- 症狀: 同請求有時成功有時失敗。
- 原因: 參數順序不一致、URL 編碼差異、空白/大小寫、時鐘不同步、使用 Base64 與 Base64URL 混淆。
- 解法: 固定排序與編碼;雙方使用 Base64URL;比對前常數時間;同步 NTP。
- 預防: 封裝簽名中介層與相容測試向量。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q12, C-Q2, B-Q20
Q5: Cookie 被竄改卻未偵測,原因是什麼?
- A簡: 只用裸雜湊或可推算簽名。改用 HMAC 並管理金鑰與到期機制。
- A詳:
- 症狀: 攻擊者修改 Cookie 值仍通過驗證。
- 原因: 使用裸雜湊、可預測簽名、無到期/綁定欄位、弱金鑰。
- 解法: 改 HMAC-SHA256;簽名含到期與關鍵欄位;常數時間比較。
- 預防: 金鑰輪替、縮短有效期、httpOnly/secure/sameSite。
- 難度: 初級
- 學習階段: 核心
- 關聯概念: A-Q16, C-Q9, B-Q9
Q6: 大量檔案雜湊效能不佳的原因?
- A簡: I/O 瓶頸、過小緩衝、單執行緒與未使用最佳化庫。需並行與硬體加速。
- A詳:
- 症狀: 批次掃描耗時。
- 原因: 磁碟 I/O 限制、緩衝設定不當、缺少多工、使用慢速實作。
- 解法: 並行處理、增大讀取緩衝、批次 I/O、使用 OpenSSL/SHA-NI。
- 預防: 基準測試、監視 I/O 與 CPU、合理分片與快取策略。
- 難度: 中級
- 學習階段: 進階
- 關聯概念: B-Q6, B-Q17, C-Q8
Q7: 數位簽章驗證常報錯如何排查?
- A簡: 比對演算法與填充是否一致、資料序列化一致、公私鑰是否匹配。
- A詳:
- 症狀: verify 失敗或格式錯誤。
- 原因: 使用不同填充(PSS vs PKCS#1 v1.5)、雜湊不一致、資料 canonical 不同、金鑰不匹配。
- 解法: 兩端統一算法與參數;固定序列化;校驗金鑰指紋。
- 預防: 明確 API 契約與測試向量;金鑰管理流程。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q8, C-Q7, B-Q12
Q8: 雜湊儲存長度不一致或比對失敗?
- A簡: 檢查 Hex/Base64 表示法、大小寫、是否截斷。統一格式與比較方式。
- A詳:
- 症狀: 同值不同長度或比對不相等。
- 原因: 混用大小寫 Hex、Base64/URL 變體、去掉填充、截斷長度不同。
- 解法: 規範儲存一種表示(建議 Base16 小寫);比較前轉回位元組並常數時間比較。
- 預防: 契約化欄位與驗證器;資料庫欄位長度足夠。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q13, C-Q2, C-Q3
Q9: 檔案完整性驗證的 TOCTOU 風險如何避免?
- A簡: 驗證後檔案可能被換包。採用原子移動、封存與再次驗證。
- A詳:
- 症狀: 驗證通過但後續使用出現異常。
- 原因: 驗證與使用之間檔案被替換(TOCTOU)。
- 解法: 驗證於臨時目錄→原子 rename 到最終位置;使用前再次校驗;唯讀權限。
- 預防: 使用簽章清單;最終讀取時校驗;限制寫入者。
- 難度: 中級
- 學習階段: 進階
- 關聯概念: C-Q3, C-Q6, B-Q7
Q10: 微服務簽名遭重放攻擊如何防禦?
- A簡: 在簽名中加入時戳與 nonce,伺服端保存短期使用記錄並檢查時間窗。
- A詳:
- 症狀: 攻擊者複製合法請求重送仍通過。
- 原因: 簽名不含時間與唯一性、伺服端未記錄。
- 解法: 簽名含 ts 與 nonce;時間窗 5 分鐘;伺服端記錄已用 nonce;綁定身分/IP。
- 預防: 同步 NTP;觀測與告警;金鑰輪替。
- 難度: 中級
- 學習階段: 進階
- 關聯概念: B-Q20, C-Q10, B-Q9
學習路徑索引
- 初學者:建議先學習哪 15 題
- A-Q1: 什麼是雜湊(Hash)演算法?
- A-Q2: 雜湊的核心特性有哪些?
- A-Q3: 為什麼需要雜湊演算法?
- A-Q4: 雜湊與加密有何差異?
- A-Q5: 雜湊與檢查碼(CRC)差異是什麼?
- A-Q6: 什麼是訊息摘要(Message Digest)?
- A-Q10: 常見雜湊演算法有哪些?
- A-Q11: MD5 與 SHA-1 還能用嗎?
- A-Q12: SHA-256 與 SHA-512 有何差異?
- A-Q18: 如何用雜湊比對兩份檔案?
- C-Q1: 如何用 Python 計算字串與檔案的 SHA-256?
- C-Q3: 如何用命令列計算並驗證檔案雜湊?
- D-Q1: 計算雜湊在不同環境結果不一致怎麼辦?
- D-Q3: 使用 MD5 導致資料被偽造或誤判相同怎麼辦?
- A-Q20: 身分證最後一碼檢查碼算是雜湊嗎?
- 中級者:建議學習哪 20 題
- A-Q7: 什麼是碰撞(Collision)?
- A-Q8: 什麼是前像抗性與次前像抗性?
- A-Q9: 什麼是雪崩效應(Avalanche effect)?
- A-Q13: 什麼是鹽(Salt),為何要用在密碼雜湊?
- A-Q15: 什麼是金鑰延展(Key Stretching)?
- A-Q16: 什麼是 HMAC?為何比單純雜湊更安全?
- A-Q17: 數位簽章與雜湊的關係是什麼?
- B-Q1: 雜湊函數高階運作原理是什麼?
- B-Q2: SHA-256 的執行流程為何?
- B-Q4: HMAC 的機制與步驟是什麼?
- B-Q6: 檔案雜湊的串流與增量計算原理?
- B-Q12: 為何雜湊前需資料正規化?
- B-Q13: 雜湊輸出常用編碼差異?
- C-Q2: 如何在 Node.js 產生並驗證 URL 的 HMAC-SHA256 簽名?
- C-Q4: 如何用 Python Argon2 安全儲存與驗證密碼?
- C-Q5: 如何用 Node.js PBKDF2-SHA256 雜湊與驗證密碼?
- C-Q6: 如何建立檔案下載的完整性驗證(雜湊+簽章)?
- D-Q2: 密碼驗證總是失敗如何診斷?
- D-Q4: URL 簽名偶發驗證失敗怎處理?
- D-Q5: Cookie 被竄改卻未偵測,原因是什麼?
- 高級者:建議關注哪 15 題
- B-Q3: SHA-3(Keccak)的海綿結構如何運作?
- B-Q7: 去重系統基於雜湊的架構如何設計?
- B-Q8: 數位簽章(RSA/ECDSA)與雜湊的技術流程?
- B-Q10: 雜湊長度與安全位元的關係是?
- B-Q11: 生日攻擊如何影響碰撞安全?
- B-Q15: 什麼是滾動雜湊(Rolling Hash)?
- B-Q16: 如何選擇 SHA-256 或 SHA-512?
- B-Q17: 雜湊的效能優化與硬體加速有哪些?
- B-Q19: Hash、HMAC 與簽章在安全性上的界線?
- B-Q20: URL 簽名的時間窗與防重放如何設計?
- C-Q7: 如何用 Python cryptography 實作 RSA 簽章與驗證?
- C-Q8: 如何寫一個檔案去重小工具(Python)?
- C-Q10: 如何為微服務請求加上簽名(HMAC + 時戳 + Nonce)?
- D-Q6: 大量檔案雜湊效能不佳的原因?
- D-Q9: 檔案完整性驗證的 TOCTOU 風險如何避免?