# S.S.S.

This is a writeup for HexionCTF 2020, where we placed third.

### Challenge Description:

``````Math is so beautiful and can always be used for cryptographic
encryption!
nc challenges1.hexionteam.com 5001
``````

### Solving :

We are given an sss.py. See here for source.

We found that SSS stands for Shamir’s Secret Sharing by copy-pasting the loop from `eval_at`, which brought me to this Wikipedia Page. Shamir Secret Sharing is based on polynomials and lagrange interpolation.

Most of this code (nearly everything except main) is taken from Wikipedia’s example implementation of Shamir’s Secret Sharing. The concept is relatively simple. The sss.py that we are given is giving out “shares”, with the flag as the secret. We can just request enough shares until we meet the minimum threshold to be able to recover the secret. From there, we can use langrage interpolation to calculate y for x=0 and retrieve our flag.

### Solve Script :

``````from Crypto.Util.number import long_to_bytes
from pwn import remote

P = 2 ** 521 - 1

def eval_at(poly, x, prime):
accum = 0
for coeff in reversed(poly):
accum *= x
accum += coeff
accum %= prime
return accum

def extended_gcd(a, b):
x = 0
last_x = 1
y = 1
last_y = 0
while b != 0:
quot = a // b
a, b = b, a % b
x, last_x = last_x - quot * x, x
y, last_y = last_y - quot * y, y
return last_x, last_y

def divmod(num, den, p):
inv, _ = extended_gcd(den, p)
return num * inv

def _lagrange_interpolate(x, x_s, y_s, p):
k = len(x_s)
assert k == len(set(x_s)), "points must be distinct"

def PI(vals):  # product of inputs
accum = 1
for v in vals:
accum *= v
return accum

nums = []
dens = []
for i in range(k):
others = list(x_s)
cur = others.pop(i)
nums.append(PI(x - o for o in others))
dens.append(PI(cur - o for o in others))
den = PI(dens)
num = sum([divmod(nums[i] * den * y_s[i] % p, dens[i], p)
for i in range(k)])
return (divmod(num, den, p) + p) % p

def recover_secret(shares, prime=P):
x_s, y_s = zip(*shares)
return _lagrange_interpolate(0, x_s, y_s, prime)

def main():
# connect to the nc server
r = remote("challenges1.hexionteam.com", 5001)
r.recvuntil(">>>")
shares = []

# request 78 shares, just to be safe (min is a random int between 48 and 63, inclusive)
for i in range(0x1, 0x50):
if i == ord('\n'):
continue
r.sendline(long_to_bytes(i))
resp = r.recvline().decode()
resp = resp.strip().strip('>').strip()
shares.append((i,int(resp)))

if len(shares) % 5 == 0:
print("Acquired", len(shares), "shares")

# print(shares)
print(long_to_bytes(recover_secret(shares)))

if __name__ == '__main__':
main()
``````

Flag : hexCTF{d0nt_us3_shar3s_lik3_that}