rsa合集
gcd(a,b)
1 | def gcd(a:int,b:int): |
互素
1 | def prime(a,b): |
Euler(n)
1 | def Euler(n): |
Exgcd(a,b)
- ax + by = gcd(a,b)
- 求存在整数x,y
- 对于a>b,当b=0,gcd(a,b)=a;x=1,y=0
- 设ax1+by1=gcd(a,b)
- 有bx2+(a%b)y2=gcd(b,a%b)
- 有gcd(a,b)=gcd(b,a%b)
- 则ax1+by1=bx2+(a%b)y2
- ax1+by1=bx2+(a-[a/b]*b)*y2=ay2+bx2-[a/b]*by2
- 即ax1+by1 == ay2+b(x2-[a/b]*y2)
- x1=y2, y1=x2-[a/b]*y2
- x1,y1的值根据x2,y2求出
- 递归定义,b总有为0的时候
1
2
3
4
5
6
7def exgcd(a,b):
if b==0:
return a,1,0
else:
d,x,y=exgcd(b,a%b)
x,y=y,x-(a//b)*y
return d,x,ymod_invert(a,b)
1
2
3
4
5
6
7
8def mod_invert(a,b):
# 求模逆
d,x,y=exgcd(a,b)
# 判断是否互质
if d!=1:
print('no')
else:
print((x%b+b)%b)中国剩余定理
- 有x≡x1 mod n1
- x≡x2 mod n2
- x≡x3 mod n3…
- 求解所有模数的乘积N=n1*n2*n3…
- 对于每个i计算ni’=N//ni,求解m*ni’≡1(mod ni)的一个解m,m和ni’互质,用扩展欧几里得算法求解
- 计算x=求和(xi*ni’*m)
1
2
3
4
5
6
7
8
9
10
11
12import gmpy2
from funtools import reduce
def CRT(items):
N=reduce(lamda: x,y:x*y, (i[1] for i in items))
result=0
for x,n in items:
ni=N//n
d,r,s=gmpy2.gcdext(n,ni)
if d!=1:
raise "gcd error"
result+=x*ni*s
return result%N, NRSA已知p,q,e求解D
原理
- φ(pq)=(p-1)*(q-1)
- e*d ≡1 mod φ(pq) 求解d
题目
1
2在一次RSA密钥对生成中,假设p=473398607161,q=4511491,e=17
求解出d作为flag提交题解
1
2
3
4
5
6
7import gmpy2
p=473398607161
q=4511491
e=17
phi_n=(p-1)*(q-1)
d=gmpy2.invert(e,phi_n)
print(d)RSA已知p,q,e,c求解明文
- c=m^e(mod n)
- m=c^d(mod n)
题目
1
2
3
4
5
6
7
8Math is cool! Use the RSA algorithm to decode the secret message, c, p, q, and e are parameters for the RSA algorithm.
p = 9648423029010515676590551740010426534945737639235739800643989352039852507298491399561035009163427050370107570733633350911691280297777160200625281665378483
q = 11874843837980297032092405848653656852760910154543380907650040190704283358909208578251063047732443992230647903887510065547947313543299303261986053486569407
e = 65537
c = 83208298995174604174773590298203639360540024871256126892889661345742403314929861939100492666605647316646576486526217457006376842280869728581726746401583705899941768214138742259689334840735633553053887641847651173776251820293087212885670180367406807406765923638973161375817392737747832762751690104423869019034
Use RSA to find the secret message题解
1
2
3
4
5
6
7
8
9
10
11
12import gmpy2
# p=
# q=
# e=
# c=
n=p*q
phi_n=(p-1)*(q-1)
d=gmpy2.invert(e,phi_n)
m=pow(c,d,n)
print(m)RSA已知q,p,dp,dq,c求解明文
- dp=d(mod p-1)
- dq=d(mod q-1)
- n=p*q
- m1=c^dp(mod p)
- m2=c^dq(mod q)
- invp=gmpy2.invert(p,q)
- (m=((m2-m1)*invp%q)+m1)(mod n)
题目
1
2
3
4
5p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229
q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469
dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929
dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041
c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852题解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import gmpy2
import libnum
# p =
# q =
# dp =
# dq =
# c =
# gmpy2.invert返回mpz类型转为int型
invq=int(gmpy2.invert(p,q))
mp=pow(c,dp,p)
mq=pow(c,dq,q)
m=((mp-mq)*invq%p)*q+mq
print(libnum.n2s(m))dp泄露,已知e,n,c,dp
- dp = d (mod p-1)
- n=p*q
- m = c^d (mod n)
- e * dp = e * d(mod p-1)
- e * d = k2(p-1) + e * dp
- d * e = k1(p-1) * (q-1) +1
- k2(p-1) + e * dp = k1(p-1) * (q-1) +1
- (p-1) * (k1 * (q-1) -k2 )+1=e * dp
- 设i=k1 * (q-1) -k2
- (p-1)i + 1 = dp * e
- 1< i < e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# e=
# n=
# dp=
# c=
import gmpy2
from Crypto.Util.number import long_to_bytes
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) #快速求幂取模运算
print(long_to_bytes(m))共模攻击,已知c1,c2,e1,e2,n
- 适用情况:明文m、模数n相同,公钥指数e、密文c不同,gcd(e1,e2)=1也就是e1和e2互质。
1
2
3
4
5
6
7
8
9
10
11
12
13
14# c1=
# c2=
# e1=
# e2=
# n=
import gmpy2
from Crypto.Util.number import long_to_bytes
assert gmpy2.gcd(e1,e2)==1
_, r, s = gmpy2.gcdext(e1, e2)
m = pow(c1, r, n) * pow(c2, s, n) % n
print (long_to_bytes(m))rsa公钥读取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import gmpy2
from Crypto.Util.number import *
from Crypto.PublicKey import RSA
# 从公钥里面提取n 和 e
with open('./pub.key','r') as f:
key = RSA.import_key(f.read())
e = key.e
n = key.n
#通过分解n得到p和q
#p =
#q =
d = gmpy2.invert(e,(p-1)*(q-1))
with open('./flag.enc','rb')as f:
c = bytes_to_long(f.read())
m = pow(c,d,n)
print(long_to_bytes(m))rsaroll
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import libnum
from Crypto.Util.number import long_to_bytes
import gmpy2
# list1=[1123,123,123,132]
flag=""
n=920139713
q=18443
p=49891
e=19
for i in list1:
c=i
d = gmpy2.invert(e,(p-1)*(q-1))
m = pow(c, d, n)
string = long_to_bytes(m)
flag+=string.decode()
print(flag)低加密指数攻击
普通
- e很小,n很大
- 设e=3,m^3 = c (mod n)
- c = m^3(mod n)
- c^(-3) = m(mod n)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import gmpy2
import os
from functools import reduce
from Crypto.Util.number import long_to_bytes
# gmpy2.crt(c,n)
def CRT(items):
N = reduce(lambda x, y: x * y, (i[1] for i in items))
result = 0
for a, n in items:
m = N // n
d, r, s = gmpy2.gcdext(n, m)
if d != 1:
raise Exception("Input not pairwise co-prime")
result += a * s * m
return result % N, N
# e, n, c
# e = 0x3
# n=[]
# c=[]
data = list(zip(c, n))
x,n = CRT(data)
m = int(gmpy2.iroot(x,e)[0])
print(long_to_bytes(m)) - 利用二分法逼近明文数值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41from math import isqrt, gcd
from Crypto.Util.number import long_to_bytes
def rsa_low_exponent_attack(n, e, c):
# 计算n的平方根
sqrt_n = isqrt(n)
# 使用二分搜索逐步逼近m的值
low = 0
high = n
while low <= high:
mid = (low + high) // 2
# 计算mid ^ e % n
result = pow(mid, e, n)
# 如果result和c的值一样,说明mid是m的一个候选值
if result == c:
return mid
# 如果result比c的值小,则将搜索范围移到[mid+1, high]
elif result < c:
low = mid + 1
# 如果result比c的值大,则将搜索范围移到[low, mid-1]
else:
high = mid - 1
# 如果搜索失败,则返回None
return None
# 测试
if __name__ == "__main__":
# n=
# e=
# c=
m = rsa_low_exponent_attack(n, e, c)
# 通过整数转换成明文并打印出来
print(long_to_bytes(m))爆破
- 爆破e,给出多组c和n
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36import gmpy2
import os
from functools import reduce
from Crypto.Util.number import long_to_bytes
import numpy as np
# 生成15个素数
primes = np.array([2])
p = 3
while len(primes) < 15:
if np.all(p % primes != 0):
primes = np.append(primes, p)
p += 2 # 步长为2
def CRT(items):
N = reduce(lambda x, y: x * y, (i[1] for i in items))
result = 0
for a, n in items:
m = N // n
d, r, s = gmpy2.gcdext(n, m)
if d != 1:
raise Exception("Input not pairwise co-prime")
result += a * s * m
return result % N, N
# n1 =
# c1 =
# n2 =
# c2 =
# n3 =
# c3 =
# c=[c1,c2,c3]
# n=[n1,n2,n3]
data = list(zip(c, n))
x,n = CRT(data)
for i in primes:
e = int(i)
m = int(gmpy2.iroot(x, e)[0])
print(long_to_bytes(m))公因数求解d,p
- 当有多个n和c时,求解ni和nj的公因数d,当d!=1,ni=d*p,分解成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14import gmpy2
import libnum
# e=65537
# c=[c1,c2,c3,c4...]
# n=[n1,n2,n3,n4...]
for i in range(len(n)):
for j in range(i+1,len(n)):
d=gmpy2.gcd(n[i],n[j])
if d!=1:
p=d
q=n[i]//p
d=gmpy2.invert(e,(p-1)*(q-1))
m=pow(c[i],d,n[i])
print(libnum.n2s(int(m)))低解密指数攻击
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 0xchang's Blog!