密码学|公钥密码
公钥密码概述
加密与解密使用不同密钥,分公钥与私钥
公钥密码体制安全性依赖于计算困难问题,
单向函数\((OWF--one way function)\): 由x计算\(y=f(x)\)是容易的,但反之是计算困难的
计算难易以计算复杂性理论为依据
陷门\((trapdoor)\)单向函数: 有陷门(私钥)可以求\(f\)的逆,用于构造单向函数的计算困难问题。
- 大数分解 (factering):求\(N=p*q\)中的\(p\)和\(q\)
- 离散对数\((DL)\): 求\(y= g^xmod p\)的\(x\)
- 椭圆曲线上离散对数: 求\(y=xP\)的\(x\)
- 二次剩余\((QR)\): 求\(y = x^2 modN\)的\(x\)
-\(Diffe-Hullman\)问题\((DH)\):\(g^xg^y ↛ g^{xy}\) - 椭圆曲线上双线性对\(( pairing )\)的问题
公钥密码的计算都在相应的代数结构中进行
RSA
基于数论中大整数分解的困难性
密钥生成 (Key Generation)
- 随机选择两个不同的大素数,记为\(p\)和\(q\)。这两个素数需要足够大,必须保密
- 计算\(n = p * q\)。\(n\)将作为公钥和私钥的一部分,是加密和解密运算的模数。\(n\)的长度(以位为单位)通常决定了RSA密钥的强度
- 计算欧拉函数\(φ(n) = (p - 1) * (q - 1)\)。这个值用于后续计算,但不会直接出现在公钥或私钥中,必须保密。
- 选择公钥指数\(e\),满足:
- \(1 < e < φ(n)\)
- \(e\)与\(φ(n)\)互质,即\(gcd(e, φ(n)) = 1\)
- 通常选择一些固定的值,如
e = 65537(即0x10001),
- 计算私钥指数\(d\),使得\(d\)是\(e\)关于模\(φ(n)\)的乘法逆元。也就是说,需要找到一个\(d\)满足:
- \(e * d ≡ 1 (mod φ(n))\)
- 或者等价地,\(e * d = k * φ(n) + 1\),其中\(k\)是某个整数
- \(d\)通过扩展欧几里得算法。\(d\)必须保密
- 生成密钥对:
- 公钥:\((e, n)\)可以安全地公开分享
- 私钥:\((d, n)\)必须严格保密
加密 (Encryption)
假设Alice想给Bob发送一条加密消息,她需要使用Bob的公钥
- Alice获取Bob的公钥\((e, n)\)
- Alice将要发送的消息\(M\)转换为一个整数\(m\)。这个整数\(m\)必须满足\(0 ≤ m < n\)。如果原始消息太大,需要使用填充方案将其分割或编码成符合要求的块
- 计算密文\(c ≡ m^e (mod n)\)
解密 (Decryption)
Bob收到密文\(c\)后,使用自己的私钥来恢复原始消息。
- Bob使用自己的私钥\((d, n)\)
- 计算明文对应的整数\(m' ≡ c^d (mod n)\)
- Bob将整数\(m'\)转换回原始的消息\(M\)
实现
https://www.cnblogs.com/luminescence/p/18931824
RSA的计算
加解密的计算证明
如果\(m\)和\(n\)互质,那么\(m^φ(n) ≡ 1 (mod n)\)
\(e * d ≡ 1 (mod φ(n))\),所以存在整数\(k\)使得\(e * d = k * φ(n) + 1\)
\(m ≡ c^d ≡ (m^e)^d ≡ m^{(e*d)} ≡ m^{(k*φ(n) + 1)} ≡ (m^{φ(n)})^k * m^1 ≡ 1^k * m ≡ m (mod n)\)
模逆算法
拓展欧几里得算法Extended Euclidean Algorithm
通过贝组等式找到乘法逆元
\(a \cdot x + b \cdot y = \gcd(a, b)\)
- 递归形式:
- 基础情况:如果\(b = 0\),则\(\gcd(a, b) = a\),此时\(x = 1\),\(y = 0\)
- 递归步骤:假设\(\gcd(b, a \mod b) = x' \cdot b + y' \cdot (a \mod b)\),则:
\(\gcd(a, b) = x' \cdot b + y' \cdot (a - \lfloor a/b \rfloor \cdot b) = y' \cdot a + (x' - \lfloor a/b \rfloor \cdot y') \cdot b\)
因此,新的\(x = y'\),\(y = x' - \lfloor a/b \rfloor \cdot y'\)
- 迭代形式:
- 初始化:\(x = 1\),\(y = 0\),\(x' = 0\),\(y' = 1\)
- 循环:当\(b \neq 0\)时:
- 计算\(q = \lfloor a / b \rfloor\),\(r = a \mod b\)
- 更新\(a = b\),\(b = r\)
- 更新\((x, y, x', y') = (x' - q \cdot x, y' - q \cdot y, x, y)\)
\({a}*{x} + {b}*{y} = gcd(a,b)\)
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
\(gcd(a,b) = 1\)时,即求a在模b下的乘法逆元
快速模幂运算
求\(𝒎^𝒅mod𝒏\)快速算法步骤:
1、将指数d表示为二进制\(a_{k-1}⋯a_1a_0\);
2、令\(x = 1, y = m\);
3、迭代从下标 i = 0开始,
如果\(a_i = 1\),计算\(x = xy mod n\),\(y = y^𝟐 mod n\)
如果\(a_i = 0\),只计算\(y = y^2 mod n\)
4、迭代至\(k-1\),最后结果就是此时的\(x\)
def fast_modular_exponentiation(m, d, n):
"""
快速模幂运算
"""
# 将指数d转换为二进制字符串
binary_d = bin(d)[2:]
k = len(binary_d)
x = 1
y = m % n
for i in range(k):
a_i = int(binary_d[i])
if a_i == 1:
x = (x * y) % n
y = (y * y) % n
else:
y = (y * y) % n
return x
本质上是将次幂\(d\)转化为二的次幂和
例题
设在一个使用 RSA 体制的密码应用系统中,有两个用户 A 与 B 使用了相同模数为 161、且公钥(加密指数)分别为 5 与 7,你作为一个攻击者,当同时截获到用户 C 分别发给用户 A 与 B 的、加密同一消息\(m\)的密文\(c_1 = 27\)与\(c_2 = 55\)时,试恢复出消息\(m\)
解:
由于\(e_A\)和\(e_B\)互质(即\(\gcd(5, 7) = 1\)),可以利用扩展欧几里得算法求解方程\(5x + 7y = 1\),得到整数解\(x = 3\)和\(y = -2\)。因此,消息\(m\)可以恢复为:
\(m \equiv (c_1)^x \cdot (c_2)^y \pmod{n}\)
代入值:
\(m \equiv 27^3 \cdot 55^{-2} \pmod{161}\)
\(27^3 \equiv 41 \pmod{161}\)
使用扩展欧几里得算法:
\(55^{-1} \equiv 41 \pmod{161}\)
\(55^{-2} = (55^{-1})^2 = 41^2 \mod 161\)
\(55^{-2} \equiv 71 \pmod{161}\)
代入:
\(m \equiv 13 \pmod{161}\)
ElGamal公钥加密算法
算法概述
基于离散对数问题的非对称加密算法
安全性依赖于在有限域中求解离散对数的困难性
特点在于每次加密后生成的密文不同,可以有效防止重放攻击。
给定\(g\)和\(h = g^x \mod p\),求解\(x\)是困难的
具体步骤
密钥生成
- 选择参数:
- 选择一个大素数\(p\),并选择一个生成元\(g\)(即\(g\)是模\(p\)的本原元)
- 随机选择一个整数\(x\)作为私钥,满足\(1 \leq x \leq p-2\)
- 计算\(y = g^x \mod p\),其中\(y\)为公钥
- 密钥组成:
- 公钥:\((p, g, y)\)
- 私钥:\(x\)
加密过程
使用公钥\((p, g, y)\)对明文\(M\)进行加密
- 选择随机数:随机选择一个整数\(k\),满足\(1 \leq k \leq p-2\),且\(k\)与\(p-1\)互质。
- 计算密文分量:
- 计算\(C_1 = g^k \mod p\)
- 计算\(C_2 = M \cdot y^k \mod p\)
- 生成密文:密文为\((C_1, C_2)\)
解密过程
使用私钥\(x\)对密文\((C_1, C_2)\)进行解密
- 计算共享密钥:\(K = C_1^x \mod p\)
- 计算明文:\(M = C_2 \cdot K^{-1} \mod p\),其中\(K^{-1}\)是\(K\)的模逆元。
Python实现
import random
from math import gcd
def power_mod(a, b, c):
"""模幂运算"""
result = 1
a = a % c
while b > 0:
if b % 2 == 1:
result = (result * a) % c
a = (a * a) % c
b = b // 2
return result
def generate_key(p, g):
"""生成密钥"""
x = random.randint(1, p-2) # 私钥
y = power_mod(g, x, p) # 公钥
return (p, g, y), x
def encrypt(p, g, y, M):
"""加密"""
k = random.randint(1, p-2)
C1 = power_mod(g, k, p)
C2 = (M * power_mod(y, k, p)) % p
return (C1, C2)
def decrypt(p, x, C1, C2):
"""解密"""
K = power_mod(C1, x, p)
K_inv = pow(K, -1, p)
M = (C2 * K_inv) % p
return M
椭圆曲线
椭圆曲线的定义
满足方程\(y^2 = x^3 + ax + b\)的点集,其中\(a\)和\(b\)是常数,且满足判别式\(4a^3 + 27b^2 \neq 0\)这确保了曲线没有奇点(即曲线是光滑的)
密码学中椭圆曲线通常定义在有限域上
椭圆曲线上的运算
椭圆曲线上的运算主要包括点加法和点倍乘法
点加法
给定椭圆曲线上的两点\(P(x_1, y_1)\)和\(Q(x_2, y_2)\),它们的和\(R(x_3, y_3)\)的计算方法如下:
- 如果\(P \neq Q\):
- 斜率\(\lambda = \frac{y_2 - y_1}{x_2 - x_1} \mod p\)
-\(x_3 = \lambda^2 - x_1 - x_2 \mod p\)
-\(y_3 = \lambda(x_1 - x_3) - y_1 \mod p\)
- 斜率\(\lambda = \frac{y_2 - y_1}{x_2 - x_1} \mod p\)
- 如果\(P = Q\)(即点倍乘):
- 斜率\(\lambda = \frac{3x_1^2 + a}{2y_1} \mod p\)
-\(x_3 = \lambda^2 - 2x_1 \mod p\)
-\(y_3 = \lambda(x_1 - x_3) - y_1 \mod p\)
- 斜率\(\lambda = \frac{3x_1^2 + a}{2y_1} \mod p\)
- 如果\(P = -Q\)(即\(x_1 = x_2\)且\(y_1 = -y_2\)),则\(P + Q\)为无穷远点\(O\)
点倍乘法
点倍乘法是指将一个点\(P\)乘以一个标量\(k\),即计算\(kP\)
这实际上是通过反复的点加法实现的,例如\(3Q = Q + Q + Q\)
点倍乘法是椭圆曲线密码学中的核心运算,其安全性依赖于离散对数问题的困难性。
计算椭圆曲线上的点时,需要用到二次剩余
椭圆曲线ElGamal公钥密码体制
算法概述
是传统ElGamal算法在椭圆曲线上的扩展,利用椭圆曲线上的离散对数问题来保证安全性。与传统的ElGamal相比,ECElGamal在提供同等安全性的情况下,可以使用更短的密钥,因此效率更高,可以应用于计算和存储能力小的智能卡等。
密钥生成
- 选择一条定义在有限域\(\mathbb{F}_p\)上的椭圆曲线\(E\),并选择一个基点\(G\)(生成元),该点满足阶数\(n\)。
- 生成私钥:随机选择一个整数\(d\)作为私钥,满足\(1 \leq d \leq n-1\)。
- 计算公钥:计算\(Q = dG\),其中\(Q\)为公钥。
加密过程
假设发送方想要加密消息\(M\)(消息\(M\)必须是椭圆曲线上的一个点),步骤如下:
- 选择随机数:发送方随机选择一个整数\(k\),满足\(1 \leq k \leq n-1\)。
- 计算密文:
- 计算\(C_1 = kG\)
- 计算\(C_2 = M + kQ\)(即\(C_2 = M + k(dG)\))
- 发送密文:发送方将密文\((C_1, C_2)\)发送给接收方
解密过程
接收方使用私钥\(d\)解密密文\((C_1, C_2)\):
- 计算\(S = dC_1 = d(kG) = k(dG) = kQ\)
- 计算明文\(M = C_2 - S = (M + kQ) - kQ = M\)
示例
假设椭圆曲线\(E\)定义为\(y^2 = x^3 + x + 1 \mod 23\),基点\(G = (1, 5)\),阶数\(n = 28\)
- 密钥生成:
- 接收方选择私钥\(d = 6\),计算公钥\(Q = 6G\)
- 加密:
- 发送方选择随机数\(k = 4\),计算\(C_1 = 4G\),\(C_2 = M + 4Q\)
- 解密:
- 接收方计算\(S = 6C_1 = 6(4G) = 24G\),然后\(M = C_2 - S\)

浙公网安备 33010602011771号