← Back to Writeups
CUSTOMEasyCrypto

Только RSA (JustRSA)

XESXOR9/10/20262 min read
#crypto#custom#easy#factordb_lookup#rsa_decryption

Только RSA (JustRSA)

Platform: duckerz | Category: Crypto | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-01-09 | Status: Solved Techniques: factordb_lookup, rsa_decryption

Summary

Task: RSA with standard parameters (n, e=65537, ct). Solution: OSINT hint leads to factordb.com lookup where modulus n is already fully factored, enabling standard RSA decryption.

Только RSA (JustRSA) — duckerz CTF

Description

"Иногда криптография - это просто осинт." (Translation: "Sometimes cryptography is just OSINT.")

Provided file JustRSA.txt with RSA parameters:

  • n (modulus)
  • e = 65537 (public exponent)
  • ct (ciphertext)

Analysis

  1. Hint in description: The phrase "cryptography is just OSINT" clearly points to using public databases to find factorization.

  2. Checking factordb.com: The RSA modulus n was already factored and is in the factordb.com database with status "FF" (Fully Factored). ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

  3. Vulnerability: Using a known (already factored) modulus n is a critical RSA implementation flaw.

Solution

Step 1: Getting factors from factordb

Query to factordb.com API returns two prime factors p and q.

Step 2: Standard RSA decryption

  • Calculate φ(n) = (p-1)(q-1)
  • Find private key d = e⁻¹ mod φ(n)
  • Decrypt: m = ct^d mod n
  • Convert to bytes

Solve Script

python
#!/usr/bin/env python3
"""
Duckerz CTF - JustRSA
Solution: factordb lookup + standard RSA decryption
"""
from Crypto.Util.number import long_to_bytes
import requests
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

n = 17327286385030297619055609812547395532303350738357039187271762800476355565047902196480182952525970808148340374159153211958450440378498794350454268441698198116395593570968780817193848386119467551056846736050217957904655068683306568686860949952622952069871723551854065721708810178405245808610636319206090568675639505989380448963390500784981938837344148741951935352345831138854398944969527820495720840504098981923332332034403797978425789401021243205986351856289983707620600473774106442080605714538190714676992843800728968866308968923652890236623555171107158471771943494381582012510740446793672404982545209615196896091487
e = 65537
ct = 10058608948455821517641796320876011023614836796389494478289770080895990145870826644857969839992640585885225869358903291661065502710233826943640547100261977038126317835614724458212737865746925695551722600139789223080269322672678031681099087414479454274217041959345200125049563630298968200294252181290051200843671428154845959200679407462916623249773961868051826650122066566171538180083749594010332408045836052918502082832344876781528408062647612902902289406787553102682822923150153637606960244027051196087271248059857781508527868441976847867511668607671562042452093738644785668851178349867195740709620527744312510486456
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Query factordb API
url = f"http://factordb.com/api?query={n}"
resp = requests.get(url, timeout=30)
data = resp.json()

if data.get('status') != 'FF':
    print(f"[!] Status: {data.get('status')} - may not be fully factored")
    
factors = data.get('factors', [])
p = int(factors[0][0])
q = int(factors[1][0])

print(f"[+] p = {p}")
print(f"[+] q = {q}")

# Verify factorization
assert p * q == n, "Factorization failed!"

# Calculate private key and decrypt
phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
m = pow(ct, d, n)
flag = long_to_bytes(m)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

print(f"[+] Flag: {flag.decode()}")

Alternative Method (without API)

python
#!/usr/bin/env python3
"""If factors are already known"""
from Crypto.Util.number import long_to_bytes

n = 17327286385030297619055609812547395532303350738357039187271762800476355565047902196480182952525970808148340374159153211958450440378498794350454268441698198116395593570968780817193848386119467551056846736050217957904655068683306568686860949952622952069871723551854065721708810178405245808610636319206090568675639505989380448963390500784981938837344148741951935352345831138854398944969527820495720840504098981923332332034403797978425789401021243205986351856289983707620600473774106442080605714538190714676992843800728968866308968923652890236623555171107158471771943494381582012510740446793672404982545209615196896091487
e = 65537
ct = 10058608948455821517641796320876011023614836796389494478289770080895990145870826644857969839992640585885225869358903291661065502710233826943640547100261977038126317835614724458212737865746925695551722600139789223080269322672678031681099087414479454274217041959345200125049563630298968200294252181290051200843671428154845959200679407462916623249773961868051826650122066566171538180083749594010332408045836052918502082832344876781528408062647612902902289406787553102682822923150153637606960244027051196087271248059857781508527868441976847867511668607671562042452093738644785668851178349867195740709620527744312510486456
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Pre-known factors from factordb
p = 8300337493644121780493117020378845940459960810575368241208483955396033269630503231303070845417321910406019424747630744273420768812998703720743832842344763881555713806174559171575672684544155159559903709548085184274292300067413344439112860644504557360257489927307675873524183578682403658103
q = 2087539982355952095352940591481182316534226033893916513431522538203193520762524106594022783007866775889494900254987221649795202213419228734556286567814291577680141913972513242659019754608685871868492014601186827830818090245390932534369400308423585229696958659515265119460457285099551187329600050104076864250940595905060827485529
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
m = pow(ct, d, n)
print(long_to_bytes(m).decode())

Useful Resources

  • factordb.com — database of factored numbers
  • factordb API — programmatic access to the database
  • factordb statuses: C (Composite), CF (Composite, factors known), FF (Fully Factored), P (Prime)

Lessons

  1. Always check factordb — this is the first step when analyzing RSA tasks
  2. OSINT in cryptography — sometimes the solution doesn't require math
  3. Key generation — in real systems always generate fresh prime numbers ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍