Annonce

Réduire
Aucune annonce.

[JAVA] STEGANO Cacher du texte dans les LSB/MSB d'une Image

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • [JAVA] STEGANO Cacher du texte dans les LSB/MSB d'une Image

    STEGANO LSB/MSB



    Introduction:
    Bonjour à tous ! Aujourd'hui nous allons voir comment utiliser les LSB et MSB d'une image pour cacher du texte dans une image. Ce tutoriel est réalisé en Java, mais avec un peu d'imagination il peut être reproduit dans n'importe quel langage.
    Je suis pour ma part loin d'être un expert en Java, donc si vous trouvez des erreurs qui ne m'auront pas nécessairement sautées aux yeux, c'est normal.



    Présentation théorique:
    Avant de s'attaquer à la pratique, penchons nous sur la théorie, puisque recopier le code qui va suivre sans en comprendre le fonctionnement serait un peu dommage. Ceux qui connaissent déjà les termes que nous allons aborder peuvent sauter à la partie pratique.

    Pour commencer : Comment ça marche une couleur?
    Vulgairement une couleur c'est un composé de 3 couleurs, le Rouge, le Vert et le Bleu, chacun représentés par un octet. Chaque image sur votre ordinateur est composée de millions de trios de rouge, de vert et de bleu, chaque trio représente un pixel. Chaque partie d'une couleur étant présente sous forme d'octet. On reviendra sur les détails techniques plus loin.


    Ensuite : LSB/MSB késaco ?
    LSB => Least Significant Bit.
    MSB => Most Significant Bit.
    Qu'on traduit en français par Bit de Poids Faible et Bit de Poids Fort. Autant dire que ça nous avance beaucoup...


    On voudrait bien éviter la longue et douloureuse explication d'informatique théorique pour aller directement à ce qui nous intéresse mais on va quand même se la faire ^^.

    Classiquement vous avez déjà tous vu un octet, ou au moins vous avez une vague notion de ce que c'est.
    Mais si cette jolie suite de 0 et de 1 qu'on voit partout à la télé dès qu'un mec avec des lunettes pirate la NASA avec son 3310 "branché" à son micro ondes en infrarouge.

    Pour ceux ayant raté cette incroyable scène de l'histoire du cinéma, ceci par exemple est un Octet : 01001101 !
    Il n'est pas franchement beau à voir, il parle difficilement notre langue, mais il est gentil et il va nous aider le long de ce tutoriel. On va l'appeler Bob



    Bob, comme tous les octets, est divisé en huit chiffres ayant soit la valeur 1 soit la valeur 0, et représente un chiffre entre 0 et 255. Mais comment me direz-vous?

    Tout simplement en fait, chaque 0 ou 1 représente une puissance de 2 allant de 0 à 7 en fonction de son emplacement dans l'octet, ce sont les bits (pas la peine de tenter une vanne sur le nombre de bits de Bob, la langue française en à fait le tour il y a un bon moment ).



    Prenons [Bob et calculons sa valeur:
    0 1 0 0 1 1 0 1 ce qui nous donne 0(2^7)+64(2^6)+0(2^5)+0(2^4) +8(2^3)+4(2^2)+0(2^1)+1(2^0) = 77

    Et c'est là qu'on en vient à ce qui nous intéresse !!! Car on vient de croiser innocemment nos amis MSB et LSB !
    Ils sont seuls et sans défense le long d'une route de campagne abandonnée et notre dernière poupée gonflable vient de rendre l'âme. Et dans ce tutoriel nous allons littéralement les retourner comme des gants ^^

    Donc pour ceux qui n'ont pas saisie la signification de LSB et MSB, je vais gentiment vous mettre des couleurs et on recommence ! Donc suivez bien, le LSB est en vert et le MSBen rouge :
    0 1 0 0 1 1 0 1


    Voilà ! Ceux qui ont suivi l'histoire des puissances de 2 devraient commencer à faire le lien entre les appellations de ces pauvres bits et ce que l'on vient de voir. En effet le MSB vaut 2^7, soit 128, ce qui fait que sa valeur à beaucoup d'importance dans la valeur de l'octet, il est signifiant. Et le LSB vaut 2^0, soit 1, ce qui fait qu'il vaut presque que dalle, il est triste et suicidaire, il est insignifiant.

    Pour rester dans les couleurs je vous donne un petit exemple en changeant la valeur du MSB.
    En considérant notre fidèle Bob comme le Rouge d'une couleur, et on va choisir arbitrairement dans le public deux autres octets pour gentiment jouer le Vert et le Bleu.

    Applaudissez bien fort Alice 1001 1110 et Jack 0000 0001.
    On se retrouve donc avec une couleur ayant pour valeurs 77, 158 et 1. Ce qui nous donne ce magnifique vert dégueulasse


    Or si on s'amuse à faire de la chirurgie esthétique sur le MSB de notre ami Bob, pour qu'il devienne un 1, Bob devient 11001101, et notre vert dégueulasse devient un un magnifique jaune dégueulasse.

    Autant dire que ça se voit beaucoup, et que si on s'amuse à péter la gueule d'un millions de MSB dans un photo de Clara Morgane on va rapidement se retrouver avec un monstre fluo sur l'image.

    Mais en revanche, si on laisse le MSB tranquille, et qu'on s'acharne sur son pote que personne n'aime, le LSB, ça devient totalement différent.
    Le LSB de Bob était à 1, passons le à 0 et observons ce qu'il advient de notre trio. SURPRISE ! On retrouve notre vert dégueulasse !
    Et en fait, pas du tout, l’œil humain est persuadé qu'il s'agit du même vert, mais il y a une différence. Ceci nous prouvant bien que tout le monde s'en foutait du pauvre petit LSB.


    Et ceux qui se demandaient jusque là pourquoi je passais trois plombes à vous présenter la chose, commencent à saisir l'intérêt de tout ce fatras !

    Parce que si personne ne remarque la présence ou non du petit LSB, peut-être qu'on peut s'en servir nous, pour par exemple...dissimuler des informations !

    Car à l'instar des couleurs, le texte aussi est écrit en octets, ce qui avouons-le, est vachement pratique (et surtout logique). Sans oublier que là, on a touché qu'au rouge du trio Bob, Alice et Jack. Mais si nous jouons avec les LSB de tout le trio, on peut cacher trois bits dans chaque couleur, même quatre si on appelle Franck, notre gentil canal Alpha dont le but est de gérer la transparence et de faire des photomontages bien pourris.

    Explications: Imaginons que nous voulons cacher la lettre M dans le LSB du rouge d'une suite de couleurs. On sait que M dans les normes ASCII est égal à 77 soit la valeur exacte de notre ami Bob avant qu'on vienne jouer avec ses bits. On veut donc dissimuler Bob (01001101) dans les LSB de 8 couleurs différentes.
    Prenons une série de rouges au hasard et en ignorant le reste des couleurs:
    0001 0000
    0001 0000
    0010 1001
    0010 1001
    1010 1111
    1010 1110
    1110 0110
    1110 0110
    0011 0010
    0011 0011
    1001 1111
    1001 1111
    0000 1001
    0000 1000
    0101 0100
    0101 0101
    On voit bien Bob apparaitre en gras dans cette série de rouges, si on y ajoutait autant de séries de bleu et de vert, on se retrouverait avec une ligne de pixels bien moches. Mais dans le cas d'une photo, personne ne verrait la différence entre cette série de rouge
    Notre ami Bob a donc été dissimulé dans cette suite de 8 couleurs sans le moindre problème, et on a donc notre L dissimulé dans 8 pixels sur une image. Enfin ça c'est en théorie, dans les faits vous avez juste huit octets sous les yeux et vous vous demandez sérieusement ce que vous foutez encore là

    Et bien là réponse est simple, car nous allons voir maintenant comment faire en sorte de cacher des milliers de Bob (notre texte) dans des millions de Alice, Jack et compagnie (nos pixels). Vous avez deviné, nous passons maintenant à


    La Pratique !

    Nous allons donc maintenant voir comment mettre toutes ces informations en pratique, afin d'ouvrir une image, d'en modifier tous les LSB et MSb qu'on veut pour cacher notre texte avant de l’enregistrer.
    Avant de commencer je tiens à préciser qu'il existe évidement des façons mieux optimisées de faire la même chose, en utilisant moins de variables et en s'épargnant des étapes, mais vu que ceci est un tutoriel j'essaie surtout de faire en sorte que le code soit compréhensible.
    J'ai fait en sorte que le code soit le plus lisible possible et commenté de façon claire et précise, donc ça devrait aller, mais je vais quand même vous accompagner dans la lecture du code ^^

    Pour commencer on va assumer que vous savez créer un nouveau projet sur Eclipse, avec une nouvelle classe Main pour lancer le tout. Si ce n'est pas le cas, renseignez vous et revenez dans quinze secondes


    Commençons par créer notre classe ainsi que son constructeur, que l'on va sobrement baptiser LessAndMostSignificantBitStegano, ce qui est relativement explicite comme nom de classe :
    Code:
    public class LessAndMostSignificantBitStegano{
    
    	public BufferedImage ImgToSave; // L'image que l'on enregistrera une fois le traitement terminé
    	public BufferedImage ImgToLoad; // L'image que l'on va utiliser comme support
    	public Color[][] Pixels;        // Le magnifique tableau qui va contenir les couleurs à traiter
    	public String TextToEncrypt;    // Notre texte en clair
    	public String Datas;            // Notre texte sous forme d'octets
    	
    	public LessAndMostSignificantBitStegano()
    	{
                TextToEncrypt="Je suis un texte destiné à être dissimulé";
    	    Datas = CastStringToBitArray(TextToEncrypt); 
                Initialize("Capture.png");
    	   
    	    if(ImgToSave!=null) 
    		{
    			SetPixels();
    		}
    	    else
    		{
    			System.out.println("Ce programme vient de se vautrer");
    		}
                Action("imageFinale.png");
             }
    
            public void Initialize(String imageToLoadName)
    	 {
    		//Du très classique, on charge l'image dans ImgToLoad et on initialise ImgToSave aux bonnes dimensions
    		ImgToLoad = null;
    		try {
    			ImgToLoad = ImageIO.read(new File(imageToLoadName));
    		} catch (IOException e) {
    			
    			e.printStackTrace();
    		}
    		if(ImgToLoad != null)
    		{
    			ImgToSave = new BufferedImage(ImgToLoad.getWidth(), ImgToLoad.getHeight(), BufferedImage.TYPE_INT_ARGB);  
    			
    		}
    		else
    		{
    			System.out.println("Erreur chargement image");
    			
    		 }
    		
    		
    	 }
    
             public void SetPixels()
    	{
    		/* Et là on se contente de mettre CHAQUE pixel de l'image source dans un tableau de couleurs histoire des les avoir  sous la main quand on voudra jouer avec leur bit de poids faible*/
    		Pixels = new Color[ImgToLoad.getWidth()][ImgToLoad.getHeight()];
    		for(int i=0; i<ImgToLoad.getWidth();i++)
    		{
    			for(int j=0; j<ImgToLoad.getHeight();j++)
    			{
    				Pixels[i][j] = new Color(ImgToLoad.getRGB(i, j));
    			}
    		}
    	}
    Okay faisons un petit debriefing de ce que nous venons de voir. Déjà les développeurs expérimentés doivent tirer une tronche de 8 pieds de long, vu qu'ils voient débarquer des fonctions dont on ignore tout. Ne vous inquiétez pas, on y arrive ^^
    Nous n'allons pas nous attarder sur Initialize et SetPixels, ces deux fonctions se contentent d'initialiser nos variables.

    Nous avons donc deux fonctions inconnues qui sont respectivement CastStringToBitArray(), et Action(). Fort heureusement leurs noms sont assez explicites, mais voici leur présentation en détail :

    Code:
    public String CastStringToBitArray(String stringToCast)
    	{
    		/*ici rien de bien compliqué, on se content de mettre la valeur en octet de chaque lettre dans une chaine de         caractères, aussi nommé String en java.*/
    		String conv= new String();
    		
    		for(int i=0; i<stringToCast.length();i++)
    		{
    
    			conv+=String.format("%8s", Integer.toBinaryString((byte)stringToCast.charAt(i) & 0xFF)).replace(' ', '0');
    			
    		}
    		return conv;
    	}
    Bon là vous devriez gueuler un peu, parce que merde quoi, ça veut rien dire:
    conv+=String.format("%8s", Integer.toBinaryString((byte)stringToCast.charAt(i) & 0xFF)).replace(' ', '0');
    Et en plus c'est moche, mais au moins vous devriez comprendre étape par étape comment on transforme la lettre en octet. En fait c'est tout con:
    - on prend notre ième caractère dans la chaine à transformer en octet
    - on le cast en byte/octet (qui connement en java est un entier compris entre 0 et 255, ce qui nous arrange pas)
    - donc tout aussi connement on le convertit en huit 0 et 1 (sauf que connement en java il remplace les zéros par des espaces)
    - donc toujours aussi connement on remplace les espaces par des 0 et on balance ce groupe de huit 0 et 1 à la suite de la chaine de caractères qu'on retourne à la fin

    Dans les faits, après ce traitement notre chaine est devenue une longue série de Bob : 0100101001100101001000000111001101110101011010010111001100100000011101010110111000100000011101000110 0101011110000111010001100101001000000110010001100101011100110111010001101001011011101110100100100000 1110000000100000111010100111010001110010011001010010000001100100011010010111001101110011011010010110 1101011101010110110011101001

    Et vu que nous sommes très paranoïaque nous allons cacher ces 328 bits dans 328 couleurs différentes, plus précisément dans le rouge de 328 pixels différents sur notre image.

    Passons maintenant à la fonction Action() !

    Code:
            public void Action(String nomFichierToSave)
    	{
    		int incrChar=0;
    		
    		for(int i=0; i<Pixels.length;i++)
    		{
    			for(int j=0; j<Pixels[i].length;j++)
    			{
    				if(incrChar<Datas.length())
    				 {
    					/* tant qu'on a pas utilisé toute notre chaine on répète l'opération*/
    						System.out.println("Le pixel rentre et vaut sa valeur Red = "+Pixels[i][j].getRed());
    						
    
    						Pixels[i][j] =LSBOnRed(Datas.charAt(incrChar),Pixels[i][j]);
    						//On change la valeur Red avec celle de notre chaine de bits
    						System.out.println("Le pixel sort et vaut "+Pixels[i][j].getRed());
    						incrChar++;
    					
    				}
                                     /*dès qu'on a fini on mets le reste des pixels de l'image*/
    				ImgToSave.setRGB(i, j, Pixels[i][j].getRGB());
    			}
    		}
    		try {
    			ImageIO.write(ImgToSave, "png", new File(nomFichierToSave)); //Et on sauvegarde l'image
    		} catch (IOException e) {
    			
    			e.printStackTrace();
    		}
    	}
    Et encore une fois certains doivent se demander d'où sors cette fonction Pixels[i][j]=LSBOnRed(Datas.charAt(incrChar),Pixels[i][j]). On va y revenir très vite !
    Donc là on voit bien qu'Action() se contente de parcourir tous les pixels de notre tableau, d'effectuer l'opération sur le LSB du rouge de chaque pixel et puis de remplir l'image avec le reste. Une fois l'opération terminée il sauvegarde notre image.

    Maintenant venons à l'opération la plus importante, celle à la base de ce tuto, la fonction LSBonRed(), qui prend en argument le bit à écrire et la couleur à modifier puis nous retourne la couleur avec le LSB modifié. A cause de la portée des variables en Java nous
    sommes obligé de réaffecter dans la foulée notre Pixel[i][j], cela étant on aurait très bien pu utiliser une couleur temporaire .

    Concentrons nous maintenant sur cette fonction miracle :

    Code:
            public Color LSBOnAlpha(char currbit, Color curpixel)
    	{
    		
    		
    		if(currbit%2==0) //on teste si le bit entré vaut 0 ou 1
    		{
    			//si la valeur a entrer vaut 0 et que le LSB de la cible vaut 1 on le modifie, sinon on ne fait rien
    			
    			 if(curpixel.getRed()%2==1) // on teste si le LSB du rouge vaut 0 et ou 1
    			 {
    				
    				 Color temp= curpixel;
    				 curpixel = new Color(temp.getRed()-1, temp.getGreen(), temp.getBlue(), temp.getAlpha());
    				
    			 }
    		}
    		else
    		 {
    			//si la valeur a entrer vaut 1 et que le LSB de la cible vaut 0 on le modifie, sinon on ne fait rien
    			
    			if(curpixel.getRed()%2==0)
    			{
    				Color temp= curpixel;
    				curpixel = new Color(temp.getRed()+1, temp.getGreen(), temp.getBlue(), temp.getAlpha());
    				
    			}
    		}
    		Color temp = curpixel;
    		return temp;
    	}
    On remarquera que dans 50 % des cas on ne fait rien, car la valeur cible valant soit 0, soit 1, on a 50% de chances d'avoir la bonne valeur d'entrée de jeu, si c'est pas pratique ça !
    Ceux qui ne connaissent pas l'opérateur modulo (%) doivent se poser une question ou deux. En réalité c'est très simple. Tout nombre est soit pair ou impair, or le bit cible vaut en théorie soit 2^0 soit 0. Ce qui fait qu'à l'échelle du nombre c'est lui qui détermine si ce dernier est pair ou impair.

    Donc si notre Red est impair son LSB vaut 1, sinon 0. Et pour le modifier on a donc juste à ajouter ou soustraire 1.
    Et vu que tout octet pair à forcément une valeur comprise entre 0 et 254 on n'a aucun risque à lui ajouter 1 pour le rendre impair. De même tout octet impair est compris entre 1 et 255 donc aucun problème non plus à lui soustraire 1.
    Alors que si on se contentait d'ajouter 1 à chaque fois, on aurait un léger risque d'atteindre 256, ce qui pourrait éventuellement faire planter la machine (après j'ai pas testé peut être cela fait-il juste apparaitre une Megan Fox en bikini sur votre canapé).
    Le problème est similaire en cas de soustraction systématique.


    Et voilà avec ça vous avez de quoi cacher du texte dans une image. Ce qui ne nous sert absolument à rien... si on a pas ce qu'il faut pour récupérer le texte

    Voici donc le code et les fonctions qui font le travail inverse :
    Code:
            public char UnLSBR(Color curpixel)
    	{
    		System.out.println(curpixel.getRed() +"valeur en entrée ");
    		 char bit='0';
    		
    		if(curpixel.getRed()%2==1)
     		{
    			 bit='1';
    		 }
    		
    		System.out.println("Char retourné = "+bit);
    		return bit;
    	}
    
            public String CastBitArrayToString(String bitArrayToCast)
    	{
    		String resultat="";
    		String[] temp  = bitArrayToCast.split("(?<=\\G........)");
    		
    		System.out.println(temp[0].length());
    		for(int i=0; i<temp.length;i++)
    		{
    			resultat+=(char)Byte.parseByte(temp[i], 2);
    		}
    		
    		return resultat;
    	}
            public String Decode()
           {
               String decode="";
               for(int i=0; i<1;i++)
    		{
    			for(int j=0; j<Datas.length();j++)
    			{
    				
    				decode+=UnLSBR(new Color(ImgToLoad.getRGB(i, j)));
    			}
    		}
    		
    		return Decode;
           }

    Et là c'est super simple, vous effectuez un System.out.println(CastBitArrayToString(Decode())); et vous avez votre texte en clair.
    Niveau explications il n'y a rien de bien compliqué :
    - On traite chaque pixel de l'image (ici j'ai mis directement la longueur de la chaine vu que je la connais)
    - S'il est pair on ajoute un 0 à notre chaine de bit sinon on ajoute un 1
    - La fonction CastBitArrayToString découpe la chaine en morceaux de 8 bits via une expression régulière bien moche (bitArrayToCast.split("(?<=\\G........)") et fait la conversion en lettres
    - On affiche le tout à la fin !


    Et voilà, vous avez tout ce qu'il vous faut à votre disposition. A partir de là de nombreuses possibilités s'offrent à vous, comme le fait de crypter le message avant, de répartir les bits encodés suivant une suite prédéfinie, de les mettre alternativement dans le rouge puis le bleu, puis le vert etc. Vous pouvez aussi faire le programme en fenêtré, faire une version pour android, ou que le mettre sur le système embarqué des A380 si vous bossez chez airbus ^^
    Je déconseilles l'utilisation du canal alpha si l'image n'a pas de transparence à l'origine, sinon ça va se voir énormément.

    Et en bonus je vous met le code pour le MSB (vous pouvez essayer, vous allez voir ça fait des jolis pixels fluos partout ^^), après libre à vous de le modifier pour qu'il rende toutes les images en noir et blanc, ce qui le rendrait moins détectable à l'oeil nu.

    Code:
            public Color MSBOnAlpha(char currbit, Color curpixel)
    	{
    		/*
    		Meme système que pour le lsb ou presque.
    		Si le bit a écrire vaut 0 on teste si le Red est divisble par 128 
    		(donc que le bit cible est à 1), si c'est le cas on le met à 0
    		 (on enlève 128), sinon on laisse comme tel
    		*/
    		
    		if(currbit%2==0)
    		{
    			
    			
    			if(curpixel.getRed()>=128)
    			{
    				
    				Color temp= curpixel;
    				curpixel = new Color(temp.getRed()-128, temp.getGreen(), temp.getBlue(), temp.getAlpha());
    				
    			}
    		}
    		else
    		{
    			
    			if(curpixel.getRed()<128)
    			{
    				Color temp= curpixel;
    				curpixel = new Color(temp.getRed()+128, temp.getGreen(), temp.getBlue(), temp.getAlpha());
    				
    			}
    		}
    		Color temp = curpixel;
    		return temp;
    	}
    
            public char UnMSBR(Color curpixel)
    	{
    		System.out.println(curpixel.getRed() +"valeur en entrée ");
    		char bit='0';
    		
    		if(curpixel.getRed()>=128)
    		{
    			bit='1';
    		}
    		
    		System.out.println("Char retourné = "+bit);
    		return bit;
    	}
    Dernière modification par reader117, 28 juillet 2014, 16h11.

  • #2
    Salut reader117,

    Tout d'abord, merci pour ce petit tuto sur le lsb/msb ça faisait longtemps qu'on en avait pas parlé ! Bon, j'ai pas tout lu mais je le ferai un peu plus tard. J'ai vu que les scripts étaient en Java, un langage pour lequel j'éprouve la plus grande affection comme beaucoup le savent ici... Donc du coup ça pourrait être sympa de le
    - porter en python et en C, C++.
    Ca pourrait d'ailleurs faire l'objet d'un exercice un peu plus poussé que fred pourrait intégrer à ses cours. Par la même, s'il est porté en python,
    - nous pourrions l'intégrer à Cyprium
    (à voir dans le footer du site). De plus, la
    - fonction d'importation/extraction d'image (une image dans une image) et la
    - fonction d'importation/extraction de son (du son dans du son) ainsi que
    - les fonctions parallèles.

    Candy tue ?
    sigpic

    Cyprium Download Link

    Plus j'étudie plus j'me rends compte que je n'sais rien.

    †|

    Commentaire


    • #3
      Merci beaucoup enorme ce tutoriel et surtout super bien expliquer. Je suis un débutant S en steno et crypto et la c'est que du bonheur.
      J'espère qu'il y en aura d'autres même sur crypto si tu peux car cela m'interresse beaucoup de m'améliorer.
      Dernière modification par DreAmuS, 28 juillet 2014, 17h08.

      Commentaire


      • #4
        Envoyé par SAKAROV Voir le message
        Salut reader117,

        Tout d'abord, merci pour ce petit tuto sur le lsb/msb ça faisait longtemps qu'on en avait pas parlé ! Bon, j'ai pas tout lu mais je le ferai un peu plus tard. J'ai vu que les scripts étaient en Java, un langage pour lequel j'éprouve la plus grande affection comme beaucoup le savent ici... Donc du coup ça pourrait être sympa de le
        - porter en python et en C, C++.
        Ca pourrait d'ailleurs faire l'objet d'un exercice un peu plus poussé que fred pourrait intégrer à ses cours. Par la même, s'il est porté en python,
        - nous pourrions l'intégrer à Cyprium
        (à voir dans le footer du site). De plus, la
        - fonction d'importation/extraction d'image (une image dans une image) et la
        - fonction d'importation/extraction de son (du son dans du son) ainsi que
        - les fonctions parallèles.

        Candy tue ?
        Ouaip pour Cyprium j'avais vu que la partie LSB était vide. Pour une conversion python/C++ je suis pas contre, le temps que je m'y remette et j’essaierai de faire ça.
        Pour l'image dans l'image, aucun problème c'est basiquement le même code. Pour le son je regarderais. Les fonctions parallèles ? Je vois pas ce que t'entends par là.
        Après je pense qu'il y a moyen de faire une façon plus propre mais beaucoup moins facile à lire, en se contentant de faire de la manipulation bit à bit sans se soucier du type de fichier, mais je dis ça je suis pas du tout allé voir ce que ça donnait de ce coté.

        Au passage si quelqu'un connait un bon lien pour expliquer la théorie derrière le LSB enhancement et les attaques chi square, j'ai pas encore trouvé de bon lien qui se contente pas de lancer des tools.

        @Dreamus Merci beaucoup, je suis content que le tuto plaise et soit accessible, j'ai fait de monm mieux. Pour les tutos sur la crypto ou autre c'est une bonne idée !

        Commentaire


        • #5
          Bon vu que l'edit se bloque après 24 heures apparemment, voici le code pour transformer une image en chaine de bits :

          Code:
          public String CastPictureToBitArray(String fileToLoadPath)
          	{
          		String resultat="";
          		BufferedImage imageToLoad =null;
          		try {
          			imageToLoad = ImageIO.read(new File(fileToLoadPath));
          		} catch (IOException e) {
          			
          			e.printStackTrace();
          		}
          		
          		try {
          			for(int i =0; i< imageToLoad.getWidth();i++)
          			{
          				for(int j=0; j< imageToLoad.getHeight();j++)
          				{
          					Color temp = new Color(imageToLoad.getRGB(i, j));
          					resultat+=String.format("%8s", Integer.toBinaryString((byte)temp.getRed() & 0xFF)).replace(' ', '0');
          					System.out.println(temp.getRed()+" "+String.format("%8s", Integer.toBinaryString((byte)temp.getRed() & 0xFF)).replace(' ', '0'));
          				}
          			}
          		} catch (Exception e) {
          			// TODO: handle exception
          		}
          		
          		
          		return resultat;
          	}
          Je l'ai fait en 30 secondes, donc il y a peut être un ou deux trucs moches, mais ça fonctionne très bien, après il y a juste à changer la ligne
          Code:
          Datas = CastStringToBitArray(TextToEncrypt);
          par
          Code:
          Datas = CastPictureToBitArray("test.png");
          Et évidement il vaut mieux s'assurer que l'image à coder soit beaucoup plus petite que la cible, ou en noir et blanc. A la limite il est possible de modifier le code d'Action() pour qu'il agrandisse l'image cible, mais là on rentre dans des considérations plus pointues.

          Commentaire


          • #6
            Envoyé par reader117
            Les fonctions parallèles ? Je vois pas ce que t'entends par là.
            e.g. du texte dans du son
            (fonctions transversales aurait peut-être été plus parlant)
            sigpic

            Cyprium Download Link

            Plus j'étudie plus j'me rends compte que je n'sais rien.

            †|

            Commentaire

            Chargement...
            X