Sei sulla pagina 1di 20

//Steg.

h
Designed and Implementation: Renjith G

/********************** header file*************************/


#define BUFSIZE 1024 //512
#define DATASIZE 64
#define STARTBYTE 64

/************type definition***********************/
/* typedefs */
typedef unsigned char UBYTE;

/***********struture definition********************/
struct steg_header
{
unsigned long datalen;
char key[10];
};

struct BMPFILEHEADER
{
unsigned char bfType; //2 Bitmap identifier. Must be 'BM'.
unsigned int bfSize; //4 Can be set to 0 for for uncompressed bitmaps, which is the kind we have.
short int bfReserved1;//2 Set to 0.
short int bfReserved2;//2 Set to 0.
unsigned int bfOffbits; //4 Specifies the location (in bytes) in the file of the image data.
// For our 8-bit bitmaps, this will be sizeof(BITMAPFILEHEADER) +
//sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * numPaletteEntries.
};

struct BMPINFOHEADER
{
unsigned int biSize; //4 This is the size of the BMPINFOHEADER structure. Thus, it is
//sizeof(BITMAPINFOHEADER).
unsigned int biWidth; //4 The width of the bitmap, in pixels.
unsigned int biHeight; //4 The height of the bitmap, in pixels.
short int biPlanes; //2 Set to 1.
short int biBitCount; //2 The bit depth of the bitmap. For 8-bit bitmaps, this is 8.
unsigned int biCompression; //4 Our bitmaps are uncompressed, so this field is set to 0.
unsigned int biSizeImage; //4 The size of the padded image, in bytes.
unsigned int biXPelsPerMeter; //4 Horizontal resolution, in pixels per meter, of device displaying bitmap. This number is not significant for us, and will be set
to 0.
unsigned int biYPelsPerMeter; //4 Vertical resolution, in pixels per meter, of device displaying bitmap. This number is not significant for us, and will be set to
0.
unsigned int biClrUsed; //4 This indicates how many colors are in the palette.
unsigned int biClrImportant; //4 This indicates how many colors are needed to display the bitmap. We will set it to 0, indicating all colors should be used.

};
/********************************************************/

//Steg.cpp
Designed and Implementation: Renjith G

/*My Special Thanks to -----Peter Kieltyka----For the Main Idea of hiding Data
on LSB of Bitmap File. New program Modified and designed by renjith.
Creation Date ->Saturday, January 31, 2004, 10:48:42 PM
Last Modification ->Tuesday , March 02 , 2004, 10:44:54 PM
*/
#include "steg.h"
#include

#include
#include
//#include

/**************Function Prototypes*************************/
void MediaInfo(char *);
CheckMediaFile (FILE *);
void Eof(void);
void usage(char *);
int MaxCapacity(unsigned long);
int FileSize(FILE *);
int SteganoHide(char *, char *, char *, char *);
int SteganoExtract(char *, char *, char *);
/*************************Usage()*************************/
void usage(char *argv)
{
fprintf(stderr,
"\n\n"
"usage: \t\t To Hide\n"

"%s \n "
"\n\n"
"usage:\t\t To Extract\n"
"%s \n\n"
"\n\n"
"usage:\t\t To get Information about MediaFile File\n"
"%s <-i> "
"\n\n",argv,argv,argv);
exit(-1);
}
/******************EOF()*********************************/

void Eof(void)
{
puts("Error: End of file encountered - So aborting...\n");
}
/********************************************************/

/*********************************************************/
CheckMediaFile (FILE *fpin)
{
int b;

if ((b = getc (fpin)) == EOF)


Eof();
//printf("b=%d\n",b); /* ren check*/
return (UBYTE) b;
}
/****************Checking MaxCapacity()********************/
int MaxCapacity(unsigned long fsize)
{
return((fsize-STARTBYTE)/8);

}
/***************FileSize()***********************************/
int FileSize(FILE *fp)
{
unsigned long fsize;

(void)fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
(void)fseek(fp, 0, SEEK_SET);
return(fsize);
}
/**********************************************************/
void MediaInfo(char *fin)
{

struct BMPINFOHEADER bmih;


FILE *fpin;
long int hresol,vresol;
unsigned long int value;

if((fpin = fopen(fin, "rb")) == NULL)


{
fprintf(stderr, "Error! Cannot open input file!\n");
exit(-1);
}

switch (CheckMediaFile (fpin))


{
case 'M':
break;
case 'A':
puts ("File is probably an OS/2 bitmap ARRAY.\n");
fclose(fpin);
break;
case 'B':
{
puts("\n\n");
puts("File is Probably a Bitmap!\n");
puts("Media File Information\n");
rewind(fpin); /*set file pointer to beginning
please refer linux man pages */
fseek(fpin,14,SEEK_SET);
fread(&value,4,1,fpin);
printf("Bitmap Type -->");
switch(value)
{
case 12:
puts(" Bitmap of OS/2 (1)");
break;
case 40:
puts(" Windows Bitmap");
break;
case 64:
puts(" Bitmap of OS/2 (2)");
break;
default:
puts(" Unknown Type");
break;
}
////////////////////////////////printf("VALUE =%ld\n",value);
rewind(fpin);
fseek(fpin,14,SEEK_SET);

fread(&bmih,sizeof(bmih),1,fpin);

printf("Size of %s = %dKB\n",fin,bmih.biSizeImage/1024);
printf("Width of Bitmap File = %d\n", bmih.biWidth );
printf("Height of Bitmap File = %d\n", bmih.biHeight);
hresol = bmih.biXPelsPerMeter/39.3700787401;
vresol = bmih.biYPelsPerMeter/39.3700787401;
printf("Horizontal Resolution = %ld dpi\n",hresol);
printf("Vertical Resolution = %ld dpi\n",vresol);
switch(bmih.biBitCount)
{
case 1:
puts ("Monochrome Image 1bit (2 color)\n");
break;
case 4:
puts ("VGA Image ->4bit (16 color)\n");
break;
case 8:
puts ("SVGA or greyscale ->8bit (256 color)\n");
break;
case 16:
puts ("High Color ->16bit (65536 colour)\n");
break;
case 24:
puts ("True Color ->24bit (16.7 Mio colour)\n");
break;
default:
printf ( "Unknown color depth = %i\n",bmih.biBitCount );
} /*End o 2nd switch*/
if(bmih.biCompression != 0) /*Refer 6th field of BMPinfoHeader structure */
printf("BitMap File <%s> is Compressed\n",fin);
else
printf("Bitmap File <%s> is UnCompressed\n",fin);

}
fclose(fpin);
// printf("file closed");

} /*End of 1st switch*/

/***********************SteganoHide()***********************/
/* notes:- when hiding:
a = (a & ~1) | (((b >> (7-k)) & 1) & 1);

this takes the bit of byte 'b' at location 'k' (k goes from 0-7, 0 being the LSB)
and stores it in the LSB of byte 'a'

*/

int SteganoHide(char *fin, char *fout, char *fdata, char *key)


{
FILE *fpin, *fpout, *fpdata;
unsigned long media,fhide;
struct steg_header steg = {0};
char data[DATASIZE];
char buf[BUFSIZE];
int c,n,i,k,x,j,h;
int mediatype;
int count;/*Media file Type */
if((fpin = fopen(fin, "rb")) == NULL)
{
fprintf(stderr, "Error! Cannot open input file!\n");
exit(-1);
}
if((fpout = fopen(fout, "wb")) == NULL)
{
fprintf(stderr, "Error! Cannot open output file!\n");
exit(-1);
}
if((fpdata = fopen(fdata, "rb")) == NULL)
{
fprintf(stderr, "Error! Cannot open %s!\n", fdata);
exit(-1);
}

mediatype = CheckMediaFile (fpin);


if(!(mediatype == 'B'))
{
printf("GETSREGABYTE = %d\n",mediatype);
fprintf(stderr, "Error! %s ->s Not a BITMAP File!\n", fin);
exit(-1);
}
media = FileSize(fpin);
fhide = FileSize(fpdata);

//if(MaxCapacity(FileSize(fpin)) < FileSize(fpdata))


if(MaxCapacity(media) < fhide)
{
printf("\nMedia size = %ld\n",media);
printf("File-to-Hide = %ld\n",fhide);
fprintf(stderr, "Error!! Hiding File %s will not fit in %s, %d Bytes Capacity!\n",
fdata,fin, MaxCapacity(media));
return(-1);
}
steg.datalen = FileSize(fpdata);
memcpy(steg.key, key, sizeof(steg.key));
puts("Please wait while Hiding............");
x = 0;
k = 0;
j = 0;
i = STARTBYTE;
h = sizeof(steg);
count=0;

while(n = fread(buf, 1, sizeof(buf), fpin)) /* total no of bytes read = size(buf) * 1 */


{
if(x != 0)
i = 0;

while(i < n)
{
if(j <= 0)
{
c = 0;
memset(data, 0, sizeof(data)); /* returns data */
j = fread(data+h, 1, sizeof(data)-h, fpdata);
// j = fread(data, 1, sizeof(data), fpdata);
// printf("j==================%d\n",j);

if(h != 0)
{
j += h;
memcpy(data, &steg, sizeof(steg));
h = 0;
}
}

if(j > 0)
{
printf("count=%d\n",count);
printf("the val buf[%d] =%d\n",i,buf[i]);
printf("The data[%d] =%d\n",c,(((data[c] >> (7-k)) & 1) & 1));

// printf("i=%d \t c=%d\n",i,c);
buf[i] = (buf[i] & ~1) | (((data[c] >> (7-k)) & 1) & 1);
printf("the val buf[%d] =%d\n\n\n",i,buf[i]);
count=count+1;

// getch();

k++;
//printf("buff %c\n",buf[i] );
if(k > 7)
{
k = 0;
c++;
j--;
}
}

i++;
} /* End Of While */

fwrite(buf, 1, n, fpout);
x += n;
}

fclose(fpin);
fclose(fpout);
fclose(fpdata);

return(0);
}

/****************Stegano Extraction()********************/
/* note to follow:- when extracting:
a = (a & ~(1 << (7-k))) | ((b & 1) << (7-k));

this assigns 'a' the LSB of 'b' to location 'k' (k goes from 0-7, 0 being the LSB)
*/
int SteganoExtract(char *fin, char *fout, char *key)
{
FILE *fpin, *fpout;
struct steg_header steg = {0};
char buf[BUFSIZE], data[DATASIZE], c;
int done,n,x,i,k,j;

if((fpin = fopen(fin, "rb")) == NULL)


{
fprintf(stderr, "Error! Cannot open input file!\n");
exit(-1);
}
if((fpout = fopen(fout, "wb")) == NULL)
{
fprintf(stderr, "Error! Cannot open output file!\n");
exit(-1);
}

// Get header
x = 0;
j = 0;
k = 0;
done = 0;
puts("Please wait while Extracting............");
memset(data, 0, sizeof(data));
while((n = fread(buf, 1, sizeof(buf), fpin)) && done == 0)
{
if(x == 0)
i = STARTBYTE;
else
i = 0;

while(i < n)
{
if(j < sizeof(steg))
{
data[j] = (data[j] & ~(1 << (7-k))) | ((buf[i] & 1) << (7-k));
k++;

if(k > 7)
{
k = 0;
j++;
}
}
else
{
done = 1;
break;
}

i++;
} /*end of While */

x += n;
}
memcpy(&steg, data, sizeof(steg));
(void)fseek(fpin, 0, SEEK_SET);

// Check key's
if(strcmp(steg.key, key))
{
printf("Incorrect Key! No data for you!\n");
fclose(fpin);
fclose(fpout);
return(-1);
}

// Get data
x = 0;
k = 0;
j = steg.datalen;
i = STARTBYTE+(sizeof(steg)*8);
while(n = fread(buf, 1, sizeof(buf), fpin))
{
if(x != 0)
i = 0;

while(i < n)
{
c = (c & ~(1 << (7-k))) | ((buf[i] & 1) << (7-k));
k++;

if(k > 7)
{
k = 0;
j--;
if(j >= 0)
fputc(c, fpout);
}

i++;
}

x += n;
}

fclose(fpin);
fclose(fpout);

return(0);
}

/********************Main()******************************/

int main(int argc, char **argv)


{
///int c; /////////////////////////
if(argc <> 5)

usage(argv[0]);
if(argc == 3)
{
if(strcmp (argv[1],"-i") == 0)
{
//puts("in hai");
MediaInfo(argv[2]);
exit(-1);
}
else
puts("out hai");
usage(argv[0]);
exit(-1);
///////////////////////////srecmp(argv[2],"-i")==0?usage(argv[0]):exit(-1));
}
if(argc == 4)
{
if(strlen(argv[3]) > 10)
{
printf("Sorry, the key cannot be greater then 10 characters long!\n");
exit(-1);
}

SteganoExtract(argv[1], argv[2], argv[3]);


}
else
{
if(strlen(argv[4]) > 10)
{
printf("Sorry, the key cannot be greater then 10 characters long!\n");
exit(-1);
}

SteganoHide(argv[1], argv[2], argv[3], argv[4]);


}
exit(0);
}
/**********************end of main()************************/

*
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 *Steganography Empty Constructor
029 */
030 public Steganography()
031 {
032 }
033
034 /*
035 *Encrypt an image with text, the output file will be of type .png
036 *@param path The path (folder) containing the image to modify
037 *@param original The name of the image to modify
*@param ext1 The extension type of the image to modify (jpg,
038
png)
039 *@param stegan The output name of the file
040 *@param message The text to hide in the image
*@param type integer representing either basic or advanced
041
encoding
042 */

043 public boolean encode(String path, String original, String ext1, String
stegan, String message)
044 {
045 String file_name = image_path(path,original,ext1);
046 BufferedImage image_orig = getImage(file_name);
047
048 //user space is not necessary for Encrypting
049 BufferedImage image = user_space(image_orig);
050 image = add_text(image,message);
051
05 return(setImage(image,new File(image_path(path,stegan,"png")),"png"
2 ));
053 }
054
055 /*
*Decrypt assumes the image being used is of type .png, extracts the
056
hidden text from an image
*@param path The path (folder) containing the image to extract the
057
message from
058 *@param name The name of the image to extract the message from
059 *@param type integer representing either basic or advanced encoding
060 */
061 public String decode(String path, String name)
062 {
063 byte[] decode;
064 try
065 {
066 //user space is necessary for decrypting
BufferedImage image =
067
user_space(getImage(image_path(path,name,"png")));
068 decode = decode_text(get_byte_data(image));
069 return(new String(decode));
070 }
071 catch(Exception e)
072 {
073 JOptionPane.showMessageDialog(null,
074 "There is no hidden message in this image!","Error",
075 JOptionPane.ERROR_MESSAGE);
076 return "";
077 }
078 }
079
080 /*
081 *Returns the complete path of a file, in the form: path\name.ext
082 *@param path The path (folder) of the file
083 *@param name The name of the file
084 *@param ext The extension of the file
085 *@return A String representing the complete path of a file
086 */
087 private String image_path(String path, String name, String ext)
088 {
089 return path + "/" + name + "." + ext;
090 }
091
092 /*
093 *Get method to return an image file
094 *@param f The complete path name of the image.
095 *@return A BufferedImage of the supplied file path
096 *@see Steganography.image_path
097 */
098 private BufferedImage getImage(String f)
099 {
100 BufferedImage image = null;
101 File file = new File(f);
102
103 try
104 {
105 image = ImageIO.read(file);
106 }
107 catch(Exception ex)
108 {
109 JOptionPane.showMessageDialog(null,
"Image could not be
110
read!","Error",JOptionPane.ERROR_MESSAGE);
111 }
112 return image;
113 }
114
115 /*
116 *Set method to save an image file
117 *@param image The image file to save
118 *@param file File to save the image to
*@param ext The extension and thus format of the file to be
119
saved
120 *@return Returns true if the save is succesful
121 */
122 private boolean setImage(BufferedImage image, File file, String ext)
123 {
124 try
125 {
126 file.delete(); //delete resources used by the File
127 ImageIO.write(image,ext,file);
128 return true;
129 }
130 catch(Exception e)
131 {
132 JOptionPane.showMessageDialog(null,
"File could not be
133
saved!","Error",JOptionPane.ERROR_MESSAGE);
134 return false;
135 }
136 }
137
138 /*
139 *Handles the addition of text into an image
140 *@param image The image to add hidden text to
141 *@param text The text to hide in the image
142 *@return Returns the image with the text embedded in it
143 */
144 private BufferedImage add_text(BufferedImage image, String text)
145 {
146 //convert all items to byte arrays: image, message, message length
147 byte img[] = get_byte_data(image);
148 byte msg[] = text.getBytes();
149 byte len[] = bit_conversion(msg.length);
150 try
151 {
152 encode_text(img, len, 0); //0 first positiong
encode_text(img, msg, 32); //4 bytes of space for length:
153
4bytes*8bit = 32 bits
154 }
155 catch(Exception e)
156 {
157 JOptionPane.showMessageDialog(null,
158 "Target File cannot hold message!", "Error",JOptionPane.ERROR_MESSAGE);
159 }
160 return image;
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
165
interferences
166 *@return The user space version of the supplied image
167 */
168 private BufferedImage user_space(BufferedImage image)
169 {
170 //create new_img with the attributes of image

171 BufferedImage new_img = new BufferedImage(image.getWidth(),


image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
172 Graphics2D graphics = new_img.createGraphics();
173 graphics.drawRenderedImage(image, null);
174 graphics.dispose(); //release all allocated memory for this image
175 return new_img;
176 }
177
178 /*
179 *Gets the byte array of an image
180 *@param image The image to get byte data from
181 *@return Returns the byte array of the image supplied
182 *@see Raster
183 *@see WritableRaster
184 *@see DataBufferByte
185 */
186 private byte[] get_byte_data(BufferedImage image)
187 {
188 WritableRaster raster = image.getRaster();
189 DataBufferByte buffer = (DataBufferByte)raster.getDataBuffer();
190 return buffer.getData();
191 }
192
193 /*
194 *Gernerates proper byte format of an integer
195 *@param i The integer to convert
*@return Returns a byte[4] array converting the supplied integer into
196
bytes
197 */
198 private byte[] bit_conversion(int i)
199 {
200 //originally integers (ints) cast into bytes
201 //byte byte7 = (byte)((i & 0xFF00000000000000L) >>> 56);
202 //byte byte6 = (byte)((i & 0x00FF000000000000L) >>> 48);
203 //byte byte5 = (byte)((i & 0x0000FF0000000000L) >>> 40);
204 //byte byte4 = (byte)((i & 0x000000FF00000000L) >>> 32);
205
206 //only using 4 bytes
207 byte byte3 = (byte)((i & 0xFF000000) >>> 24); //0
208 byte byte2 = (byte)((i & 0x00FF0000) >>> 16); //0
209 byte byte1 = (byte)((i & 0x0000FF00) >>> 8 ); //0
210 byte byte0 = (byte)((i & 0x000000FF) );
211 //{0,0,0,byte0} is equivalent, since all shifts >=8 will be 0
212 return(new byte[]{byte3,byte2,byte1,byte0});
213 }
214
215 /*
*Encode an array of bytes into another array of bytes at a supplied
216
offset
217 *@param image Array of data representing an image
*@param addition Array of data to add to the supplied image data
218
array
*@param offset The offset into the image array to add the addition
219
data
220 *@return Returns data Array of merged image and addition data
221 */
222 private byte[] encode_text(byte[] image, byte[] addition, int offset)
223 {
224 //check that the data + offset will fit in the image
225 if(addition.length + offset > image.length)
226 {
227 throw new IllegalArgumentException("File not long enough!");
228 }
229 //loop through each addition byte
230 for(int i=0; i<addition.length; ++i)
231 {
232 //loop through the 8 bits of each byte
233 int add = addition[i];

234 for(int bit=7; bit>=0; --bit, ++offset) //ensure the new


offset value carries on through both loops
235 {
236 //assign an integer to b, shifted by bit spaces AND 1
237 //a single bit of the current byte
238 int b = (add >>> bit) & 1;
//assign the bit by taking: [(previous byte value) AND
239
0xfe] OR bit to add
//changes the last bit of the byte in the image to be the
240
bit of addition
241 image[offset] = (byte)((image[offset] & 0xFE) | b );
242 }
243 }
244 return image;
245 }
246
247 /*
248 *Retrieves hidden text from an image
249 *@param image Array of data, representing an image
250 *@return Array of data which contains the hidden text
251 */
252 private byte[] decode_text(byte[] image)
253 {
254 int length = 0;
255 int offset = 32;
256 //loop through 32 bytes of data to determine text length

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

Potrebbero piacerti anche