0% found this document useful (0 votes)
69 views20 pages

#Include #Include //#include / Function Prototypes

This C/C++ code implements a steganography program to hide data in the least significant bits of a bitmap image file. It includes function definitions and prototypes for hiding data by modifying the LSBs of the bitmap file to store bits of the data file. It also includes functions for extracting the hidden data by reading the LSBs and reconstructing the original data file. The main() function checks the arguments and calls the appropriate hiding or extracting function based on the options passed.

Uploaded by

MISGANU CHIMDESA
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
69 views20 pages

#Include #Include //#include / Function Prototypes

This C/C++ code implements a steganography program to hide data in the least significant bits of a bitmap image file. It includes function definitions and prototypes for hiding data by modifying the LSBs of the bitmap file to store bits of the data file. It also includes functions for extracting the hidden data by reading the LSBs and reconstructing the original data file. The main() function checks the arguments and calls the appropriate hiding or extracting function based on the options passed.

Uploaded by

MISGANU CHIMDESA
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 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 }

You might also like