89 lines
2.7 KiB
Markdown
89 lines
2.7 KiB
Markdown
# 4096
|
|
|
|
by [haskal](https://awoo.systems)
|
|
|
|
crypto / 360 pts / 219 solves
|
|
|
|
>I heard 4096 bit RSA is secure, so I encrypted the flag with it.
|
|
|
|
provided files: [source.py](source.py) [output.txt](output.txt)
|
|
|
|
## solution
|
|
|
|
inspecting the source you can see the provided source implements RSA. the weakness is it uses many
|
|
small primes instead of 2 large primes. this makes it extremely easy to factor the number
|
|
(factoring the public key in RSA leads to recovery of the private key)[^1]
|
|
|
|
```python
|
|
m = bytes_to_long(flag)
|
|
primes = [getPrime(32) for _ in range(128)]
|
|
n = prod(primes)
|
|
e = 65537
|
|
print(n)
|
|
print(pow(m, e, n))
|
|
```
|
|
|
|
i turned to my trusted factoring tool, [yafu](https://sourceforge.net/projects/yafu/) and _quickly_
|
|
discovered that in 2021 yafu is very crashy (at least on my system... i assume this is some glibc or
|
|
gmp ABI incompatibility)[^2]
|
|
|
|
yafu provides a shell in which you can invoke the `factor` operation
|
|
```
|
|
factor(50630448182626893495....)
|
|
```
|
|
|
|
this should complete in a few seconds even on old machines. it produces a list like
|
|
```
|
|
...
|
|
P10 = 3991834969
|
|
P38 = 66683226414537879762507759703783429499
|
|
C20 = 15613277632742914627
|
|
P10 = 3959814431
|
|
P10 = 3943871257
|
|
P10 = 2602521199
|
|
P10 = 3177943303
|
|
P10 = 3625437121
|
|
P10 = 2707095227
|
|
P10 = 3346647649
|
|
P10 = 2572542211
|
|
P10 = 2753147143
|
|
P10 = 3488338697
|
|
P10 = 2525697263
|
|
P10 = 3291377941
|
|
P10 = 4141964923
|
|
...
|
|
```
|
|
|
|
some of the output was not factored enough, there are still some composite numbers and incorrectly
|
|
identified primes -- we know from the source that all the primes are 32 bit so we're looking for all
|
|
`P10` lines. the solution is simple just run `factor(...)` again on any non-P10 outputs... and this
|
|
is where i wrote a quick script to do this automatically except for some reason yafu consistently
|
|
crashed when run under python (;___;) so i ended up doing it by hand (time wasted that could be
|
|
spent pwning but whatever)
|
|
|
|
anyway once you have all the primes you just need to calculate the private key and do decryption.
|
|
the private key is computed by `65537^{-1} mod phi`, where `phi` (the easier one to calculate) is
|
|
the product of all the primes minus 1. then do `{encrypted message}^d mod n` and you have the flag
|
|
|
|
```python
|
|
[ins] In [1]: import math
|
|
|
|
[nav] In [2]: factors = [int(x) for x in open("factors")]
|
|
|
|
[nav] In [3]: phi = math.prod([x - 1 for x in factors])
|
|
|
|
[nav] In [4]: [n, enc] = [int(x) for x in open("output.txt")]
|
|
|
|
[ins] In [5]: d = pow(65537, -1, phi)
|
|
|
|
[ins] In [6]: dec = pow(enc, d, n)
|
|
|
|
[ins] In [7]: dec.to_bytes(dec.bit_length()//8+1,"big")
|
|
Out[8]: b'corctf{to0_m4ny_pr1m3s55_63aeea37a6b3b22f}'
|
|
```
|
|
|
|
[^1]: i assume we are familiar with RSA but if not, wikipedia is a good reference:
|
|
<https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Operation>
|
|
|
|
[^2]: time to get a new factoring tool of choice probably
|