Writeups
  • UMASS CTF 2024
    • Crypto-Brutal Mogging
    • Crypto - Shuffling as a Service
  • GPN CTF 2024
    • Crypto-Boombox
  • WANICTF 2024
    • Crypto - Replacement
    • Crypto - Easy Calc
    • Crypto - dance
    • Crypto - speedy
    • Crypto - Many Xor Shift
    • Crypto - uf
  • UIUCTF 2024
    • Crypto-Without a Trace
    • Crypto-Determined
    • Crypto-Naptime
    • Crypto-Snore Signatures
    • Crypto-Groups
  • DeadSec CTF 2024
    • Crypto - Raul Rosas
    • Crypto - SSP
    • Crypto - Password Guesser
  • corCTF 2024
    • Crypto - Steps
    • Crypto - Monkfish
    • Crypto - Anglerfish
  • LITCTF 2024
    • Crypto- Symmetric RSA
    • Crypto -Truly Symmetric RSA
  • IrisCTF 2025
    • Crypto - knutsacque
  • UofTCTF 2025
    • Misc - Simple Signing
  • HTB CyberApocalypse
    • Crypto - Copperbox
  • BreachCTF 2025
    • Crypto - Taaffeite Encryption
    • Crypto - Big Stuff
Powered by GitBook
On this page
  • Full Implementation
  • Challenge
  1. WANICTF 2024

Crypto - speedy

I made a super speedy keystream cipher!! - Gureisya

PreviousCrypto - danceNextCrypto - Many Xor Shift

Last updated 11 months ago

Challenge

First, we see how the flag is encrypted

class MyCipher:
    def __init__(self, s0, s1):
        self.X = s0
        self.Y = s1
        self.mod = 0xFFFFFFFFFFFFFFFF
        self.BLOCK_SIZE = 8

    
    def encrypt(self, pt: bytes):
        ct = b''
        for i in range(0, len(pt), self.BLOCK_SIZE):
            ct += long_to_bytes(self.X)
            key = self.get_key_stream()
            block = pt[i:i+self.BLOCK_SIZE]
            ct += bytes([block[j] ^ key[j] for j in range(len(block))])
        return ct

The ciphertext is basically the key xor'ed with the plaintext with some information about one of the parameters of the keystream generation

Let's see how the keystream is being generated

def get_key_stream(self):
    s0 = self.X
    s1 = self.Y
    sum = (s0 + s1) & self.mod
    s1 ^= s0
    key = []
    for _ in range(8):
        key.append(sum & 0xFF)
        sum >>= 8
    
    self.X = (rotl(s0, 24) ^ s1 ^ (s1 << 16)) & self.mod
    self.Y = rotl(s1, 37) & self.mod
    return key

If we knew the initial state with which the keystream is initialized, then we can predict any output which comes from it

We know the initial s0 and final s0, so we have to find out the initial value of s1. The final value of s0 is

s0 = rotl(s0,24)^ s1 ^ (s1<<16) & self.mod

Since we know the value of the inital s0, therefore the value of rotl(s0,24) is known to us. We can use z3 to find the value of s1.

from z3 import *
t1=rotl(i0,24)
x0 = BitVec("x0",64)
x1 = BitVec("x1",64)
s = Solver()
s.add(i1==(t1^x1^(x1<<16))&0xFFFFFFFFFFFFFFFF )
s.check()
l1=s.model()
ac = i0^l1
cipher = MyCipher(i0, ac)
for i in b2:
    p1+=cipher.encrypt(i)
p1
#FLAG{x013_ro74te_5hif7!!}
Full Implementation