a l'aide svp , je galere en C sur un projet de steganographie - Programmation
Marsh Posté le 17-11-2001 à 07:50:18
Tu essayes le code sur quel format d'image?
Parce qu'il faut tenir compte de l'en-tete...
A+,
[edtdd]--Message édité par gilou--[/edtdd]
Marsh Posté le 17-11-2001 à 09:00:25
moi, je suis étonné que cette portion de code marche :
/*texte à crypter*/
printf("entrez le texte a steganografier :\n" );
scanf("%d",&texte);
ta var texte est un tableau....tu mets pas d'indice?
et remarque: y'a plusieurs entêtes de bmp
Marsh Posté le 17-11-2001 à 10:29:43
Bon notons certains des pb:
Citation : main() |
int main() ca te permettra de retourner des codes d'erreurs eventuellement, en sortie.
Citation : FILE *entree = fopen("image.bmp", "r" ); |
FILE *entree = fopen("image.bmp", "rb" );
FILE *sortie = fopen("sortie.bmp", "wb" );
/* Ca change rien mais ca fait pas de mal pour relire */
Bon un petit test pour verifier que les operations ont reeussi ca serait pas mal...
if (!entree || !sortie)
{
/* Ecrire un zoli msg d'erreur */
exit (0);
}
Citation : struct pixel |
Bof, je ferais:
typedef struct pixel{
long pfort :31;
unsigned pfaible:1;
}pixel;
De toute facon, je vois pas a quoi ca va te servir puisque un masque sera bien plus efficace.
Citation : while (copybuf<40) |
{
char copybuf[40];
fread(©buf,sizeof(int),40,entree);
fwrite(©buf,sizeof(int),40, sortie);
}
Citation : printf("entrez le texte a steganografier :\n" ); |
scanf("%s",&texte);
Ben oui, car c'est pas un nombre que tu lis en entree.
De plus, scanf s'arretera au premier blanc, ce qui n'est sans doute pas suffisant pour le texte a crypter qui a priori est sans doute compose de plusieurs mots.
etc.
A+,
[edtdd]--Message édité par gilou--[/edtdd]
Marsh Posté le 17-11-2001 à 10:54:09
Au fait, l'essentiel de l'algo tient en ceci:
Citation : while (fread(&buf, 1, 1, fp2)) |
Decomposons:
Citation : while (fread(&buf, 1, 1, fp2)) {...} |
Il boucle en lecture sur fp2, le fichier qui contient le texte a coder, et traite un caractere a la fois.
Citation : (a&0xFE) | (b&1) |
(b&0xFE): on met a 0 le bit de poids faible de a
(b&1): on recupere le bit de poids faible de b
D'ou (a&0xFE) | (b&1) : on met le bit de poids faible de b a la place de celui de a.
Citation : for (i = 0; i < 8; i++) { a>>i; } |
Il decale un a un les bits du caractere a.
Avec tout ca l'algo est vraiment evident:
On prend un caractere a coder c dans le fichier.
Pour le coder, on fait:
On prend un pixel de l'image pix (l'algo suppose qu'elle est codee sur un caractere, sinon, il faut adapter)
on prend le bit de poids faible de c, on le met dans le bit de poids faible de pix, on decale les bits de c de un pour traiter le second bit au prochain tour, il est range en bit de poids faible.
On ecrit le pixel modifie, et on recommence 7 fois pour les autres bits de c.
C'est pas tres complique comme algo.
Il serait un poil plus efficace ecrit ainsi d'ailleurs, en bossant sur 8 pixels a la fois:
Citation : char pixel[8], c; |
(Et si tu sais que ton texte est en ascii pur, tu peux bosser sur 7 pixels a la fois, plutot que 8...).
Il faut aussi prevoir un test pour voir si l'image est assez grande pour coder le texte: verifier que le nb de pixels de l'image est superieur a 8 fois la longueur du texte a coder avant de demarrer le codage, ou alors tronquer le texte a coder en fonction de la taille de l'image.
A+,
[edtdd]--Message édité par gilou--[/edtdd]
Marsh Posté le 17-11-2001 à 23:49:35
franchement je suis bluffé , je vous remerci tous bcp
sinon , notre prof à crypter une image , on doit la decrypter , c une image 24bits (true collor) elle a modifie le bit de faible poids tous les 4 octets , normalement le texte fait 100 caractere.
pour le moment g fait ca :
#include <stdio.h>
#include "librairie.h"
void decrypt()
{
int enteteimage[40]; /* correspond à l'entête de l'image de 80octets */
int curseur;
long img_texte; /*correspond à la partie d'image encryptée */
long masque=1;/*filtre permettant de décrypter l'image */
long step_one[8];
int i=0;
char lettre;
char mot[100];
FILE *entree = fopen("image.bmp", "rb" );
/*entete*/
for (curseur =0 ; curseur< 40 ; curseur++ )
{
fread(&enteteimage,sizeof(int),2,entree);
}
for (curseur =40 ; curseur< 1640 ; curseur=curseur+16 )
{
while (i<8)
{
fread(&img_texte,sizeof(long),1,entree);
step_one[i]=img_texte&masque;
step_one[i]<<31-i);
i++;
lettre=step_one[0]+step_one[1]+step_one[2]+step_one[3]+step_one[4]+step_one[5]+step_one[6]+step_one[7];
printf("%c",lettre);
}
/* mot[]=*/
}
fclose (entree);
}
si vous voulez essayer , l'image est sur www.chez.comsebienimage.bmp
Marsh Posté le 18-11-2001 à 00:07:02
ton lien marche pas
Forbidden
You don't have permission to access the requested URL on this server.
Sinon c cool je viens de decouvrir c koi la s-t-e-g-a-n-o-g-r-a-p-h-i-e (:sweat et comment ca fonctionne
histoire de contribuer :
Code :
|
c'est pour sauter l'entete du bitmap (si mes souvenirs sont bons)
car au debut y'a pas les couleurs, mais des indications sur la tailles, le nombre de couleurs ... tu peux trouver tres facilement de la doc dessus si tu veux faire un truc propre (car il peux y avoir une palette en suivant si <= 256 couleurs je crois et dans ce cas ca ferait desordre sur l'image finale
Marsh Posté le 18-11-2001 à 17:25:08
enfait , vu que je suis chez un hebergeur un peu special , on est obligé de se connecter à http://www.chez.com/sebien/ , puis de taper ensuite "image.bmp" et on peut la telecharger , desole .
merci bcp à toi aussi . , le programme d'encryptrage marche , reste celui qui permet de decrypter ....
pour l'entete de l'image , je considere qu'il est de 80 octets , comme ca g de la marge .
[edtdd]--Message édité par gilou--[/edtdd]
Marsh Posté le 19-11-2001 à 03:58:15
le pb du lien, c'etait la virgule collee a l'url.
A+,
[edtdd]--Message édité par gilou--[/edtdd]
Marsh Posté le 19-11-2001 à 07:01:48
rufo a écrit a écrit : moi, je suis étonné que cette portion de code marche : /*texte à crypter*/ printf("entrez le texte a steganografier :\n" ); scanf("%d",&texte); ta var texte est un tableau....tu mets pas d'indice? et remarque: y'a plusieurs entêtes de bmp |
euh, comme chacun le sais, un tableau en C est un bete pointeur ...
DOnc forcément oui ca amrche
Enfin sans le & ...
Marsh Posté le 19-11-2001 à 07:02:27
gilou a écrit a écrit : le pb du lien, c'etait la virgule collee a l'url. A=, |
OUAIIIIIIIIIIIIIIIIIIIII
Y SAI ENFIN PLANTAI , Y SAI ENFIN PLANTAI !
gilou
[edtdd]--Message édité par Tetedeiench--[/edtdd]
Marsh Posté le 19-11-2001 à 08:07:01
C' est mon clavier qui deconne entre les majuscules et les minuscules.
A+,
Marsh Posté le 19-11-2001 à 08:17:50
Pour ton probleme, j' ai essaye un truc comme ca:
Code :
|
Il a pas l'air de decoder ton image, mais peut etre les infos que tu as donnees sont insuffisantes(ou mon programme estil bugge). Le principe general devrait etre bon. A toi d' adapter a tes donnees.
A+,
[edtdd]--Message édité par gilou--[/edtdd]
Marsh Posté le 19-11-2001 à 10:37:55
yes , quel boss!
le pb , du decryptage , c que la convention est :
1- entete = 80octets pour avoir de la marge
2- l'image en true color (24 bits) : le bit de faible poids tous les 4 octets est remplace par le code binaire du caractere .
, un tres tres grand merci , g tout compris now, je devrais pouvoir m'en sortir
Marsh Posté le 19-11-2001 à 11:04:03
Ah OK, je comprends, elle demarre pas au debut du bitmap, OK!
Sachant ca, il est facile de decoder l'image pour trouver le texte suivant:
LE SUJET DU PARTIEL SE TROUVE DANS LE CHATEAU DE ARGHHHHH !
(suffit de remplacer la ligne
Code :
|
par:
Code :
|
dans mon post precedent).
A+,
[edtdd]--Message édité par gilou--[/edtdd]
Marsh Posté le 19-11-2001 à 11:51:26
bon ben c pas le tout, mais qqun sait comment faire de la steganographie resistant a un algo de compression, comme le jpg ?
Marsh Posté le 19-11-2001 à 23:05:26
j'y suis aussi arrive avec l'algo precedent comme ceci :#include <stdio.h>
#define masque 0x01 /* 1 en hexadécimal*/
main()
{
char bytes[32]; /* 8*4 = 32 octets pour coder une lettre */
char letter;
int i, j, count; /* compteurs utilisés pour manipuler les bits*/
FILE *in = fopen("point.bmp", "r" );
fseek(in,sizeof(char)*80,0) ;/* on zappe l'en tête*/
count = 0; /* compte les lettres lues */
printf("message decode : \n" );
while (fread(&bytes, 1,32,in) && (count< 100))
{
letter = '\0';
for (i = 0; i < 8; i++)
{
j=4*i+3;
letter = ((bytes[31-j])&masque) | (letter<<1);
/* les octets de poids fort sont a la fin, et doivent etre lus en premier */
}
printf("%c", letter);
count++;
}
printf("\n" );
printf("lettres lues " );
printf("%d\n",count);
fclose(in);
}
uin tres grand merci
Marsh Posté le 20-11-2001 à 00:49:37
Si tu veux une bonne note a ton exo (ainsi qu'un bon entrainement au programmes c sous unix/linux), tu peux:
* changer main() en int main() et retourner un code d'erreur si il y a erreur.
* recuperer un parametre -i nom_de_fichier en entree
* recuperer un parametre -o nom_de_fichier en sortie et le cas echeant, ecrire le texte dans ce fichier en sortie.
* recuperer un parametre -s step et modifier l'algo afin que l'on cherche tout les step octets (ici, step=4)
* recuperer un parametre -h head et modifier l'algo afin que l'on saute les head premiers octets (ici head=80)
* recuperer un parametre -n num et ne decripter que les n premiers caracteres (ici, n=100).
* recuperer un parametre -? et afficher le manuel (resume) d'utilisation. Afficher aussi ce manuel si la ligne de commande est erronnee.
* par defaut, supposer que le fichier en entree est sur stdin (et verifier cela avec la signature du fichier, qui doit demarrer par "BM" ).
* Tester si fopen echoue (ainsi que les autres operations de lecture et positionnement dans le fichier. Ecrire sur stderr un message d'erreur approprié.
A+,
Marsh Posté le 20-11-2001 à 01:36:15
Au fait, tu peux probablement remplacer:
Code :
|
par:
Code :
|
A+,
[edtdd]--Message édité par gilou--[/edtdd]
Marsh Posté le 22-11-2001 à 23:15:01
heu desole , g encore un pb , j'encrypte bien l'image avec mon texte , mais a parement , pas selon la bonne convention , ca j'arrive pas à la decrypter , si qqun pouvait me dire ou est l'erreur , ca serait cool
/**********************************************
********************************************/
/**********sous programme qui permet de steganografier un texte dans une image*************/
/*************************************************
*****************************************/
void encrypt()
{
#define masque_encrypt 0xFE
#define CHARMAX 101
char copybuf[80];
char nomfic[51];
char pixel[32], c;
int i=0,j=0,k=0;
char ligne[CHARMAX]=""; /*message saisi par l'utilisateur*/
int rang=0;
int vide=0;
FILE *image_crypt; /*ouverture en lecture de l'image initiale*/
FILE * TEMP; /*fichier temporaire ou est stocke le message*/
FILE *image_encrypt = fopen("out.bmp", "w" );/*ouverture en écriture de l'image finale (avec le message)*/
printf("indiquez le chemin ou se trouve l'image support de steganographie :" );
scanf("%s",&nomfic);
image_crypt=fopen(nomfic, "r" );
TEMP=fopen("message.txt","w" );
printf(" VEUILLEZ TAPER LE MESSAGE A CODER :" );
scanf("%d",&vide); /*vidage à la barbare du buffer */
gets(ligne); /*chargement du message dans une string*/
fputs(ligne,TEMP); /*copie de la string dans un fichier temp*/
fclose(TEMP);
printf("\n" );
// sauvegarde de l'entête de l'image:
while (j<80)
{
fread(©buf,sizeof(char),1,image_crypt);
fwrite(©buf,sizeof(char),1, image_encrypt);
j++;
}
printf("\n" );
// encrypte texte dans image
TEMP=fopen("message.txt", "r" ); /*ouverture du fichier en lecture pour traitement*/
while (fread(&c, sizeof(char), 1, TEMP))
{
fread(&pixel,sizeof(char), 8, image_crypt);
for (k=0; k<32; k=k+4)
{
for (i = 0; i < 8; i++)
{
pixel[i] = ((pixel[i])&masque_encrypt) | ((c>>i)&1);//remplace le bit de faible poids de pixel par le bit de c
}
}
fwrite(&pixel, 1, 8, image_encrypt);
}
//copie fin image
printf ("copie fin...\n" );
while (!feof(image_crypt))
{
fread(©buf,sizeof(char),1,image_crypt);
fwrite(©buf,sizeof(char),1,image_encrypt);
}
printf ("done\n" );
// clean up, such as it is
fclose (image_crypt);
fclose (TEMP);
fclose (image_encrypt);
}
/*************************************************
*****************************************/
/****sous programme qui permet de decrypter le texte à partir d'une image steganografiée***/
/*************************************************
*****************************************/
void decrypt()
{
#define masque_decrypt 0x01 /* 1 en hexadécimal*/
char octets[32]; /* 8*4 = 32 octets pour coder une lettre */
char lettre;
int i, j, cpt; /* compteurs utilisés pour manipuler les bits*/
FILE *f_encrypt = fopen("out.bmp", "r" ); /* a adapter */
fseek(f_encrypt,sizeof(char)*80,0) ;/* on zappe l'en tête*/
cpt = 0; /* compte les lettres lues */
printf("message decode : \n" );
while (fread(&octets, 1,32,f_encrypt) && (cpt< 100))
{
lettre = '\0';
for (i = 0; i < 8; i++)
{
j=4*i+3; /* Cf la ligne suivante, pour bytes[31-j] */
lettre = ((octets[31-j])&masque_decrypt) | (lettre<<1);
/* les octets de poids fort sont a la fin, et doivent etre lus en premier */
}
printf("%c", lettre);
cpt++;
}
printf("\n" );
printf("lettres lues " );
printf("%d\n",cpt);
fclose(f_encrypt);
}
Marsh Posté le 23-11-2001 à 23:08:49
/*************************************************
*****************************************/
/**********sous programme qui permet de steganografier un texte dans une image*************/
/*************************************************
*****************************************/
void encrypt()
{
#define masque_encrypt 0xFE
#define CHARMAX 101
char copybuf[80];
char nomfic[51];
unsigned char pixel[4], c;
unsigned char pixel_code[32];
int i=0,j=0,k=0;
char ligne[CHARMAX]=""; /*message saisi par l'utilisateur*/
int rang=0;
int vide=0;
FILE *image_crypt; /*ouverture en lecture de l'image initiale*/
FILE * Temp; /*fichier temporaire ou est stocke le message*/
FILE *image_encrypt = fopen("out.bmp", "w" );/*ouverture en écriture de l'image finale (avec le message)*/
printf("indiquez le chemin ou se trouve l'image support de steganographie :" );
scanf("%s",&nomfic);
image_crypt=fopen(nomfic, "r" );
Temp=fopen("message.txt","w" );
printf(" VEUILLEZ TAPER LE MESSAGE A CODER :" );
scanf("%d",&vide); /*vidage à la barbare du buffer */
gets(ligne); /*chargement du message dans une string*/
fputs(ligne,Temp); /*copie de la string dans un fichier temp*/
fclose(Temp);
printf("\n" );
// sauvegarde de l'entête de l'image:
while (j<80)
{
fread(©buf,sizeof(char),1,image_crypt);
fwrite(©buf,sizeof(char),1, image_encrypt);
j++;
}
printf("\n" );
// encrypte texte dans image
fseek(image_crypt,sizeof(char)*80,0);
Temp=fopen("message.txt", "r" ); /*ouverture du fichier en lecture pour traitement*/
while (fread(&c, sizeof(char), 1, Temp))
{
for (i = 0; i < 8; i++)
{
fread(&pixel,sizeof(char), 4, image_crypt);
for (j=0; j<3 ; j++)
{
pixel_code[j] = pixel[j];
}
pixel_code[3] = ((pixel[3])&masque_encrypt) | ((c>>i)&0x01);//remplace le bit de faible poids de pixel par le bit de c
}
fwrite(&pixel_code, 1, 32, image_encrypt);
}
//copie fin image
printf ("copie fin...\n" );
fseek(image_crypt,sizeof(char)*3200,0);
while (!feof(image_crypt))
{
fread(©buf,sizeof(char),1,image_crypt);
fwrite(©buf,sizeof(char),1,image_encrypt);
}
printf ("done\n" );
// FERMETURE DES FICHIERS
fclose (image_crypt);
fclose (Temp);
fclose (image_encrypt);
getch();
menu();
}
a l'aide gilou ou qqun d'autre , pkoi ca marche pas ??
Marsh Posté le 24-11-2001 à 12:20:42
Ca ne marche pas car tu as loupé un point important du cours de C !
L'ADRESSE D'UN TABLEAU, C'EST LE NOM DU TABLEAU TOUT COURT !!
Il faut donc que tu remplaces :
* scanf("%s",&nomfic);
* fread(©buf,sizeof(char),1,image_crypt);
* fwrite(©buf,sizeof(char),1, image_encrypt);
* etc...
par :
* scanf("%s",nomfic);
* fread(copybuf,sizeof(char),1,image_crypt);
* fwrite(copybuf,sizeof(char),1, image_encrypt);
* etc...
Par contre, pour les variables de type int et char, il faut effectivement mettre le '&'.
Marsh Posté le 16-11-2001 à 22:24:54
voila , je dois faire un prog qui encode et decode du texte ds une image , en modifiant le bit de faible poids tous les 4 octets , et je m'embrouille tout seul !
ce que g fait , cad presque rien :
#include <stdio.h>
main()
{
int texte[100];
int i;
FILE *entree = fopen("image.bmp", "r" );
FILE *sortie = fopen("sortie.bmp", "w" );
long copybuf[25600];
struct pixel
{
long pfort :31;
unsigned pfaible:1;
};
typedef struct pixel s_pixel;
/*entete*/
while (copybuf<40)
{
fread(©buf,sizeof(int),1,entree);
fwrite(©buf,sizeof(int),1, sortie);
}
/*texte à crypter*/
printf("entrez le texte a steganografier :\n" );
scanf("%d",&texte);
/*cryptage
while(fread(©buf,sizeof(int),3200,entree))
{
for
}
*/
et voila une source que g trouve, qui est sencée marche mais c pas le cas chez moi
/* ensteg.c
** do steganography stuff
** note that this assumes a binary-type pnm (P4,P5,P6) without a comment field
**
** usage:
** steg image.pnm file.dat output.pnm
** enstegs the file in file.dat into image.pnm to form output.pnm. Assumes
** that the destegged file can have trailing garbage without a problem
** (.tar.gz is fine).
*/
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp1 = fopen(argv[1], "r" );
FILE *fp2 = fopen(argv[2], "r" );
FILE *fout = fopen(argv[3], "w" );
int w, h, max;
char buf, copybuf[1024];
fscanf(fp1, "%1024s", copybuf);
fscanf(fp1, "%d%d%d\n", &w, &h, &max);
fprintf(fout, "%s\n%d %d\n%d\n", copybuf, w, h, max);
// ensteg the data
printf ("enstegging...\n" );
while (fread(&buf, 1, 1, fp2))
{
int i;
for (i = 0; i < 8; i++)
{
char b = fgetc(fp1);
char s = (b&0xFE) | ((buf>>i)&1);
fwrite(&s, 1, 1, fout);
}
}
// copy the remainder of the file (random-pad everything though)
printf ("copying rest/adding garbage...\n" );
while ((max = fread(copybuf, 1, 1024, fp1)))
{
int i;
for (i = 0; i < 1024; i++)
copybuf[i] &= (0xFE | (rand()>>3));
fwrite(copybuf, 1, max, fout);
}
printf ("done\n" );
// clean up, such as it is
fclose (fp1);
fclose (fp2);
fclose (fout);
return 0;
}
merci a tous .
fclose (entree);
fclose (sortie);
}