begin process at 2012 05 27 19:25:59
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Sécurité & Cryptage

 > STÉGANOGRAPHIE [BORLAND C++]

STÉGANOGRAPHIE [BORLAND C++]


 Information sur la source

Note :
7 / 10 - par 1 personne
7,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Sécurité & Cryptage Niveau :Débutant Date de création :31/05/2003 Date de mise à jour :31/05/2003 11:18:17 Vu :4 856

Auteur : Draven

Ecrire un message privé
Commentaire sur cette source (13)
Ajouter un commentaire et/ou une note

 Description

Le but de ce programme est de cacher une chaîne de caractères dans une image bitmap. Ces caractères seront cacher dans la données de l'image.
Il y a sûrement des bugs, merci de me les signaler.

Source

  • #include <stdio.h> /* printf(), scanf, fopen() ... */
  • #include <stdlib.h> /* exit() */
  • #include <windows.h> /*BITMAPFILEHEADER et BITMAPINFOHEADER */
  • #include <math.h> /* pow() */
  • #include <string.h> /* strlen(), gets() */
  • /* structure comprenant les 2 en-têtes du fichier bitmap (54 octets) */
  • typedef struct
  • {
  • BITMAPFILEHEADER file; /*information sur le fichier (ex type,taille du fichier ) */
  • BITMAPINFOHEADER info; /*information sur la données de l'image (ex nbrcouleur utilise, longueur,largeur, taille de l'image) */
  • }HEADER;
  • void cacher(FILE *,char *);
  • void convertir(int,int *);
  • void reveler(FILE*);
  • void main()
  • {
  • char nom_fichier[50],choix;
  • FILE *source;
  • printf("Faites votre sélection:\n\n1- Cacher un texte dans une image \n2- Révéler un texte caché dans une image\n\nChoix : ");
  • scanf("%c",&choix);
  • if(choix=='1')
  • {
  • printf("Entrez le nom du fichier: ");
  • scanf("%s",nom_fichier);
  • if((source=fopen(nom_fichier,"rb"))==NULL)
  • {
  • printf("erreur à l'ouverture du fichier\n");
  • exit(-1);
  • }
  • cacher(source,nom_fichier);
  • }
  • else if(choix=='2')
  • {
  • printf("Entrez le nom du fichier: ");
  • scanf("%s",nom_fichier);
  • if((source=fopen(nom_fichier,"rb"))==NULL)
  • {
  • printf("erreur à l'ouverture du fichier\n");
  • exit(-1);
  • }
  • reveler(source);
  • }
  • printf("\n\tFIN");
  • }
  • void cacher(FILE *source, char *nom_fichier)
  • {
  • int valeur,binaire[8],i,j,octet,nbr_couleur,deplacement=0;
  • char phrase[250];
  • FILE *destination;
  • HEADER header;
  • fflush(stdin); /* vider le buffer clavier, pour utiliser juste apres 'gets' */
  • printf("Entrez la phrase à cacher : ");
  • gets(phrase); /* j'ai choisis 'gets' pour pouvoir saisir les espaces, car 'scanf' ne permet pas la saisie du caractere espace */
  • fread(&header,sizeof(HEADER),1,source); /* lire les 54 premiers octets qui constitue l'en-tete */
  • /* tester si les 2 premiers octets sont B et M */
  • if(header.file.bfType!=0x4D42)
  • {
  • printf("%s n'est pas un fichier bitmap\n",nom_fichier);
  • fclose(source);
  • exit(-1);
  • }
  • /* créer un fichier temporaire pour recopier une partie du fichier source*/
  • if((destination=fopen("tempo.dat","wb"))==NULL)
  • {
  • printf("erreur à l'ouverture du fichier\n");
  • exit(-1);
  • }
  • /* copie de l'entete bmp (54 premiers octets) de le fichier "tempo.bmp" */
  • fwrite(&header,sizeof(HEADER),1,destination);
  • /*biBitCount renvoie la valeur 1,4,8 ou 24 */
  • nbr_couleur=pow(2,header.info.biBitCount);
  • /* calcule de la taille de la palette*/
  • if(header.info.biBitCount!=24)
  • deplacement=nbr_couleur*4;
  • /* si l'image est en 16 millions de couleurs il n'y a pas de palettes, la données de l'image commence dès la fin de l'en-tête*/
  • else
  • deplacement=0;
  • /* recopier la palette du fichier source dans le fichier temporaire */
  • for(i=0;i<deplacement;i++)
  • {
  • octet=fgetc(source);
  • fputc(octet,destination);
  • }
  • /* cacher le texe dans la données de l'image*/
  • for(i=0;i<=strlen(phrase);i++)
  • {
  • valeur=(int)phrase[i]; /* transtyper un caractère en entier */
  • convertir(valeur,binaire); /* convertir un entier en binaire */
  • /*un caractere sera cacher dans huit octets de la données de l'image */
  • for(j=0;j<8;j++)
  • {
  • octet=fgetc(source);
  • /* on modifie le dernier bit de chaque octet */
  • if(binaire[j]==0)
  • octet= octet & 0xFE; /*forcer le dernier bit à '0' */
  • else
  • octet=octet | 0x01; /*forcer le dernier bit à '1' */
  • fputc(octet,destination); /* copier l'octet modifier dans le fichier destination */
  • /* Le fait de modifier l'octet change légèrement la couleur du pixel */
  • /* mais ceci n'est pas visible sur une image en 16 millions de couleurs*/
  • /* le changement de couleurs est plus visible avec des images en 2,16 ou 256 couleurs */
  • }
  • }
  • /*copier la fin du fichier*/
  • while(octet!=EOF)
  • {
  • octet=fgetc(source);
  • if(octet!=EOF)
  • fputc(octet,destination);
  • }
  • fclose(source);
  • fclose(destination);
  • remove(nom_fichier); /* supprimer le fichier source */
  • rename("tempo.dat",nom_fichier); /*renommer le fichier temporaire avec le nom du fichier source */
  • }
  • void convertir(int valeur,int *tableau)
  • {
  • int i;
  • int compteur=0;
  • int tempo[8];
  • /* convertir un entier en binaire*/
  • /* l'entier aura une taille de 8 bits car le caractere est un caractère ASCII */
  • while(valeur!=0)
  • {
  • tempo[compteur]=valeur%2;
  • valeur=valeur/2;
  • compteur++;
  • }
  • /* compléter la fin du tableau avec des '0' */
  • for(i=compteur;i<8;i++)
  • tempo[i]=0;
  • /* inverser la chaîne pour obtenir le poids fort à gauche */
  • for(i=0;i<8;i++)
  • tableau[i]=tempo[7-i];
  • }
  • void reveler(FILE *source)
  • {
  • int deplacement,i,nbr_couleur,octet,binaire[8],valeur,compteur=0;
  • char phrase[250],caractere;
  • HEADER header;
  • fread(&header,sizeof(HEADER),1,source); /* lire les 54 premiers octets qui constitue l'en-tete */
  • /* teste si les 2 premier octets sont B et M */
  • if(header.file.bfType!=0x4D42)
  • {
  • printf("le fichier ouvert n'est pas un fichier bitmap\n");
  • fclose(source);
  • exit(-1);
  • }
  • /* calculer la taille de la palette */
  • nbr_couleur=pow(2,header.info.biBitCount);
  • if(header.info.biBitCount!=24)
  • deplacement=nbr_couleur*4;
  • else
  • deplacement=0;
  • /*se placer au niveau de la données de l'image (après la taille en-tête + palette)*/
  • fseek(source, deplacement+54, SEEK_SET);
  • do
  • {
  • valeur=0;
  • /* lire 8 octets pour obtenir 1 caractère caché */
  • for(i=0;i<8;i++)
  • {
  • octet=fgetc(source);
  • binaire[i]=octet & 0x01; /* faire un masque qui donnera soit '0' ou '1'*/
  • valeur= binaire[i]*pow(2,(7-i))+valeur; /* convertir la chaine de '0' et '1' en entier */
  • }
  • caractere=(char)valeur; /* transtyper un entier en caractère */
  • phrase[compteur]=caractere; /* stocker ce caractère dans une chaine de caractères */
  • compteur++;
  • }
  • while(caractere!='\0');
  • /* écrire le message révélé */
  • printf("\nLe message caché est : %s\n",phrase);
  • fclose(source); /* fermer le fichier*/
  • }
#include <stdio.h>      /* printf(), scanf, fopen() ... */
#include <stdlib.h>		/* exit() */
#include <windows.h>		/*BITMAPFILEHEADER et BITMAPINFOHEADER */
#include <math.h>       /* pow() */
#include <string.h>     /* strlen(), gets() */

/* structure comprenant les 2 en-têtes du fichier bitmap (54 octets) */
typedef struct
{
     BITMAPFILEHEADER file; /*information sur le fichier (ex type,taille du fichier ) */
     BITMAPINFOHEADER info; /*information sur la données de l'image (ex nbrcouleur utilise, longueur,largeur, taille de l'image) */
}HEADER;


void cacher(FILE *,char *);
void convertir(int,int *);
void reveler(FILE*);


void main()
{
   char nom_fichier[50],choix;
	FILE *source;
   printf("Faites votre sélection:\n\n1- Cacher un texte dans une image \n2- Révéler un texte caché dans une image\n\nChoix : ");
   scanf("%c",&choix);
   if(choix=='1')
   {
   	printf("Entrez le nom du fichier: ");
   	scanf("%s",nom_fichier);
   	if((source=fopen(nom_fichier,"rb"))==NULL)
   	{
   		printf("erreur à l'ouverture du fichier\n");
      	exit(-1);
  		}
   	cacher(source,nom_fichier);
   }
   else if(choix=='2')
   {
   	printf("Entrez le nom du fichier: ");
   	scanf("%s",nom_fichier);
   	if((source=fopen(nom_fichier,"rb"))==NULL)
   	{
   		printf("erreur à l'ouverture du fichier\n");
      	exit(-1);
  		}
   	reveler(source);
   }
   printf("\n\tFIN");
}



void cacher(FILE *source, char *nom_fichier)
{
   int valeur,binaire[8],i,j,octet,nbr_couleur,deplacement=0;
   char phrase[250];
   FILE *destination;
   HEADER header;
   fflush(stdin); /* vider le buffer clavier, pour utiliser juste apres 'gets' */
   printf("Entrez la phrase à cacher : ");
   gets(phrase);  /* j'ai choisis 'gets' pour pouvoir saisir les espaces, car 'scanf' ne permet pas la saisie du caractere espace */
   fread(&header,sizeof(HEADER),1,source); /* lire les 54 premiers octets qui constitue l'en-tete */
   /* tester si les 2 premiers octets sont B et M */
   if(header.file.bfType!=0x4D42)
   {
   	printf("%s n'est pas un fichier bitmap\n",nom_fichier);
      fclose(source);
      exit(-1);
   }
   /* créer un fichier temporaire pour recopier une partie du fichier source*/
   if((destination=fopen("tempo.dat","wb"))==NULL)
   {
   	printf("erreur à l'ouverture du fichier\n");
      exit(-1);
   }

   /* copie de l'entete bmp (54 premiers octets) de le fichier "tempo.bmp" */
   fwrite(&header,sizeof(HEADER),1,destination);

   /*biBitCount renvoie la valeur 1,4,8 ou 24 */
   nbr_couleur=pow(2,header.info.biBitCount);
   /* calcule de la taille de la palette*/
   if(header.info.biBitCount!=24)
	   deplacement=nbr_couleur*4;
   /* si l'image est en 16 millions de couleurs il n'y a pas de palettes, la données de l'image commence dès la fin de l'en-tête*/
   else
      deplacement=0;
   /* recopier la palette du fichier source dans le fichier temporaire */
   for(i=0;i<deplacement;i++)
   {
   	octet=fgetc(source);
      fputc(octet,destination);
   }
   /* cacher le texe dans la données de l'image*/
   for(i=0;i<=strlen(phrase);i++)
   {
   	valeur=(int)phrase[i];  /* transtyper un caractère en entier */
   	convertir(valeur,binaire); /* convertir un entier en binaire */
      /*un caractere sera cacher dans huit octets de la données de l'image */
   	for(j=0;j<8;j++)
      {
			octet=fgetc(source);
         /* on modifie le dernier bit de chaque octet */
         if(binaire[j]==0)
            octet= octet & 0xFE; /*forcer le dernier bit à '0' */
         else
         	octet=octet | 0x01; /*forcer le dernier bit à '1' */
         fputc(octet,destination); /* copier l'octet modifier dans le fichier destination */
         /* Le fait de modifier l'octet change légèrement la couleur du pixel */
         /* mais ceci n'est pas visible sur une image en 16 millions de couleurs*/
         /* le changement de couleurs est plus visible avec des images en 2,16 ou 256 couleurs */
      }
   }
   /*copier la fin du fichier*/
   while(octet!=EOF)
   {
   	octet=fgetc(source);
      if(octet!=EOF)
      	fputc(octet,destination);
   }
   fclose(source);
   fclose(destination);
   remove(nom_fichier);  /* supprimer le fichier source */
   rename("tempo.dat",nom_fichier); /*renommer le fichier temporaire avec le nom du fichier source */

}
void convertir(int valeur,int *tableau)
{
   int i;
	int compteur=0;
   int tempo[8];
   /* convertir un entier en binaire*/
   /* l'entier aura une taille de 8 bits car le caractere est un caractère ASCII */
   while(valeur!=0)
   {
   	tempo[compteur]=valeur%2;
      valeur=valeur/2;
      compteur++;
   }
   /* compléter la fin du tableau avec des '0' */
   for(i=compteur;i<8;i++)
   	tempo[i]=0;
   /* inverser la chaîne pour obtenir le poids fort à gauche */
   for(i=0;i<8;i++)
   	tableau[i]=tempo[7-i];
}

void reveler(FILE *source)
{
   int deplacement,i,nbr_couleur,octet,binaire[8],valeur,compteur=0;
   char phrase[250],caractere;
	HEADER header;
   fread(&header,sizeof(HEADER),1,source); /* lire les 54 premiers octets qui constitue l'en-tete */
   /* teste si les 2 premier octets sont B et M */
   if(header.file.bfType!=0x4D42)
   {
   	printf("le fichier ouvert n'est pas un fichier bitmap\n");
      fclose(source);
      exit(-1);
   }
	/* calculer la taille de la palette */
   nbr_couleur=pow(2,header.info.biBitCount);
   if(header.info.biBitCount!=24)
	   deplacement=nbr_couleur*4;
   else
      deplacement=0;
   /*se placer au niveau de la données de l'image (après la taille en-tête + palette)*/
   fseek(source, deplacement+54, SEEK_SET);
   do
   {
      valeur=0;
      /* lire 8 octets pour obtenir 1 caractère caché */
      for(i=0;i<8;i++)
      {
			octet=fgetc(source);
         binaire[i]=octet & 0x01;  /* faire un masque qui donnera soit '0' ou '1'*/
         valeur= binaire[i]*pow(2,(7-i))+valeur;  /* convertir la chaine de '0' et '1' en entier */
      }
      caractere=(char)valeur; /* transtyper un entier en caractère */
      phrase[compteur]=caractere; /* stocker ce caractère dans une chaine de caractères */
      compteur++;
   }
   while(caractere!='\0');
   /* écrire le message révélé */
   printf("\nLe message caché est : %s\n",phrase);
   fclose(source);      /* fermer le fichier*/
} 

 Conclusion

Bien entendu pour améliorer la sécurité il faudrait crypter la chaine saisie par l'utilisateur, mais je n avais pas envie de surcharger le programme.


 Sources du même auteur

Source avec Zip Source avec une capture TESTER VOTRE RAPIDITÉ À CLIQUER [BUILDER]
Source avec Zip APPLIQUER UN FILTRE À UNE IMAGE
CONVERTIR UNE IMAGE 16 MILLIONS DE COULEURS EN NIVEAUX DE GR...
Source avec Zip THREADS SOUS BUILDER
Source avec Zip MARCHEZ LEMMINGS MARCHEZ... [BORLAND C++]

 Sources de la même categorie

PROJET DE CRYPTOGRAPHIE: RSA À JEU REDUIT D'INSTRUCTION par samatarahmed
Source avec Zip Source avec une capture CRYPTOSYSTÈME ELGAMAL LIBRAIRIE GMP par louelh95
Source avec Zip Source .NET (Dotnet) NOUVEL ALGORITHME D'ENCRYPTION-DÉSENCRYPTION DYNAMIQUE (INFA... par vletktol
Source avec Zip A2DCRYPT - CRYPTAGE 2048 BITS par darkor
Source avec Zip Source avec une capture CRYPTEUR-DÉCRYPTEUR-IP par antho974

Commentaires et avis

Commentaire de rezoman le 31/05/2003 17:23:30

interessant comme source. on peut aussi utiliser ton prog pour inserer un copyright sur une image sans que cela se voit. dommage que tu n en a pas fait un qui fonctionne avec les fichiers jpeg, qui sont tout de meme nettement plus utilisé sur le net. Si jamais tu le fais tiens moi au courant stp.

Commentaire de Draven le 31/05/2003 21:49:51

Salut rezoman
Justement je suis en train de me documenter sur les autres types de formats (notamment jpg) pour ameliorer ce prog.
Si j avais vous avez de bonne docs sur le jpg ou tiff... n hesite pas a me les envoyer. merci d avance.
draven426@hotmail.com

Commentaire de Rabah71B le 01/06/2003 01:55:27

salut
c mon premier message ici
je connais un tres bon site et tu y va trouvras plein de documentations
   www.wotsit.org
je trouve ce site(cppfrance)formidable mais malheureusement je viens juste d apprendre le c++ alors je ne peux pas participer
je serais tres reconnaissant si vous m aidiez par des cours tutos...et surtout en ce qui concerne les api windows
je vous remercie bcp pour tous vos efforts
bye et c++

Commentaire de Galett le 01/06/2003 12:40:30

sans vouloir être le trouble-fête, je vois mal comment l'implémenter sur du jpeg, étant donné que le jpeg altère l'image ...

Commentaire de Draven le 01/06/2003 15:59:09

merci Rabah71B je vais y jetez un oeil.
Galett je recherche de la doc pour justement tenter de trouver une solution.  

Commentaire de Kirua le 01/06/2003 16:39:39

eh bien le fait que JPEG altère l'image ne sera pas un problème puisque le message est "caché" dans le code de l'image. ce code n'est pas changé, i lest seulement interpreté, donc c pas un problème je pense.

Commentaire de revinc le 02/06/2003 08:49:28

Le JPEG Independant Group : http://www.ijg.org/
avec toutes les sources C du format...

Quand a planquer des données dans une image JPEG, y'a pas de contre-indication mais c'est plutôt chaud...

Commentaire de ishahn le 09/06/2003 03:42:53

Pour ce qui est de planquer kek chose dans une image jpeg, moi j'y crois pas des masses (à cause de la compression avec pertes), ou alors ça devient vraiment compliqué. Par contre, il existe un format qui s'appelle le JPEG2000 et qui est capable de faire de la compression sans pertes : le taux de compression dépendra bien sûr de la complexité de l'image.
Juste pour info : le JPEG2000 exactement comme le JPEG (c'est à dire transformée de fourier discrète de l'image puis élimination des "termes" non significatifs) sauf que les fonctions utilisées pour la transformation ne sont plus des sinusoïdes mais des ondelettes... (c'est plus du Fourier mais l'équation est la même, avec une base formée d'ondelettes au lieu de sin).

Seul petit soucis, le JPEG2000 n'est pas encore très répandu... mais c'est format qui détronera tous les autres d'ici peu de temps.

Commentaire de exar le 04/02/2004 21:42:39

Si: la dissimulation de messages dans u JPEG est possible et d'ailleurs déjà implémentée dans de nombreux logiciels de stéganographie...
Ca fonctionne d'ailleurs aussi avec du MPEG, qui est aussi un format compressé !

Commentaire de lastpixl le 05/03/2004 20:52:07

Toutel'image est dégradée par cette méthode, et la phrase ne fait qu'au maximum 250 octets : il faudrait par exemple ajouter un int au début, dans les 1ers octets cachée, qui indiqueraient la longueur à lire...


+++,
Lastpix'l

Commentaire de Draven le 06/03/2004 11:42:50

Cette méthode dégrade un bit par octet de donnée. Donc si tu arrive à voir la différence sur une image en 16 millions de couleurs tu es très fort. C'est sur que ce n'est pas la méthode à appliquer sur une image 2 couleurs.

a+

Commentaire de lastpixl le 06/03/2004 14:34:09

Quelqu'un qui cherchera une image stéganographiée verra tout de suite que presque tout les derniers bits sont à zero, ce qui est un peu bizarre... Sinon, pourquoi dégrader une image quand c'est inutile ?

Je suis en train de faire un programme de stéganographie en mode graphique (VCL) pour mes TPE c'est pour ca que je viens poster ces commentaires...

Commentaire de Draven le 06/03/2004 18:42:02

Je ne vois pas comment tu peux cacher du texte sans dégrader, même légèrement, l'image.

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,764 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales