# Cube Challenge Script: ```python= from Crypto.Util.number import bytes_to_long, getPrime, isPrime FLAG = <REDACTED> def gen(n): while True: p = getPrime(n - 1) * 2 + 1 if (isPrime(p)): return p def cube(m, n, p): res = m for i in range(n): res = (res * res * res) % p return res p = gen(1024) m = bytes_to_long(FLAG) c = cube(m, 2 ** 100, p) print(p) print(c) # p = 147271787827929374875021125075644322658199797362157810465584602627709052665153637157027284239972360505065250939071494710661089022260751215312981674288246413821920620065721158367282080824823494257083257784305248518512283466952090977840589689160607681176791401729705268519662036067738830529129470059752131312559 # c = 117161008971867369525278118431420359590253064575766275058434686951139287312472337733007748860692306037011621762414693540474268832444018133392145498303438944989809563579460392165032736630619930502524106312155019251740588974743475569686312108671045987239439227420716606411244839847197214002961245189316124796380 ``` Summary: This challenge essentially involves performing ``2^100`` consecutive modular cube roots on ``c`` to derive the flag. More formally, ``flag = c^(1/(3^(2^100))) mod p``, where ``p`` is prime. Since ``p`` is prime, modular roots can be easily computed, as modular root algorithms such as [Tonelli-Shanks Algorithm](https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm) and [Adleman-Manders-Miller Algorithm](http://www.cs.cmu.edu/~glmiller/Publications/AMM77.pdf) all require prime moduli. In the case of modular cube roots, from [this post](https://stackoverflow.com/a/6752874), it can be seen that there are only a few possible valid cases for which a modular cube root can be calculated. Test Script: ```python= # Value from Challenge Script p = 147271787827929374875021125075644322658199797362157810465584602627709052665153637157027284239972360505065250939071494710661089022260751215312981674288246413821920620065721158367282080824823494257083257784305248518512283466952090977840589689160607681176791401729705268519662036067738830529129470059752131312559 print(p%3, p%9) ``` Output: ``` 2 8 ``` This implies that the cube root of ``c mod p`` can be calculated as ``pow(c, (2*p - 1)//3, p)``. However, since we need to compute ``2^100`` consecutive cube roots, ``flag = pow(c, ((2*p - 1)//3)^(2^100), p)``. This is an issue, since ``((2*p - 1)//3)^(2^100)`` is too large of an exponent to use in modular exponentiation. Fortunately, the exponent can be simplified using modular arithmetic. [Euler's Theorem](https://en.wikipedia.org/wiki/Euler%27s_theorem) states that ``a^k ≡ a^(k mod φ(n)) mod n`` if ``gcd(a, n) = 1`` for ``k >= 1``, where ``φ(n)`` is Euler's totient function. Test Script: ```python= # Values from Challenge Script p = 147271787827929374875021125075644322658199797362157810465584602627709052665153637157027284239972360505065250939071494710661089022260751215312981674288246413821920620065721158367282080824823494257083257784305248518512283466952090977840589689160607681176791401729705268519662036067738830529129470059752131312559 c = 117161008971867369525278118431420359590253064575766275058434686951139287312472337733007748860692306037011621762414693540474268832444018133392145498303438944989809563579460392165032736630619930502524106312155019251740588974743475569686312108671045987239439227420716606411244839847197214002961245189316124796380 print(gcd(c, p)) ``` Output: ``` 1 ``` This shows that ``c`` and ``p`` are coprime (i.e. their gcd is ``1``), meaning that Euler's Theorem can be applied. Since ``p`` is prime, ``φ(p) = p-1``. Solve Script: ```python= # Values from Challenge Script p = 147271787827929374875021125075644322658199797362157810465584602627709052665153637157027284239972360505065250939071494710661089022260751215312981674288246413821920620065721158367282080824823494257083257784305248518512283466952090977840589689160607681176791401729705268519662036067738830529129470059752131312559 c = 117161008971867369525278118431420359590253064575766275058434686951139287312472337733007748860692306037011621762414693540474268832444018133392145498303438944989809563579460392165032736630619930502524106312155019251740588974743475569686312108671045987239439227420716606411244839847197214002961245189316124796380 assert p%3 == 2 assert gcd(c, p) == 1 exp = pow((2*p - 1)//3, 2^100, p-1) # Apply Euler's Theorem to make the exponent smaller c = pow(c, exp, p) from Crypto.Util.number import long_to_bytes print(long_to_bytes(Integer(c))) ``` Output: ``` b'grey{CubeIsSquarerThanSquare_FjUFynTNUdTyJu5x}' ```