You are on page 1of 7

/* 002 *@author William_Wilson 003 *@version 1.

6 004 *Created: May 8, 2007 005 */ 006 007 /* 008 *import list 009 */ 010 import java.io.File; 011 012 import java.awt.Point; 013 import java.awt.Graphics2D; 014 import java.awt.image.BufferedImage; 015 import java.awt.image.WritableRaster; 016 import java.awt.image.DataBufferByte; 017 018 import javax.imageio.ImageIO; 019 import javax.swing.JOptionPane; 020 021 /* 022 *Class Steganography 023 */ 024 public class Steganography 025 { 026 027 028 029 030 031 032 033 034 035 /* *Encrypt an image with text, the output file will be of type .png *@param path The path (folder) containing the image to 036 modify 037 *@param original *@param ext1 038 (jpg, png) 039 040 041 *@param stegan *@param message The name of the image to modify The extension type of the image to modify The output name of the file The text to hide in the image integer representing either basic or advanced /* *Steganography Empty Constructor */ public Steganography() { }

*@param type encoding 042 */

public boolean encode(String path, String original, String ext1, String stegan, String message) 044 { 043 045 046 047 048 049 050 051 052 053 054 055 /* *Decrypt assumes the image being used is of type .png, extracts 056 the hidden text from an image *@param path The path (folder) containing the image to extract the message from 058 *@param name The name of the image to extract the message from 057 *@param type integer representing either basic or advanced encoding 060 */ 059 061 062 063 064 065 066 067 public String decode(String path, String name) { byte[] decode; try { //user space is necessary for decrypting return(setImage(image,new File(image_path(path,stegan,"png")),"png")); } //user space is not necessary for Encrypting BufferedImage image = user_space(image_orig); image = add_text(image,message); String BufferedImage file_name image_orig = image_path(path,original,ext1); = getImage(file_name);

BufferedImage image = user_space(getImage(image_path(path,name,"png"))); 068 decode = decode_text(get_byte_data(image)); 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 /* *Returns the complete path of a file, in the form: path\name.ext *@param path The path (folder) of the file *@param name The name of the file } } return(new String(decode)); } catch(Exception e) { JOptionPane.showMessageDialog(null, "There is no hidden message in this image!","Error", JOptionPane.ERROR_MESSAGE); return "";

084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109

*@param ext

The extension of the file

*@return A String representing the complete path of a file */ private String image_path(String path, String name, String ext) { return path + "/" + name + "." + ext; } /* *Get method to return an image file *@param f The complete path name of the image. *@return A BufferedImage of the supplied file path *@see Steganography.image_path */ private BufferedImage getImage(String f) { BufferedImage File try { image = ImageIO.read(file); } catch(Exception ex) { file image = null; = new File(f);

JOptionPane.showMessageDialog(null, "Image could not be 110 read!","Error",JOptionPane.ERROR_MESSAGE); 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 saved *@return Returns true if the save is succesful */ private boolean setImage(BufferedImage image, File file, String ext) { try { file.delete(); //delete resources used by the File ImageIO.write(image,ext,file); /* *Set method to save an image file *@param image The image file to save *@param file File to save the image to *@param ext The extension and thus format of the file to be } } return image;

128 129 130 131 132 133

return true; } catch(Exception e) { JOptionPane.showMessageDialog(null,

"File could not be saved!","Error",JOptionPane.ERROR_MESSAGE); 134 return false; 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 /* *Handles the addition of text into an image *@param image The image to add hidden text to *@param text The text to hide in the image *@return Returns the image with the text embedded in it */ private BufferedImage add_text(BufferedImage image, String text) { //convert all items to byte arrays: image, message, message length byte img[] = get_byte_data(image); byte msg[] = text.getBytes(); byte len[] try { encode_text(img, len, 0); //0 first positiong = bit_conversion(msg.length); } }

encode_text(img, msg, 32); //4 bytes of space for length: 4bytes*8bit = 32 bits 154 } 155 156 catch(Exception e) {

157 JOptionPane.showMessageDialog(null, 158 "Target File cannot hold message!", "Error",JOptionPane.ERROR_MESSAGE); 159 160 161 162 163 /* *Creates a user space version of a Buffered Image, for editing and 164 saving bytes *@param image The image to put into user space, removes compression interferences 166 *@return The user space version of the supplied image 165 167 168 169 */ private BufferedImage user_space(BufferedImage image) { } } return image;

170 171

//create new_img with the attributes of image

BufferedImage new_img = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR); 172 Graphics2D graphics = new_img.createGraphics(); 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 /* *Gernerates proper byte format of an integer } /* *Gets the byte array of an image *@param image The image to get byte data from *@return Returns the byte array of the image supplied *@see Raster *@see WritableRaster *@see DataBufferByte */ private byte[] get_byte_data(BufferedImage image) { WritableRaster raster = image.getRaster(); DataBufferByte buffer = (DataBufferByte)raster.getDataBuffer(); return buffer.getData(); image return new_img; } graphics.drawRenderedImage(image, null); graphics.dispose(); //release all allocated memory for this

*@param i The integer to convert *@return Returns a byte[4] array converting the supplied integer 196 into bytes 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 //only using 4 bytes byte byte3 = (byte)((i & 0xFF000000) >>> 24); //0 byte byte2 = (byte)((i & 0x00FF0000) >>> 16); //0 byte byte1 = (byte)((i & 0x0000FF00) >>> 8 ); //0 byte byte0 = (byte)((i & 0x000000FF) ); //{0,0,0,byte0} is equivalent, since all shifts >=8 will be 0 return(new byte[]{byte3,byte2,byte1,byte0}); */ private byte[] bit_conversion(int i) { //originally integers (ints) cast into bytes //byte byte7 = (byte)((i & 0xFF00000000000000L) >>> 56); //byte byte6 = (byte)((i & 0x00FF000000000000L) >>> 48); //byte byte5 = (byte)((i & 0x0000FF0000000000L) >>> 40); //byte byte4 = (byte)((i & 0x000000FF00000000L) >>> 32);

213 214 215

/* *Encode an array of bytes into another array of bytes at a 216 supplied offset 217 218 219 array *@param image Array of data representing an image *@param addition Array of data to add to the supplied image data

*@param offset The offset into the image array to add the addition data 220 *@return Returns data Array of merged image and addition data 221 */ private byte[] encode_text(byte[] image, byte[] addition, int 222 offset) 223 224 225 226 227 228 229 230 231 232 233 { //check that the data + offset will fit in the image if(addition.length + offset > image.length) { throw new IllegalArgumentException("File not long enough!"); } //loop through each addition byte for(int i=0; i<addition.length; ++i) { //loop through the 8 bits of each byte

int add = addition[i]; for(int bit=7; bit>=0; --bit, ++offset) //ensure the new 234 offset value carries on through both loops 235 236 237 238 239 { //assign an integer to b, shifted by bit spaces AND 1 //a single bit of the current byte int b = (add >>> bit) & 1;

//assign the bit by taking: [(previous byte value) AND 0xfe] OR bit to add //changes the last bit of the byte in the image to be 240 the bit of addition 241 242 243 244 245 246 247 248 249 250 251 252 /* *Retrieves hidden text from an image *@param image Array of data, representing an image *@return Array of data which contains the hidden text */ private byte[] decode_text(byte[] image) } image[offset] = (byte)((image[offset] & 0xFE) | b ); } } return image;

253 254 255 256 257

{ int length = 0; int offset = 32; //loop through 32 bytes of data to determine text length

for(int i=0; i<32; ++i) //i=24 will also work, as only the 4th byte contains real data 258 { 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 } } AND 1] result[b] = (byte)((result[b] << 1) | (image[offset] & 1)); } } return result; //loop through each byte of text for(int b=0; b<result.length; ++b ) { //loop through each bit within a byte of text for(int i=0; i<8; ++i, ++offset) { //assign bit: [(new byte value) << 1] OR [(text byte) byte[] result = new byte[length]; length = (length << 1) | (image[i] & 1); }

You might also like