I have a story that is encrypted with XXTEA, I have the key but in python I cannot decode it. the data in my source file is constructed in packets of 12 Bytes. I know that the result in text is of the form 000\12345678. I am attaching my code in case a charitable soul would like to help me. import struct import itertools from tqdm import tqdm from multiprocessing import Pool, cpu_count import signal # XXTEA implementation def xxtea_cipher(data, key, mode='DECIPHER'): def to_int_array(data, byteorder): return [int.from_bytes(data[i:i+4], byteorder) for i in range(0, len(data), 4)] def from_int_array(data, byteorder): return b''.join(d.to_bytes(4, byteorder) for d in data) def xxtea_decrypt(data, key): n = len(data) delta = 0x9E3779B9 sum = (delta * 6) & 0xFFFFFFFF mask = 0xFFFFFFFF for _ in range(6): e = (sum >> 2) & 3 for p in range(n - 1, 0, -1): data[p] = (data[p] - (((data[p - 1] >> 5) ^ (data[p] << 2)) + ((data[p - 1] << 4) ^ (data[p] >> 3)) + ((sum ^ data[p - 1]) + (key[(p & 3) ^ e] ^ data[p]))) & mask) data[0] = (data[0] - (((data[n - 1] >> 5) ^ (data[0] << 2)) + ((data[n - 1] << 4) ^ (data[0] >> 3)) + ((sum ^ data[n - 1]) + (key[0 ^ e] ^ data[0]))) & mask) sum = (sum - delta) & mask return data data_ints = to_int_array(data, 'little') key_ints = to_int_array(key, 'big') if mode == 'DECIPHER': decrypted_data = xxtea_decrypt(data_ints, key_ints) return from_int_array(decrypted_data, 'little') # Global variable for manual stop stop_flag = False def signal_handler(sig, frame): """Handle Ctrl+C to set stop_flag.""" global stop_flag print("\nManual stop requested. Exiting gracefully...") stop_flag = True def format_hex(data): """Convert a byte array into a hexadecimal string.""" return ' '.join(format(byte, '02x') for byte in data) # Decode the first N segments of the file def decode_file_segments(file_path, key_hex, segment_size, num_segments): # Convert the key from hex to bytes key = bytes.fromhex(key_hex) print(f"Decoding the first {num_segments} segments of size {segment_size} bytes...") decoded_segments = [] with open(file_path, "rb") as file: for i in range(num_segments): # Read one segment from the file segment = file.read(segment_size) if len(segment) < segment_size: print(f"Segment {i + 1} is incomplete. Stopping...") break # Decrypt the segment decrypted_segment = xxtea_cipher(segment, key, mode='DECIPHER') # Add the decrypted segment as a hexadecimal string decoded_segments.append(format_hex(decrypted_segment)) return decoded_segments # Example usage if __name__ == "__main__": # Register signal handler for Ctrl+C signal.signal(signal.SIGINT, signal_handler) # File path to the binary file to decode file_path = "path/to/your/file.bin" # Replace with your actual file path # XXTEA decryption key in hex key_hex = "91bd7a0aa75440a9bbd49d6ce0dcc0e3" # Replace with your actual key # Segment size (12 bytes for your file format) segment_size = 12 # Number of segments to decode num_segments = 5 # Decode the file decoded_segments = decode_file_segments(file_path, key_hex, segment_size, num_segments) # Print the decoded segments print("\nDecoded Segments (Hex):") for i, segment in enumerate(decoded_segments, start=1): print(f"Segment {i}: {segment}") The current code for decoding and encoding is in JAVA : public class XXTEACipher { private static final int DELTA = 0x9e3779b9; private static final byte[] COMMON_KEY = SecurityUtils.decodeHex("91bd7a0aa75440a9bbd49d6ce0dcc0e3"); public enum CipherMode { CIPHER, DECIPHER } private XXTEACipher() { throw new IllegalArgumentException("Utility class"); } /** (De-)cipher a block of data with a key. */ public static byte[] cipher(CipherMode mode, byte[] data, int minSize, byte[] key) { byte[] block = Arrays.copyOfRange(data, 0, Math.min(minSize, data.length)); int[] dataInt = toIntArray(block, ByteOrder.LITTLE_ENDIAN); int[] keyInt = toIntArray(key, ByteOrder.BIG_ENDIAN); int op = Math.min(128, data.length / 4); int[] encryptedInt = btea(dataInt, mode == CipherMode.DECIPHER ? -op : op, keyInt); return toByteArray(encryptedInt, ByteOrder.LITTLE_ENDIAN); } /** (De-)cipher data with the common key. */ public static byte[] cipherCommonKey(CipherMode mode, byte[] data) { byte[] encryptedBlock = cipher(mode, data, 512, COMMON_KEY); ByteBuffer bb = ByteBuffer.allocate(data.length); bb.put(encryptedBlock); if (data.length > 512) { bb.put(Arrays.copyOfRange(data, 512, data.length)); } return bb.array(); } public static int[] toIntArray(byte[] data, ByteOrder endianness) { ByteBuffer bb = ByteBuffer.wrap(data); bb.order(endianness); List<Integer> ints = new ArrayList<>(); for (int i=0; i<data.length/4; i++) { ints.add(bb.getInt()); } return ints.stream().mapToInt(i->i).toArray(); } public static byte[] toByteArray(int[] data, ByteOrder endianness) { ByteBuffer bb = ByteBuffer.allocate(data.length*4); bb.order(endianness); for (int i : data) { bb.putInt(i); } return bb.array(); } public static int[] btea(int[] v, int n, int[] k) { int y; int z; int sum; int p; int rounds; int e; if (n > 1) { /* Coding Part */ rounds = 1 + 52/n; sum = 0; z = v[n-1]; do { sum += DELTA; e = (sum >>> 2) & 3; for (p=0; p<n-1; p++) { y = v[p+1]; z = v[p] += mx(k, e, p, y, z, sum); } y = v[0]; z = v[n-1] += mx(k, e, p, y, z, sum); } while (--rounds != 0); } else if (n < -1) { /* Decoding Part */ n = -n; rounds = 1 + 52/n; sum = rounds*DELTA; y = v[0]; do { e = (sum >>> 2) & 3; for (p=n-1; p>0; p--) { z = v[p-1]; y = v[p] -= mx(k, e, p, y, z, sum); } z = v[n-1]; y = v[0] -= mx(k, e, p, y, z, sum); sum -= DELTA; } while (--rounds != 0); } return v; } private static int mx(int[] k, int e, int p, int y, int z, int sum) { return (((z>>>5^y<<2) + (y>>>3^z<<4)) ^ ((sum^y) + (k[(p&3)^e] ^ z))); } } The problem is that the decoding is not functional. Continue reading...