http://mslc.ctf.su/wp/0ctf-2016-quals-equation-crypto-2-pts/
-----BEGIN RSA PRIVATE KEY-----
[masked]
Os9mhOQRdqW2cwVrnNI72DLcAXpXUJ1HGwJBANWiJcDUGxZpnERxVw7s0913WXNt
V4GqdxCzG0pG5EHThtoTRbyX0aqRP4U/hQ9tRoSoDmBn+3HPITsnbCy67VkCQBM4
xZPTtUKM6Xi+16VTUnFVs9E4rqwIQCDAxn9UuVMBXlX2Cl0xOGUF4C5hItrX2woF
7LVS5EizR63CyRcPovMCQQDVyNbcWD7N88MhZjujKuSrHJot7WcCaRmTGEIJ6TkU
8NWt9BVjR4jVkZ2EqNd0KZWdQPukeynPcLlDEkIXyaQx
-----END RSA PRIVATE KEY-----
要想了解RSA私钥的具体构成,可以参考以下链接:
http://blog.sina.com.cn/s/blog_4fcd1ea30100yh4s.html
我将已知的片段base64解码,其16进制表示如下:
3acf6684e41176a5b673056b9cd23bd832dc017a57509d471b(属于q)
0241
00d5a225c0d41b16699c4471570eecd3dd7759736d5781aa7710b31b4a46e441d386da1345bc97d1aa913f853f850f6d4684a80e6067fb71cf213b276c2cbaed59(属于exponent1)
0240
1338c593d3b5428ce978bed7a553527155b3d138aeac084020c0c67f54b953015e55f60a5d31386505e02e6122dad7db0a05ecb552e448b347adc2c9170fa2f3(属于exponent2)
0241
00d5c8d6dc583ecdf3c321663ba32ae4ab1c9a2ded6702691993184209e93914f0d5adf415634788d5919d84a8d77429959d40fba47b29cf70b943124217c9a431(属于coefficient)
因为:
e * dp == 1 (mod (p-1)) = d mod (p-1)
e * dq == 1 (mod (q-1)) = d mod (q-1)
q * qi == 1 (mod p) = q^-1 mod p
所以:
(e * dp -1)/k +1 == (p) (e * dq -1)/j +1 == (q) (q * qi -1)/l == (p)
已知的片段是
q = 0x3acf6684e41176a5b673056b9cd23bd832dc017a57509d471b
dp = 0x00d5a225c0d41b16699c4471570eecd3dd7759736d5781aa7710b31b4a46e441d386da1345bc97d1aa913f853f850f6d4684a80e6067fb71cf213b276c2cbaed59
dq = 0x1338c593d3b5428ce978bed7a553527155b3d138aeac084020c0c67f54b953015e55f60a5d31386505e02e6122dad7db0a05ecb552e448b347adc2c9170fa2f3
qi = 0x00d5c8d6dc583ecdf3c321663ba32ae4ab1c9a2ded6702691993184209e93914f0d5adf415634788d5919d84a8d77429959d40fba47b29cf70b943124217c9a431
首先根据上面的式子计算q:
for j in range(N,1,-1):
q_ = (e * dq -1)/j +1
if "3acf6684e41176a5b673056b9cd23bd832dc017a57509d471b" in str(hex(q_)):
print q_, j
得到的q_(即想要的q):
12502893634923161599824465146407069882228513776947707295476805997311776855879024002289593598657949783937041929668443115224477369136089557911464046118127387
接下来先定义两个函数用来求模逆:
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
#raise Exception('modular inverse does not exist')
return -1
else:
return x % m
然后需要求p:
M = 1
N = 100000
for k in range(M,N,1):
p1 = (dp * 0x10001-1)/k+1
m = modinv(q_, p1)
if m == qi:
print "p_:",p1, k
sys.exit(1)
得到的p如下:
12883429939639100479003058518523248493821688207697138417834631218638027564562306620214863988447681300666538212918572472128732943784711527013224777474072569
由此就可以得到n,并利用上面的模逆函数得到d。
print modinv(e, f(n))
d = 12441639692099655517376308833932392670257420848582256919212988552216677594845086557017745931627109670194928630671056032860651983223301005431608062335676428430110171020554477490159485308455680772826276447201841772149055876380443034602731403064627486237285806604612267999273183028007861118868108999965277036321
到目前为止,已经得到了我想要的的参数值,那么就可以开始解密文件:
fp = open('flag.enc','rb')
x = fp.read()
print x.encode('hex')
print int(x.encode('hex'),16)
d = 12441639692099655517376308833932392670257420848582256919212988552216677594845086557017745931627109670194928630671056032860651983223301005431608062335676428430110171020554477490159485308455680772826276447201841772149055876380443034602731403064627486237285806604612267999273183028007861118868108999965277036321
n = 161080154188292201430717335450301702574211890587423028785946588452513709903864566907797711402814280216429284407010865117658741411399738837015270166197792615276511302372234182990420185803542388458087342116253675425489502589540709488892694405415013333511961708962693793627275736479090319881934245022826824347203
def str2num(s):
return int(s.encode('hex'),16)
def num2str(n):
d = ('%x' % n)
if len(d) % 2 == 1:
d = '0' + d
return d.decode('hex')
x = 22950838243355051507735476344130216859576434035671340145571506267533078667102139095850647801394751140978861909254514064618936561207518062388831395696067732470866299734394736771987882752821762750879035746758561421031626630277903489313416714548078647228307878986111206166442661515283012588864037384850878485926
print num2str(pow(x,d,n))
最后得到flag:
http://blog.sina.com.cn/s/blog_4fcd1ea30100yh4s.html
https://0day.work/0ctf-2016-quals-writeups/
http://mslc.ctf.su/wp/0ctf-2016-quals-equation-crypto-2-pts/
在做题的过程中发现一些相关资源可能本题没有用到:
解密文件:
https://www.cnblogs.com/alittlebitcool/archive/2011/09/22/2185418.html
libnum库的安装方法
http://www.cnblogs.com/pcat/p/7225782.html