# by cers 29/12/2003
# www.cers.tk

use open IO => 'bytes';

sub inietta() {

$bytes_indice_controllo=1;
$bytes_controllo_frequenza=2;
$bytes_intestazione='';

open(LEGGO,"<$file_bmp") || die "\nImpossibile aprire il file $file_bmp: $!\n";

$bytes_bmp=0;

while (!eof(LEGGO)) {
$bytes_bmp+=length(<LEGGO>);
}
if ($bytes_bmp == 0) {print "\nFile bmp non valido\n";exit;}
print "\nAnalisi:\n";
print "Bytes bmp: $bytes_bmp\n";


seek(LEGGO,10,0);
read(LEGGO,$bytes_intestazione,4);
@bit_intestazione=split("",$bytes_intestazione);
$contatore =3;
$bytes_intestazione='0b';
while ( $contatore>=0) {
$bytes_intestazione.= sprintf("%08d",sprintf("%b",ord($bit_intestazione[$contatore])));
$contatore -=1;
}
$bytes_intestazione =oct($bytes_intestazione);

close(LEGGO);

open(LEGGO,"<$file_cryptato")|| die "\nImpossibile aprire il file $file_cryptato: $!\n";

$bytes_cryptato=0;

while (!eof(LEGGO)) {
$bytes_cryptato+=length(<LEGGO>);
}
close(LEGGO);

if ($bytes_cryptato == 0) {print "\nTesto da nascondere non valido\n";exit;}
print "Bytes testo: $bytes_cryptato\n";
$bytes_controllati=255;
$bytes_controllo =1;
while ($bytes_cryptato > $bytes_controllati) {
					$bytes_controllo+=1;
					$bytes_controllati=$bytes_controllati**$bytes_controllo;}

$bytes_riservati=$bytes_controllo+$bytes_indice_controllo+$bytes_controllo_frequenza;

print "Bytes di controllo necessari: $bytes_riservati\n";
print "Bytes intestazione: $bytes_intestazione\n";

$bytes_iniettabili= sprintf("%d",($bytes_bmp-$bytes_controllo-$bytes_intestazione)/8);
print "Bytes iniettabili: $bytes_iniettabili\n";

if ($bytes_cryptato > $bytes_iniettabili) {print "Utilizzare un bmp piu' grosso\n"; exit;}

$frequenza=sprintf("%d",$bytes_iniettabili/$bytes_cryptato);
if ($frequenza > 65025 ) { $frequenza = 65025;}
$frequenza_in_bit = $frequenza*8;
print "Frequenza del disturbo 1/$frequenza_in_bit\n";


################### INIEZIONE #########################


# APERTURA FILES # 

open(BMP,"<$file_bmp");
open(CRYPTATO,"<$file_cryptato");
open(IBRIDO,">$file_iniettato")|| die "\nImpossibile aprire il file $file_iniettato: $!\n";

# INIEZIONE BYTES DI CONTROLLO #

# INTESTAZIONE

print "\nScrittura intestazione....\n";
read (BMP,$bmp_byte,$bytes_intestazione);
syswrite (IBRIDO,$bmp_byte);

# FREQUENZA
print "Inserimento bytes frequenza....\n";
$contatore=0;
$elevazione=16;
$totale_rappresentabile = 2**$elevazione;
$bytes_residui = $frequenza;

while ($contatore < $elevazione) {
	$valore[$contatore] = $totale_rappresentabile= $totale_rappresentabile/2;
	if ($valore[$contatore] <= $bytes_residui) {$valore[$contatore]=1; $bytes_residui-=$totale_rappresentabile;}
								else {$valore[$contatore]=0;}
$frequenza_binario .= $valore[$contatore];
	$contatore+=1;
	}

@bit_frequenza = split("",$frequenza_binario);

$contatore=0;

while ($contatore < 16) {
				read (BMP,$bmp_byte,1);
				$bmp_binario = sprintf("%08d",sprintf("%b",ord($bmp_byte)));
				@bit_bmp = split("",$bmp_binario);
				$bit_bmp[7] = $bit_frequenza[$contatore];	
		$bit_convertibile = '0b';
		$i=0;
		while ( $i < 8) {
			if ($bit_bmp[$i] == 0 ) { $i +=1; next; }
			else { while ($i <8) 
					{ $bit_convertibile .= $bit_bmp[$i]; $i +=1; } ; 			
				}	
			}
		$ibrido_byte=chr(oct($bit_convertibile));
		syswrite (IBRIDO,$ibrido_byte);
		$contatore +=1;
}

# BYTE INDICE
print "Inserimento byte di controllo primario....\n";
$controllo_binario = sprintf("%08d",sprintf("%b",$bytes_controllo));
@bit_controllo = split("",$controllo_binario);
$contatore=0;
while ($contatore < 8) {
				read (BMP,$bmp_byte,1);
				$bmp_binario = sprintf("%08d",sprintf("%b",ord($bmp_byte)));
				@bit_bmp = split("",$bmp_binario);
				$bit_bmp[7] = $bit_controllo[$contatore];	
		$bit_convertibile = '0b';
		$i=0;
		while ( $i < 8) {
			if ($bit_bmp[$i] == 0 ) { $i +=1; next; }
			else { while ($i <8) 
					{ $bit_convertibile .= $bit_bmp[$i]; $i +=1; } ; 			
				}	
			}
		$ibrido_byte=chr(oct($bit_convertibile));
		syswrite (IBRIDO,$ibrido_byte);
		$contatore +=1;
}


# BYTE LUNGHEZZA

print "Inserimento bytes di controllo secondari....\n";
$contatore=0;
$elevazione=8*$bytes_controllo;
$totale_rappresentabile = 2**$elevazione;
$bytes_residui = $bytes_cryptato;

while ($contatore < $elevazione) {
	$valore[$contatore] = $totale_rappresentabile= $totale_rappresentabile/2;
	if ($valore[$contatore] <= $bytes_residui) {$valore[$contatore]=1; $bytes_residui-=$totale_rappresentabile;}
								else {$valore[$contatore]=0;}
$lunghezza_binario .= $valore[$contatore];
	$contatore+=1;
	}
@bit_lunghezza = split("",$lunghezza_binario);
$contatore=0;
while ($contatore < 8*$bytes_controllo) {
				read (BMP,$bmp_byte,1);
				$bmp_binario = sprintf("%08d",sprintf("%b",ord($bmp_byte)));
				@bit_bmp = split("",$bmp_binario);
				$bit_bmp[7] = $bit_lunghezza[$contatore];	
		$bit_convertibile = '0b';
		$i=0;
		while ( $i < 8) {
			if ($bit_bmp[$i] == 0 ) { $i +=1; next; }
			else { while ($i <8) 
					{ $bit_convertibile .= $bit_bmp[$i]; $i +=1; } ; 			
				}	
			}
		$ibrido_byte=chr(oct($bit_convertibile));
		syswrite (IBRIDO,$ibrido_byte);
		$contatore +=1;
}

# TESTO

print "Iniettazione dei bits nel codice originale in corso....\n";

while (!eof(CRYPTATO)) {

read(CRYPTATO,$cryptato_byte,1);
$cryptato_binario = sprintf("%08d",sprintf("%b",ord($cryptato_byte)));
@bit_cryptato = split("",$cryptato_binario);
$contatore=0;
while ($contatore < 8) {
				read (BMP,$bmp_byte,1);
				$bmp_binario = sprintf("%08d",sprintf("%b",ord($bmp_byte)));
				@bit_bmp = split("",$bmp_binario);
				$bit_bmp[7] = $bit_cryptato[$contatore];	
				$bit_convertibile = '0b';
				$i=0;
				while ( $i < 8) {
					if ($bit_bmp[$i] == 0 ) { $i +=1; next; }
					else { while ($i <8) 
					{ $bit_convertibile .= $bit_bmp[$i]; $i +=1; } ; 
				  }			
				}	
		$ibrido_byte=chr(oct($bit_convertibile));
		syswrite (IBRIDO,$ibrido_byte);
		$contatore +=1;
		$intatti =1;
		read (BMP,$bmp_byte,$frequenza-1);
		syswrite (IBRIDO,$bmp_byte);
		}
}

# COMPLETAMENTO IMMAGINE

print "Completamento immagine....\n";

while (!eof(BMP)) {				
		read (BMP,$bmp_byte,1);
		syswrite (IBRIDO,$bmp_byte);
		$bytes_mancanti -=1;
		}
print "Operazione completata.\n";
exit;
}

sub estrazione() {

$bytes_intestazione='';

open(BMP,"<$file_bmp")|| die "\nImpossibile aprire il file $file_bmp: $!\n";
open(OUT,">$file_out")|| die "\nImpossibile aprire il file $file_out: $!\n";

# INTESTAZIONE

seek(BMP,10,0);
read(BMP,$bytes_intestazione,4);
@bit_intestazione=split("",$bytes_intestazione);
$contatore =3;
$bytes_intestazione='0b';
while ( $contatore>=0) {
$bytes_intestazione.= sprintf("%08d",sprintf("%b",ord($bit_intestazione[$contatore])));
$contatore -=1;
}
$bytes_intestazione =oct($bytes_intestazione);


# BYTE FREQUENZA

seek(BMP,$bytes_intestazione,0);
$contatore=0;

while ($contatore < 16) {
		read(BMP,$bmp_byte,1);
		$bmp_binario = sprintf("%08d",sprintf("%b",ord($bmp_byte)));
		@bit_bmp = split("",$bmp_binario);
		$byte_frequenza .= $bit_bmp[7]; 
		$contatore +=1;
		}	
$bit_convertibile = '0b'.$byte_frequenza;
$byte_frequenza=oct($bit_convertibile);
$frequenza_in_bit= $byte_frequenza*8;
print "\nFrequenza rilevata: 1/$frequenza_in_bit\n";

# BYTE DI CONTROLLO PRIMARIO

$contatore=0;

while ($contatore < 8) {
		read(BMP,$bmp_byte,1);
		$bmp_binario = sprintf("%08d",sprintf("%b",ord($bmp_byte)));
		@bit_bmp = split("",$bmp_binario);
		$byte_controllo .= $bit_bmp[7]; 
		$contatore +=1;
		}	
$bit_convertibile = '0b'.$byte_controllo;
$byte_controllo=oct($bit_convertibile);
$totale_bytes_controllo=$byte_controllo+3;
print "Bytes di controllo rilevati: $byte_controllo\n";

# BYTES DI CONTROLLO SECONDARI

$contatore=0;

while ($contatore < 8*$byte_controllo) {
		read(BMP,$bmp_byte,1);
		$bmp_binario = sprintf("%08d",sprintf("%b",ord($bmp_byte)));
		@bit_bmp = split("",$bmp_binario);
		$byte_lunghezza .= $bit_bmp[7]; 
		$contatore +=1;
		}	
$bit_convertibile = '0b'.$byte_lunghezza;
$byte_lunghezza=oct($bit_convertibile);
print "Bytes da estrarre: $byte_lunghezza\n";

# TESTO

print "Estrazione testo in corso....\n";
$byte_estratti=0;
while ($byte_estratti < $byte_lunghezza) {
$contatore=0;
$byte_testo='';
while ($contatore <8) {
				read(BMP,$bmp_byte,1);
				$bmp_binario = sprintf("%08d",sprintf("%b",ord($bmp_byte)));
				@bit_bmp = split("",$bmp_binario);
				$byte_testo .= $bit_bmp[7];
				seek(BMP,$byte_frequenza-1,1);
				$contatore +=1;
				}
			$bit_convertibile = '0b'.$byte_testo;
			$byte_testo=chr(oct($bit_convertibile));
			syswrite (OUT,$byte_testo);	
			$byte_estratti +=1;
		}

print "Operazione completata.\n";
exit;
}


print "\nSteganografia 1.2\n";
print "-------------------\n";
print "1) Nascondi testo\n";
print "2) Rileva testo\n";
print "\nScelta: ";
$scelta = <STDIN>;

SWITCH: for ($scelta) {
/1/ && do {	print "\nFile bmp: "; 
	 	$file_bmp=<STDIN>;
		chomp $file_bmp;
	    	print "File da nascondere: ";
		$file_cryptato=<STDIN>;
		chomp $file_cryptato;
	     	print "File bmp output: "; 	
		$file_iniettato=<STDIN>;
		chomp $file_iniettato;
		inietta();}
|| /2/ && do {print "\nFile bmp: ";
		  $file_bmp=<STDIN>;
		  chomp $file_bmp;
		  print "File output: ";
		  $file_out=<STDIN>;
		  chomp $file_out;
		  estrazione();}
|| print "\nScelta non riconosciuta\n";
exit;
}



