#!/bin/env python import random from math import gcd # the modulus for the lcg prng n = 256 # the header of the pdf v1.5 file header = [ 0x25, 0x50, 0x44, 0x46, 0x2d, 0x31, 0x2e ] def get_factors(ct:bytes, n:int=256) -> (int, int): ''' find a and b for n and ct ''' # first generate a list of all numbers without common divisor with 256 nogcds = [ x for x in range(1, n) if gcd(x, n) == 1 ] for b in range(1, n): for a in nogcds: for i, enc in enumerate(header): candidate = (a * enc + b) % n if candidate != ct[i]: break if(i+1 == len(header)): return (a,b) print('[-] No solution found.') return (0,0) def generate_lookuptable(a:int, b:int) -> dict[int,int]: ''' generate a lookuptable for the translation of the enc file''' out = {} for i in range(0, 256): lt = (i * a + b) % 256 out[lt] = i return out def decrypt(ct:bytes, lut:dict) -> bytes: ''' decrypt the file using the lookup table ''' res = b'' for byte in ct: dec = lut[byte] res += bytes([dec]) return res if __name__ == '__main__': ct = open('encrypted.bin', 'rb').read() a, b = get_factors(ct) print(f'[+] Factors solved: a={a}, b={b}') lut = generate_lookuptable(a, b) print(f'[+] Lookuptable generated: \nlookup = {lut}') dec = decrypt(ct,lut) print(f'[+] Encrypted file decrypted') with open('letter.pdf', 'wb') as f: f.write(dec)