备忘(题外话)
1B(字节)=8bit(位)
B是Byte的缩写
几个概念
互质数
公约数只有1的两个数
gcd(e,φ(n))=1
欧拉函数
φ(n)为<=n的正整数中与n构成互质关系的个数
模反元素(逆元)
若a * b mod p=1,则称b为a mod p的逆元。
e * d mod φ(n) = 1,d为e mod φ(n)的逆元
dp泄露
已知e,n,dp,c
dp = d mod (p-1)
m = c^d mod n
d x e mod (p-1)(q-1) = 1
因为 e x dp = e x d mod (p-1)
所以 e x d = k₂(p-1) + e x dp
又 d x e = k₁(p-1)(q-1) + 1
所以 k₁(p-1)(q-1) + 1 = k₂(p-1) + e x dp
所以 (p-1)[k₁(q-1)-k₂] + 1 = dp x e
设 i = k₁(q-1)-k₂
即 (p-1)i + 1 = dp x e
因为 dp = d mod (p-1)
所以 dp < (p-1)
所以 e > i
所以 1 < i < e
通过遍历i,可求得使得n%p=0成立的p,进而求得q和(p-1)(q-1),就能求得d。
for i in range(1,e): #在范围(1,e)之间进行遍历
if(dp*e-1)%i == 0:
if n%(((dp*e-1)//i)+1) == 0: #存在p,使得n能被p整除
p=((dp*e-1)//i)+1
q=n//p
phi=(q-1)*(p-1) #欧拉定理
d=gmpy2.invert(e,phi) #求模逆
m=pow(c,d,n) #快速求幂取模运算
共模攻击
已知n,c1,e1,c2,e2
gcd(e1,e2)=1
有e1 * s1+e2 * s2=1(s1,s2一正一负)
(c1 ^ s1 * c2 ^ s2) mod n = ((m ^ e1 mod n) ^ s1 * (m ^ e2 mod n) ^ s2) mod n
根据模运算性质,可以化简为
(c1 ^ s1 * c2 ^ s2) mod n = ((m ^ e1) ^ s1 * (m ^ e2) ^ s2) mod n
即 (c1 ^ s1 * c2 ^ s2) mod n = (m ^ (e1 ^ s1 + e2 ^ s2)) mod n
又 e1s1+e2s2 = 1
所以 c1 ^ s1 * c2 ^ s2 = m
在数论模运算中,要求一个数的负数次幂,与常规方法并不一样。
比如此处要求c2的s2次幂,就要先计算c2的模反元素c2r,然后求c2r的-s2次幂。
s = gcdext(e1, e2)
s1 = s[1]
s2 = s[2]
# 求模反元素
if s1<0:
s1 = - s1
c1 = invert(c1, n)
elif s2<0:
s2 = - s2
c2 = invert(c2, n)
m = pow(c1,s1,n)*pow(c2,s2,n) % n
低加密指数攻击
e很小,比如=3
假设m^e / n 商 k 余数为c,
所以m^e = kn + c,对k进行爆破,只要k满足 kn + c能够开方就可以
k = 0
while 1:
res=iroot(c+k*n,3)
if(res[1]==True):
print(libnum.n2s(int(res[0])))
break
k=k+1