1 <?php
  2
  3 /** ************************************************** **/
  4 /*** Proposition d'un scrit PHP sur la stéganographie ***/
  5 /** ************************************************** **/
  6
  7 /* On suppose que l'image qui cache, et l'image cachée ont les mêmes dimensions */
  8
  9 /** Cacher une image dans une autre **/
 10
 11 /* Récupérer le type mime d'une image */
 12 function getMIMEType($picPath) {
 13         if(function_exists('finfo_open')) {
 14                 $finfo = finfo_open(FILEINFO_MIME);
 15                 $mime = finfo_file($finfo, $picPath);
 16                 finfo_close($finfo);
 17                 return $mime;
 18         }
 19         elseif(function_exists('mime_content_type')) {
 20                 return mime_content_type($picPath);
 21         }
 22         else{
 23                 /* Sinon, on utilise une fonction système */
 24                 $picPath = str_replace(' ', '\ ', $picPath);
 25                 return system("file -i $picPath");
 26         }
 27 }
 28
 29 /* Récupérer la taille de l'image */
 30 function picHeight($res) {
 31         return imagesy($res);
 32 }
 33
 34 function picWidth($res) {
 35         return imagesx($res);
 36 }
 37
 38 /* Créer une resource à partir d'une image */
 39 function fromPicture($path) {
 40
 41         $mime = getMIMEType($path);
 42         
 43         if( strpos($mime, 'image/jpeg') !== false) {
 44                 return fromJPEG($path);
 45         }
 46         elseif( strpos($mime, 'image/png') !== false ) {
 47                 return fromPNG($path);
 48         }
 49         elseif( strpos($mime, 'image/gif') !== false ) {
 50                 return fromGIF($path);
 51         } 
 52         
 53         return false;
 54 }
 55
 56 function fromPNG($path) {
 57         return @imagecreatefrompng($path);
 58 }
 59
 60 function fromJPG($path) {
 61         return @imagecreatefromjpeg($path);
 62 }
 63
 64 function fromJPEG($path) {
 65         return @imagecreatefromjpeg($path);
 66 }
 67
 68 function fromGIF($path) {
 69         return @imagecreatefromgif($path);
 70 }
 71
 72 /* Créer une resource "true color" */
 73 function trueColor($width, $height) {
 74         return  imagecreatetruecolor($width, $height);
 75 }
 76
 77 /* Cacher l'image dans une autre */
 78 function steganoHide($picFinal, $picToDisplay, $picToHide) {
 79         /* On parcoure chaque pixel avec 2 boucles imbriquées */
 80         for($x=0; $x< picWidth($picFinal); $x++) {
 81                 for($y=0; $y< picHeight($picFinal); $y++) {
 82                         
 83                         /* Extraction des bits "visibles" */
 84                         $dispColor = deleteColorLowBits(getPixelColor($picToDisplay, $x, $y));
 85
 86                         /* Extraction des bits "cachés" */
 87                         $hideColor = deleteColorHighBits(getPixelColor($picToHide, $x, $y));
 88                         
 89                         /* Superposition des bits */
 90                         $color = joinColorBits($dispColor, $hideColor);
 91                         
 92                         /* On ajoute le pixel à la nouvelle image */
 93                         $color = imagecolorallocate($picFinal, (($color >> 16) & 0xFF), (($color >> 8 ) & 0xFF), ($color & 0xFF));
 94                         imagesetpixel($picFinal, $x, $y, $color);
 95                         
 96                 }
 97         }
 98         
 99         return $picFinal;
100 }
101
102 /* Récupérer l'image cachée */
103 function steganoDisplay($resFinal, $resHiddenPic) {
104         for($x=0; $x< picWidth($resFinal); $x++) {
105                 for($y=0; $y< picHeight($resFinal); $y++) {
106                         /* On supprime les bits de poids fort, c'est une autre manière de réaliser la fonction deleteColorHighBits */
107                         $color = (getPixelColor($resHiddenPic, $x, $y) << 4);
108                         $color = imagecolorallocate($resFinal, (($color >> 16) & 0xFF), (($color >> 8 ) & 0xFF), ($color & 0xFF));
109                         imagesetpixel($resFinal, $x, $y, $color);
110                 }
111         }
112         
113         return $resFinal;
114 }
115
116 /* Enregistrement de l'image (vérifiez les droits d'accès...) au format PNG
117 0 <--- qualité --- compression ---> 9 */
118 function recordPNGPic($picRes, $path, $quality = 0, $filters = PNG_NO_FILTER ) { 
119         imagepng($picRes, $path, $quality, $filters);
120 }
121
122 /* On récupère la couleur d'un pixel */
123 function getPixelColor($res, $x, $y) {
124         return imagecolorat($res, $x, $y);
125 }
126
127 /* On applique un filtre pour supprimer les bits de poids faible */
128 function deleteColorLowBits($intColor) {
129         return ($intColor & 0xF0F0F0);
130 }
131
132 /* On applique un filtre pour supprimer les bits de poids fort */
133 function deleteColorHighBits($intColor) {
134         return ($intColor & 0x0F0F0F);
135 }
136
137 /* On superpose les 2 couleurs */
138 function joinColorBits($intColor1, $intColor2) {
139         return ($intColor1 | $intColor2);
140 }
141
142 /* Créer une image PNG cachant une autre image et l'enregistrer sur le disque */
143 function generatePNGSteganoPicture($imToHide, $imToDisp, $pathToRecord) {
144         $resPicToHide = fromPicture($imToHide);
145         $resPicToDisplay = fromPicture($imToDisp);
146         $resPicFinal = trueColor(picWidth($resPicToDisplay), picHeight($resPicToDisplay));
147
148         recordPNGPic( steganoHide($resPicFinal, $resPicToDisplay, $resPicToHide) , $pathToRecord);
149 }
150
151 /* Créer une image PNG semblable à celle qui a été cachée, et l'enregistrer sur le disque */
152 function generatePNGSteganoPictureReverse($steganoPicture, $pathToRecord) {
153         $resSteganoPicture = fromPicture($steganoPicture);
154         $resPicFinal = trueColor(picWidth($resSteganoPicture), picHeight($resSteganoPicture));
155
156         recordPNGPic( steganoDisplay($resSteganoPicture, $resSteganoPicture) , $pathToRecord);
157 }
158
159 /** Cacher une image **/
160 /* L'image à cacher */
161 $imToHide = 'imageACacher.png';
162
163 /* L'image qui cachera l'image à cacher */
164 $imToDisp = 'iMageQuiCachera.jpg';
165
166 /* Le nom de l'image finale */
167 $steganoRecordPath ='stegano.png';
168
169 /** ************************************************** **/
170 /** ****** On lance donc la création de l'image ****** **/
171 generatePNGSteganoPicture($imToHide, $imToDisp, $steganoRecordPath);
172 /** ************************************************** **/
173 /** ************************************************** **/
174
175
176 /** Récupérer une image cachée **/
177 /* L'image contenant une autre image */
178 $steganoPicture = 'stegano.png';
179
180 /* L'image qui a été cachée et qui est maintenant découverte */
181 $imUnhide = 'steganoReverse.png';
182
183 /** ************************************************** **/
184 /** ****** On lance donc la création de l'image ****** **/
185 generatePNGSteganoPictureReverse($steganoPicture, $imUnhide);
186 /** ************************************************** **/
187 /** ************************************************** **/
188
189 ?>