RSA算法要点总结
RSA 算法的可靠性由极大整数因数分解的难度决定。换言之,对一极大整数做因数分解愈困难,RSA 算法愈可靠
1、公钥与私钥的产生:
(1)进行加密之前,首先找出2个不同的互质数 p 和 q
(2)计算 n = p*q
(3)根据欧拉函数,求得φ(n) = (p−1)(q−1)
(4)找出一个公钥e,e要满足: 1 < e < φ(n) 的整数,且使 e 和 φ(n) 互质。
(5)根据 (e*d) % φ(n) = 1 的方式, 找到私钥d。
(6)所以,公钥就是 e,私钥就是 d 。
2、加密和解密的过程:
加密: % n = c
解密: % n = m
m 为明文,c 为密文,公钥为 e,私钥为 d。
3、安全性——传播的过程:
传播信息:n、e、c
解密:n、d、c
,
φ(n) = p * q,求φ(n) 即求p、q。即质数分解。
例题1:
题目:求出m,转换成二进制,即位flag
p+q : 0x1232fecb92adead91613e7d9ae5e36fe6bb765317d6ed38ad890b4073539a6231a6620584cea5730b5af83a3e80cf30141282c97be4400e33307573af6b25e2ea
(p+1)(q+1) : 0x5248becef1d925d45705a7302700d6a0ffe5877fddf9451a9c1181c4d82365806085fd86fbaab08b6fc66a967b2566d743c626547203b34ea3fdb1bc06dd3bb765fd8b919e3bd2cb15bc175c9498f9d9a0e216c2dde64d81255fa4c05a1ee619fc1fc505285a239e7bc655ec6605d9693078b800ee80931a7a0c84f33c851740
e : 0xe6b1bee47bd63f615c7d0a43c529d219
d : 0x2dde7fbaed477f6d62838d55b0d0964868cf6efb2c282a5f13e6008ce7317a24cb57aec49ef0d738919f47cdcd9677cd52ac2293ec5938aa198f962678b5cd0da344453f521a69b2ac03647cdd8339f4e38cec452d54e60698833d67f9315c02ddaa4c79ebaa902c605d7bda32ce970541b2d9a17d62b52df813b2fb0c5ab1a5
enc_flag: 0x50ae00623211ba6089ddfae21e204ab616f6c9d294e913550af3d66e85d0c0693ed53ed55c46d8cca1d7c2ad44839030df26b70f22a8567171a759b76fe5f07b3c5a6ec89117ed0a36c0950956b9cde880c575737f779143f921d745ac3bb0e379c05d9a3cc6bf0bea8aa91e4d5e752c7eb46b2e023edbc07d24a7c460a34a9a
解题思路:
- (p+1)*(q+1) = p*q + p+q + 1 = n + p+q + 1
- n = (p+1)*(q+1) - (p+q + 1)
- m =
% n
解题代码:
from Crypto.Util.number import long_to_bytes
q = 0x1232fecb92adead91613e7d9ae5e36fe6bb765317d6ed38ad890b4073539a6231a6620584cea5730b5af83a3e80cf30141282c97be4400e33307573af6b25e2ea
w = 0x5248becef1d925d45705a7302700d6a0ffe5877fddf9451a9c1181c4d82365806085fd86fbaab08b6fc66a967b2566d743c626547203b34ea3fdb1bc06dd3bb765fd8b919e3bd2cb15bc175c9498f9d9a0e216c2dde64d81255fa4c05a1ee619fc1fc505285a239e7bc655ec6605d9693078b800ee80931a7a0c84f33c851740
e = 0xe6b1bee47bd63f615c7d0a43c529d219
d = 0x2dde7fbaed477f6d62838d55b0d0964868cf6efb2c282a5f13e6008ce7317a24cb57aec49ef0d738919f47cdcd9677cd52ac2293ec5938aa198f962678b5cd0da344453f521a69b2ac03647cdd8339f4e38cec452d54e60698833d67f9315c02ddaa4c79ebaa902c605d7bda32ce970541b2d9a17d62b52df813b2fb0c5ab1a5
c = 0x50ae00623211ba6089ddfae21e204ab616f6c9d294e913550af3d66e85d0c0693ed53ed55c46d8cca1d7c2ad44839030df26b70f22a8567171a759b76fe5f07b3c5a6ec89117ed0a36c0950956b9cde880c575737f779143f921d745ac3bb0e379c05d9a3cc6bf0bea8aa91e4d5e752c7eb46b2e023edbc07d24a7c460a34a9a
n = w - q - 1
m = pow(c,d,n)
print(long_to_bytes(m) )
例题2:
本题目得到的是一个pyc反编译文件,首先进入反编译网址进行反编译
得到代码:
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.9
import gmpy2
from Crypto.Util.number import *
from binascii import a2b_hex, b2a_hex
flag = '******************'
p = 0xED7FCFABD3C81C78E212323329DC1EE2BEB6945AB29AB51B9E3A2F9D8B0A22101E467
q = 0xAD85852F9964DA87880E48ADA5C4487480AA4023A4DE2C0321C170AD801C9
e = 65537
n = p * q
c = pow(int(b2a_hex(flag), 16), e, n)
print(c)
c = 0x75AB3202DE3E103B03C680F2BEBBD1EA689C8BF260963FE347B3533B99FB391F0A358FFAE5160D6DCB9FCD75CD3E46B2FE3CFFE9FA2E9508702FD6E4CE43486631
解题思路:
- 题目已知,e、n、c,根据 (e*d) % φ(n) = 1 ,即可求出d
- 求出d后,根据
% n = m,即可得到m,
- 求出发现 是 b'ZmxhZ3tJbGlrZUNURmJ1dENURmRvbid0bGlrZW1lfQ=='
- 根据经验得知这是base64的,然后进行base64解码即可
解题代码:
import base64
import gmpy2
from Crypto.Util.number import *
from binascii import a2b_hex, b2a_hex
# flag = '******************'
p = int('0xED7FCFABD3C81C78E212323329DC1EE2BEB6945AB29AB51B9E3A2F9D8B0A22101E467',16)
q = int('0xAD85852F9964DA87880E48ADA5C4487480AA4023A4DE2C0321C170AD801C9',16)
e = 65537
phi = (p-1)*(q-1)
n = p * q
# c = pow(int(b2a_hex(flag), 16), e, n)
# print(c)
c = int('0x75AB3202DE3E103B03C680F2BEBBD1EA689C8BF260963FE347B3533B99FB391F0A358FFAE5160D6DCB9FCD75CD3E46B2FE3CFFE9FA2E9508702FD6E4CE43486631',16)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
flags = long_to_bytes(m)
print(flags)
print(base64.b64decode(flags))
flag{IlikeCTFbutCTFdon'tlikeme}
例题3:
下载题目得到代码
from Crypto.Util.number import *
from secret import flag
from sympy import nextprime
flag=b''
r = getRandomNBitInteger(64)
p1 = r**5 + r**4 - r**3 + r**2 - r + 2024
q1 = r**5 - r**4 + r**3 - r**2 + r + 2024
p =nextprime(p1)
q =nextprime(q1)
n = p*q
def enc(flag, n):
m = bytes_to_long(flag)
return pow(m, 65537, n)
c = enc(flag, n)
print(n)
print(c)
#1058756604181685917958185571746711428601045466594619627088399455470892502310139608978164573773765910533535849969889860275644658086339362201840191861497991951344100284004205747279828567835277683
#643011921358774538378881505518732362708757638007688649119354348647468190640688857686213431516881297805187671774564672497176686191162897918672339254715366498963369868410476737543157157149810569
解题思路:
- 做RSA的题上来先读题,搜选已知条件,看题目给的代码可知,题目已给出了n,c,e=65537,同时题目给了n的计算方式,因此我们需要得到p、q来求解φ(n) ,因此就涉及到了分解n
- 根据题目求解n的方式,同时结合数学中的思想可以得到,对p和q影响最大的是r的5次方,p*q = n,因此对n影响最大的即为n的10次方,因此我们可以率先对n进行开10次方根进行遍历,然后分解获取p和q的值,获取之后求得φ(n)即为phi
- 根据 (e*d) % φ(n) = 1 ,即可求出d,求出d后,根据
% n = m,即可得到m
- 根据经验得知这是base64的,然后进行base64解码即可
解题代码:
import gmpy2
from Crypto.Util.number import *
from sympy import nextprime
flag=b''
c = 643011921358774538378881505518732362708757638007688649119354348647468190640688857686213431516881297805187671774564672497176686191162897918672339254715366498963369868410476737543157157149810569
n = 1058756604181685917958185571746711428601045466594619627088399455470892502310139608978164573773765910533535849969889860275644658086339362201840191861497991951344100284004205747279828567835277683
e = 65537
r_n = gmpy2.iroot(n , 10)[0]
for r in range(r_n-10 , r_n+10):
p1 = r**5 + r**4 - r**3 + r**2 - r + 2024
q1 = r**5 - r**4 + r**3 - r**2 + r + 2024
p = nextprime(p1)
q = nextprime(q1)
if p*q == n:
phi = (p - 1) * (q - 1)
break;
d = gmpy2.invert(e,phi)
m = pow(c , d , n)
print(m)
print(long_to_bytes(m))
bugku{01a25ea3fd6349c6e635a1d0196e75fb}