#!/usr/bin/env python3 """ Strumento per dividere e ricostruire file con XOR (One-Time Pad analogico). Utilizza CSPRNG del sistema operativo. Sintassi: Separa python xor.py split documento.pdf parte1.bin parte2.bin Unisce python xor.py merge parte1.bin parte2.bin documento_ricostruito.pdf """ import sys import argparse # Fallback per versioni Python < 3.6 try: from secrets import token_bytes def secure_random_bytes(n): return token_bytes(n) except ImportError: import os def secure_random_bytes(n): return os.urandom(n) def split_file(original_path, part1_path, part2_path): """ Divide un file in due parti (B e C) tali che: B XOR C = Originale """ try: with open(original_path, 'rb') as f: data = f.read() except FileNotFoundError: print(f"ERRORE: Il file '{original_path}' non esiste.") sys.exit(1) except Exception as e: print(f"ERRORE nella lettura del file: {e}") sys.exit(1) size = len(data) print(f"Dimensione file originale: {size} byte") # Genera la maschera casuale B (parte1) part1 = secure_random_bytes(size) # Calcola parte2 = originale XOR parte1 part2 = bytes(a ^ b for a, b in zip(data, part1)) try: with open(part1_path, 'wb') as f: f.write(part1) with open(part2_path, 'wb') as f: f.write(part2) except Exception as e: print(f"ERRORE nella scrittura dei file: {e}") sys.exit(1) print(f"File divisi con successo:") print(f" Maschera casuale (B): {part1_path}") print(f" Dato mascherato (C): {part2_path}") print("Conserva questi due file in luoghi separati.") def merge_files(part1_path, part2_path, output_path): """ Ricostruisce il file originale facendo: Originale = part1 XOR part2 """ try: with open(part1_path, 'rb') as f: part1 = f.read() with open(part2_path, 'rb') as f: part2 = f.read() except FileNotFoundError as e: print(f"ERRORE: File non trovato - {e}") sys.exit(1) except Exception as e: print(f"ERRORE nella lettura dei file: {e}") sys.exit(1) if len(part1) != len(part2): print("ERRORE: I due file hanno dimensioni diverse. Non possono essere accoppiati.") sys.exit(1) # Ricostruzione tramite XOR original = bytes(a ^ b for a, b in zip(part1, part2)) try: with open(output_path, 'wb') as f: f.write(original) except Exception as e: print(f"ERRORE nella scrittura del file di output: {e}") sys.exit(1) print(f"File ricostruito con successo: {output_path}") if __name__ == "__main__": parser = argparse.ArgumentParser( description="Dividi o ricostruisci file con XOR (sicurezza perfetta se B è casuale)." ) subparsers = parser.add_subparsers(dest='command', required=True, help='Modalità') # Parser per split parser_split = subparsers.add_parser('split', help='Dividi un file in due parti') parser_split.add_argument('original', help='Percorso del file originale') parser_split.add_argument('part1', help='Percorso per salvare la prima parte (maschera casuale)') parser_split.add_argument('part2', help='Percorso per salvare la seconda parte (dato mascherato)') # Parser per merge parser_merge = subparsers.add_parser('merge', help='Ricostruisci file da due parti') parser_merge.add_argument('part1', help='Percorso della prima parte') parser_merge.add_argument('part2', help='Percorso della seconda parte') parser_merge.add_argument('output', help='Percorso per salvare il file ricostruito') args = parser.parse_args() if args.command == 'split': split_file(args.original, args.part1, args.part2) elif args.command == 'merge': merge_files(args.part1, args.part2, args.output)