diff --git a/SMILES_please/chall.yaml b/SMILES_please/chall.yaml index 679d099..f77ab58 100644 --- a/SMILES_please/chall.yaml +++ b/SMILES_please/chall.yaml @@ -1,7 +1,7 @@ name: SMILES Please! categories: - crypto -value: 100 +value: 125 # Alternatively: flag: bcactf{nepetalactone} diff --git a/stuffed-hot-dog/challenge.yml b/stuffed-hot-dog/challenge.yml new file mode 100644 index 0000000..3ca5023 --- /dev/null +++ b/stuffed-hot-dog/challenge.yml @@ -0,0 +1,17 @@ +name: A Stuffed Hot Dog +author: Nikhil Palempalle +category: crypto +description: 'Have you ever had a hotdog with 8 frankfurters? Well, now you have! + You may assume that the private key (d) is small' +attribution: Written by Nikhil Palempalle +value: 100 +type: standard +version: '0.1' +image: null +protocol: null +host: null +flags: +- bcactf{WIENeR$-@7t4ck-$t1L1-w0rkS} +files: +- ciphertext.txt +state: visible diff --git a/stuffed-hot-dog/ciphertext.txt b/stuffed-hot-dog/ciphertext.txt new file mode 100644 index 0000000..d6df4aa --- /dev/null +++ b/stuffed-hot-dog/ciphertext.txt @@ -0,0 +1,3 @@ +ct = 1403606209868942650017364781576409477533484940516733222678051441319828847601408018318695284696537768100387645849435033406395627111973401324147563843448828424364415458400620022961409081291642827781984767909939401353554467293446356038287624457996091615012438622445962622285628097228207927045070754740243417930063146873255888923289971553781435068706561993227472499017170223886822405113488632448284153937575166022419812373238594078089088518171681792410288332808055107621502447489488173535957121552175879998398750034287197924824000774340061028648447596339146746245943402086560160152142586971494777596849345985466354971505 +e = 1007923536615788429308488626562273211764727739603326916716750134757664859102073538280046418621787956357694898611090496120711455465224553954057342423556585864474681775436484905703166080638087909964613464766175288771778765019262046300385293725834520490146106084530018338265651235516001622215244910020449661899742921948751900636529806699757780399920028084163545701117923463204472171540818124208844178088280319819213976811837266042606657104570279825807114809806757441716609936054298761798056420164827224473480042981060226017719191829286695719239693689441374116653221590962307342429813079248395613750792817430371356594717 +N = 3142349849449222750197052776929440013148857070528019210940456302479778678377349221584305162900604179911170769605069112228661293689628798943752570668861571068370627895414215745934141568783366676577579694116896916592106172835563014721257927354554808271620276995876625139065060816229893239617933923156203739805679179566345893480110255015050793281719874347689696637016196087752107854121307424464809067709547299049058279638185061382180884911772431967390831248346428244837807805068895517131666882598514171040165192668331369711579630965507768056880328273522003332433801987301518965550233528877714754322637238086401755369743 \ No newline at end of file diff --git a/stuffed-hot-dog/gen.py b/stuffed-hot-dog/gen.py new file mode 100644 index 0000000..4dddc12 --- /dev/null +++ b/stuffed-hot-dog/gen.py @@ -0,0 +1,34 @@ +import math +from Crypto.Util.number import getPrime +from random import randint + +def get_upper_bound_of_d(n, no_of_primes): + for _ in range(no_of_primes): + n = math.isqrt(n) + return n // 3 + +def create_keys(pub_key_size=2048, no_of_primes=8): + primes_arr = [getPrime(pub_key_size//no_of_primes) for i in range(no_of_primes)] + N = math.prod(primes_arr) + phi_N = math.prod([a - 1 for a in primes_arr]) + upper_bound = get_upper_bound_of_d(N, no_of_primes) + while True: + d = randint(2, upper_bound) + try: + e = pow(d, -1, phi_N) + except: + continue + if (e * d) % phi_N == 1: + return primes_arr, N, d, e + +def main(): + primes_arr, N, d, e = create_keys() + flag = "bcactf{WIENeR$-@7t4ck-$t1L1-w0rkS}" + flag_int = int.from_bytes(flag.encode()) + ctext = pow(flag_int, e, N) + print(f"ciphertext = {ctext}\ne = {e}\nN = {N}") + ptext = pow(ctext, d, N) + print(f"plaintext = {int.to_bytes(pow(ctext, d, N), math.ceil(ptext.bit_length()/8))}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/stuffed-hot-dog/solve.py b/stuffed-hot-dog/solve.py new file mode 100644 index 0000000..868fb0e --- /dev/null +++ b/stuffed-hot-dog/solve.py @@ -0,0 +1,64 @@ +from fractions import Fraction +import math + +def continued_fraction(n, d): + """Compute the continued fraction expansion of n/d.""" + cf = [] + while d: + q = n // d + cf.append(q) + n, d = d, n - q * d + return cf + +def convergents(cf): + """Compute the convergents from a continued fraction.""" + convs = [] + for i in range(1, len(cf) + 1): + frac = Fraction(0) + for q in reversed(cf[:i]): + if frac.numerator == 0: + frac = Fraction(q, 1) + else: + frac = 1 / frac + frac += q + convs.append((frac.numerator, frac.denominator)) + return convs + +def is_perfect_square(n): + h = n & 0xF + if h > 9: + return False + if h not in (0, 1, 4, 9): + return False + t = math.isqrt(n) + return t * t == n + +def wiener_attack(e, n, ct): + cf = continued_fraction(e, n) + print(len(cf)) + for k, d in convergents(cf): + if k == 0: + continue + # check if (ed - 1) % k == 0 + if (e * d - 1) % k != 0 and d % 2 == 1: + continue + + ct_length = math.ceil(ct.bit_length() / 8) + res = pow(ct, d, n) + res_str = int.to_bytes(res, math.ceil(res.bit_length()/8)) + print(res_str) + if (res_str[:6] == b'bcactf'): + return res_str + return None + +# Example usage: +if __name__ == "__main__": + # Replace with your e and n + ciphertext = 1403606209868942650017364781576409477533484940516733222678051441319828847601408018318695284696537768100387645849435033406395627111973401324147563843448828424364415458400620022961409081291642827781984767909939401353554467293446356038287624457996091615012438622445962622285628097228207927045070754740243417930063146873255888923289971553781435068706561993227472499017170223886822405113488632448284153937575166022419812373238594078089088518171681792410288332808055107621502447489488173535957121552175879998398750034287197924824000774340061028648447596339146746245943402086560160152142586971494777596849345985466354971505 + e = 1007923536615788429308488626562273211764727739603326916716750134757664859102073538280046418621787956357694898611090496120711455465224553954057342423556585864474681775436484905703166080638087909964613464766175288771778765019262046300385293725834520490146106084530018338265651235516001622215244910020449661899742921948751900636529806699757780399920028084163545701117923463204472171540818124208844178088280319819213976811837266042606657104570279825807114809806757441716609936054298761798056420164827224473480042981060226017719191829286695719239693689441374116653221590962307342429813079248395613750792817430371356594717 + N = 3142349849449222750197052776929440013148857070528019210940456302479778678377349221584305162900604179911170769605069112228661293689628798943752570668861571068370627895414215745934141568783366676577579694116896916592106172835563014721257927354554808271620276995876625139065060816229893239617933923156203739805679179566345893480110255015050793281719874347689696637016196087752107854121307424464809067709547299049058279638185061382180884911772431967390831248346428244837807805068895517131666882598514171040165192668331369711579630965507768056880328273522003332433801987301518965550233528877714754322637238086401755369743 + flag = wiener_attack(e, N, ciphertext) + if flag: + print(f"Recovered flag: {flag}") + else: + print("Failed to recover flag.") \ No newline at end of file