Hash 與加密技術完全指南

深入理解 Hash 雜湊函數、對稱加密與非對稱加密的原理、常見演算法與實務應用


目錄

  1. 概念總覽
  2. Hash 雜湊函數
  3. 對稱式加密
  4. 非對稱式加密
  5. 三種技術比較
  6. 實戰應用場景
  7. 常見問題
  8. 總結

概念總覽

三者的根本差異

特性 Hash 雜湊 對稱加密 非對稱加密
轉換方向 單向(不可還原) 雙向可逆 雙向可逆
可逆性 ❌ 不可逆 ✅ 可逆 ✅ 可逆
金鑰數量 無需金鑰 1 把(加解密同鑰) 2 把(公鑰/私鑰)
運算速度 慢(100-1000x)
輸出長度 固定 與輸入相關 與輸入相關
主要用途 驗證、指紋 資料加密 金鑰交換、數位簽章
運作流程 明文 → Hash 值 明文 ⇄ 密文(同鑰) 明文 ⇄ 密文(公私鑰)
常見演算法 SHA-256、SHA-3、bcrypt、Argon2 AES、ChaCha20、3DES RSA、ECC、Ed25519

Hash 雜湊函數

什麼是 Hash?

Hash(雜湊) 是一種將任意長度的輸入資料,轉換為固定長度輸出的單向函數。

任意長度輸入           Hash 函數           固定長度輸出
─────────────        ──────────          ─────────────
"Hello"         →    SHA-256    →    2cf24dba5fb0a30e...(64 字元)
"Hello World"   →    SHA-256    →    a591a6d40bf420404...(64 字元)
1GB 檔案        →    SHA-256    →    7d865e959b2466918...(64 字元)

Hash 的核心特性

特性 說明 範例
單向性 無法從 Hash 值反推原始資料 Hash(明文) → Hash 值
Hash 值 → 明文
確定性 相同輸入永遠產生相同輸出 Hash("abc") 永遠相同
雪崩效應 輸入微小變化造成輸出巨大差異 "abc" vs "abd" 的 Hash 完全不同
抗碰撞性 難以找到兩個不同輸入產生相同輸出 很難找到 Hash(A) = Hash(B)A ≠ B
固定長度 無論輸入多長,輸出長度固定 SHA-256 永遠輸出 256 bits

雪崩效應示範

# 只差一個字元,Hash 完全不同
echo -n "hello" | sha256sum
# 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

echo -n "hallo" | sha256sum
# d3751d33f9cd5049c4af2b462735457e4d3baf130bcbb87f389e349fbaeb20b9

常見 Hash 演算法

1. MD5(已不安全)

項目 說明
全名 Message Digest 5
輸出長度 128 bits(32 字元十六進位)
狀態 ⚠️ 已被破解,不建議用於安全用途
用途 檔案校驗(非安全場景)
echo -n "hello" | md5sum
# 5d41402abc4b2a76b9719d911017c592

2. SHA-1(已不安全)

項目 說明
全名 Secure Hash Algorithm 1
輸出長度 160 bits(40 字元十六進位)
狀態 ⚠️ 2017 年被 Google 實現碰撞攻擊
用途 Git commit ID(歷史原因)
echo -n "hello" | sha1sum
# aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d

3. SHA-2 系列(目前標準)

變體 輸出長度 十六進位字元數 安全性
SHA-224 224 bits 56 字元 ✅ 安全
SHA-256 256 bits 64 字元 ✅ 推薦
SHA-384 384 bits 96 字元 ✅ 安全
SHA-512 512 bits 128 字元 ✅ 最安全
# SHA-256(最常用)
echo -n "hello" | sha256sum
# 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

# SHA-512
echo -n "hello" | sha512sum
# 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043

4. SHA-3(最新標準)

項目 說明
全名 Secure Hash Algorithm 3(Keccak)
特點 完全不同於 SHA-2 的設計,更高安全性
變體 SHA3-224, SHA3-256, SHA3-384, SHA3-512
狀態 ✅ NIST 標準(2015 年發布)
# 需要安裝支援 SHA-3 的工具
echo -n "hello" | openssl dgst -sha3-256

密碼專用 Hash 演算法

一般 Hash 太快,容易被暴力破解密碼。密碼專用 Hash 特意設計成慢速。

bcrypt

項目 說明
特點 內建 salt、可調整運算成本(work factor)
輸出格式 $2b$成本$salt+hash
推薦用途 密碼儲存
$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/X4beS6pN8wBMxAnWu
 │  │  │
 │  │  └── Salt + Hash 值
 │  └───── 成本因子(2^12 = 4096 次迭代)
 └──────── 演算法版本

scrypt

項目 說明
特點 記憶體密集型,抵抗 GPU/ASIC 攻擊
參數 N(CPU 成本)、r(記憶體成本)、p(平行度)
推薦用途 密碼儲存、加密貨幣

Argon2(目前最佳)

項目 說明
特點 2015 年密碼雜湊競賽冠軍
變體 Argon2d(抗 GPU)、Argon2i(抗側通道)、Argon2id(混合)
推薦 目前密碼儲存的首選
變體比較:
Argon2d  - 資料相依,最強抗 GPU,可能有側通道風險
Argon2i  - 資料無關,抗側通道攻擊,適合金鑰推導
Argon2id - 混合模式,推薦用於密碼儲存

Hash 演算法比較表

演算法 輸出長度 速度 安全性 推薦用途
MD5 128 bit 極快 ❌ 已破解 非安全校驗
SHA-1 160 bit 很快 ❌ 已破解 不建議使用
SHA-256 256 bit ✅ 安全 通用 Hash
SHA-512 512 bit ✅ 安全 高安全需求
SHA-3 可變 中等 ✅ 最安全 未來標準
bcrypt 184 bit ✅ 安全 密碼儲存
scrypt 可變 ✅ 安全 密碼/加密貨幣
Argon2 可變 ✅ 最佳 密碼儲存首選

Hash 的應用場景

┌────────────────────────────────────────────────────────────┐
│                    Hash 應用場景                            │
├────────────────────────────────────────────────────────────┤
│                                                            │
│  1. 密碼儲存                                                │
│     ────────                                               │
│     使用者密碼 → bcrypt/Argon2 → 儲存 Hash                   │
│     登入驗證:輸入密碼 → Hash → 比對儲存的 Hash                 │
│                                                            │
│  2. 資料完整性                                               │
│     ────────────                                           │
│     檔案下載驗證:比對 SHA-256 checksum                       │
│     Git commit:SHA-1 作為 commit ID                        │
│                                                            │
│  3. 數位簽章                                                │
│     ────────                                               │
│     訊息 → Hash → 用私鑰加密 Hash → 數位簽章                   │
│                                                            │
│  4. 區塊鏈                                                  │
│     ──────                                                 │
│     交易資料 → Hash → 區塊 → Hash → 鏈結                     │
│                                                            │
│  5. 快取鍵                                                  │
│     ──────                                                 │
│     URL/參數 → Hash → 作為快取的 key                         │
│                                                            │
└────────────────────────────────────────────────────────────┘

對稱式加密

什麼是對稱式加密?

對稱式加密使用同一把金鑰進行加密和解密。

加密:明文 + 金鑰 K → 密文
解密:密文 + 金鑰 K → 明文

(加密和解密使用同一把金鑰)

對稱加密的特點

優點 缺點
✅ 運算速度快 ❌ 金鑰分發問題
✅ 適合大量資料加密 ❌ 金鑰管理困難
✅ 實作相對簡單 ❌ 無法確認身份

常見對稱加密演算法

1. DES(已淘汰)

項目 說明
全名 Data Encryption Standard
金鑰長度 56 bits
區塊大小 64 bits
狀態 ❌ 已被暴力破解,不要使用

2. 3DES(逐漸淘汰)

項目 說明
全名 Triple DES
金鑰長度 112 或 168 bits
原理 DES 執行三次(加密→解密→加密)
狀態 ⚠️ 逐漸被 AES 取代
3DES 流程:
明文 → DES 加密(K1) → DES 解密(K2) → DES 加密(K3) → 密文

3. AES(目前標準)

項目 說明
全名 Advanced Encryption Standard
金鑰長度 128 / 192 / 256 bits
區塊大小 128 bits
狀態 目前的業界標準
AES 變體:
├── AES-128:10 輪加密,適合一般用途
├── AES-192:12 輪加密,中等安全需求
└── AES-256:14 輪加密,最高安全需求(政府/軍事級)

4. ChaCha20

項目 說明
特點 串流加密、無需硬體加速也很快
金鑰長度 256 bits
狀態 ✅ Google 推薦,用於 TLS 1.3
優勢 軟體實作效能優於 AES

加密模式(Block Cipher Modes)

區塊加密需要搭配加密模式來處理超過一個區塊的資料。

ECB(電子密碼本模式)- 不安全

明文區塊1 → 加密 → 密文區塊1
明文區塊2 → 加密 → 密文區塊2
明文區塊3 → 加密 → 密文區塊3

問題:相同明文區塊產生相同密文,洩漏資料模式

著名案例:ECB 企鵝

原圖的企鵝輪廓在 ECB 加密後仍可辨識,因為相同顏色區塊加密後相同

CBC(密碼區塊鏈結模式)

IV ──────┐
明文1 → XOR → 加密 → 密文1 ──┐
明文2 ─────→ XOR → 加密 → 密文2 ──┐
明文3 ──────→ XOR → 加密 → 密文3

特點:每個區塊依賴前一個密文,需要 IV(初始向量)

CTR(計數器模式)

Nonce + Counter1 → 加密 → XOR ← 明文1 → 密文1
Nonce + Counter2 → 加密 → XOR ← 明文2 → 密文2
Nonce + Counter3 → 加密 → XOR ← 明文3 → 密文3

特點:可平行處理、不需要 padding

GCM(Galois/Counter Mode)- 推薦

CTR 模式加密 + 認證標籤(Authentication Tag)

特點:
✅ 同時提供加密和完整性驗證
✅ 可偵測資料被竄改
✅ TLS 1.2/1.3 的預設模式

加密模式比較

模式 平行處理 需要 IV 認證 推薦度
ECB ❌ 不要用
CBC ⚠️ 可用
CTR ⚠️ 可用
GCM 推薦

對稱加密程式碼範例

Python(使用 cryptography 套件)

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

# 生成金鑰(256 bits)
key = AESGCM.generate_key(bit_length=256)

# 加密
aesgcm = AESGCM(key)
nonce = os.urandom(12)  # GCM 建議 96 bits nonce
plaintext = b"Hello, World!"
associated_data = b"header"  # 可選的額外認證資料

ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data)

# 解密
decrypted = aesgcm.decrypt(nonce, ciphertext, associated_data)
print(decrypted)  # b"Hello, World!"

OpenSSL 命令列

# AES-256-GCM 加密
openssl enc -aes-256-gcm -salt -in plaintext.txt -out encrypted.bin -pass pass:mypassword

# AES-256-GCM 解密
openssl enc -aes-256-gcm -d -in encrypted.bin -out decrypted.txt -pass pass:mypassword

非對稱式加密

什麼是非對稱式加密?

非對稱式加密使用一對金鑰:公鑰(public key)和私鑰(private key)。

        公鑰加密                    私鑰解密
        ────────                    ────────
明文 ─────────────→ 密文 ─────────────→ 明文
         │                    │
         │ 公鑰(任何人可持有)│ 私鑰(僅持有者可用)
         └────────────────────┘

數學關係:
公鑰加密的內容 → 只有對應的私鑰能解密
私鑰簽署的內容 → 任何人可用公鑰驗證

兩種使用方式

1. 加密通訊(Encryption)
   ─────────────────────
   發送方用「接收方的公鑰」加密
   接收方用「自己的私鑰」解密

   目的:確保只有接收方能讀取

2. 數位簽章(Digital Signature)
   ─────────────────────────
   發送方用「自己的私鑰」簽署
   接收方用「發送方的公鑰」驗證

   目的:確認發送方身份、確保內容未被竄改

非對稱加密的特點

優點 缺點
✅ 解決金鑰分發問題 ❌ 運算速度慢(比對稱慢 100-1000 倍)
✅ 可實現數位簽章 ❌ 不適合加密大量資料
✅ 可驗證身份 ❌ 金鑰長度需要更長

常見非對稱加密演算法

1. RSA

項目 說明
全名 Rivest-Shamir-Adleman
原理 基於大質數分解的困難性
金鑰長度 2048 / 3072 / 4096 bits
用途 加密、數位簽章、金鑰交換
狀態 ✅ 廣泛使用,但逐漸被 ECC 取代
RSA 原理簡化:
1. 選擇兩個大質數 p, q
2. 計算 n = p × q
3. 公鑰 = (n, e)
4. 私鑰 = (n, d)
5. 加密:C = M^e mod n
6. 解密:M = C^d mod n

安全性基於:
已知 n 很難分解回 p 和 q(大數分解問題)

2. ECC(橢圓曲線加密)

項目 說明
全名 Elliptic Curve Cryptography
原理 基於橢圓曲線離散對數問題
金鑰長度 256 / 384 bits(等效安全性更短)
用途 數位簽章(ECDSA)、金鑰交換(ECDH)
狀態 現代標準,逐漸取代 RSA
ECC vs RSA 金鑰長度對照(等效安全性):
┌──────────────┬──────────────┐
│  ECC 金鑰     │  RSA 金鑰    │
├──────────────┼──────────────┤
│  256 bits    │  3072 bits   │
│  384 bits    │  7680 bits   │
│  521 bits    │  15360 bits  │
└──────────────┴──────────────┘

ECC 優勢:更短的金鑰、更快的運算、更小的憑證

常見橢圓曲線

曲線名稱 位元數 說明
P-256 (secp256r1) 256 NIST 標準,廣泛使用
P-384 (secp384r1) 384 更高安全性
P-521 (secp521r1) 521 最高安全性
Curve25519 256 現代設計,高效能
secp256k1 256 Bitcoin 使用

3. DSA

項目 說明
全名 Digital Signature Algorithm
用途 僅用於數位簽章(不能加密)
狀態 ⚠️ 逐漸被 ECDSA 取代

4. Ed25519

項目 說明
基於 Curve25519 橢圓曲線
特點 快速、安全、實作簡單
用途 SSH 金鑰、數位簽章
狀態 現代推薦選擇

非對稱加密程式碼範例

Python RSA 加密

from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes

# 生成金鑰對
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048
)
public_key = private_key.public_key()

# 加密(使用公鑰)
message = b"Hello, RSA!"
ciphertext = public_key.encrypt(
    message,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

# 解密(使用私鑰)
plaintext = private_key.decrypt(
    ciphertext,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)
print(plaintext)  # b"Hello, RSA!"

OpenSSL 生成金鑰

# 生成 RSA 私鑰
openssl genrsa -out private.pem 2048

# 從私鑰導出公鑰
openssl rsa -in private.pem -pubout -out public.pem

# 生成 ECC 私鑰(P-256 曲線)
openssl ecparam -genkey -name prime256v1 -out ec_private.pem

# 生成 Ed25519 金鑰
openssl genpkey -algorithm Ed25519 -out ed25519_private.pem

三種技術比較

完整比較表

特性 Hash 雜湊 對稱加密 非對稱加密
目的 產生固定長度 Hash 值 加密資料保密 金鑰交換、身份驗證
可逆性 ❌ 單向不可逆 ✅ 雙向可逆 ✅ 雙向可逆
金鑰 無需金鑰 單一金鑰 公鑰 + 私鑰
速度 非常快 慢(100-1000x)
輸出長度 固定 與輸入相關 與輸入相關
金鑰分發 N/A 需安全通道 公鑰可公開
代表演算法 SHA-256, Argon2 AES-256 RSA, ECC

選擇指南

需要驗證資料完整性?
├── Yes → Hash(SHA-256)
└── No ↓

需要加密資料?
├── Yes ↓
│   需要雙方共享秘密?
│   ├── Yes → 對稱加密(AES-GCM)
│   └── No ↓
│       需要安全交換金鑰?
│       └── Yes → 非對稱加密(RSA/ECC)
└── No ↓

需要數位簽章?
├── Yes → 非對稱加密(ECDSA/Ed25519)
└── No → 可能不需要加密

實務中的組合使用

現實世界通常混合使用這三種技術:

HTTPS/TLS 握手流程:
─────────────────────

1. 非對稱加密:交換對稱金鑰
   Client → Server: 用 Server 公鑰加密的對稱金鑰

2. 對稱加密:加密實際資料
   Client ⇄ Server: 用對稱金鑰加密的資料

3. Hash + 數位簽章:驗證身份和完整性
   Server → Client: 憑證(含公鑰 + CA 簽章)

為什麼混合使用?
├── 非對稱加密:解決金鑰分發問題,但速度慢
├── 對稱加密:高效加密大量資料
└── Hash:確保資料完整性

實戰應用場景

場景 1:密碼儲存

❌ 錯誤做法:
   明文儲存密碼
   MD5/SHA-1 儲存密碼

✅ 正確做法:
   使用 Argon2id(首選)或 bcrypt

實作:
password = "user_password"
hash = argon2id(password, salt, memory=64MB, iterations=3, parallelism=4)
# 儲存 hash 到資料庫

場景 2:檔案完整性驗證

# 產生校驗碼
sha256sum important_file.zip > checksum.txt

# 驗證檔案
sha256sum -c checksum.txt

場景 3:API 請求簽名

import hmac
import hashlib
import time

def sign_request(api_key, secret_key, params):
    # 組合待簽名字串
    timestamp = str(int(time.time()))
    message = f"{api_key}{timestamp}{sorted(params.items())}"

    # 使用 HMAC-SHA256 簽名
    signature = hmac.new(
        secret_key.encode(),
        message.encode(),
        hashlib.sha256
    ).hexdigest()

    return {
        'api_key': api_key,
        'timestamp': timestamp,
        'signature': signature,
        **params
    }

場景 4:敏感資料加密儲存

from cryptography.fernet import Fernet

# 生成金鑰(需安全儲存)
key = Fernet.generate_key()
cipher = Fernet(key)

# 加密敏感資料
sensitive_data = b"credit_card_number"
encrypted = cipher.encrypt(sensitive_data)

# 解密
decrypted = cipher.decrypt(encrypted)

場景 5:JWT Token

JWT 結構:
Header.Payload.Signature

Header: {"alg": "RS256", "typ": "JWT"}  ← Base64
Payload: {"sub": "user123", "exp": ...}  ← Base64
Signature: RS256(Header.Payload, private_key)  ← 非對稱簽章

驗證流程:
1. Base64 解碼 Header 和 Payload
2. 用公鑰驗證 Signature
3. 檢查 Payload 中的過期時間

常見問題

問題 1:Hash 和加密有什麼不同?

Hash 加密
單向,不可還原 雙向,可以解密
用於驗證、指紋 用於保護資料機密性
輸出固定長度 輸出與輸入相關

問題 2:為什麼密碼不能用 SHA-256?

SHA-256 太快了!

假設:
- SHA-256 每秒可計算 10 億次
- 8 位數字密碼:10^8 種組合
- 暴力破解時間:0.1 秒

bcrypt/Argon2 設計為慢速:
- 每秒僅能計算數千次
- 暴力破解時間:數年

問題 3:什麼是 Salt?

Salt = 隨機字串,加在密碼前再 Hash

目的:
1. 防止彩虹表攻擊
2. 相同密碼產生不同 Hash

user1: password123 + salt1 → hash1
user2: password123 + salt2 → hash2

即使密碼相同,Hash 也不同

問題 4:RSA 和 ECC 該選哪個?

選擇 ECC:
├── 效能優先(行動裝置、IoT)
├── 頻寬有限
├── 新系統開發
└── TLS 1.3

選擇 RSA:
├── 相容性優先
├── 既有系統維護
└── 特定硬體需求

問題 5:AES-128 還是 AES-256?

AES-128:
✅ 對目前技術足夠安全
✅ 效能較好
✅ 一般應用推薦

AES-256:
✅ 更長的安全期限
✅ 抵抗量子計算(理論上)
✅ 政府/軍事/金融級需求

總結

核心要點

密碼學三劍客:
─────────────

Hash 雜湊 → 產生指紋,驗證完整性
├── 推薦:SHA-256(通用)、Argon2id(密碼)
└── 用途:密碼儲存、檔案校驗、數位簽章輔助

對稱加密 → 高效加密大量資料
├── 推薦:AES-256-GCM
└── 用途:資料加密、磁碟加密、通訊加密

非對稱加密 → 安全金鑰交換、身份驗證
├── 推薦:ECC(新系統)、RSA-2048+(相容性)
└── 用途:金鑰交換、數位簽章、憑證

選擇快速參考

需求 推薦方案
密碼儲存 Argon2id
檔案校驗 SHA-256
資料加密 AES-256-GCM
金鑰交換 ECDH (Curve25519)
數位簽章 Ed25519 / ECDSA
TLS/HTTPS ECC + AES-GCM
SSH 金鑰 Ed25519

安全建議

✅ 使用成熟、經過驗證的演算法
✅ 使用足夠長的金鑰
✅ 正確使用隨機 IV/Nonce
✅ 使用認證加密(如 GCM)
✅ 安全儲存金鑰

❌ 不要自己發明加密演算法
❌ 不要使用 MD5/SHA-1 於安全用途
❌ 不要使用 ECB 模式
❌ 不要重複使用 IV/Nonce
❌ 不要在程式碼中寫死金鑰

建立日期:2025-12-16 最後更新:2025-12-16

🔗相關文章