This repository has been archived by the owner on Dec 5, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
StegoMalignani.cpp
305 lines (241 loc) · 11.5 KB
/
StegoMalignani.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
/*##############################################################################
###### NOME: StegoMalignani ################
###### AUTORE: Riccardo Marin ################
###### ULTIMO AGGIORNAMENTO (v 1.2): 30/04/18 10:00 ################
###### DESCRIZIONE: Programma per permette di scrivere e ################
###### leggere messaggi sulle immagini in formato bmp ################
###### sfruttando il bit meno significativo del blu ################
###### di ogni pixel. ################
##############################################################################
NOTE: allo stato attuale i messaggi nascosti sono facilmente individuabili
da steganalisi (attacco statistico). E' necessaria maggiore sicurezza.
Possibili miglioramenti:
- scrittura in pixel casuali sparsi per l'immagine
*/
#include <cstdlib> // libreria standard
#include <iostream> // libreria standard
#include <stdio.h> // libreria standard
#include <fstream> // per input/output file
#include <string> // per manipolare stringhe
#include "EasyBMP.h" // per leggere e scrivere dati nelle immagini
#define numVers "1.2" // numero versione attuale
using namespace std;
void mostraUtilizzo() // funzione che spiega l'utilizzo del programma
{
cout << "Utilizzo: ./StegoMalignani -comando percorsoImmagineBMP\n\n";
cout << "\t -r/--rivela Comando per rivelare dati nascosti nell'immagine\n";
cout << "\t -n/--nascondi Comando per nascondere dati nell'immagine\n";
cout << "\t -f/--file Per specificare un file da/verso cui direzionare i dati (opzionale)\n";
}
void cripta (string &testo, string &chiave, string &cifrato) { // realizza cifratura vigenere con xor
string chiaveEstesa = testo;
for(int i = 0; i < testo.length(); i++) { // ciclo per tutta la lunghezza del testo
chiaveEstesa.at(i) = chiave.at(i%(chiave.length())); // chiave ripetuta se lunghezza testo > lunghezza chiave
// quando avviene xor tra valori uguali, ottengo 0, che verrebbe interpretato come fine stringa
// tramite un artificio si può ovviare questo problema:
cifrato.at(i) = ((testo.at(i)-'0') ^ (chiaveEstesa.at(i)-'0')) + '0';
}
}
void nascondi(BMP &img, char percorso[], bool &usaFile, char percorsoFile[])
{
img.ReadFromFile(percorso);
// INPUT MESSAGGIO DA CRIPTARE
string testo; // testo completo da nascondere
string buffer; // contenitore parziale/temporaneo
string chiave; // chiave cifratura del testo
string cifrato; // testo cifrato
if(usaFile == true) // input da file di testo
{
ifstream fileTesto; // apro il file
fileTesto.open(percorsoFile);
while (getline (fileTesto,buffer)) // salvo una riga alla volta fino alla fine del file
{
testo = testo + buffer + "\n";
buffer = "";
}
fileTesto.close(); // chiudo il file
cout << "Input ricevuto dal file\n";
}
else
{
cout << "Inserisci il testo da nascondere, scrivi \"<end>\" per terminare:\n";
cin >> buffer;
do
{
testo = testo + buffer + "\n";
buffer = "";
cin >> buffer;
} while(buffer != "<end>");
}
cout << "Inserisci la chiave di cifratura:\n";
cin >> chiave;
cifrato = testo; // stringa cifrata della stessa lunghezza del testo in chiaro
cripta(testo, chiave, cifrato);
// SCRIVO SULL'IMMAGINE IL MESSAGGIO
int x=0; // coordinata x del pixel
int y=0; // coordinata y del pixel
int altezza=img.TellHeight(); // salvo altezza immagine
int larghezza=img.TellWidth(); // salvo larghezza immagine
for(int i=0;i<cifrato.length();i++) // scorro tutto il testo
{
char carattere = cifrato.at(i); // prendo un carattere alla volta
for(int j=0;j<8;j++)
{
int blu = (int) img(x,y)->Blue; // estraggo il valore del blu
blu &= ~1; // conservo 7 bit e azzero il meno significativo
blu |= (carattere >> j) & 1; // metto in OR il risultato con il bit da scrivere
img(x,y)->Blue = blu; // sovrascrivo il valore blu
x++; // aggiorno coordinate (mi sposto a destra)
if(x==larghezza) // vado a capo (sono arrivato all'ultimo pixel in larghezza)
{
x=0; // riparto dalla prima colonna
y++; // linea successiva
}
}
}
// INSERISCO IL FINE STRINGA
for(int j=0;j<8;j++) // un carattere = 8 bit
{
int blu = (int) img(x,y)->Blue; // estraggo il valore del blu
blu &= ~1; // valore /0 = 00000000
img(x,y)->Blue = blu; // sovrascrivo il valore blu
x++; // aggiorno coordinate (mi sposto a destra)
if(x==larghezza) // vado a capo (sono arrivato all'ultimo pixel in larghezza)
{
x=0; // riparto dalla prima colonna
y++; // linea successiva
}
}
img.WriteToFile(percorso); // output immagine
}
void rivela(BMP &img, char percorso[], bool &usaFile, char percorsoFile[])
{
img.ReadFromFile(percorso);
char carattere = '\0'; // singolo carattere decifrato, valore \0 = 00000000
string testo = ""; // azzero inizialmente il testo
string chiave;
string decifrato;
int x=0; // coordinata x del pixel
int y=0; // coordinata y del pixel
int altezza=img.TellHeight(); // salvo altezza immagine
int larghezza=img.TellWidth(); // salvo larghezza immagine
do // scorro tutto il testo finchè non trovo il fine stringa (vedi condizione while)
{
for(int j=0;j<8;j++) // 8 bit = 1 byte = 1 carattere
{
int blu = (int) img(x,y)->Blue; // estraggo il valore del blu
carattere = carattere << 1; // shifto a sinistra
carattere |= blu & 1; // isolo l'ultimo bit
x++; // aggiorno coordinate (mi sposto a destra nei pixel)
if(x==larghezza) // vado a capo (sono arrivato all'ultimo pixel in larghezza)
{
x=0; // riparto dalla prima colonna
y++; // linea successiva
}
}
// inverto ordine bit
carattere = (carattere & 0xF0) >> 4 | (carattere & 0x0F) << 4;
carattere = (carattere & 0xCC) >> 2 | (carattere & 0x33) << 2;
carattere = (carattere & 0xAA) >> 1 | (carattere & 0x55) << 1;
testo += carattere; // aggiungo il carattere in coda al testo da decifrare
} while(carattere != '\0'); // in scrittura ogni messaggio ha un fine stringa: \0, ovvero 00000000
cout << "Inserire chiave di cifratura:\n";
cin >> chiave;
decifrato = testo; // stringa in chiaro della stessa lunghezza del testo cifrato
cripta(testo, chiave, decifrato);
for(int i = 0; i < decifrato.length(); i++) // rimozione degli a capo
{
if (decifrato.at(i) == '\n') decifrato.at(i) = ' ';
}
decifrato.at(decifrato.length()-1) = ' '; // rimozione del fine stringa
// COMUNICO ALL'UTENTE IL RISULTATO
if(usaFile == true) // nel file di testo
{
// apro il file
ofstream fileTesto;
fileTesto.open(percorsoFile);
fileTesto << decifrato; // ciò che ho decriptato, lo salvo nel file
fileTesto.close(); // chiudo il file
cout << "Output inserito nel file.\n";
}
else cout << "Messaggio letto: " << decifrato; // oppure direttamente nel terminale
}
int main(int argc, char *argv[])
{
BMP img;
string percorsoImg = "";
bool usaFile = false;
string strPercorsoFile;
char percorsoFile[20];
char percorso[20];
// PARSING PARAMETRI AVVIO
if (argc < 2 || argc == 4 || argc > 5) // numero di parametri insufficiente o eccessivo
{
cout << "Numero argomenti errato.\n";
mostraUtilizzo();
return 1;
}
if ((argv[1] == string("-h")) || (argv[1] == string("--help"))) // help, che mostra versione e autore, oltre all'utilizzo
{
mostraUtilizzo();
cout << "\nVersione " << numVers << " | Riccardo Marin | riccardomarin23@gmail.com | 0x264834Ebf2Ac311429cFb66C587734Ea742586D5\n";
return 0;
}
else if( (argv[1] != string("-r")) && (argv[1] != string("--rivela")) && (argv[1] != string("-n")) && (argv[1] != string("--nascondi")) ) // l'utente digita un comando inesistente
{
cout << "La tua richiesta non e' chiara.\n";
mostraUtilizzo();
return 1;
}
if (argc == 2) // non è stato inserito il percorso immagine
{
cout << "Devi specificare il percorso dell'immagine.\n";
cout << "[Esempio: ./StegoMalignani -n areaTest/desktop.bmp]\n";
return 1;
}
else if (argc == 5) // vengono utilizzati i file di testo (-f file.txt)
{
if ((argv[3] == string("-f")) || (argv[3] == string("--file")))
{
strPercorsoFile = argv[4];
// fstream vuole il percorso come vettore di caratteri
strcpy (percorsoFile,strPercorsoFile.c_str()); // converto stringa in array di char
// apro il file
fstream fileTesto;
fileTesto.open(percorsoFile, ios::in);
// controllo esistenza file
if (fileTesto.good() == true) usaFile = true;
else // se non trovo il file
{
cout << "Il file di testo non esiste!\n\n"; // comunico errore
return 1;
}
fileTesto.close(); // chiudo file
}
else // l'utente digita un comando inesistente
{
cout << "La tua richiesta non e' chiara.\n";
mostraUtilizzo();
return 1;
}
}
percorsoImg = argv[2]; // salvo il parametro successivo (percorso immagine)
strcpy (percorso,percorsoImg.c_str()); // converto stringa in array di char
// apro il file
ifstream file;
file.open(percorso, ios::in);
if (file.good() == true) // controllo esistenza file
{
// chiama una delle due funzioni disponibili (per inserire o estrarre dati dall'immagine) in base ai parametri passati dall'utente
if( (argv[1] == string("-r")) || (argv[1] == string("--rivela")) ) rivela(img, percorso, usaFile, percorsoFile);
else if( (argv[1] == string("-n")) || (argv[1] == string("--nascondi")) ) nascondi(img, percorso, usaFile, percorsoFile);
cout << "\nOperazioni completate con successo!\n";
return 0;
}
else // se non trovo il file
{
cout << "Il file dell'immagine non esiste!\n"; // comunico errore
file.close(); // chiudo file
return 1;
}
}