2022ACTF-Crypto-impossible RSA

impossible RSA wp

0x01 题目源码

server.py
from Crypto.Util.number import *
from Crypto.PublicKey import RSA

e = 65537
flag = b'ACTF{...}'

while True:
    p = getPrime(1024)
    q = inverse(e, p)
    if not isPrime(q):
        continue
    n = p * q;
    public = RSA.construct((n, e))
    with open("public.pem", "wb") as file:
        file.write(public.exportKey('PEM'))
    with open("flag", "wb") as file:
        file.write(long_to_bytes(pow(bytes_to_long(flag), e, n)))
    break
public.pem
-----BEGIN PUBLIC KEY-----
MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQB+pWAiyLgiiDUmsUJs4sGi
BJeEwLvitqUvBVtcgPEFK4vO4G6CNAd3JlN8zBqJRBVn1FRlcxGPPXuJgIjMOkyV
G4vo3mLr/v/pER79JrPgP8E5hShao5rujsue8NUq9+r1dUsnqU3gEiPyZspAG+//
8P7TW0XcvCy5olRZqkV/QD6dlqjBaufWgTL2iMCtkadXT99ETmmgDVJ/GE51xErz
pE8poKXjJqnwZEWEjdcqO1RXHKLAcmm3mpQEGbFOXWlb2cqSnKTbtJ0cVQ93y3gA
mjCCBJrQLulx+5Oyn2+1rkRlHuMSq82DC0qAMvbc/DTjlTVYSC+GvIpEEFR344/5
AgMBAAE=
-----END PUBLIC KEY-----
bytes_to_long(flag)
8273086882440893360458062957389163084656045191542493618199369528956277216626884353986044368396198156428766254991928690583227149075264217246716715502497271453823598984519037301602775476502736840821942623288225980044817912940317041496675271105285924648202112216540495276381694590948153181922044287087121526235593090625653756288948499134042427779455887781328892794911088854654421379942237290840799205667104402295294924690771201447934282318850564703279100891083617354084345663030868007048086929831020873706613566948846194280096109248694845560054847526215721665897469865078997234299897107511688667705001432037926136840958

0x02 分析

\(\qquad\) 总览

\(\qquad\) 给了我们三个文件,1.公钥文件;2.密文;3.加密程序。前两个文件我们再熟悉不过了,通过公钥文件拿到 n ,解密时要拿到密文的整数类型(密文文件原本是字符文件)

\(\qquad\) 分段

  • p = getPrime(1024)
    q = inverse(e, p)
    if not isPrime(q):
    	continue
    

    \(\qquad\) 这里出了 pq 的值, p 的值是随机的我们不得而知,我们可以研究一下 q 的值,在给出的这个函数中我们可以得知一些数学关系:

    image ,还可以修改一下: image k为正整数,并且 q 是个素数。

0x03 decrypt

\(\qquad\) 整理

\(\qquad\) 我们整理一下我们已有的信息: imageimage ,怎么将他们联系起来呢。

image

image

image

image

\(\qquad\) 到这里,是不是很明确了?其实整个程序最重要的部分已经分析完了,但是小数的计算并不方便,我们还需要再化简一下:

image

\(\qquad\) 我们都知道 gmpy2 的库中有一个函数 iroot() 可以帮助我们开方,我们只要遍历出 k 的值就可以解题啦,接下来的事情就交给脚本了。\(\qquad\)

\(\qquad\) 脚本

点击查看代码
from gmpy2 import *
from Crypto.Util.number import *
n = 15987576139341888788648863000534417640300610310400667285095951525208145689364599119023071414036901060746667790322978452082156680245315967027826237720608915093109552001033660867808508307569531484090109429319369422352192782126107818889717133951923616077943884651989622345435505428708807799081267551724239052569147921746342232280621533501263115148844736900422712305937266228809533549134349607212400851092005281865296850991469375578815615235030857047620950536534729591359236290249610371406300791107442098796128895918697534590865459421439398361818591924211607651747970679849262467894774012617335352887745475509155575074809

e = 65537

num = 2

ne = n * e
k = 1

with open('flag','rb')as f:
    c = f.read()
c = bytes_to_long(c)
while (True):
    num1 = 4 * k * ne + 1
    if (iroot(num1, 2)[1] == True):
        num2 = iroot(num1, 2)[0] - 1
        p = num2 // k // 2
        print('p = ', p, ' ', is_prime(p))
        break
    k += 1
q = n //p
d = invert(e,(p-1)*(q-1))
m = pow(c,d,n)
print(long_to_bytes(m))
posted @ 2022-06-29 15:36  Sentry_InkCity  阅读(331)  评论(0编辑  收藏  举报