辛德拉 / Coser月潋寒觞
3253 字
16 分鐘
🔐 密碼學基礎知識總結

📚 內容目錄
基礎編碼篇
現代密碼篇
實戰技術篇
一、Base編碼
Base編碼是一種將二進制數據轉換為文本的編碼方式,廣泛應用於CTF競賽和實際數據傳輸中。
1. Base系列特征
編碼類型 | 字符集 | 特征 | 填充字符 | 應用場景 |
---|---|---|---|---|
Base16 | 0-9, A-F | 密文長度為偶數 | 無 | 十六進制表示 |
Base32 | A-Z, 2-7 | 包含數字2-7 | = | DNS編碼 |
Base64 | A-Z, a-z, 0-9, +, / | 密文長度為4的倍數 | = | 郵件、URL編碼 |
Base58 | A-Z, a-z, 0-9 (去除0,O,I,l) | 無混淆字符 | 無 | Bitcoin地址 |
Base85 | ASCII 33-117 | 高效編碼 | 無 | PDF、Git |
Base91 | A-Z, a-z, 0-9, !#$%&()*+,./:;<=>?@[]^_`{ | }~- | 高密度編碼 | 無 |
Base100 | Emoji表情符號 | 表情符號組成 | 無 | 隱寫術 |
2. 識別技巧
def identify_base_encoding(text): """ 根據字符特征識別Base編碼類型 """ if all(c in '0123456789ABCDEF' for c in text.upper()): return "可能是Base16 (Hex)"
if all(c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=' for c in text.upper()): return "可能是Base32"
if all(c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' for c in text): return "可能是Base64"
# 檢查是否包含emoji if any(ord(c) > 127 for c in text): return "可能是Base100或其他Unicode編碼"
return "未知編碼"
3. CTF常見題型
疊套加密(多層編碼)
import base64
# 示例:三層Base64編碼def multi_base64_decode(text, layers=3): result = text for i in range(layers): try: result = base64.b64decode(result).decode('utf-8') print(f"第{i+1}層解碼結果: {result}") except: print(f"第{i+1}層解碼失敗") break return result
換表加密(自定義字符映射)
# 換表解密示例def custom_base64_decode(cipher, custom_table): standard_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
# 構建轉換字典 trans = str.maketrans(custom_table, standard_table) standard_cipher = cipher.translate(trans)
return base64.b64decode(standard_cipher)
# 實際案例custom_table = "J K L M N O x y U V z A B C D E F G H 7 8 9 P Q I a b c d e f g h i j k l m W X Y Z 0 1 2 3 4 5 6 R S T n o p q r s t u v w + / ="cipher = "FlZNfnF6Qol6e9w17WwQQoGYBQCgIkGTa9w3IQKw"print(custom_base64_decode(cipher, custom_table))
異或編碼組合
def base64_xor_decode(cipher, key): # 先Base64解碼 decoded = base64.b64decode(cipher)
# 再進行XOR運算 result = bytes([decoded[i] ^ ord(key[i % len(key)]) for i in range(len(decoded))])
return result.decode('utf-8')
二、古典密碼
1. 替換密碼
-
凱撒密碼:位移變換
# 凱撒解密腳本def caesar_decrypt(cipher, shift):return ''.join([chr((ord(c)-ord('A')-shift)%26+ord('A')) if c.isupper()else chr((ord(c)-ord('a')-shift)%26+ord('a')) for c in cipher]) -
埃特巴什碼:字母表鏡像映射(A↔Z, B↔Y…)
-
簡單替換:隨機字母映射(需詞頻分析破解)
2. 移位密碼
-
柵欄密碼:
明文: THEQUICKBROWNFOX2欄柵欄:T E U C B O N F XH Q I K R W O密文: TEUCBOFNXHQIKRWO -
Playfair密碼:5×5矩陣雙字母加密
-
維吉尼亞密碼:多表替換(需卡西斯基試驗破譯)
3. 特殊編碼
- 社會主義核心價值觀編碼:中文詞語映射
- 豬圈密碼:符號替代
三、近代密碼
1. Enigma機
- 德國二戰加密設備,通過轉子機械實現多表替換
四、現代密碼學
1. 對稱密碼(Symmetric Cryptography)
對稱加密使用相同的密鑰進行加密和解密,速度快但密鑰分發困難。
分組密碼(Block Cipher)
算法 | 密鑰長度 | 分組大小 | 工作模式 | 安全狀態 |
---|---|---|---|---|
DES | 56位 | 64位 | ECB/CBC/CFB/OFB | ❌ 已破解 |
3DES | 112/168位 | 64位 | 同DES | ⚠️ 逐步淘汰 |
AES | 128/192/256位 | 128位 | ECB/CBC/GCM/CTR | ✅ 安全 |
Blowfish | 32-448位 | 64位 | 各種模式 | ✅ 安全 |
Twofish | 128/192/256位 | 128位 | 各種模式 | ✅ 安全 |
AES加密模式詳解
from Crypto.Cipher import AESfrom Crypto.Random import get_random_bytesfrom Crypto.Util.Padding import pad, unpad
# ECB模式 - 不推薦使用def aes_ecb_encrypt(plaintext, key): cipher = AES.new(key, AES.MODE_ECB) padded_text = pad(plaintext.encode(), AES.block_size) return cipher.encrypt(padded_text)
# CBC模式 - 推薦使用def aes_cbc_encrypt(plaintext, key): iv = get_random_bytes(AES.block_size) cipher = AES.new(key, AES.MODE_CBC, iv) padded_text = pad(plaintext.encode(), AES.block_size) ciphertext = cipher.encrypt(padded_text) return iv + ciphertext # IV需要傳輸
# GCM模式 - 提供認證def aes_gcm_encrypt(plaintext, key): nonce = get_random_bytes(12) cipher = AES.new(key, AES.MODE_GCM, nonce=nonce) ciphertext, tag = cipher.encrypt_and_digest(plaintext.encode()) return nonce + tag + ciphertext
流密碼(Stream Cipher)
算法 | 密鑰長度 | 特點 | 應用場景 |
---|---|---|---|
RC4 | 40-2048位 | 快速但存在弱點 | ❌ 已廢棄 |
ChaCha20 | 256位 | 現代流密碼,高安全性 | TLS、VPN |
Salsa20 | 256位 | ChaCha20的前身 | 學術研究 |
from Crypto.Cipher import ChaCha20
def chacha20_encrypt(plaintext, key): nonce = get_random_bytes(12) cipher = ChaCha20.new(key=key, nonce=nonce) ciphertext = cipher.encrypt(plaintext.encode()) return nonce + ciphertext
2. 非對稱密碼(Asymmetric Cryptography)
非對稱加密使用不同的密鑰進行加密和解密,解決了密鑰分發問題。
RSA算法
數學基礎:基於大整數分解的困難性
-
密鑰生成:
- 選擇兩個大質數 p, q
- 計算 n = p × q, φ(n) = (p-1)(q-1)
- 選擇 e 使得 gcd(e,φ(n)) = 1
- 計算 d 滿足 ed ≡ 1 (mod φ(n))
- 公鑰:(n, e),私鑰:(n, d)
-
加密/解密:
- 加密:c ≡ m^e (mod n)
- 解密:m ≡ c^d (mod n)
# RSA完整實現示例from Crypto.Util.number import long_to_bytes, bytes_to_long, isPrime, getRandomNBitInteger
def generate_rsa_keypair(bits=2048): """生成RSA密鑰對""" while True: p = getRandomNBitInteger(bits // 2) if isPrime(p): break
while True: q = getRandomNBitInteger(bits // 2) if isPrime(q) and q != p: break
n = p * q phi = (p - 1) * (q - 1) e = 65537 # 常用的公鑰指數 d = pow(e, -1, phi)
return { 'public': (n, e), 'private': (n, d), 'primes': (p, q) }
def rsa_encrypt(message, public_key): """RSA加密""" n, e = public_key m = bytes_to_long(message.encode()) c = pow(m, e, n) return c
def rsa_decrypt(ciphertext, private_key): """RSA解密""" n, d = private_key m = pow(ciphertext, d, n) return long_to_bytes(m).decode()
# CTF中的RSA解密示例def ctf_rsa_decrypt(): p = 152276107194759839394339252953668929833379494272797635215678777394989176086311370136035478447887926444275784082066390686965320698243113804043171803008108957334907494436138284735908220245791716231134027668300903468613086977898318244422816904811663818867009341751581380232066351461067404386138711392602905182327 q = 165862216368738151171691047077971125385823304861583668749112440485286071513555171553668744837558717911342949436706045003893101207778257828156155579957939073590381726467515305197248665285721804095245979532718423232742857246879254699058634781094524194465195004455721760308439281036465034307352501227102299122599 e = 65537 c = 8714149934588122613890609205826559063957396235456334581066750104141833387128819259074228632737215784067681665337373847122241506740977460425676706234123688048971299968252735566083061567386357327514300746902937654004543191945690400727133317228366779579116882233771039719002815276546167694160681831378762223177951840415429867605824997691072569915435484862548063841182891523397571914055707256503122950455644515402154037908557382756498138387988939464887512595990270123841900640997837144301259531459279512993819808359480410211723491073722980281648910041025010174785548169983002872841283535091066006242941399443173584257860
n = p * q phi = (p-1) * (q-1) d = pow(e, -1, phi)
plaintext = pow(c, d, n) return long_to_bytes(plaintext)
橢圓曲線密碼學(ECC)
數學基礎:基於橢圓曲線離散對數問題
# ECC點運算示例class ECCPoint: def __init__(self, x, y, curve): self.x = x self.y = y self.curve = curve
def __add__(self, other): """橢圓曲線點加法""" if self.x == other.x: if self.y == other.y: # 點倍乘 s = (3 * self.x * self.x + self.curve.a) * pow(2 * self.y, -1, self.curve.p) else: # 逆元,返回無窮遠點 return None else: s = (other.y - self.y) * pow(other.x - self.x, -1, self.curve.p)
x3 = (s * s - self.x - other.x) % self.curve.p y3 = (s * (self.x - x3) - self.y) % self.curve.p
return ECCPoint(x3, y3, self.curve)
算法 | 密鑰長度 | 安全強度等效RSA | 特點 |
---|---|---|---|
ECC-256 | 256位 | RSA-3072 | 密鑰短,速度快 |
ECC-384 | 384位 | RSA-7680 | 高安全性 |
ECC-521 | 521位 | RSA-15360 | 最高安全級別 |
3. 哈希函數(Hash Functions)
哈希函數將任意長度的輸入映射為固定長度的輸出,具有單向性、抗碰撞性等特性。
算法 | 輸出長度 | 內部狀態 | 安全性 | 應用場景 |
---|---|---|---|---|
MD5 | 128位 | 128位 | ❌ 已破解 | 文件校驗(不推薦) |
SHA-1 | 160位 | 160位 | ⚠️ 逐步淘汰 | Git(逐漸替換) |
SHA-256 | 256位 | 256位 | ✅ 安全 | Bitcoin、證書 |
SHA-3 | 可變 | 1600位 | ✅ 安全 | 新一代標準 |
Blake2b | 可變 | 512位 | ✅ 安全 | 高性能場景 |
RIPEMD-160 | 160位 | 160位 | ✅ 安全 | Bitcoin地址生成 |
import hashlibimport hmac
# 常用哈希函數示例def hash_examples(): message = b"Hello, Cryptography!"
# MD5(不安全,僅作演示) md5_hash = hashlib.md5(message).hexdigest() print(f"MD5: {md5_hash}")
# SHA-256(推薦) sha256_hash = hashlib.sha256(message).hexdigest() print(f"SHA-256: {sha256_hash}")
# SHA-3(新標準) sha3_hash = hashlib.sha3_256(message).hexdigest() print(f"SHA3-256: {sha3_hash}")
# HMAC(帶密鑰的哈希) key = b"secret_key" hmac_hash = hmac.new(key, message, hashlib.sha256).hexdigest() print(f"HMAC-SHA256: {hmac_hash}")
# 哈希長度擴展攻擊示例def length_extension_attack(): """演示SHA-1/SHA-256的長度擴展攻擊""" # 已知:hash(secret || known_message) = known_hash # 目標:計算hash(secret || known_message || padding || attack_message)
from hashlib import sha256 import struct
def sha256_padding(msg_len): """計算SHA-256的填充""" msg_bit_len = msg_len * 8 padding = b'\x80'
# 填充到448 mod 512 while (len(padding) + msg_len) % 64 != 56: padding += b'\x00'
# 添加長度(8字節大端序) padding += struct.pack('>Q', msg_bit_len) return padding
# 這只是演示概念,實際攻擊需要更復雜的實現 print("長度擴展攻擊需要已知消息長度和哈希值")
七、數字簽名(Digital Signatures)
數字簽名提供身份認證、完整性保護和不可否認性。
RSA簽名
from Crypto.Hash import SHA256from Crypto.PublicKey import RSAfrom Crypto.Signature import PKCS1_v1_5
def rsa_sign_verify(): # 生成密鑰對 key = RSA.generate(2048) private_key = key public_key = key.publickey()
# 要簽名的消息 message = b"Important document"
# 創建簽名 hash_obj = SHA256.new(message) signer = PKCS1_v1_5.new(private_key) signature = signer.sign(hash_obj)
# 驗證簽名 verifier = PKCS1_v1_5.new(public_key) try: verifier.verify(hash_obj, signature) print("簽名驗證成功") except ValueError: print("簽名驗證失敗")
ECDSA簽名
from ecdsa import SigningKey, VerifyingKey, SECP256k1import hashlib
def ecdsa_sign_verify(): # 生成密鑰對 private_key = SigningKey.generate(curve=SECP256k1) public_key = private_key.get_verifying_key()
# 簽名 message = b"Blockchain transaction" signature = private_key.sign(message, hashfunc=hashlib.sha256)
# 驗證 try: public_key.verify(signature, message, hashfunc=hashlib.sha256) print("ECDSA簽名驗證成功") except: print("ECDSA簽名驗證失敗")
八、攻擊技術
1. 密碼分析(Cryptanalysis)
對稱密碼攻擊
- 差分分析:分析明文差異對密文的影響(針對DES)
- 線性分析:利用線性逼近攻擊(針對AES)
- 積分攻擊:針對AES的高級攻擊方法
- 中間相遇攻擊:針對多輪加密的攻擊
非對稱密碼攻擊
# RSA攻擊示例集合def rsa_attacks(): """常見RSA攻擊方法"""
# 1. 小指數攻擊(e=3時) def small_exponent_attack(c, n, e=3): import gmpy2 if e == 3: # 如果c < n,則m^3 = c m = gmpy2.iroot(c, 3)[0] return m
# 2. 共模攻擊(相同n,不同e) def common_modulus_attack(c1, c2, e1, e2, n): import gmpy2 # 擴展歐幾里得算法求s1, s2使得s1*e1 + s2*e2 = 1 def extended_gcd(a, b): if a == 0: return b, 0, 1 gcd, x1, y1 = extended_gcd(b % a, a) x = y1 - (b // a) * x1 y = x1 return gcd, x, y
gcd, s1, s2 = extended_gcd(e1, e2) if gcd == 1: m = pow(c1, s1, n) * pow(c2, s2, n) % n return m
# 3. 威納攻擊(d較小時) def wiener_attack(e, n): # 使用連分數分解e/n # 這裡簡化演示概念 print("威納攻擊適用於d < n^0.25的情況")
# 模數分解攻擊def factorization_attacks(): """RSA模數分解方法"""
# Pollard's rho算法 def pollards_rho(n): import math if n % 2 == 0: return 2
x = 2 y = 2 d = 1
def f(x): return (x * x + 1) % n
while d == 1: x = f(x) y = f(f(y)) d = math.gcd(abs(x - y), n)
return d if d != n else None
2. 側信道攻擊(Side-Channel Attacks)
# 計時攻擊演示import timeimport statistics
def timing_attack_demo(): """演示計時攻擊的概念"""
def vulnerable_compare(guess, target): """有漏洞的字符串比較""" for i in range(min(len(guess), len(target))): if guess[i] != target[i]: return False time.sleep(0.001) # 模擬處理時間 return len(guess) == len(target)
def timing_attack(target_length): """通過計時攻擊猜測密碼""" charset = 'abcdefghijklmnopqrstuvwxyz0123456789' result = ""
for pos in range(target_length): best_char = '' max_time = 0
for char in charset: guess = result + char + 'a' * (target_length - pos - 1)
# 測量多次取平均值 times = [] for _ in range(10): start = time.time() vulnerable_compare(guess, "secret123") # 假設目標 times.append(time.time() - start)
avg_time = statistics.mean(times) if avg_time > max_time: max_time = avg_time best_char = char
result += best_char print(f"當前猜測: {result}")
return result
3. 社會工程攻擊
- 密碼字典攻擊:使用常見密碼列表
- 彩虹表攻擊:預計算哈希表
- 鍵盤模式攻擊:基於鍵盤布局的密碼
九、CTF解題技巧
1. 題型識別
def crypto_challenge_identifier(ciphertext): """CTF密碼學題型識別工具"""
# 統計字符頻率 char_freq = {} for c in ciphertext: char_freq[c] = char_freq.get(c, 0) + 1
# 分析長度特征 length = len(ciphertext)
# 判斷可能的編碼類型 if all(c in '01' for c in ciphertext): return "二進制編碼"
if all(c in '0123456789ABCDEF' for c in ciphertext.upper()): return "十六進制編碼"
if length % 4 == 0 and all(c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' for c in ciphertext): return "Base64編碼"
# 頻率分析 most_common = max(char_freq.values()) if most_common / length > 0.12: # 英語中E的頻率約12% return "可能是單表替換密碼"
return "複雜密碼或多重編碼"
# 自動化解題腳本def auto_decode_pipeline(ciphertext): """自動化解碼流水線""" import base64
results = []
# 嘗試Base64 try: decoded = base64.b64decode(ciphertext).decode('utf-8') results.append(f"Base64: {decoded}") except: pass
# 嘗試十六進制 try: decoded = bytes.fromhex(ciphertext).decode('utf-8') results.append(f"Hex: {decoded}") except: pass
# 嘗試凱撒密碼(所有可能的偏移) for shift in range(26): decoded = ''.join([chr((ord(c) - ord('A') - shift) % 26 + ord('A')) if c.isupper() else chr((ord(c) - ord('a') - shift) % 26 + ord('a')) if c.islower() else c for c in ciphertext]) if 'flag' in decoded.lower() or 'ctf' in decoded.lower(): results.append(f"Caesar {shift}: {decoded}")
return results
2. 常見出題套路
- 多層編碼:Base64 → Hex → Caesar
- 異或運算:flag ⊕ key = cipher
- RSA變形:小指數、共模攻擊、威納攻擊
- 古典密碼:維吉尼亞、Playfair、柵欄密碼
- 現代密碼:AES-ECB模式、CBC字節翻轉攻擊
十、工具與資源
1. 在線工具
工具名稱 | 功能 | 網址 |
---|---|---|
CyberChef | 萬能編解碼工具 | https://gchq.github.io/CyberChef/ |
dCode | 古典密碼分析 | https://www.dcode.fr/ |
CMD5 | MD5哈希查詢 | https://www.cmd5.com/ |
FactorDB | 大數分解查詢 | http://factordb.com/ |
QuipQuip | 替換密碼求解 | https://quipqiup.com/ |
2. 本地工具
# 密碼破解工具sudo apt install hashcat john
# 密碼學庫pip install pycryptodome gmpy2 sympy
# CTF專用工具git clone https://github.com/Ganapati/RsaCtfTool.gitgit clone https://github.com/hellman/xortool.git
3. Python密碼學庫
# 推薦的Python密碼學庫libraries = { 'pycryptodome': '現代密碼學實現', 'cryptography': '高級密碼學API', 'hashlib': '哈希函數(內建)', 'gmpy2': '大數運算', 'sympy': '數學計算', 'ecdsa': '橢圓曲線數字簽名', 'sage': '數學計算框架(CTF神器)'}
4. 學習資源
-
書籍推薦:
- 《應用密碼學》- Bruce Schneier
- 《現代密碼學教程》- Jonathan Katz
- 《密碼編碼學與網絡安全》- William Stallings
-
在線課程:
- Coursera: Cryptography I (Stanford)
- edX: Introduction to Cryptography
-
CTF平台:
- CryptoPals: https://cryptopals.com/
- OverTheWire: https://overthewire.org/
- PicoCTF: https://picoctf.org/
結語
密碼學是一個不斷發展的領域,從古典的手工密碼到現代的量子密碼學,技術在不斷進步。掌握密碼學基礎不僅有助於CTF競賽,更是現代信息安全的核心技能。
持續學習建議:
- 理論與實踐並重
- 關注最新的密碼學進展
- 參與CTF競賽鍛煉技能
- 深入研究感興趣的特定領域
記住:密碼學不是萬能的,但沒有密碼學是萬萬不能的。
參與討論
使用 GitHub 帳號登入參與討論