第4章 数论与密码学 (Number Theory and Cryptography)
一、导读
1.1 本章学习目标
完成本章学习后,你将能够:
理解整除性、素数、最大公约数和最小公倍数的基本概念
掌握欧几里得算法及其扩展版本,能够计算模逆元
熟练运用模运算的性质解决同余方程
理解费马小定理和欧拉定理及其在密码学中的应用
掌握RSA公钥加密算法的原理、实现和安全性分析
理解离散对数问题及其在Diffie-Hellman密钥交换中的应用
掌握哈希函数的性质和在数据完整性验证中的应用
了解椭圆曲线密码学的基本概念
1.2 为什么本章如此重要
数论曾被认为是"最纯粹"的数学分支,如今却是现代信息安全的基石。
在互联网安全中:HTTPS协议依赖RSA或椭圆曲线密码学保护数据传输;SSH使用公钥认证;数字签名确保软件来源可信。
在区块链与加密货币中:比特币使用椭圆曲线数字签名算法(ECDSA)验证交易;以太坊使用Keccak哈希函数。
在日常应用中:密码存储使用加盐哈希;校验和检测数据传输错误;随机数生成用于游戏和模拟。
在算法设计中:模运算用于哈希表设计;中国剩余定理用于大数运算;素数测试用于密钥生成。
对于程序员而言,理解数论不仅有助于实现安全系统,还能避免常见陷阱(如使用弱随机数、错误的模运算实现等)。
1.3 核心问题引导
在学习本章之前,请思考以下问题:
为什么1既不是素数也不是合数?
如何高效判断一个大数是否为素数?
为什么RSA加密是安全的?破解它需要什么?
模运算中的"除法"如何实现?为什么不能直接除?
什么是"陷门函数"?它在密码学中有什么作用?
为什么两个不同的消息可能产生相同的哈希值?这安全吗?
Diffie-Hellman密钥交换如何在不安全的信道上建立共享密钥?
量子计算机对现有密码系统有什么威胁?
二、核心概念详解
4.1 整除性与素数
整除性
定义:如果存在整数k使得 b = ka,则称a整除b,记作 a | b。
例如:3 | 12(因为 12 = 3 × 4),但 5 ∤ 12。
性质:
- 如果 a | b 且 a | c,则 a | (b + c)
- 如果 a | b,则 a | bc 对任意整数c成立
- 如果 a | b 且 b | c,则 a | c
素数
定义:大于1的整数p是素数,如果它的正因子只有1和p本身。
前几个素数:2, 3, 5, 7, 11, 13, 17, 19, 23, 29, ...
注意:1不是素数(这是约定,为了使算术基本定理简洁)。
算术基本定理:每个大于1的整数都可以唯一地表示为素数的乘积(不考虑顺序)。
例如:60 = 2² × 3 × 5
素数判定
试除法:检查从2到√n的所有整数是否整除n。
时间复杂度:O(√n),对于大数效率低下。
米勒-拉宾素性测试:概率性算法,广泛用于实际应用中。
原理基于费马小定理的推广。通过多次测试,可以将错误概率降到任意低。
素数定理:不超过n的素数个数约为 n/ln(n)。
即素数的"密度"随数值增大而降低。
4.2 最大公约数与欧几里得算法
最大公约数(GCD)
定义:gcd(a, b) 是能同时整除a和b的最大正整数。
例如:gcd(12, 18) = 6
性质:
- gcd(a, 0) = |a|
- gcd(a, b) = gcd(b, a)
- gcd(a, b) = gcd(|a|, |b|)
欧几里得算法
原理:gcd(a, b) = gcd(b, a mod b)
算法:
输入:a, b(非负整数,a ≥ b)
输出:gcd(a, b)
while b ≠ 0:
r = a mod b
a = b
b = r
return a示例:gcd(48, 18)
- 48 mod 18 = 12
- 18 mod 12 = 6
- 12 mod 6 = 0
- gcd = 6
时间复杂度:O(log(min(a, b))),非常高效。
证明正确性:
关键引理:如果 a = bq + r,则 gcd(a, b) = gcd(b, r)。
证明:设 d = gcd(a, b)。则 d | a 且 d | b。
由于 r = a - bq,所以 d | r。
因此 d 是 b 和 r 的公因数。
反之,设 e = gcd(b, r)。则 e | b 且 e | r。
由于 a = bq + r,所以 e | a。
因此 e 是 a 和 b 的公因数。
所以 gcd(a, b) = gcd(b, r)。∎
扩展欧几里得算法
除了计算gcd,还能找到整数x和y使得 ax + by = gcd(a, b)。
这在计算模逆元时非常有用。
算法:
def extended_gcd(a, b):
if b == 0:
return a, 1, 0
g, x1, y1 = extended_gcd(b, a % b)
x = y1
y = x1 - (a // b) * y1
return g, x, y应用:求解 ax ≡ 1 (mod m),即找a的模逆元。
如果 gcd(a, m) = 1,则存在x使得 ax + my = 1,即 ax ≡ 1 (mod m)。
4.3 模运算
同余
定义:如果 m | (a - b),则称a与b模m同余,记作 a ≡ b (mod m)。
等价地:a mod m = b mod m。
例如:17 ≡ 5 (mod 12),因为 17 - 5 = 12。
模运算的性质
| 性质 | 公式 |
|---|---|
| 加法 | (a + b) mod m = ((a mod m) + (b mod m)) mod m |
| 减法 | (a - b) mod m = ((a mod m) - (b mod m)) mod m |
| 乘法 | (a · b) mod m = ((a mod m) · (b mod m)) mod m |
| 幂运算 | aⁿ mod m 可通过快速幂高效计算 |
注意:模运算中没有直接的"除法"。要计算 a/b mod m,需要找到b的模逆元b⁻¹,然后计算 a · b⁻¹ mod m。
快速幂(模幂运算)
计算 aⁿ mod m 的高效算法。
原理:利用二进制分解指数。
例如:a¹³ = a^(1101)₂ = a⁸ · a⁴ · a¹
算法:
def modular_exponentiation(base, exp, mod):
result = 1
base = base % mod
while exp > 0:
if exp % 2 == 1: # 如果当前位为1
result = (result * base) % mod
exp = exp >> 1 # 右移一位
base = (base * base) % mod
return result时间复杂度:O(log n),远优于朴素方法的 O(n)。
4.4 费马小定理与欧拉定理
费马小定理
定理:如果p是素数,a不是p的倍数,则 a^(p-1) ≡ 1 (mod p)。
等价形式:a^p ≡ a (mod p) 对所有整数a成立。
应用:
- 素性测试的基础
- 计算模逆元:a^(p-2) ≡ a⁻¹ (mod p)
示例:p = 7, a = 3
- 3⁶ = 729
- 729 mod 7 = 1 ✓
欧拉函数
定义:φ(n) 表示不超过n且与n互质的正整数个数。
计算:
- 如果p是素数,φ(p) = p - 1
- 如果p是素数,φ(pᵏ) = pᵏ - pᵏ⁻¹
- 如果gcd(m, n) = 1,φ(mn) = φ(m)φ(n)
一般公式:如果 n = p₁^k₁ · p₂^k₂ · ... · pᵣ^kᵣ,则
$$\phi(n) = n \prod_{i=1}^{r} \left(1 - \frac{1}{p_i}\right)$$
示例:φ(12) = φ(2² · 3) = 12 · (1 - 1/2) · (1 - 1/3) = 12 · 1/2 · 2/3 = 4
与12互质的数:1, 5, 7, 11(共4个)✓
欧拉定理
定理:如果gcd(a, n) = 1,则 a^φ(n) ≡ 1 (mod n)。
费马小定理是欧拉定理在n为素数时的特例(因为φ(p) = p - 1)。
应用:RSA加密的正确性证明。
4.5 RSA加密算法
历史背景
RSA由Ron Rivest、Adi Shamir和Leonard Adleman于1977年提出,是第一个实用的公钥加密系统。
密钥生成
选择两个大素数 p 和 q
计算 n = pq
计算 φ(n) = (p-1)(q-1)
选择整数 e,使得 1 < e < φ(n) 且 gcd(e, φ(n)) = 1
计算 d,使得 ed ≡ 1 (mod φ(n))
公钥:(e, n)
私钥:(d, n)
加密与解密
加密:c = m^e mod n(使用公钥)
解密:m = c^d mod n(使用私钥)
正确性证明
需要证明:(m^e)^d ≡ m (mod n)
即 m^(ed) ≡ m (mod n)
由于 ed ≡ 1 (mod φ(n)),有 ed = 1 + k·φ(n) 对某个整数k。
所以 m^(ed) = m^(1 + k·φ(n)) = m · (m^φ(n))^k
由欧拉定理,如果 gcd(m, n) = 1,则 m^φ(n) ≡ 1 (mod n)。
所以 m^(ed) ≡ m · 1^k ≡ m (mod n)。
当 gcd(m, n) ≠ 1 时(即 m 是 p 或 q 的倍数),需要使用中国剩余定理证明,结论仍然成立。∎
安全性
RSA的安全性基于大数因数分解问题的难度:给定n = pq,找出p和q。
目前最好的经典算法(通用数域筛法)的时间复杂度约为:
$$\exp\left(\left(\sqrt[3]{\frac{64}{9}} + o(1)\right)(\ln n)^{1/3}(\ln \ln n)^{2/3}\right)$$
对于2048位的n,这在经典计算机上是不可行的。
推荐密钥长度:
- 1024位:已不安全
- 2048位:目前安全
- 4096位:长期安全
4.6 Diffie-Hellman密钥交换
协议描述
Alice和Bob希望在不安全的信道上建立共享密钥。
公开参数:大素数p和原根g(生成元)
Alice选择私钥a,发送 A = g^a mod p 给Bob
Bob选择私钥b,发送 B = g^b mod p 给Alice
Alice计算 s = B^a mod p = g^(ba) mod p
Bob计算 s = A^b mod p = g^(ab) mod p
双方得到相同的共享密钥 s = g^(ab) mod p。
安全性
基于离散对数问题的难度:给定g, p, g^a mod p,求a。
目前没有已知的多项式时间算法解决此问题。
注意:基本的Diffie-Hellman容易受到中间人攻击,需要结合身份认证使用。
4.7 哈希函数
定义与性质
密码学哈希函数 h: {0,1}* → {0,1}ⁿ 将任意长度的输入映射为固定长度的输出。
理想性质:
确定性:相同输入总是产生相同输出
高效性:计算h(x)是高效的
原像抗性(单向性):给定y,找到x使得h(x)=y是困难的
第二原像抗性:给定x,找到x'≠x使得h(x')=h(x)是困难的
碰撞抗性:找到x≠x'使得h(x)=h(x')是困难的
常见哈希算法
| 算法 | 输出长度 | 状态 |
|---|---|---|
| MD5 | 128位 | 已破解,不应用于安全场景 |
| SHA-1 | 160位 | 已发现碰撞,逐步淘汰 |
| SHA-256 | 256位 | 目前安全,广泛使用 |
| SHA-3 | 可变 | 最新标准 |
应用
- 密码存储:存储h(password + salt)而非明文密码
- 数据完整性:文件哈希验证下载完整性
- 数字签名:对消息哈希值签名而非整个消息
- 区块链:工作量证明、Merkle树
4.8 椭圆曲线密码学(简介)
椭圆曲线密码学(ECC)基于椭圆曲线上的离散对数问题。
优势:相比RSA,ECC可以用更短的密钥提供相同的安全性。
| 安全级别 | RSA密钥长度 | ECC密钥长度 |
|---|---|---|
| 80位 | 1024位 | 160位 |
| 112位 | 2048位 | 224位 |
| 128位 | 3072位 | 256位 |
| 256位 | 15360位 | 512位 |
ECC广泛用于移动设备和物联网设备,以及比特币等加密货币。
三、程序员的视角
3.1 在计算机科学中的应用
哈希表
哈希函数将键映射到数组索引。好的哈希函数应该:
- 均匀分布
- 计算快速
- 对相似输入产生不同输出
# Python字典内部使用哈希表
my_dict = {"key": "value"}随机数生成
线性同余生成器:Xₙ₊₁ = (aXₙ + c) mod m
虽然不适合密码学用途,但在模拟和游戏中广泛使用。
校验和
CRC(循环冗余校验)使用模2多项式除法检测数据传输错误。
3.2 常见陷阱与误区
使用弱随机数
# 不安全!
import random
secret_key = random.randint(0, 2**128)
# 安全
import secrets
secret_key = secrets.randbits(128)模运算中的负数
在不同语言中,-5 mod 3 的结果可能不同:
- Python: 1(始终非负)
- C/C++: -2(符号跟随被除数)
定时攻击
比较哈希值时使用普通字符串比较可能泄露信息:
# 不安全:可能在第一个不匹配字符处提前返回
if user_hash == correct_hash:
...
# 安全:恒定时间比较
import hmac
if hmac.compare_digest(user_hash, correct_hash):
...3.3 与其他层级的联系
- 硬件层:AES-NI指令集加速加密运算
- 操作系统层:/dev/random 提供熵源
- 网络层:TLS握手使用公钥密码学
- 应用层:JWT令牌使用数字签名
四、代码实战
4.1 欧几里得算法与扩展版本
"""
欧几里得算法及其扩展版本的实现
"""
def gcd(a, b):
"""
计算最大公约数
时间复杂度: O(log(min(a, b)))
"""
a, b = abs(a), abs(b)
while b:
a, b = b, a % b
return a
def lcm(a, b):
"""计算最小公倍数"""
return abs(a * b) // gcd(a, b)
def extended_gcd(a, b):
"""
扩展欧几里得算法
返回: (g, x, y) 使得 ax + by = g = gcd(a, b)
"""
if a == 0:
return b, 0, 1
g, x1, y1 = extended_gcd(b % a, a)
x = y1 - (b // a) * x1
y = x1
return g, x, y
def modular_inverse(a, m):
"""
计算a模m的逆元
前提: gcd(a, m) = 1
返回: a^(-1) mod m
"""
g, x, _ = extended_gcd(a % m, m)
if g != 1:
raise ValueError(f"模逆元不存在 (gcd({a}, {m}) = {g})")
return x % m
def demonstrate_euclidean():
"""演示欧几里得算法"""
print("=== 欧几里得算法 ===")
test_cases = [
(48, 18),
(1071, 462),
(123456789, 987654321),
]
for a, b in test_cases:
g = gcd(a, b)
l = lcm(a, b)
print(f"gcd({a}, {b}) = {g}")
print(f"lcm({a}, {b}) = {l}")
print()
print("=== 扩展欧几里得算法 ===")
a, b = 35, 15
g, x, y = extended_gcd(a, b)
print(f"{a}×{x} + {b}×{y} = {g}")
print(f"验证: {a*x + b*y} = {g}")
print()
print("=== 模逆元 ===")
a, m = 3, 11
inv = modular_inverse(a, m)
print(f"{a}^(-1) mod {m} = {inv}")
print(f"验证: {a} × {inv} mod {m} = {(a * inv) % m}")
if __name__ == "__main__":
demonstrate_euclidean()4.2 RSA算法实现
"""
RSA加密算法的简化实现(用于教学目的)
注意:这不是生产级实现!实际应用中应使用经过审计的库。
"""
import random
import math
def is_prime_miller_rabin(n, k=10):
"""
米勒-拉宾素性测试
返回: True(可能是素数)或 False(一定是合数)
"""
if n < 2:
return False
if n == 2 or n == 3:
return True
if n % 2 == 0:
return False
# 将 n-1 写为 2^r × d
r, d = 0, n - 1
while d % 2 == 0:
r += 1
d //= 2
# 进行k轮测试
for _ in range(k):
a = random.randrange(2, n - 1)
x = pow(a, d, n)
if x == 1 or x == n - 1:
continue
for _ in range(r - 1):
x = pow(x, 2, n)
if x == n - 1:
break
else:
return False
return True
def generate_prime(bits):
"""生成指定比特数的随机素数"""
while True:
candidate = random.getrandbits(bits)
candidate |= (1 << bits - 1) | 1 # 确保最高位和最低位为1
if is_prime_miller_rabin(candidate):
return candidate
def gcd(a, b):
while b:
a, b = b, a % b
return a
def extended_gcd(a, b):
if a == 0:
return b, 0, 1
g, x1, y1 = extended_gcd(b % a, a)
x = y1 - (b // a) * x1
y = x1
return g, x, y
def modular_inverse(a, m):
g, x, _ = extended_gcd(a % m, m)
if g != 1:
raise ValueError("模逆元不存在")
return x % m
class RSACipher:
"""RSA加密解密类"""
def __init__(self, key_bits=512):
"""生成密钥对"""
# 生成两个大素数
self.p = generate_prime(key_bits // 2)
self.q = generate_prime(key_bits // 2)
# 计算n和φ(n)
self.n = self.p * self.q
self.phi_n = (self.p - 1) * (self.q - 1)
# 选择公钥指数e
self.e = 65537 # 常用值,是素数且二进制只有两个1
# 确保e与φ(n)互质
while gcd(self.e, self.phi_n) != 1:
self.e += 2
# 计算私钥指数d
self.d = modular_inverse(self.e, self.phi_n)
self.public_key = (self.e, self.n)
self.private_key = (self.d, self.n)
def encrypt(self, message):
"""
加密消息
参数: message (int) < n
返回: ciphertext (int)
"""
if message >= self.n:
raise ValueError("消息太大")
return pow(message, self.e, self.n)
def decrypt(self, ciphertext):
"""
解密密文
参数: ciphertext (int)
返回: message (int)
"""
return pow(ciphertext, self.d, self.n)
def encrypt_string(self, text):
"""将字符串转换为整数并加密"""
# 简单编码:每个字符转为ASCII值拼接
message_int = int.from_bytes(text.encode('utf-8'), 'big')
if message_int >= self.n:
raise ValueError("文本太长,需要更大的密钥")
ciphertext = self.encrypt(message_int)
return ciphertext
def decrypt_string(self, ciphertext):
"""解密并还原为字符串"""
message_int = self.decrypt(ciphertext)
# 计算需要的字节数
byte_length = (message_int.bit_length() + 7) // 8
message_bytes = message_int.to_bytes(byte_length, 'big')
return message_bytes.decode('utf-8')
def demonstrate_rsa():
"""演示RSA加密解密"""
print("=== RSA密钥生成 ===")
rsa = RSACipher(key_bits=64) # 小密钥用于演示
print(f"p = {rsa.p}")
print(f"q = {rsa.q}")
print(f"n = {rsa.n}")
print(f"φ(n) = {rsa.phi_n}")
print(f"公钥 (e, n) = ({rsa.e}, {rsa.n})")
print(f"私钥 (d, n) = ({rsa.d}, {rsa.n})")
print()
print("=== 整数加密解密 ===")
message = 42
print(f"原始消息: {message}")
ciphertext = rsa.encrypt(message)
print(f"密文: {ciphertext}")
decrypted = rsa.decrypt(ciphertext)
print(f"解密消息: {decrypted}")
print(f"验证: {message == decrypted}")
print()
print("=== 字符串加密解密 ===")
text = "Hello RSA!"
print(f"原始文本: {text}")
try:
ct = rsa.encrypt_string(text)
print(f"密文: {ct}")
dt = rsa.decrypt_string(ct)
print(f"解密文本: {dt}")
print(f"验证: {text == dt}")
except ValueError as e:
print(f"错误: {e}")
if __name__ == "__main__":
demonstrate_rsa()4.3 哈希函数与数据完整性
"""
哈希函数应用:数据完整性验证和密码存储
"""
import hashlib
import os
import json
def compute_sha256(data):
"""计算SHA-256哈希值"""
if isinstance(data, str):
data = data.encode('utf-8')
return hashlib.sha256(data).hexdigest()
def verify_file_integrity(file_path, expected_hash):
"""
验证文件完整性
返回: True如果哈希匹配,False否则
"""
with open(file_path, 'rb') as f:
file_hash = hashlib.sha256(f.read()).hexdigest()
return file_hash == expected_hash
class PasswordHasher:
"""
安全的密码哈希类
使用PBKDF2-HMAC-SHA256进行密钥派生
"""
def __init__(self, iterations=100000):
self.iterations = iterations
def hash_password(self, password):
"""
哈希密码,生成随机盐
返回: (salt_hex, hash_hex)
"""
salt = os.urandom(32) # 256位盐
hash_value = hashlib.pbkdf2_hmac(
'sha256',
password.encode('utf-8'),
salt,
self.iterations
)
return salt.hex(), hash_value.hex()
def verify_password(self, password, salt_hex, hash_hex):
"""
验证密码
返回: True如果密码正确
"""
salt = bytes.fromhex(salt_hex)
expected_hash = bytes.fromhex(hash_hex)
computed_hash = hashlib.pbkdf2_hmac(
'sha256',
password.encode('utf-8'),
salt,
self.iterations
)
return hashlib.compare_digest(computed_hash, expected_hash)
def demonstrate_hashing():
"""演示哈希函数应用"""
print("=== SHA-256哈希 ===")
messages = [
"Hello, World!",
"Hello, World",
"",
"a" * 1000,
]
for msg in messages:
hash_val = compute_sha256(msg)
print(f"'{msg[:30]}{'...' if len(msg) > 30 else ''}' -> {hash_val[:16]}...")
print("\n=== 雪崩效应 ===")
msg1 = "password"
msg2 = "passwore" # 只改变一个字符
hash1 = compute_sha256(msg1)
hash2 = compute_sha256(msg2)
print(f"'{msg1}' -> {hash1}")
print(f"'{msg2}' -> {hash2}")
# 计算哈希值的差异位数
diff_bits = sum(
bin(int(a, 16) ^ int(b, 16)).count('1')
for a, b in zip(hash1, hash2)
)
total_bits = len(hash1) * 4
print(f"差异位数: {diff_bits}/{total_bits} ({100*diff_bits/total_bits:.1f}%)")
print("\n=== 密码哈希 ===")
hasher = PasswordHasher(iterations=10000) # 减少迭代次数以加快演示
password = "MySecurePassword123!"
salt, hash_val = hasher.hash_password(password)
print(f"盐: {salt[:16]}...")
print(f"哈希: {hash_val[:16]}...")
# 验证正确密码
correct = hasher.verify_password(password, salt, hash_val)
print(f"正确密码验证: {correct}")
# 验证错误密码
wrong = hasher.verify_password("WrongPassword", salt, hash_val)
print(f"错误密码验证: {wrong}")
if __name__ == "__main__":
demonstrate_hashing()五、深入思考
5.1 历史背景
数论有着悠久的历史:
- 欧几里得(约公元前300年):《几何原本》中包含欧几里得算法
- 费马(1601-1665):提出费马小定理和费马大定理
- 欧拉(1707-1783):发展模运算理论
- 高斯(1777-1855):《算术研究》系统化数论
密码学的历史:
- 凯撒密码:移位替换
- 恩尼格玛机:二战期间德国使用
- Diffie-Hellman(1976):公钥密码学开端
- RSA(1977):第一个实用公钥加密系统
5.2 前沿方向
- 后量子密码学:抵抗量子计算机攻击的算法
- 基于格的密码学(Lattice-based)
- 基于编码的密码学(Code-based)
- 多变量密码学
- 同态加密:在加密数据上直接计算
- 零知识证明:证明某事为真而不泄露额外信息
- 安全多方计算:多方联合计算而不泄露各自输入
5.3 延伸阅读
- 《An Introduction to the Theory of Numbers》by Hardy and Wright
- 《Handbook of Applied Cryptography》by Menezes, van Oorschot, Vanstone
- 《Understanding Cryptography》by Paar and Pelzl
六、实验笔记
实验1:RSA实现与分析
目标:完整实现RSA算法并分析其安全性。
任务:
实现素数生成(米勒-拉宾测试)
实现密钥生成、加密、解密
测试小密钥(32-64位)的因数分解难度
分析不同密钥长度下的性能
(进阶)实现简单的计时侧信道攻击
提交物:源代码、性能数据、安全分析报告。
实验2:哈希碰撞探索
目标:理解哈希函数的碰撞抗性。
任务:
实现生日攻击:寻找MD5的部分碰撞
分析不同哈希算法的输出分布
实现一个简单的密码破解工具(针对弱密码)
研究彩虹表原理
注意:仅在教育环境中进行,不得用于非法目的。
提交物:源代码、实验结果、伦理讨论。
七、本章小结
本章介绍了数论基础及其在密码学中的应用。整除性、素数、最大公约数是数论的基本概念,欧几里得算法提供了高效计算GCD的方法。
模运算构成了现代密码学的数学基础。费马小定理和欧拉定理是理解RSA算法的关键。RSA的安全性依赖于大数因数分解的困难性,而Diffie-Hellman密钥交换基于离散对数问题。
哈希函数在数据完整性验证、密码存储和数字签名中有广泛应用。理想的密码学哈希函数应具备单向性和碰撞抗性。
随着量子计算机的发展,现有公钥密码系统面临威胁,后量子密码学正在成为研究热点。
八、习题
习题1(基础):计算下列各题:
(a) gcd(1234, 5678)
(b) 17 mod 5
(c) 3¹⁰ mod 7
(d) φ(100)
习题2(基础):使用扩展欧几里得算法,找到整数x和y使得 35x + 15y = gcd(35, 15)。
习题3(中等):证明:如果p是素数,则 (p-1)! ≡ -1 (mod p)。(威尔逊定理)
习题4(中等):在RSA中,设p=61, q=53, e=17。计算:
(a) n和φ(n)
(b) 私钥d
(c) 加密消息m=65
(d) 验证解密正确性
习题5(中等):解释为什么基本的Diffie-Hellman协议容易受到中间人攻击,并提出改进方案。
习题6(较难):实现米勒-拉宾素性测试,并用它生成100位的素数。
习题7(较难):研究中国剩余定理,并用它优化RSA解密过程。
习题8(挑战):实现一个简单的哈希碰撞寻找程序(针对简化哈希函数),分析生日悖论。
习题9(挑战):研究并报告一种后量子密码算法的原理和现状。
习题10(开放):设计一个安全的用户认证系统,包括注册、登录、密码重置功能,详细说明使用的密码学技术及其理由。