from gmpy2 import next_prime, is_prime import random, os, sys if __name__ == "__main__": random.seed(os.urandom(32)) p = next_prime(random.randrange((1<<1024), (1<<1024) + (1<<600))) pp = (p * 7) // 11 q = next_prime(random.randrange(pp - (1<<520), pp + (1 << 520))) with open(sys.argv[1], "rb") as f: flag = int.from_bytes(f.read(), "big") assert is_prime(p) assert is_prime(q) N = p * q assert flag < N e = 0x10001 c = pow(flag, e, N) with open("out.txt", "w") as f: f.write(f"N = {hex(N)}\n") f.write(f"e = {hex(e)}\n") f.write(f"c = {hex(c)}\n")
であるようなSuspicious Prime RSA 。まず思い出すのは CONFidence CTF 2019 Teaser|Really Suspicious AcronymやMidnightsun CTF 2021 Quals | ocat_024 だが、これらの方法ではうまく行かない。なぜ?
そこで すなわち であることに着目すると
よって フェルマー法 が有効
を満たすで、これはであるが、もっと簡単に表して である
N = 0xa2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba93f56d1e890d1827d8ae8d40172a2dfafaa73523dd318c608bd4169d702442e6d153ae0637766f635255f4c1ee6bc694589b2708ae9061fb84f9db9da7199996c519635decfb53b4ccfde2bf9e89f70de9172bd370be887e8e1009b278774ee2449ce3ea3b76428506b4a98beda6e3c9aabbf1164e088f27554282d7909ef2ae61fb5316e705e3ea72cba9df06af06e54c3ee898dab8ed245e26290f59feeec9f58e61c4a2051086234fe48b42399a74452b87829da28f3e88a5a4b01b72d045b296297a3da34b9a5c20cb e = 0x10001 c = 0x2d1f77201435e00d3355246cc4de54b3c98a801f688500ff1e824d985f225f95415019188af01c39c80393e648e5e51bab80e1abfda82a74490fe58ef82afde4bed2999b10ac71f241f20564f5d2461cd57b50033c0fe64319b246ad241846b2ab37328f83d0a77fe5c3564cec18dbc577fdacad417925d208735d8b916779f567ef863dba594d9d035c99e6210db9397797c10e900a1d4a3bce2f87502c23f2e909808c10ac675affb41b3e0769360c959289338ce2877813c723524718d84a75b2209ba4f3560fcbc82da69d6b2f86c32970b325ec034a060fc62f6b3a97ae01cdfc8aeb35df03d92af88a7b60831254095fb66ce73b2c5941440721899dc1 import gmpy2 def fermat(n): x = gmpy2.isqrt(n) a = x*x - n while not gmpy2.is_square(a): x += 1 a = x*x - n return x, gmpy2.isqrt(a) # int(x - gmpy2.isqrt(a)), int(x + gmpy2.isqrt(a)) a, b = fermat(11 * 7 * N) if (a + b) % 7 == 0: p = (a + b) // 7 q = N // p else: p = (a + b) // 11 q = N // p assert N % q == 0 d = pow(e, -1, (p-1)*(q-1)) m = pow(c, d, N) print(bytes.fromhex(hex(m)[2:]))