Tags: crypto 

Rating:

**Task:**
Break the RSA-2048 cryptosystem, where `p` is a string prime and `q` is computed from `p` by complicated function:

```
from Crypto.Util.number import isPrime, getStrongPrime
from math import isqrt, sin, ceil
from secrets import flag

def f(p):
return isqrt(p**2 + p * (2**512-6) + ceil(isqrt(p)*sin(p))) + 2**1023

while True:
p = getStrongPrime(1024)
if p < 2**1023:
continue
q = f(p)
if isPrime(q):
break

N = p * q
e = 0x10001
m = int.from_bytes(flag, 'big')
c = pow(m, e, N)

print(f'N = {N}')
print(f'c = {c}')
```

**Solution:**

* `q` is computed as `f(p)` and verified if it is prime, where
* `f(p) = isqrt(p**2 + p * (2**512-6) + ceil(isqrt(p)*sin(p))) + 2**1023`

**Approach 1**:
* `f(p)` is an increasing function, so `p*f(p)` is increasing function, too
* we can use binary search to find the correct value of `p`, which satisfies the condition `p*f(p) == N`

**Approach 2**
* `f(p)` is almost `isqrt((p+2**511)**2) + 2 **1024`
* it turns out that for big `p > 2**1023` holds:
* `f(p) = p + 2**1023 + 2**511 - 2**2`
* now let `q = p + a`, then `p**2 + a*p - N = 0`
* roots of quadratic equation:
* `p = (isqrt(a**2 + 4*N)-a) / 2`

**Python solver:**

```
from math import isqrt

N = 36517404305297844159564250986998364545749151568667732337564141796428285198409567155495468780386611544242689580089026301007867731616501462571857014948329304677585682534513311931280592743677919741211277066420279973665839898693462080087384474270473468411814863104608060945012301810206919347219744349831947632420533489933798065496290612931089442978868423837068735855183319271953531607892676482508704408482509645764820088854762889436761417245871075875762331247987854763068633058894469255779600684845456979405817748289218533715177711802661303055514957438072072036882111277967476497338901040854808789173453802590826788192053
c = 10955441460830702971387335888341162305090757526159743008807609823673521696863955454033040842132899414049783504960968117620860408142538216669369693386110678382112863315608217382774969191050306778748875856817288367369848881561750362221050586276876239956129985854245190619132772579774800480316624847309710595491090120189333272498817039509311650265968036568364234815921263181086438290844976279974023236010641698308664245573159698211860696725554580817928576304048869309097043078452170158082597167199813821750238244173483019805092246803337196768846732908994751887507198151471659940647272634351206676375579258509003076141110
e = 0x10001

a = 2**1023 + 2**511 - 2**2
p = (isqrt(a**2+4*N)-a)>>1
q = p + a
d = pow(e, -1, (p-1)*(q-1))
m = pow(c, d, N)
print(m.to_bytes((m.bit_length()-1)//8 + 1, 'big'))
```

* flag: `TSGCTF{From which angle did you solve this, binary search or convergence of f(p)-p?}`