[Python] Python decrypt XXTEA

Discussão em 'Python' iniciado por Stack, Novembro 23, 2024.

  1. Stack

    Stack Membro Participativo

    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...

Compartilhe esta Página