Insertion de texte dans une image (cf. Wikipedia -> stéganographie) par parité des composantes de chaque pixel. Les caractères sont convertis en mots binaires qui sont ensuite écris dans les bits de poids faible de chaque composante (RVB), ceci est fait en modifiant la parité des octets.
Source / Exemple :
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void Coder(int *binaire, char *adr, int nbBits);
void Decoder(int *binaire, char *adr, int cle);
void ToBin(int taille, char *texte, int *texte_binaire);
void ToASCII(int *binaire, int taille);
int CarRestants(char *adr);
#pragma pack(push, 1) typedef struct{
unsigned short type;
unsigned long size;
unsigned short reserved1;
unsigned short reserved2;
unsigned long offsetbits;
} bmpheader;
#pragma pack(pop) typedef struct{
unsigned long headersize;
unsigned long width;
unsigned long height;
unsigned short planes;
unsigned short bitcount;
unsigned long compression;
unsigned long sizeimage;
unsigned long xpelspermeter;
unsigned long ypelspermeter;
unsigned long colorsused;
unsigned long colorsimportant;
unsigned char *palette;
unsigned char *pixels;
} bmpinfo;
int main(int argc, char *argv[]) {
while(1) {
int choix, cle, texte_len=-1;
long caracteresMax;
char *texte, adr[MAX_PATH]="";
system("color F9");
system("cls");
printf("\t\t**************STEGANOGRAPHIE**************\n\t\t\t\tBy M@gicT0\n\n\n\n\n\t\t\t1 - Coder\n\t\t\t2 - Decoder\n\n\n\n\n\n\t\t\t");
scanf("%d",&choix);
getchar();
if(choix==1){
system("cls");
printf("\t\t**************STEGANOGRAPHIE**************\n\t\t\t\tBy M@gicT0\n\n\n\n\n\tImage BMP (sans espaces) : ");
scanf("%s", adr);
getchar();
system("cls");
caracteresMax=CarRestants(&adr[0]);
//On récupère le nombre de caractères max
texte=malloc(caracteresMax*sizeof(char));
printf("\t\t**************STEGANOGRAPHIE**************\n\t\t\t\tBy M@gicT0\n\n\n\n\n\tTexte (%ld caracteres max): ", caracteresMax);
fgets(texte, caracteresMax, stdin);
//On récupère le texte à insérer
do {
choix=texte[texte_len];
//On cherche la longueur de la chaine de texte
texte_len++;
}
while(choix!='\0');
int *texte_binaire;
texte_binaire=malloc(texte_len*8*sizeof(int));
ToBin(texte_len, &texte[0], &texte_binaire[0]);
//Conversion du texte en binaire
Coder(&texte_binaire[0], &adr[0], texte_len*8);
//Insertion du texte dans l'image
system("cls");
printf("\t\t**************STEGANOGRAPHIE**************\n\t\t\t\tBy M@gicT0\n\n\n\n\n\t\tTexte ecrit !\n\n\t\tClef :%d\n\n\n\n", texte_len*8);
getchar();
free(texte_binaire);
}
else if(choix==2){
system("cls");
printf("\t\t**************STEGANOGRAPHIE**************\n\t\t\t\tBy M@gicT0\n\n\n\n\n\tImage BMP (dans le meme dossier) : ");
scanf("%s", adr);
system("cls");
printf("\t\t**************STEGANOGRAPHIE**************\n\t\t\t\tBy M@gicT0\n\n\n\n\n\t\tClef : ");
scanf("%d",&cle);
int *binaire;
binaire=malloc(cle*sizeof(int));
Decoder(&binaire[0], &adr[0], cle);
//Extraction du texte dans l'image
system("cls");
ToASCII(&binaire[0], cle);
//Conversion du binaire en ASCII
getchar();
getchar();
free(binaire);
}
else exit(0);
}
return 0;
}
void ToBin(int taille, char *texte, int *texte_binaire) {
unsigned int hex;
int i, j, k=8*taille;
for(j=taille-1;j>=0;j--) //Pour chaque caractère
{
hex=(int)texte[j]; //On prend son code ASCII
for(i=7;i>=0;i--) //Pour chaque bit
{
texte_binaire[k-1]=hex%2;
//On transcode le code ASCII (décimale) en un mot binaire (8 bits)
hex/=2;
k--;
}
}
return;
}
void ToASCII(int *binaire, int taille) {
int i, j, k, h=0, n, t, temp[8]={0};
printf("\t\t**************STEGANOGRAPHIE**************\n\t\t\t\tBy M@gicT0\n\n\n\n\n\tTexte : ");
for(j=0;j<(taille/8);j++) //Pour chaque mot binaire
{
n=t=0;
for(k=0;k<8;k++) temp[k] = binaire[k+(8*j)];
//On stocke mot par mot la chaine binaire pour la traiter ensuite
for(i=7;i>=0;i--) //Pour chaque bit
{
if(temp[i]==1) t+=pow(2,n);
//Conversion du mot binaire en décimale
n++;
}
printf("%c", t); //Affichage du caractère
h++;
}
printf("\n\n\n\n");
return;
}
int CarRestants(char *adr) {
FILE *img=fopen(adr, "rb");
bmpheader header; //structure du header
bmpinfo info; //structure de la partie info
fread(&header,sizeof(header),1,img); //on lit la partie header
fread(&info, sizeof(info), 1, img); //puis la partie info
if(header.type != 0x4D42){
system("cls");
printf("\n\n\n\n\n\n\n\t\t\tCe n'est pas une image Bitmap !\n\n");
getchar();
exit(0);
}
fclose(img);
return (info.width*info.height)*3/8; //On retourne la largeur * la hauteur / 8 (un caractère -> 8bits)
}
void Coder(int *binaire, char *adr, int nbBits) {
FILE *img=NULL, *gen=NULL;
img=fopen(adr,"rb"); //Ouverture des fichiers cibles/sources
gen=fopen("stegano.bmp","wb+");
int i,j, c;
if(img != NULL && gen != NULL) //Vérification d'ouverture
{
for (i=0;i<53;i++) fputc(fgetc(img), gen); //Copie du header (pour un BMP 24 bits)
for(i=0;i<nbBits;i++) //Pour chaque bit à insérer
{
if(binaire[i]==0) //Si c'est un 0
{
j=fgetc(img); //On lit l'octet de la composante Rouge
if(j%2==1) j--; //Si elle est impaire, on lui soustrait 1
fputc(j,gen); //On l'écrit dans le fichier cible
}
else //Si c'est un 1
{
j=fgetc(img); //Idem.
if(j%2==0)
{
if(j!=0) j--;
else j++;
}
fputc(j,gen);
}
}
while((c=fgetc(img)) != EOF) fputc(c,gen); //On écrit la fin du fichier
}
fclose(img); //On libère les flux en mémoire
fclose(gen);
return;
}
void Decoder(int *binaire, char *adr, int cle) {
int i;
FILE *img=NULL;
img=fopen(adr, "rb");
if(img != NULL)
{
fseek(img, 53, SEEK_SET); //On se positionne après le header
for(i=0;i<cle;i++) //Pour chaque bit
{
if(fgetc(img)%2 == 0) binaire[i]=0; //On vérifie sa parité
else binaire[i]=1; //pair = 0 | impaire = 1
}
}
fclose(img);
return;
}
Conclusion :
Je ne programme pas souvent, alors soyez indulgents :)
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.