Rating: 4.5

We are given the hex-string of the encrypted flag and the source code showing the method of encryption.

The source code suggests that it calculates `int_key` to be the following "power-tower" number of all primes between 1 and 100
```
2
3^
...
79^
83^
89^
97^
```
then calculates that number modulo the large `n` value, and uses that as the key to AES encrypt the flag.

Of coruse in reality the source code could never be ran because the power-tower number is prohibitively large so there must be another way of calculating the key value.

To do so, we can use **Euler's theorem**. Euler's theorem states if positive integers `n` and `a` are coprime then `a ^ phi(n) ≡ 1 mod n` where `phi(n)` is Euler's totient function that counts the number of integers up to `n` that are relatively prime to `n`.

`a ^ phi(n) ≡ 1 mod n` helps us because it means that where we want to calculate `a^b mod n` for some large `b`, we can reduce `b` by noticing we can find the remainder `r` such that `b = k * phi(n) + r`. Then `a^b mod n = a^(k*phi(n)+r) mod n = (a^(k*phi(n)) * a^r) mod n = ((a^phi(n))^k * a^r) mod n ≡ (1^k * a^r) mod n = a^r mod n`.

So that means: `a^b mod n ≡ a^(b mod phi(n)) mod n` when `n` and `a` are coprime.

We can calculate `phi(n)` easily so long as we know the prime factors of `n` due to **Euler's product formula** which states `phi(n) = n * Π((p-1)/p) ` where the product `Π` is over all the distinct prime factors `p` of `n`.

We can do this recursively, first calculating `phi(n)`, then `phi(phi(n))=phi^2(n)`, then `phi(phi(phi(n)))=phi^3(n)` and so on, until we have `3^2 mod phi^23(n) = 9`, then `5 ^ 9 mod phi^22(n) = 1953125` then `7^1953125 mod phi^21(n) = 5272812950246780296288348397180183079852019020305406550894936231` and so on, and because of the reduction the exponents never get larger than `n` (78 digits long) and so remain managable (as compared to the astronomical exponents if we didn't have the modulo helping us!).

Putting this all together, here is my solve script.

```python
from Crypto.Cipher import AES
from Crypto.Util import number
from functools import reduce
from sympy.ntheory import factorint

def phi(n):
print('phi', n)
if(n < 0): n = -n
if n == 0: return 0
if n == 1: return 1
if n == 2: return 1
factors = list(factorint(n).keys())
return (n * reduce(lambda x, y: x * (y - 1), factors, 1)) // reduce(lambda x, y: x * y, factors, 1)

def powertower(primes, n):
if len(primes) == 2:
result = pow(primes[1], primes[0], n)
else:
result = pow(primes[-1], powertower(primes[:-1], phi(n)), n)
print(result)
return result

# n = number.getRandomNBitInteger(256)
n = 107502945843251244337535082460697583639357473016005252008262865481138355040617

primes = [p for p in range(100) if number.isPrime(p)]

int_key = powertower(primes, n)

key = int.to_bytes(int_key, 32, byteorder="big")
cipher = open("cipher.txt", "r").read().strip()
flag = AES.new(key, AES.MODE_ECB).decrypt(bytes.fromhex(cipher))
print(flag)

###
# phi 107502945843251244337535082460697583639357473016005252008262865481138355040617
# phi 106656465954594992227312203077713006587965800635814353306369389060697410445312
# phi 29970165580857582102036857156579701495531497766270525309534476100493648068608
# phi 7467242028734943276198998296907123249252251029983571451365420952179651379200
# phi 1269237825224153827759617570784166477777435105458379290184361960133361664000
# phi 220856445409942410607579128684927171029818854024203224102779729041424384000
# phi 38426629583920220737652753398740209611581447743071490944118372004003840000
# phi 7033802026128398497275908097717361944462431356697231715680342696263680000
# phi 1398022762957197216849869932465562622501849710647896986967521529692160000
# phi 277867878351741061734135638750919279006578824476600643372426639441920000
# phi 57738779917244895944755457402788421611756638852280653168296444559360000
# phi 13997279979938156592667989673403253724062215479340764404435501711360000
# phi 3393279995136522810343755072340182720984779510143215613196485263360000
# phi 822613332154308560083334562991559447511461699428658330471875215360000
# phi 219363555241148949355555883464415852669723119847642221459166724096000
# phi 58496948064306386494814902257177560711926165292704592389111126425600
# phi 15599186150481703065283973935247349523180310744721224637096300380160
# phi 4159782973461787484075726382732626539514749531925659903225680101376
# phi 1386594324487262494691908794244208846504916510641886634408560033792
# phi 462198108162420831563969598081402948834972170213962211469520011264
# phi 154066036054140277187989866027134316278324056737987403823173337088
# phi 51355345351380092395996622009044772092774685579329134607724445696
# phi 17118448450460030798665540669681590697591561859776378202574815232
# 9
# 1953125
# 5272812950246780296288348397180183079852019020305406550894936231
# 47010857620305641428821871837048895189393315137072666330151357507
# 259722333789055990984863074249446211700306933924094190538426367381
# 280488081538048586387160854821443413866080335888230797461843708753
# 2117777436487693023514994561466359462928276264029062106743943340499
# 4055374701429556659881928730692702975027409479963256770896199235847
# 2494791660603823176461789239197686606388257943874153109936981818709
# 109293035149299131178491179622880387764337473544843328425317239808671
# 485646265807815932058941708264665358079903968069134159743356742477613
# 3071327790725066368046470174546108074909747943785779575326206258333321
# 9614633228612872034289196862990661378595176185597511932800328715732043
# 37956593305480064971193103074046330400679856772139725919007010147774223
# 27684929161307053274012908483361155757372617579528119012022484214579677
# 366948622062393746437974151402630697316787300414654475016659506234327019
# 6617478545542492438857001916498594802467225186273723309664698942942620741
# 32216562958346528413035858455059340195584270416024180842887427798476508467
# 87015953864651184206380145526079325866851497390566579152147588761577053591
# 300396861982842389028416458101446649414439111464229592512779615343883393977
# 5343132062847871879579535867063547843873934756634705632585054226177317457359
# 7390344881272852531101178942674955886694088405617803515427130767230086668699
# 55319929876539258630362464679588063193920627024882290739430771628945704297737
# 16347505767151968709743636365502606329879983155171448517653531921243027556968
# b'ENO{m4th_tr1ck5_c4n_br1ng_s0me_3ffic13ncy}______'
###
```