注意本篇大多数的题解都是直接在VsCode点击按钮运行的,如果控制台终端输入python ABC.py(ABC.py为你写的脚本的名称)很可能会报一些小错误。这里我也不知道为什么,真的想不懂。
LSFR
题目:3级线性反馈移位寄存器在c3=1时有4种线性反馈函数,设其初始状态为(a1,a2,a3)=(1,0,1),求各线性反馈函数的输出序列及周期,输出他们的密钥流,并利用生成的密钥流对明文'0x0123456789ABCDEF'进行加密,输出加密后的结果,再对密文进行解密,输出解密后的结果。 已知:
- 寄存器长度:n = 3
- 状态:(a1, a2, a3)
- 初始状态:(1, 0, 1)
- 条件:c3 = 1
LFSR 的反馈函数是:f=c1a1⊕c2a2⊕c3a3。因为:c3=1,所以:f=c1a1⊕c2a2⊕a3
因为: ,,所以一共有4种情况,对应4 个反馈函数。
| 编号 | 反馈函数 | 周期 | |
|---|---|---|---|
| 1 | 很短 | ||
| 2 | 较短 | ||
| 3 | 可能最大 | ||
| 4 | 最大周期7(m序列) |
状态更新原则:
每一轮输出值:
def lfsr_step(state, c1, c2):
a1, a2, a3 = state
f = (c1 & a1) ^ (c2 & a2) ^ a3
return (a2, a3, f)
def generate_sequence(init_state, c1, c2):
state = init_state
seen = []
output = []
while state not in seen:
seen.append(state)
output.append(state[0])
state = lfsr_step(state, c1, c2)
return output, len(seen)
def bits_to_bytes(bits):
res = []
for i in range(0, len(bits), 8):
byte = 0
for j in range(8):
if i + j < len(bits):
byte = (byte << 1) | bits[i + j]
res.append(byte)
return res
def encrypt(hex_str, keystream_bits):
data = bytes.fromhex(hex_str[2:])
ks = bits_to_bytes(keystream_bits)
return bytes([d ^ ks[i] for i, d in enumerate(data)]).hex()
def decrypt(cipher_hex, keystream_bits):
data = bytes.fromhex(cipher_hex)
ks = bits_to_bytes(keystream_bits)
return bytes([d ^ ks[i] for i, d in enumerate(data)]).hex()
# ==========================
# 主程序
# ==========================
init_state = (1, 0, 1)
plaintext = "0x0123456789ABCDEF"
configs = [
(0, 0),
(0, 1),
(1, 0),
(1, 1)
]
for c1, c2 in configs:
print("=" * 40)
print(f"反馈函数: f = {c1}*a1 ⊕ {c2}*a2 ⊕ a3")
seq, period = generate_sequence(init_state, c1, c2)
print("输出序列:", seq)
print("周期:", period)
# 生成64bit密钥流
keystream = (seq * (64 // len(seq) + 1))[:64]
print("密钥流(bit):", keystream)
# 加密
cipher = encrypt(plaintext, keystream)
print("密文:", cipher)
# 解密
plain = decrypt(cipher, keystream)
print("解密:", plain)
NFLSR
题目:设n=4,f(a1,a2,a3,a4)=a1* a4^(a2 * a3),初始状态为(a1,a2,a3,a4)=(1,1,0,1),求此非线性反馈移位寄存器的输出序列及周期,输出他的密钥流,并利用生成的密钥流对明文'0x0123456789ABCDEF'进行加密,输出加密后的结果,再对密文进行解密,输出解密后的结果。 流密码原理 1)生成密钥流(keystream);2)明文 XOR 密钥流 → 密文 3)密文 XOR 密钥流 → 明文。 加密:cipher = plaintext XOR keystream 解密:decrypt(cipher) == plaintext
- 寄存器长度:
- 状态:
- 反馈函数:
状态更新原则:
输出序列一般取:
def nlfsr_step(state):
a1, a2, a3, a4 = state
# 非线性反馈函数
f = (a1 & a4) ^ (a2 & a3)
# 移位
return (a2, a3, a4, f)
def generate_sequence(init_state):
state = init_state
seen = []
output_seq = []
while state not in seen:
seen.append(state)
output_seq.append(state[0]) # 输出 a1
state = nlfsr_step(state)
period = len(seen)
return output_seq, period
def bits_to_bytes(bits):
res = []
for i in range(0, len(bits), 8):
byte = 0
for j in range(8):
if i + j < len(bits):
byte = (byte << 1) | bits[i + j]
res.append(byte)
return res
def encrypt(plaintext_hex, keystream_bits):
plaintext = bytes.fromhex(plaintext_hex[2:])
keystream_bytes = bits_to_bytes(keystream_bits)
cipher = bytes([p ^ keystream_bytes[i] for i, p in enumerate(plaintext)])
return cipher.hex()
def decrypt(cipher_hex, keystream_bits):
cipher = bytes.fromhex(cipher_hex)
keystream_bytes = bits_to_bytes(keystream_bits)
plain = bytes([c ^ keystream_bytes[i] for i, c in enumerate(cipher)])
return plain.hex()
# ==========================
# 主流程
# ==========================
init_state = (1, 1, 0, 1)
# 生成序列
seq, period = generate_sequence(init_state)
print("输出序列:", seq)
print("周期:", period)
# 生成足够长的密钥流(明文8字节=64bit)
keystream_bits = (seq * (64 // len(seq) + 1))[:64]
print("密钥流(bit):\n", keystream_bits)
# 明文
plaintext = "0x0123456789ABCDEF"
# 加密
cipher = encrypt(plaintext, keystream_bits)
print("密文:", cipher)
# 解密
decrypted = decrypt(cipher, keystream_bits)
print("解密结果:", decrypted)
ECC
题目:已知椭圆曲线E11(1,6),编程求其上所有的点。
这个问题本质是在有限域 上求椭圆曲线
的所有点。
思路:
- 枚举
- 计算右边
- 枚举 ,找满足以下 条件的解
- 加上无穷远点
#include <stdio.h>
#define p 11
#define a 1
#define b 6
typedef struct {
int x;
int y;
} Point;
int isOnCurve(Point point) {
int left = (point.y * point.y) % p;
int right = (point.x * point.x * point.x + a * point.x + b) % p;
return left == right;
}
int main() {
int count = 0;
for (int x = 0; x < p; x++) {
for (int y = 0; y < p; y++) {
Point point = {x, y};
if (isOnCurve(point)) {
printf("(%d, %d)\n", point.x, point.y);
count++;
}
}
}
printf("Point at infinity: O\n"); //注意,必须添加无穷远点。
printf("Total points (including O): %d\n", count + 1);
return 0;
}
p = 11
a = 1
b = 6
points = []
for x in range(p):
rhs = (x**3 + a*x + b) % p
for y in range(p):
if (y*y) % p == rhs:
points.append((x, y))
# 加上无穷远点
points.append("O")
print("椭圆曲线上的点:")
for pt in points:
print(pt)
print("\n点的总数:", len(points))
背包
题目:编程实现背包密码的加密和解密,假设选取的私钥为超递增背包向量 A=[1, 3, 5, 11, 21, 44, 87, 175, 349, 701],选取模数k = 1590和乘数t = 43,计算新的背包向量B == t * A (mod k)作为公钥。利用上述密码算法对明文“SAUNA AND HEALTH”进行加密,输出密文,并对密文进行解密。
实现一个公钥加密系统:
- 私钥:超递增序列 A
- 公钥:B = t·A mod k
- 加密:用 B 做“子集和”
- 解密:用 A 做“贪心恢复”
加解密原理:
超递增序列(私钥)。A = [1, 3, 5, 11, 21, 44, 87, 175, 349, 701] 。 满足每个元素 > 前面所有元素之和
保证子集和可唯一反推(贪心)。
↓
公钥生成 Bi=(t⋅Ai)mod k , k = 1590,t = 43(i是下标)
↓
加密。把字符 → 二进制(10 bit,对应 A 长度) C=∑bi⋅Bi
↓
解密。1. 求逆元:t^-1 modk
2. 还原:C′=C⋅t^−1 modk
3. 用 A 贪心恢复 bit
# 私钥
A = [1, 3, 5, 11, 21, 44, 87, 175, 349, 701]
# 参数
k = 1590
t = 43
# 求逆元(扩展欧几里得)
def modinv(a, m):
def egcd(a, b):
if b == 0:
return a, 1, 0
g, x1, y1 = egcd(b, a % b)
return g, y1, x1 - (a // b) * y1
g, x, _ = egcd(a, m)
if g != 1:
raise Exception("无逆元")
return x % m
# 生成公钥
B = [(t * ai) % k for ai in A]
print("公钥 B:", B)
# 字符转10bit
def char_to_bits(c):
val = ord(c)
return [(val >> i) & 1 for i in reversed(range(10))]
# bits转字符
def bits_to_char(bits):
val = 0
for b in bits:
val = (val << 1) | b
return chr(val)
# 加密
def encrypt(plaintext):
ciphertext = []
for ch in plaintext:
bits = char_to_bits(ch)
c = sum(b * bi for b, bi in zip(bits, B))
ciphertext.append(c)
return ciphertext
# 解密
def decrypt(ciphertext):
inv_t = modinv(t, k)
plaintext = ""
for c in ciphertext:
c_prime = (c * inv_t) % k
# 贪心恢复
bits = [0] * len(A)
for i in reversed(range(len(A))):
if c_prime >= A[i]:
bits[i] = 1
c_prime -= A[i]
plaintext += bits_to_char(bits)
return plaintext
# ==========================
# 主程序
# ==========================
plaintext = "SAUNA AND HEALTH"
print("明文:", plaintext)
cipher = encrypt(plaintext)
print("密文:", cipher)
decrypted = decrypt(cipher)
print("解密:", decrypted)
ElGamal
题目:编程实现ElGamal的加密和解密,假设用户A选择素数p=11和本原根g=2,并且选择私钥α=5,输出A的公钥;若用户B向用户A发送消息m=6,随机数k=7,输出对该消息加密后的密文,以及对密文进行解密的明文。
已知:
- 素数:p=11
- 本原根:g=2
- A 的私钥:α=5
生成公钥。β=g^α modp,计算β=2^5 mod 11= 32 mod 11= 10,所以A的公钥为(p, g, β) = (11, 2, 10)
↓
加密(B → A)。给定,明文:m = 6,随机数:k = 7。计算 c1=g^k mod p= 2^7 mod 11= 7,c2=m⋅β^k mod p=6*10^7 mod 11=5。所以密文为(c1, c2) = (7, 5)
↓
解密(A)。m=c2⋅(c1^α)^−1 mod p=5*(7^5)^-1 mod 11=5*(7^5mod 11)^-1 mod 11=5*10^-1 mod 11=6。
# 参数
p = 11
g = 2
alpha = 5 # 私钥
# 快速幂
def mod_exp(base, exp, mod):
result = 1
base %= mod
while exp > 0:
if exp & 1:
result = (result * base) % mod
base = (base * base) % mod
exp >>= 1
return result
# 求逆元
def modinv(a, p):
for i in range(1, p):
if (a * i) % p == 1:
return i
return None
# ==========================
# 1. 生成公钥
# ==========================
beta = mod_exp(g, alpha, p)
print("公钥 (p, g, β):", (p, g, beta))
# ==========================
# 2. 加密
# ==========================
m = 6
k = 7
c1 = mod_exp(g, k, p)
c2 = (m * mod_exp(beta, k, p)) % p
print("密文 (c1, c2):", (c1, c2))
# ==========================
# 3. 解密
# ==========================
s = mod_exp(c1, alpha, p)
s_inv = modinv(s, p)
m_decrypted = (c2 * s_inv) % p
print("解密后的明文:", m_decrypted)
RSA
题目:编程实现RSA的加密和解密,选择参数p=71593,q=77041,e=1757316971,输出公钥和私钥,并对消息“I need your best time”进行加密,输出密文。最后对密文进行解密,输出明文。 已知:
- 两个大素数 p=71593,q=77041
- 公钥指数 e=1757316971
RSA 核心原理:
1.n=p⋅q
1. ϕ(n)=(p−1)(q−1)
2. 私钥 d 满足:e⋅d ≡1(modϕ(n))
3. 加密:c=m^e mod n
4. 解密:m=c^d mod n 其中 m 是明文整数。字符串 → 数字需 ASCII 编码 或 utf-8。
# 参数
p = 71593
q = 77041
e = 1757316971
# 计算 n 和 phi
n = p * q
phi = (p - 1) * (q - 1)
# 求逆元 d
def modinv(a, m):
def egcd(a, b):
if b == 0:
return a, 1, 0
g, x1, y1 = egcd(b, a % b)
return g, y1, x1 - (a // b) * y1
g, x, _ = egcd(a, m)
if g != 1:
raise Exception("No modular inverse")
return x % m
d = modinv(e, phi)
print("公钥 (n, e):", (n, e))
print("私钥 d:", d)
# ==========================
# 分块加密
# ==========================
message = "I need your best time"
message_bytes = message.encode('utf-8')
# 每块最大长度(保证 m < n)
max_block_size = (n.bit_length() - 1) // 8
blocks = [message_bytes[i:i+max_block_size] for i in range(0, len(message_bytes), max_block_size)]
cipher_blocks = []
for block in blocks:
m_int = int.from_bytes(block, 'big')
c = pow(m_int, e, n)
cipher_blocks.append(c)
print("密文分块:", cipher_blocks)
# ==========================
# 分块解密
# ==========================
decrypted_bytes = b''
for c in cipher_blocks:
m_decrypted = pow(c, d, n)
length = (m_decrypted.bit_length() + 7) // 8
decrypted_bytes += m_decrypted.to_bytes(length, 'big')
decrypted_message = decrypted_bytes.decode('utf-8')
print("解密后的明文:", decrypted_message)
DH
题目:编程计算25的所有本原根。
- 本原根定义
对于整数 和 (模 ),如果 的阶等于欧拉函数 ,则称 是 的本原根:
会生成模 的所有互质剩余类(即整数 1 到 与 互质的整数)。
- 计算步骤
- 计算
- 检查每个 ,若:
则 是本原根。
- 20 的质因子:2, 5。
def euler_phi(n):
"""计算欧拉函数 φ(n)"""
result = n
p = 2
temp = n
while p * p <= temp:
if temp % p == 0:
while temp % p == 0:
temp //= p
result -= result // p
p += 1
if temp > 1:
result -= result // temp
return result
def prime_factors(n):
"""返回 n 的质因子集合"""
i = 2
factors = set()
while i * i <= n:
if n % i == 0:
factors.add(i)
while n % i == 0:
n //= i
i += 1
if n > 1:
factors.add(n)
return factors
def is_primitive_root(g, n):
"""判断 g 是否为 n 的本原根"""
if gcd(g, n) != 1:
return False
phi = euler_phi(n)
for p in prime_factors(phi):
if pow(g, phi // p, n) == 1:
return False
return True
def gcd(a, b):
while b:
a, b = b, a % b
return a
# =====================
n = 25
roots = []
for g in range(1, n):
if is_primitive_root(g, n):
roots.append(g)
print(f"{n} 的所有本原根:",roots)
题目:编程实现Diffie-Hellman密钥交换协议,假设共享素数p=19,它的一个本原元g =3,A选秘密的随机数x=5,B选秘密的随机数y=7,输出A和B共享的密钥。
- 素数:p=19
- 本原元:g=3
- A 的私钥:x=5
- B 的私钥:y=7
A计算并发送15
B计算并发送2
计算共享密钥 A计算
B计算
所以最终的共享密钥就是K=13
# 参数
p = 19
g = 3
x = 5 # A的私钥
y = 7 # B的私钥
# 快速幂
def mod_exp(base, exp, mod):
result = 1
base %= mod
while exp > 0:
if exp & 1:
result = (result * base) % mod
base = (base * base) % mod
exp >>= 1
return result
# A计算并发送
A = mod_exp(g, x, p)
print("A发送:", A)
# B计算并发送
B = mod_exp(g, y, p)
print("B发送:", B)
# 共享密钥
K_A = mod_exp(B, x, p)
K_B = mod_exp(A, y, p)
print("A计算的共享密钥:", K_A)
print("B计算的共享密钥:", K_B)