// event. click on 'Lire' boutton du tabPage2 private void playAudioBtn2_Click(object sender, EventArgs e) { if (wavFileLabelTab2.Text != "Aucun fichier séléctionné.") { // changement de l'image + disable du boutton 'Lire' playAudioBtn2.Image = app_steganographie.Properties.Resources.loader; playAudioBtn2.Enabled = false; // lecture du fichier audio ToolsAndFunctions.playAudioFile(wavFileLabelTab2.Text); // Thread de lecture (pour eviter le plantage de l'application) /* * Thread playAudioThread = new Thread(new ParameterizedThreadStart(ToolsAndFunctions.playAudioFile)); * playAudioThread.Start(wavFileLabelTab2.Text); */ // changement de l'image + enable du boutton 'Lire' playAudioBtn2.Image = app_steganographie.Properties.Resources.media_play_icon; playAudioBtn2.Enabled = true; // focus sur l'onglet actuel this.tabControl1.SelectedTab.Focus(); } else { MessageBox.Show("Aucun fichier audio séléctionné !", "Stop", MessageBoxButtons.OK, MessageBoxIcon.Stop); } }
// event. click on 1st 'Lire' boutton private void playAudioBtn_Click(object sender, EventArgs e) { if (audioFileTxtBox.Text != "") { // changement de l'image + disable du boutton 'Lire' playAudioBtn.Image = app_steganographie.Properties.Resources.loader; playAudioBtn.Enabled = false; // lecture du fichier audio ToolsAndFunctions.playAudioFile(audioFileTxtBox.Text); // changement de l'image + enable du boutton 'Lire' playAudioBtn.Image = app_steganographie.Properties.Resources.media_play_icon; playAudioBtn.Enabled = true; // focus sur l'onglet actuel this.tabControl1.SelectedTab.Focus(); } else { MessageBox.Show("Aucun fichier audio choisi !", "Stop", MessageBoxButtons.OK, MessageBoxIcon.Stop); } }
// event. click on 'Décoder' boutton du tabPage2 private void decoderBtn_Click(object sender, EventArgs e) { try { // remise à zéro de la barre de chargement progressBar2.Value = 0; // vidage de la zone/textBox du texte caché txtCacherTab2.Text = ""; // 1 - lecture du fichier audio en bytes if (wavFileLabelTab2.Text == "Aucun fichier séléctionné.") { MessageBox.Show("Aucun fichier audio séléctionné !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } byte[] fileBytes = File.ReadAllBytes(wavFileLabelTab2.Text); // 2 - si clé stégo non saisi if (cleStegoTab2.Text == "") { MessageBox.Show("Aucune clé stégo saisie !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // 3 - si mot de passe de décryptage AES non saisi if (mdpTab2.Text == "") { MessageBox.Show("Aucun mot de passe (AES) saisi !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // 3 - Toutes les vérifications ont été faites, Let's decrypt this ! // on commence le calcul du temp d'éxecution Stopwatch sw = new Stopwatch(); sw.Start(); // conversion du fichier audio en block de 2/4 bits string[] fileBitBlocks = ToolsAndFunctions.bytesToBlocks(fileBytes, nombreDeBit); // décryptage de la clé stégo string cleStegoString = Crypt.DecryptStringAES(cleStegoTab2.Text, mdpTab2.Text); // on récupère le hash du fichier audio et les positions des blocks string[] positions = cleStegoString.Split('|'); //MessageBox.Show(cleStegoString + "," + fileBitBlocks[Convert.ToInt32(positions[0])], ""); // vérification du Hash du fichier audio avec celui contenu dans la clé string fileHash = positions[0]; if (fileHash != ToolsAndFunctions.GetFileHash(fileBytes)) // si les 2 hash ne sont pas identiques { MessageBox.Show("Fichier audio erroné !", "Stop", MessageBoxButtons.OK, MessageBoxIcon.Stop); return; } // Recherche dans les blocks du fichier audio string texteCachee = ""; // on parcours toutes les positions pour reconstituer le texte caché for (int i = 1; i < positions.Length - 1; i += (8 / nombreDeBit)) // de 1 => première position contient le hash, 8(bits) / 4(bits par block) = 2 , -1 du dernier '|' { string Blocks = ""; // contiendra 2 bloc si codage sur (4bit) ou 4 bloc si codage sur (2bit) for (int j = 0; j < (8 / nombreDeBit); j++) { Blocks += fileBitBlocks[Convert.ToInt32(positions[i + j])]; } //MessageBox.Show(positions.Length.ToString() + "," + i.ToString() + "," + texteCachee); texteCachee += ToolsAndFunctions.BlocksToString(Blocks); } // on arrête le calcul du temp d'éxecution + on l'affiche sw.Stop(); execTimeTab2.Text = sw.ElapsedMilliseconds.ToString() + " ms"; // affichage du texte caché txtCacherTab2.Text = texteCachee; // chargement complet de la barre de chargement progressBar2.Value = 100; } // fin try catch (Exception ex) { MessageBox.Show("[Erreur de décodage : " + ex.Message + "]\nIl se peut que le mot de passe ou la clé stégo soit incorrecte !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); } }
// event. click on Mdp 'Aléatoire' boutton du tabPage1 private void aleatoireBtn_Click(object sender, EventArgs e) { mdpTab1.Text = ToolsAndFunctions.createPassword(8); }
// event. click on 'Coder' boutton du tabPage1 private void coderBtn_Click(object sender, EventArgs e) { try { // remise à zéro de la barre de chargement progressBar1.Value = 0; // Désactivation des bouttons 'Relire..' et 'Décodage Rapide..' + save replayAudioBtn.Enabled = decodageRapideBtn.Enabled = saveCleStegoBtn.Enabled = false; // 1 - lecture du fichier audio en bytes if (wavFileLabelTab1.Text == "Aucun fichier séléctionné.") { MessageBox.Show("Aucun fichier audio séléctionné !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } byte[] fileBytes = File.ReadAllBytes(wavFileLabelTab1.Text); // 2 - Conversion du texte a cacher en bytes if (txtAcacherTab1.Text == "") { MessageBox.Show("Aucun texte à cacher !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } byte[] textBytes = System.Text.Encoding.ASCII.GetBytes(txtAcacherTab1.Text); // si mot de passe de cryptage AES non saisi if (mdpTab1.Text == "") { MessageBox.Show("Aucun mot de passe (AES) saisi !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // 3 - Toutes les vérifications ont été faites, Let's Go ! // on commence le calcul du temp d'éxecution Stopwatch sw = new Stopwatch(); sw.Start(); // conversion du fichier audio en block de 2/4 bits string[] fileBitBlocks = ToolsAndFunctions.bytesToBlocks(fileBytes, nombreDeBit); // conversion du text à cacher en block de 2/4 bits string[] textBitBlocks = ToolsAndFunctions.bytesToBlocks(textBytes, nombreDeBit); // Recherche Locale int[] positions = new int[textBytes.Length * (8 / nombreDeBit)]; // 8(bits) / 4 (bits par block) = 2 (positions pour chaque 8bit) if (methode == 1) // si methode Fitness et voisinage { int[] fitness = new int[textBitBlocks.Length]; // pr chaque bloc une fitness int[] randomPos = new int[textBitBlocks.Length]; // pr chaque bloc une position aléatoire Random rnd = new Random(); // Etape 1 : Position aléatoire // on parcours les blocks du texte à cacher for (int i = 0; i < textBitBlocks.Length; i++) { // pr chaque bloc de texte on génère une position aléatoire dans les blocs audio randomPos[i] = rnd.Next(0, fileBitBlocks.Length - 1); // -1 car le tableau commence de 0 // on calcule la fitness du bloc fitness[i] = ToolsAndFunctions.fitness(textBitBlocks[i], fileBitBlocks[randomPos[i]]); //MessageBox.Show(fitness[i].ToString()); } // Etape 2 : Vérification de la fitness de chaque bloc, puis recherche au voisinage si fitness != 0 // on parcours les blocks du texte à cacher for (int i = 0; i < textBitBlocks.Length; i++) { if (fitness[i] != 0) { // recherche au voisinage de l'ancienne randomPos[i] int k = randomPos[i]; // initialisation avec la randomPos[i] // 1 - recherche au voisinage droit (1er bloc a droite) for (int j = randomPos[i] + 1; j < fileBitBlocks.Length; j++) // depuis randomPos[i] + 1 { // on recalcule la fitness du bloc fitness[i] = ToolsAndFunctions.fitness(textBitBlocks[i], fileBitBlocks[j]); //MessageBox.Show(i.ToString() + " - voisinage droite - " + j.ToString()); // si la fitness != 0 tj if (fitness[i] != 0) { // 2 - recherche au voisinage gauche (1er bloc a gauche), içi on vérifie juste 1 seul bloc, pr repasser la main a la 1ere boucle for if (k > 0) // si on peu décrémenter k (=> y'a encore du voisinage gauche) { k--; // on recalcule la fitness du bloc fitness[i] = ToolsAndFunctions.fitness(textBitBlocks[i], fileBitBlocks[k]); //MessageBox.Show(i.ToString() + " - voisinage gauche - " + k.ToString()); // si fitness == 0, c'est bon, on sauvegarde la position et on sort de la boucle (1ere boucle for) if (fitness[i] == 0) { // ça veux dire qu'on a trouvé le bloc au voisinage gauche positions[i] = k; break; } } } else // si nn => fitness == 0, c'est bon, on sauvegarde la position et on sort de la boucle (1ere boucle for) { // ça veux dire qu'on a trouvé le bloc au voisinage droit positions[i] = j; break; } } // si jamais la boucle du voisinage à droite prend fin alors que la fitness != 0, on n'ai pas sur alors que la boucle du voisinage à gauche a fini aussi ! if (fitness[i] != 0) { // 3 - Finition de la recherche au voisinage gauche for (int f = k; f >= 0; f--) { // on recalcule la fitness du bloc fitness[i] = ToolsAndFunctions.fitness(textBitBlocks[i], fileBitBlocks[f]); //MessageBox.Show(i.ToString() + " - voisinage gauche (boucle) - " + f.ToString()); // si fitness == 0, c'est bon, on sauvegarde la position et on sort de la boucle if (fitness[i] == 0) { positions[i] = f; break; } } // si jamais apres tt ça la fitness != 0 tj, alors qu'on a parcouru toute la boucle, ça veux dire que le bloc est introuvable if (fitness[i] != 0) { throw new Exception("Le bloc : '" + textBitBlocks[i] + "' est introuvable dans les blocs du fichier audio !"); } } // fin if } else // si fitness == 0, autrement dit, si les blocs (texte et audio) se ressemble, on passe au prochain bloc { positions[i] = randomPos[i]; } } // fin for => Etape 2 } else // si nn (les 2 autres méthodes) { int lastPosition; Random rnd = new Random(); if (methode == 2) // si recherche en boucle { lastPosition = 0; // le nom de la variable ne reflète pas le role qu'elle joue , je sais.. } else // si nn (recherche aléatoire, car si methode == 3 on ne rentrera jamais içi), on genère un nombre aléatoire { lastPosition = rnd.Next(0, fileBitBlocks.Length - 2); // - 2 pour avoir au moin un block suivant (car le tableau de block commence de 0 et fini en fileBitBlocks.Length - 1) } // chargement à 30% de la barre de chargement //progressBar1.Value = 30; // ça ne s'applique pas, forcément car, on entre apres dans des boucles => on bloque la GUI (redessinage..) // on parcours les blocks du texte à cacher for (int i = 0; i < textBitBlocks.Length; i++) { bool positionOk = false; while (!positionOk) { // on parcours les blocks du fichier audio for (int j = lastPosition; j < fileBitBlocks.Length; j++) { //MessageBox.Show(textBitBlocks[i] + "-" + fileBitBlocks[j] + "-" + i.ToString() + "-" + j.ToString(), ""); // si on trouve un block de texte dans le fichier audio if (textBitBlocks[i] == fileBitBlocks[j]) { // on sauvegarde la position dans la clé stégo/tableau de positions positions[i] = j; //lastPosition = ++j; // ou j + 1 positionOk = true; break; // on sort de la boucle sur les blocks du fichier audio pour passer au prochain block de texte } } // fin 2eme for if (methode == 3) // si méthode de recherche aléatoire { if (!positionOk) // si on n'a pas trouvé la position du block avec la valeur aléatoire { // on vérifie si le block existe déja dans le fichier audio et on retourne sa position, si nn la fonction retourne -1 lastPosition = ToolsAndFunctions.isBlockExists(textBitBlocks[i], fileBitBlocks); if (lastPosition == -1) { throw new Exception("Le bloc : '" + textBitBlocks[i] + "' est introuvable dans les blocs du fichier audio !"); } // si nn si position trouvé la boucle va continuer son travail (meme si on l'a aider pr avoir la position + c'est plus rapide comme ça meme si ce n'est plus completement aléatoire) } else { lastPosition = rnd.Next(0, fileBitBlocks.Length - 1); // on regénère un nombre aléatoire } } else // si nn, methode en boucle { if (!positionOk) // si jamais on ne trouve pas le bloc apres avoir parcouru tout le fichier, positionOk sera = à false (c peu probable, mais si ça arrive, ça provequera une boucle infini, 'mieux vaut prévenir que guérir !') { throw new Exception("Le bloc : '" + textBitBlocks[i] + "' est introuvable dans les blocs du fichier audio !"); } else { break; // on sort de la boucle while, pour passer au bloc suivant } } } // fin while } // fin 1er for } // fin else // traitement de la clé stégo => Ajout du Hash du fichier audio string cleStegoString = ToolsAndFunctions.GetFileHash(fileBytes) + "|"; for (int i = 0; i < positions.Length; i++) // Ajout des positions des blocks { cleStegoString += positions[i].ToString() + "|"; // conversion en chaine de caractère } //MessageBox.Show(cleStegoString, "Clé stégo en clair", MessageBoxButtons.OK, MessageBoxIcon.Information); // cryptage de la clé stégo + affichage cleStegoTab1.Text = Crypt.EncryptStringAES(cleStegoString, mdpTab1.Text); // on arrête le calcul du temp d'éxecution + on l'affiche sw.Stop(); execTimeTab1.Text = sw.ElapsedMilliseconds.ToString() + " ms"; // chargement complet de la barre de chargement progressBar1.Value = 100; // Activation des bouttons 'Relire..' et 'Décodage Rapide..' + save replayAudioBtn.Enabled = decodageRapideBtn.Enabled = saveCleStegoBtn.Enabled = true; } // fin try catch (Exception ex) { MessageBox.Show(ex.Message, "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); } }
// event. click on 'Cacher' boutton private void cacherBtn_Click(object sender, EventArgs e) { // Désactivation du boutton 'Lire' du fichier audio de sortie + 'Extraction Rapide..' playOutputBtn.Enabled = ExtractionRapideBtn.Enabled = false; // remise à zéro de la barre de chargement progressBar1.Value = 0; // 1 - vérification du fichier audio d'entrée + la clé + le texte à cacher if (audioFileTxtBox.Text == "") { MessageBox.Show("Aucun fichier audio choisi !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } else if (cleTxtBox.Text == "") { MessageBox.Show("Aucune clé choisie !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } else if (txtAcacherTab1.Text == "") { MessageBox.Show("Aucun texte à cacher !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // 2 - demande d'emplacement d'enregistrement du fichier audio de sortie SaveFileDialog saveFileDialog1 = new SaveFileDialog(); saveFileDialog1.Title = "Enregistrer le fichier audio de sortie dans"; saveFileDialog1.DefaultExt = "wav"; saveFileDialog1.Filter = "audio files (*.wav)|*.wav"; if (saveFileDialog1.ShowDialog() == DialogResult.OK) // si emplacement choisi { // Let's hide the message/text ! // on commence le calcul du temp d'éxecution Stopwatch sw = new Stopwatch(); sw.Start(); // create streams Stream sourceStream = null; FileStream destinationStream = null; WaveStream audioStream = null; // create a stream that contains the message, preceeded by its length Stream messageStream = ToolsAndFunctions.stringToStream(txtAcacherTab1.Text); // create a stream that contains the key Stream keyStream = ToolsAndFunctions.stringToStream(cleTxtBox.Text); long countSamplesRequired = 0; // var to count samples required (we use it in catch() so this is the best place) try { //how man samples do we need? countSamplesRequired = WaveUtility.CheckKeyForMessage(keyStream, messageStream.Length); if (countSamplesRequired > Int32.MaxValue) { throw new Exception("Message too long, or bad key! This message/key combination requires " + countSamplesRequired + " samples, only " + Int32.MaxValue + " samples are allowed."); } // open source stream sourceStream = new FileStream(audioFileTxtBox.Text, FileMode.Open); // create destination stream destinationStream = new FileStream(saveFileDialog1.FileName, FileMode.Create, FileAccess.Write); //copy the carrier file's header audioStream = new WaveStream(sourceStream, destinationStream); if (audioStream.Length <= 0) { throw new Exception("Invalid WAV file"); } //are there enough samples in the carrier wave? if (countSamplesRequired > audioStream.CountSamples) { String errorReport = "The carrier file is too small for this message and key!\r\n" + "Samples available: " + audioStream.CountSamples + "\r\n" + "Samples needed: " + countSamplesRequired + "\r\n\r\n" + "\tOuvrir la fenêtre d'enregistrement audio ?"; throw new Exception(errorReport); } //hide the message this.Cursor = Cursors.WaitCursor; WaveUtility utility = new WaveUtility(audioStream, destinationStream); utility.Hide(messageStream, keyStream); // set output audio file path outputAudioTxtBox.Text = saveFileDialog1.FileName; // on arrête le calcul du temp d'éxecution + on l'affiche sw.Stop(); execTime.Text = sw.ElapsedMilliseconds.ToString() + " ms"; // activate 'Lire' boutton + 'Extraction Rapide..' playOutputBtn.Enabled = ExtractionRapideBtn.Enabled = true; // chargement complet de la barre de chargement progressBar1.Value = 100; } catch (Exception ex) { //this.Cursor = Cursors.Default; // if Message contains "Samples needed" , mean that wav file is not enought if (ex.Message.Contains("Samples needed")) { if (MessageBox.Show(ex.Message, "Erreur", MessageBoxButtons.YesNo, MessageBoxIcon.Stop) == System.Windows.Forms.DialogResult.Yes) { Form fen = new RecordSound(countSamplesRequired); fen.ShowDialog(); } } else { MessageBox.Show(ex.Message, "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Stop); } } finally { if (keyStream != null) { keyStream.Close(); } if (messageStream != null) { messageStream.Close(); } if (audioStream != null) { audioStream.Close(); } if (sourceStream != null) { sourceStream.Close(); } if (destinationStream != null) { destinationStream.Close(); } this.Cursor = Cursors.Default; if (sw.IsRunning) { sw.Stop(); } } // fin try } // fin if }
// event. click on 'Extraire' boutton private void extraireBtn_Click(object sender, EventArgs e) { // vidage de la zone qui contiendra le message caché txtCacherTab2.Text = ""; // remise à zéro de la barre de chargement progressBar1.Value = 0; // 1 - vérification du fichier audio d'entrée + la clé if (audioFileTxtBox.Text == "") { MessageBox.Show("Aucun fichier audio choisi !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } else if (cleTxtBox.Text == "") { MessageBox.Show("Aucune clé choisie !", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // Let's Extract the message ! // on commence le calcul du temp d'éxecution Stopwatch sw = new Stopwatch(); sw.Start(); // create streams FileStream sourceStream = null; WaveStream audioStream = null; //create an empty stream to receive the extracted message MemoryStream messageStream = new MemoryStream(); // create a stream that contains the key Stream keyStream = ToolsAndFunctions.stringToStream(cleTxtBox.Text); try { //open the carrier file sourceStream = new FileStream(audioFileTxtBox.Text, FileMode.Open); audioStream = new WaveStream(sourceStream); WaveUtility utility = new WaveUtility(audioStream); //exctract the message from the carrier wave this.Cursor = Cursors.WaitCursor; Thread thread = new Thread(() => { utility.Extract(messageStream, keyStream); }); thread.Start(); int timeout = (int)TimeoutNumericUpDown.Value * 1000; // conversion en milliseconde if (!thread.Join(timeout)) // if timeout { thread.Abort(); throw new Exception("[Timeout !]\r\nIl est probable que le fichier audio ou que la clé soit erronée !"); } // show message if (messageStream.Length > 0) { messageStream.Seek(0, SeekOrigin.Begin); txtCacherTab2.Text = new StreamReader(messageStream).ReadToEnd(); } // on arrête le calcul du temp d'éxecution + on l'affiche sw.Stop(); execTime.Text = sw.ElapsedMilliseconds.ToString() + " ms"; // chargement complet de la barre de chargement progressBar1.Value = 100; } catch (Exception ex) { //this.Cursor = Cursors.Default; MessageBox.Show(ex.Message, "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Stop); } finally { if (keyStream != null) { keyStream.Close(); } if (messageStream != null) { messageStream.Close(); } if (audioStream != null) { audioStream.Close(); } if (sourceStream != null) { sourceStream.Close(); } this.Cursor = Cursors.Default; if (sw.IsRunning) { sw.Stop(); } } }