defis_prime(n, k=5): """米勒-拉宾素数检测(增强稳定性,k=10提高检测准确率)""" if n <= 1: returnFalse if n <= 3: returnTrue if n % 2 == 0: returnFalse d = n - 1 s = 0 while d % 2 == 0: d //= 2 s += 1 for _ inrange(10): a = random.randint(2, n - 2) x = pow(a, d, n) if x == 1or x == n - 1: continue for _ inrange(s - 1): x = pow(x, 2, n) if x == n - 1: break else: returnFalse returnTrue
defgenerate_strong_prime(bit_length=256, min_value=1): """生成强素数p=2q+1""" whileTrue: q = random.getrandbits(bit_length - 1) if q % 2 == 0: q += 1 # 确保q是素数且p=2q+1>min_value if is_prime(q): p = 2 * q + 1 if is_prime(p) and p > min_value: return p, q
deffind_primitive_root(p, q): """寻找模p的原根""" if p == 2: return1 # p-1=2q,q为素数,原根需满足g^1≠1 mod p、g^2≠1 mod p、g^q≠1 mod p whileTrue: g = random.randint(2, p - 2) # 双重验证:避免g=1或g=p-1(此时g^2≡1 mod p) ifpow(g, 1, p) == 1orpow(g, 2, p) == 1: continue ifpow(g, q, p) != 1: return g
defmod_inverse(a, p): """扩展欧几里得算法求模逆""" m0 = p y = 0 x = 1 if p == 1: return0 a_original = a while a > 1: if p == 0: raise Exception(f"模逆不存在:gcd({a_original}, {m0})={a_original}≠1") q = a // p t = p p = a % p a = t t = y y = x - q * y x = t if x < 0: x += m0 # 验证逆元正确性:(a_original * x) mod m0 == 1 if (a_original * x) % m0 != 1: raise Exception(f"模逆计算错误:{a_original} * {x} mod {m0} = {(a_original * x) % m0} ≠ 1") return x
defelgamal_key_gen(p, g): """生成私钥a和公钥y=g^a mod p""" # 私钥a选取范围:[3, p-3],避免a=1或a=p-2等极端值 a = random.randint(3, p - 3) y = pow(g, a, p) return a, y
defelgamal_encrypt(m, p, g, y): """加密:返回(C1, C2)""" # 校验1:明文m必须小于p,否则溢出 if m >= p: raise ValueError(f"明文m={m} ≥ 强素数p={p},请增大p的比特长度或减小明文") # 校验2:随机数k选取范围[3, p-3],且与p-1互素 whileTrue: k = random.randint(3, p - 3) # 确保gcd(k, p-1)=1,避免密文空间缩小 if math.gcd(k, p - 1) == 1: break C1 = pow(g, k, p) yk = pow(y, k, p) C2 = (m % p) * (yk % p) % p return C1, C2, k
defelgamal_decrypt(C1, C2, p, a): """解密:返回明文m""" # 校验密文合法性:C1和C2必须在[1, p-1]之间 if C1 < 1or C1 >= p or C2 < 0or C2 >= p: raise ValueError(f"密文非法:C1={C1},C2={C2}(需满足1≤C1≤p-1,0≤C2≤p-1)") V = pow(C1, a, p) V_inv = mod_inverse(V, p) m = (C2 * V_inv) % p return m
defread_plaintext(file_path="secret1.txt"): """读取明文文件""" withopen(file_path, "r") as f: content = f.read().strip() m = int(content) print(f"成功读取明文:m={m}") return m
if __name__ == "__main__": # 1. 读取明文(先获取明文,再生成足够大的p) m = read_plaintext() # 2. 生成强素数p(确保p > m,比特长度至少256位) bit_length = max(256, m.bit_length() + 10) # p比m多10位,确保p > m p, q = generate_strong_prime(bit_length=bit_length, min_value=m + 1) # 3. 寻找模p的原根g g = find_primitive_root(p, q) # 4. 生成密钥对 a, y = elgamal_key_gen(p, g) # 5. 加密 C1, C2, k = elgamal_encrypt(m, p, g, y) # 6. 解密 m_decrypted = elgamal_decrypt(C1, C2, p, a) # 7. 输出结果 print("\n=== ElGamal算法测试结果===") print(f"强素数p(比特长度:{bit_length}): {p}") print(f"素数q(满足p=2q+1): {q}") print(f"模p的原根g: {g}") print(f"私钥a: {a}") print(f"公钥组件y=g^a mod p: {y}") print(f"随机整数k(与p-1互素): {k}") print(f"密文C1=g^k mod p: {C1}") print(f"密文C2=m*y^k mod p: {C2}") print(f"原始明文m: {m}") print(f"解密明文m': {m_decrypted}") print(f"\n=== 验证结果 ===") print(f"明文一致性验证:{'✅ 一致'if m == m_decrypted else'❌ 不一致'}")