Chujoyw CTF 2020 | baby RSA

RSA

flag = open('flag', 'rb').read()
pt = int.from_bytes(flag, 'big')

def case1(x):
    N = 0x9cca93a0eff966a6cc3426dc79f66c0526944c5a51681a3be685daee7506352dfb7bdd76e59995d2ba980158212f4797c3fc1ae81fdd3500e93634e7e5a47944d14b2de0922d0fcbe2ada121444ef6ad908992ffebaf3b710c2eb719b8b67a83711903885a6fcb0959dee527f946efd5f308dbb0e4eb720041a18e0984015da9
    e = 0x10001
    return pow(x, e, N)

def case2(x):
    N = 0x56dc3d6211ef129bbaeadd8603658fec577ff9d95ad5e5fdd09c793a25dc932c98c0af71876a396663e398ab92ff1e504919ee3f1f5eda7a255ed68ac53d5f62d5b2a5e558fbe377078f8a1534bcfc6164febc51d3e004545106198492ebde663c530aac177ec30970b83e84e04d4251220f5ef3efaa396e81207b5d191bdffb579ad
    e = 0x10001
    return pow(x, e, N)

x = case1(pt)
x = case2(x)
print(x)
# 15620344004575314381699909644476548125673811896863391476575828314467946163796453279562013347582204584161257318356658773248127199432536307725788425585122157944323601936111645375226259360207001107437486608453696480819916675738100568407249432260802623357309693764513235205165863599779333368122255526121539664687917017

2段のRSAになっていて、 case1 では N=p*pのRSAで、case 2ではgcd(phi, e) != 1のRSAになっている。

case2では、qが極端に小さいためpがNと近い大きさを持っており、 c^e \mod n \mod p = c^e \mod pとしたときに、暗号文の情報が(たぶん)欠落しない(この式が成り立つのは  p | nだから)

case1はRSAにも書いたとおり

e = 65537

def case2_decrypt(x):
    q = 917519
    p = 69707871934620509569728343326146258018582770029493511657054559474862686968409562136128616525777049328581358570890118432267895804235375130688754817769114083316475993705721434805544637977222767286061406234732498641334101774524615069140084400641451544889398258593755469676273142784457956433914529533013432954499

    d = pow(e, -1, p-1)
    return pow(x % p, d, p)

def case1_decrypt(x):
    p = 10492978880681953392127330744339615425831079360535424391240424219033821891058999100168555964454399098070169915149390329031335140789785697131896616096847731
    d = pow(e, -1, p*(p-1))
    return pow(x, d, p*p)

c = 15620344004575314381699909644476548125673811896863391476575828314467946163796453279562013347582204584161257318356658773248127199432536307725788425585122157944323601936111645375226259360207001107437486608453696480819916675738100568407249432260802623357309693764513235205165863599779333368122255526121539664687917017

from Crypto.Util.number import long_to_bytes

m = case1_decrypt(case2_decrypt(c))
print(long_to_bytes(m))