Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion SMILES_please/chall.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: SMILES Please!
categories:
- crypto
value: 100
value: 125
# Alternatively:
flag: bcactf{nepetalactone}

Expand Down
17 changes: 17 additions & 0 deletions stuffed-hot-dog/challenge.yml
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions stuffed-hot-dog/ciphertext.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ct = 1403606209868942650017364781576409477533484940516733222678051441319828847601408018318695284696537768100387645849435033406395627111973401324147563843448828424364415458400620022961409081291642827781984767909939401353554467293446356038287624457996091615012438622445962622285628097228207927045070754740243417930063146873255888923289971553781435068706561993227472499017170223886822405113488632448284153937575166022419812373238594078089088518171681792410288332808055107621502447489488173535957121552175879998398750034287197924824000774340061028648447596339146746245943402086560160152142586971494777596849345985466354971505
e = 1007923536615788429308488626562273211764727739603326916716750134757664859102073538280046418621787956357694898611090496120711455465224553954057342423556585864474681775436484905703166080638087909964613464766175288771778765019262046300385293725834520490146106084530018338265651235516001622215244910020449661899742921948751900636529806699757780399920028084163545701117923463204472171540818124208844178088280319819213976811837266042606657104570279825807114809806757441716609936054298761798056420164827224473480042981060226017719191829286695719239693689441374116653221590962307342429813079248395613750792817430371356594717
N = 3142349849449222750197052776929440013148857070528019210940456302479778678377349221584305162900604179911170769605069112228661293689628798943752570668861571068370627895414215745934141568783366676577579694116896916592106172835563014721257927354554808271620276995876625139065060816229893239617933923156203739805679179566345893480110255015050793281719874347689696637016196087752107854121307424464809067709547299049058279638185061382180884911772431967390831248346428244837807805068895517131666882598514171040165192668331369711579630965507768056880328273522003332433801987301518965550233528877714754322637238086401755369743
34 changes: 34 additions & 0 deletions stuffed-hot-dog/gen.py
Original file line number Diff line number Diff line change
@@ -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()
64 changes: 64 additions & 0 deletions stuffed-hot-dog/solve.py
Original file line number Diff line number Diff line change
@@ -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.")