密码学
一、密码学基础概念
1. CIA三要素
- 机密性 (Confidentiality) :信息不被未授权者访问。
- 例子:用钥匙锁住日记本,只有你有钥匙。
- 完整性 (Integrity) :信息在传输/存储中不被篡改。
- 例子:快递包裹封条,若破损则可能被篡改。
- 可用性 (Availability) :授权用户能随时访问资源。
- 例子:银行系统需保证7×24小时服务。
2. 密码学与隐写的区别
- 密码学:隐藏信息内容(如加密后的乱码)。
- 隐写:隐藏信息存在性(如图片藏文字)。
二、古典密码
1. 凯撒密码
- 原理 :字母表固定偏移(如偏移3)。
- 加密公式:
密文字母 = (明文字母 + 3) mod 26
- 例子:
A → D
,HELLO → KHOOR
。
- 加密公式:
Python代码示例
python
def caesar_encrypt(text, shift):
result = ""
for char in text:
if char.isalpha():
base = ord('A') if char.isupper() else ord('a')
result += chr((ord(char) - base + shift) % 26 + base)
else:
result += char
return result
print(caesar_encrypt("HELLO", 3)) # 输出:KHOOR
代码解释:
- 遍历每个字符,计算偏移后的ASCII值。
mod 26
确保字母循环(如Z + 3 → C
)。
2. 栅栏密码
- 原理 :将明文按行分组后按列读取。
-
例子:明文
THEQUICKBROWNFOX
,分2栏:T E Q I C B O O X H U K R W N F X
密文:
TEQICBOOXHUKRWNX
-
Python代码示例
python
def rail_fence_encrypt(text, rails):
fence = [[] for _ in range(rails)]
rail = 0
for char in text:
fence[rail].append(char)
rail = (rail + 1) % rails
return ''.join([''.join(row) for row in fence])
print(rail_fence_encrypt("HELLOWORLD", 2)) # 输出:HLOOL ELWRD
代码解释:
- 创建
rails
个空列表模拟栅栏。 - 按顺序循环填入字符,最后按行拼接。
3. 摩斯密码
- 原理 :用点(·)和划(−)表示字母。
- 例子:
SOS → ··· −−− ···
- 例子:
Python代码示例
python
morse_code = {'A':'.-', 'B':'-...', 'S':'...', 'O':'---'}
def to_morse(text):
return ' '.join([morse_code[c.upper()] for c in text if c.upper() in morse_code])
print(to_morse("SOS")) # 输出:... --- ...
代码解释:
- 查表替换每个字符为对应的摩斯码。
三、数学基础
1. 模运算
- 定义 :对整数取余数的运算,符号为
mod
。- 例子:
17 mod 5 = 2
(因为 17 ÷ 5 余 2)。
- 例子:
- 同余关系 :若
a mod n = b mod n
,则称a ≡ b (mod n)
。- 例子:
23 ≡ 65 (mod 7)
,因为两者余数均为 2。
- 例子:
应用场景:钟表时间(12小时制)、密码学中的循环计算。
2. 欧拉定理
- 核心公式 :若
a
与n
互质,则a^φ(n) ≡ 1 (mod n)
。φ(n)
(欧拉函数):小于n
且与n
互质的正整数的个数。- 例子:若
n = 7
(质数),则φ(7) = 6
。
计算 φ(n):
- 若
n = p×q
(p、q为不同质数),则φ(n) = (p-1)(q-1)
。 - 例子:
n = 15 = 3×5
,则φ(15) = 2×4 = 8
。
3. 费马小定理
- 特例 :若
p
是质数且a
与p
互质,则a^(p-1) ≡ 1 (mod p)
。- 例子:
3^6 mod 7 = 729 mod 7 = 1
。
- 例子:
4. 扩展欧几里得算法(求逆元)
- 目标 :找到整数
x, y
使得ax + by = gcd(a, b)
。 - 逆元 :若
a
与m
互质,则存在b
使得a×b ≡ 1 (mod m)
,称b
是a
的模m
逆元。
Python代码示例
python
def extended_gcd(a, b):
if b == 0:
return a, 1, 0
else:
g, x, y = extended_gcd(b, a % b)
return g, y, x - (a // b) * y
a, m = 3, 11
g, x, y = extended_gcd(a, m)
if g == 1:
inverse = x % m
print(f"3的模11逆元是 {inverse}") # 输出:4(因为 3×4=12 ≡1 mod11)
代码解释:
- 递归计算最大公约数
g
和系数x, y
。 - 若
g=1
,则x % m
即为a
的逆元。
四、RSA算法
1. 密钥生成步骤
- 选两个大质数
p
和q
(如 512位)。 - 计算模数
n = p×q
。 - 计算欧拉函数
φ(n) = (p-1)(q-1)
。 - 选公钥
e
,满足1 < e < φ(n)
且e
与φ(n)
互质。 - 计算私钥
d
,即d ≡ e⁻¹ (mod φ(n))
。 - 公钥为
(n, e)
,私钥为(n, d)
。
示例:
p=3
,q=11
→n=33
,φ(n)=20
。- 选
e=3
(与20互质)。 - 计算
d=7
(因为3×7=21 ≡1 mod20
)。
2. 加密与解密
- 加密公式 :
密文 c = m^e mod n
(m
是明文)。 - 解密公式 :
明文 m = c^d mod n
。
Python代码示例
python
from Crypto.Util.number import getPrime, inverse
# 密钥生成
p = getPrime(10) # 生成10位质数
q = getPrime(10)
n = p * q
phi = (p-1) * (q-1)
e = 65537 # 常用公钥
d = inverse(e, phi)
# 加密
m = 42
c = pow(m, e, n)
# 解密
m_decrypted = pow(c, d, n)
print(f"明文: {m}, 解密结果: {m_decrypted}") # 输出:42
代码解释:
getPrime
生成质数,inverse
计算逆元。pow(c, d, n)
高效计算大数幂取模。
3. 安全性原理
- 核心难点 :大整数分解问题(已知
n
难以分解出p
和q
)。 - 攻击方式 :
- 暴力分解(对小
n
有效)。 - 量子计算的Shor算法(威胁大数分解)。
- 暴力分解(对小
五、RSA常见攻击场景
1. 模数分解攻击
- 原理 :若模数
n
过小或存在特殊结构(如p
和q
接近),可通过分解n
恢复私钥。 - 工具 :
yafu
、factordb
、sagemath
。 - 示例 (费马分解):
- 若
n = p×q
,且p
和q
接近,则p ≈ √n
。 - 从
√n
开始搜索相邻素数,找到p
和q
。
- 若
Python代码示例
python
import gmpy2
def fermat_factorization(n):
a = gmpy2.isqrt(n) + 1
b2 = a*a - n
while not gmpy2.is_square(b2):
a += 1
b2 = a*a - n
b = gmpy2.isqrt(b2)
return (a + b, a - b)
n = 1234567891011121314151617181921
p, q = fermat_factorization(n)
print(f"p = {p}, q = {q}")
代码解释:
- 从
√n
开始逐步增加a
,计算b² = a² - n
,直到b
为整数。
2. 共模攻击
- 原理 :若同一明文用两个不同的公钥
(n, e1)
和(n, e2)
加密,且e1
和e2
互质,可通过扩展欧几里得算法恢复明文。 - 公式 :找到
a
和b
使得a*e1 + b*e2 = 1
,则m = (c1^a * c2^b) mod n
。
Python代码示例
python
from Crypto.Util.number import inverse
n = 123456789
e1, e2 = 3, 65537
c1 = pow(m, e1, n)
c2 = pow(m, e2, n)
# 扩展欧几里得求a和b
g, a, b = extended_gcd(e1, e2)
m = (pow(c1, a, n) * pow(c2, b, n)) % n
print(f"明文: {m}")
代码解释:
extended_gcd
函数返回a
和b
,使得a*e1 + b*e2 = 1
。
3. 低加密指数攻击
-
场景 :若公钥
e
极小(如e=3
),且明文m
较小,则m^e < n
,可直接开方恢复明文。 -
示例 :
pythone = 3 c = m**e # 假设n > m^e m_decrypted = gmpy2.iroot(c, e)[0]
六、对称密码(AES)
1. AES加密流程
- 分组长度:128位(16字节)。
- 核心步骤 :
- 轮密钥加(AddRoundKey):将密钥与数据异或。
- 字节替换(SubBytes):通过S盒替换每个字节。
- 行移位(ShiftRows):循环左移每一行。
- 列混淆(MixColumns):矩阵乘法混淆列数据。
Python代码示例(简化版)
python
from Crypto.Cipher import AES
key = b'0123456789abcdef'
data = b'ThisIsASecretMsg'
# 加密
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(data)
# 解密
plaintext = cipher.decrypt(ciphertext)
print(f"解密结果: {plaintext}")
代码解释:
AES.MODE_ECB
表示电子密码本模式(无填充)。
2. AES的S盒与逆S盒
- S盒:非线性替换表,将每个字节映射为另一个字节。
- 逆S盒:解密时反向替换。
- 生成规则:基于有限域乘法逆元和仿射变换。
七、流密码(RC4)
1. RC4算法流程
- 初始化S盒:填充0-255,并用密钥打乱顺序。
- 生成密钥流:通过交换S盒元素生成伪随机序列。
Python代码示例
python
def rc4(key):
S = list(range(256))
j = 0
# 初始化S盒
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]
# 生成密钥流
i = j = 0
while True:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
K = S[(S[i] + S[j]) % 256]
yield K
key = b'SecretKey'
plaintext = b'HelloWorld'
keystream = rc4(key)
ciphertext = bytes([p ^ next(keystream) for p in plaintext])
print(f"密文: {ciphertext}")
代码解释:
- 初始化阶段通过密钥打乱S盒,生成阶段动态交换元素并输出密钥流。
八、证书格式解析
1. PEM与DER格式
-
PEM :以
-----BEGIN/END
包裹的Base64编码文本,常用于存储公钥/私钥。-----BEGIN PUBLIC KEY----- MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQ... -----END PUBLIC KEY-----
-
DER:二进制格式,适用于程序直接解析。
2. 格式转换(OpenSSL)
-
PEM转DER :
bashopenssl rsa -in public.pem -inform PEM -outform DER -out public.der
-
DER转PEM :
bashopenssl rsa -in public.der -inform DER -outform PEM -out public.pem
3. Python解析证书
python
from Crypto.PublicKey import RSA
# 读取PEM证书
with open("public.pem", "r") as f:
pem_data = f.read()
key = RSA.import_key(pem_data)
print(f"模数n={key.n}, 公钥e={key.e}")
代码解释:
RSA.import_key
可直接解析PEM格式的公钥/私钥。
九、编码方式
1. Base64编码
-
原理:将二进制数据按6位分组,映射到64个可打印字符(A-Z, a-z, 0-9, +/)。
-
示例 :
pythonimport base64 data = b"Hello, Crypto!" encoded = base64.b64encode(data).decode() # SGVsbG8sIENyeXB0byE= decoded = base64.b64decode(encoded) # b'Hello, Crypto!'
2. URL编码
-
原理 :将特殊字符替换为
%
后跟十六进制值(如空格→%20
)。 -
示例 :
pythonfrom urllib.parse import quote, unquote url = "flag{hello world}" encoded = quote(url) # flag%7Bhello%20world%7D decoded = unquote(encoded) # flag{hello world}
3. Quoted-printable编码
-
原理 :非ASCII字符用
=XX
表示(如中
→=E4=B8=AD
)。 -
示例 :
pythonimport quopri text = "flag{中文}" encoded = quopri.encodestring(text.encode()).decode() # flag=E4=B8=AD=E6=96=87 decoded = quopri.decodestring(encoded) # b'flag{中文}'
十、现代密码学工具总结
1. 常用工具
-
OpenSSL :命令行工具,支持证书生成、格式转换、加解密。
bash# 生成RSA私钥 openssl genpkey -algorithm RSA -out private.pem # 提取公钥 openssl rsa -pubout -in private.pem -out public.pem
-
PyCryptodome :Python密码学库,支持AES、RSA、哈希等。
pythonfrom Crypto.Cipher import AES cipher = AES.new(key, AES.MODE_GCM) # AES-GCM模式加密
-
hashlib :Python标准库,支持SHA256、MD5等哈希算法。
pythonimport hashlib hash_obj = hashlib.sha256(b"data").hexdigest()
2. 在线工具
- Factordb :大整数分解(factordb.com)。
- CyberChef :多功能编解码工具(gchq.github.io/CyberChef)。
十一、补充知识点
1. 哈希函数
-
特性:单向性、抗碰撞性。
-
应用场景 :文件完整性校验、密码存储。
pythonimport hashlib password = "123456".encode() salt = os.urandom(16) hashed = hashlib.pbkdf2_hmac("sha256", password, salt, 100000)
2. 数字签名
-
流程 :
- 发送方用私钥签名数据。
- 接收方用公钥验证签名。
-
示例(RSA签名) :
pythonfrom Crypto.Signature import pkcs1_15 from Crypto.Hash import SHA256 # 签名 hash_obj = SHA256.new(data) signature = pkcs1_15.new(private_key).sign(hash_obj) # 验签 try: pkcs1_15.new(public_key).verify(hash_obj, signature) print("验签成功") except (ValueError, TypeError): print("验签失败")
-
流程 :
- 发送方用私钥签名数据。
- 接收方用公钥验证签名。
-
示例(RSA签名) :
pythonfrom Crypto.Signature import pkcs1_15 from Crypto.Hash import SHA256 # 签名 hash_obj = SHA256.new(data) signature = pkcs1_15.new(private_key).sign(hash_obj) # 验签 try: pkcs1_15.new(public_key).verify(hash_obj, signature) print("验签成功") except (ValueError, TypeError): print("验签失败")