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 ?>