密码学系列之流密码&RSA&ECC等
<p><img src="https://img2024.cnblogs.com/blog/3426414/202603/3426414-20260331195854707-1269957529.png" alt="Snipaste_2026-03-31_19-58-43" loading="lazy"><br>注意本篇大多数的题解都是直接在VsCode点击按钮运行的,如果控制台终端输入python ABC.py(ABC.py为你写的脚本的名称)很可能会报一些小错误。这里我也不知道为什么,真的想不懂。</p>
<h1 id="lsfr">LSFR</h1>
<p>题目:3级线性反馈移位寄存器在c3=1时有4种线性反馈函数,设其初始状态为(a1,a2,a3)=(1,0,1),求各线性反馈函数的输出序列及周期,输出他们的密钥流,并利用生成的密钥流对明文'0x0123456789ABCDEF'进行加密,输出加密后的结果,再对密文进行解密,输出解密后的结果。<br>
已知:</p>
<ul>
<li>寄存器长度:n = 3</li>
<li>状态:(a1, a2, a3)</li>
<li>初始状态:(1, 0, 1)</li>
<li>条件:<strong>c3 = 1</strong></li>
</ul>
<p>LFSR 的反馈函数是:f=c1a1⊕c2a2⊕c3a3。因为:c3=1,所以:f=c1a1⊕c2a2⊕a3</p>
<p>因为:<span class="math inline">\(c_1 \in \{0,1\}\)</span>,<span class="math inline">\(c_2 \in \{0,1\}\)</span>,所以一共有4种情况,对应4 个反馈函数。</p>
<table>
<thead>
<tr>
<th>编号</th>
<th><span class="math inline">\((c_1,c_2,c_3)\)</span></th>
<th>反馈函数</th>
<th>周期</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><span class="math inline">\((0,0,1)\)</span></td>
<td><span class="math inline">\(a_3\)</span></td>
<td>很短</td>
</tr>
<tr>
<td>2</td>
<td><span class="math inline">\((0,1,1)\)</span></td>
<td><span class="math inline">\(a_2 \oplus a_3\)</span></td>
<td>较短</td>
</tr>
<tr>
<td>3</td>
<td><span class="math inline">\((1,0,1)\)</span></td>
<td><span class="math inline">\(a_1 \oplus a_3\)</span></td>
<td>可能最大</td>
</tr>
<tr>
<td>4</td>
<td><span class="math inline">\((1,1,1)\)</span></td>
<td><span class="math inline">\(a_1 \oplus a_2 \oplus a_3\)</span></td>
<td>最大周期7(m序列)</td>
</tr>
</tbody>
</table>
<p>状态更新原则:</p>
<p></p><div class="math display">\[(a_1, a_2, a_3) \rightarrow (a_2, a_3, f)
\]</div><p></p><p>每一轮输出值:</p>
<p></p><div class="math display">\[\text{输出值} 为 a_1
\]</div><p></p><pre><code class="language-python">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)
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
res.append(byte)
return res
def encrypt(hex_str, keystream_bits):
data = bytes.fromhex(hex_str)
ks = bits_to_bytes(keystream_bits)
return bytes( 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( 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)
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/3426414/202603/3426414-20260331193750927-913770287.png" alt="Snipaste_2026-03-31_16-52-25" loading="lazy"></p>
<h1 id="nflsr">NFLSR</h1>
<p>题目:设n=4,f(a1,a2,a3,a4)=a1* a4^(a2 * a3),初始状态为(a1,a2,a3,a4)=(1,1,0,1),求此非线性反馈移位寄存器的输出序列及周期,输出他的密钥流,并利用生成的密钥流对明文'0x0123456789ABCDEF'进行加密,输出加密后的结果,再对密文进行解密,输出解密后的结果。<br>
流密码原理 1)生成密钥流(keystream);2)明文 XOR 密钥流 → 密文 3)密文 XOR 密钥流 → 明文。<br>
加密:cipher = plaintext XOR keystream 解密:decrypt(cipher) == plaintext</p>
<ul>
<li>寄存器长度:<span class="math inline">\(n = 4\)</span></li>
<li>状态:<span class="math inline">\((a_1, a_2, a_3, a_4)\)</span></li>
<li>反馈函数:</li>
</ul>
<p></p><div class="math display">\[f(a_1, a_2, a_3, a_4) = a_1 \cdot a_4 \oplus (a_2 \cdot a_3)
\]</div><p></p><p>状态更新原则:</p>
<p></p><div class="math display">\[(a_1, a_2, a_3, a_4) \rightarrow (a_2, a_3, a_4, f)
\]</div><p></p><p>输出序列一般取:</p>
<p></p><div class="math display">\[\text{输出} = a_1 \quad (\text{最左边})
\]</div><p></p><pre><code class="language-python">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)# 输出 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
res.append(byte)
return res
def encrypt(plaintext_hex, keystream_bits):
plaintext = bytes.fromhex(plaintext_hex)
keystream_bytes = bits_to_bytes(keystream_bits)
cipher = bytes( 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( 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)
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/3426414/202603/3426414-20260331193808603-1658601156.png" alt="Snipaste_2026-03-31_16-47-07" loading="lazy"></p>
<h1 id="ecc">ECC</h1>
<p>题目:已知椭圆曲线E11(1,6),编程求其上所有的点。</p>
<p>这个问题本质是在有限域 <span class="math inline">\(\mathbb{F}_{11}\)</span> 上求椭圆曲线</p>
<p></p><div class="math display">\[E: y^2 \equiv x^3 + x + 6 \pmod{11}
\]</div><p></p><p>的所有点。</p>
<p>思路:</p>
<ol>
<li>枚举 <span class="math inline">\(x \in \)</span></li>
<li>计算右边<p></p><div class="math display">\[rhs = x^3 + x + 6 \pmod{11}
\]</div><p></p></li>
<li>枚举 <span class="math inline">\(y \in \)</span>,找满足以下 条件的解<p></p><div class="math display">\[y^2 \equiv rhs \pmod{11}
\]</div><p></p></li>
<li>加上无穷远点 <span class="math inline">\(O\)</span></li>
</ol>
<pre><code class="language-C">#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;
}
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/3426414/202603/3426414-20260331195304921-2002982147.png" alt="Snipaste_2026-03-31_17-02-38" loading="lazy"></p>
<pre><code class="language-python">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))
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/3426414/202603/3426414-20260331195321260-1736111763.png" alt="Snipaste_2026-03-31_17-11-29" loading="lazy"></p>
<h1 id="背包">背包</h1>
<p>题目:编程实现背包密码的加密和解密,假设选取的私钥为超递增背包向量 A=,选取模数k = 1590和乘数t = 43,计算新的背包向量B == t * A (mod k)作为公钥。利用上述密码算法对明文“SAUNA AND HEALTH”进行加密,输出密文,并对密文进行解密。</p>
<p>实现一个<strong>公钥加密系统</strong>:</p>
<ul>
<li>私钥:超递增序列 A</li>
<li>公钥:B = t·A mod k</li>
<li>加密:用 B 做“子集和”</li>
<li>解密:用 A 做“贪心恢复”</li>
</ul>
<pre><code class="language-go">加解密原理:
超递增序列(私钥)。A = 。 满足每个元素 > 前面所有元素之和
保证子集和可唯一反推(贪心)。
↓
公钥生成 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
</code></pre>
<pre><code class="language-python"># 私钥
A =
# 参数
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 = * len(A)
for i in reversed(range(len(A))):
if c_prime >= A:
bits = 1
c_prime -= A
plaintext += bits_to_char(bits)
return plaintext
# ==========================
# 主程序
# ==========================
plaintext = "SAUNA AND HEALTH"
print("明文:", plaintext)
cipher = encrypt(plaintext)
print("密文:", cipher)
decrypted = decrypt(cipher)
print("解密:", decrypted)
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/3426414/202603/3426414-20260331195430721-89184755.png" alt="Snipaste_2026-03-31_17-39-48" loading="lazy"></p>
<h1 id="elgamal">ElGamal</h1>
<p>题目:编程实现ElGamal的加密和解密,假设用户A选择素数p=11和本原根g=2,并且选择私钥α=5,输出A的公钥;若用户B向用户A发送消息m=6,随机数k=7,输出对该消息加密后的密文,以及对密文进行解密的明文。</p>
<p>已知:</p>
<ul>
<li>素数:p=11</li>
<li>本原根:g=2</li>
<li>A 的私钥:α=5</li>
</ul>
<pre><code class="language-go">生成公钥。β=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。
</code></pre>
<pre><code class="language-go"># 参数
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)
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/3426414/202603/3426414-20260331195514438-840820072.png" alt="Snipaste_2026-03-31_17-44-24" loading="lazy"></p>
<h1 id="rsa">RSA</h1>
<p>题目:编程实现RSA的加密和解密,选择参数p=71593,q=77041,e=1757316971,输出公钥和私钥,并对消息“I need your best time”进行加密,输出密文。最后对密文进行解密,输出明文。<br>
已知:</p>
<ul>
<li>两个大素数 p=71593,q=77041</li>
<li>公钥指数 e=1757316971</li>
</ul>
<pre><code class="language-go">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。
</code></pre>
<pre><code class="language-python"># 参数
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 = 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)
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/3426414/202603/3426414-20260331195553279-722944016.png" alt="Snipaste_2026-03-31_18-59-50" loading="lazy"></p>
<h1 id="dh">DH</h1>
<p>题目:编程计算25的所有本原根。</p>
<ol>
<li>本原根定义</li>
</ol>
<p>对于整数 <span class="math inline">\(n\)</span> 和 <span class="math inline">\(g\)</span>(模 <span class="math inline">\(n\)</span>),如果 <span class="math inline">\(g\)</span> 的阶等于欧拉函数 <span class="math inline">\(\phi(n)\)</span>,则称 <span class="math inline">\(g\)</span> 是 <span class="math inline">\(n\)</span> 的本原根:</p>
<p></p><div class="math display">\[g^1, g^2, ..., g^{\phi(n)} \mod n
\]</div><p></p><p>会生成模 <span class="math inline">\(n\)</span> 的所有互质剩余类(即整数 1 到 <span class="math inline">\(n-1\)</span> 与 <span class="math inline">\(n\)</span> 互质的整数)。</p>
<ol start="2">
<li>计算步骤</li>
</ol>
<ul>
<li><span class="math inline">\(n = 25\)</span></li>
<li>计算 <span class="math inline">\(\phi(25) = 25 \cdot (1 - 1/5) = 20\)</span></li>
<li>检查每个 <span class="math inline">\(g \in \)</span>,若:</li>
</ul>
<p></p><div class="math display">\[g^{20/p} \neq 1 \pmod{25} \quad \forall p \text{ 是 } 20 \text{ 的质因子}
\]</div><p></p><p>则 <span class="math inline">\(g\)</span> 是本原根。</p>
<ul>
<li>20 的质因子:2, 5。</li>
</ul>
<pre><code class="language-python">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)
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/3426414/202603/3426414-20260331194056742-1906498396.png" alt="Snipaste_2026-03-31_19-08-47" loading="lazy"></p>
<p>题目:编程实现Diffie-Hellman密钥交换协议,假设共享素数p=19,它的一个本原元g =3,A选秘密的随机数x=5,B选秘密的随机数y=7,输出A和B共享的密钥。</p>
<ul>
<li>素数:p=19</li>
<li>本原元:g=3</li>
<li>A 的私钥:x=5</li>
<li>B 的私钥:y=7</li>
</ul>
<p>A计算并发送15</p>
<p></p><div class="math display">\[A = g^x \mod p = 3^5 \mod 19 = 15
\]</div><p></p><p>B计算并发送2</p>
<p></p><div class="math display">\[B = g^y\mod p = 3^7 \mod 19 =2
\]</div><p></p><p>计算共享密钥<br>
A计算</p>
<p></p><div class="math display">\[K = B^x \mod p = 2^5 \mod 19= 13
\]</div><p></p><p>B计算</p>
<p></p><div class="math display">\[K = A^y \mod p = 15^7 \mod 19= 13
\]</div><p></p><p>所以最终的共享密钥就是K=13</p>
<pre><code class="language-python"># 参数
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)
</code></pre>
<p><img src="https://img2024.cnblogs.com/blog/3426414/202603/3426414-20260331194000421-838848507.png" alt="Snipaste_2026-03-31_19-12-36" loading="lazy"></p><br><br>
来源:https://www.cnblogs.com/red1giant-star/p/19803538
頁:
[1]