|==============================================================================| |--------------------- Bliz Multifile Steganography System --------------------| |------------------------------ ver. 0x01 -------------------------------------| |------------------------------------------------------------------------------| |------------------- by Giovanni Santostefano (aka Blizzard) ------------------| |--------------------- contact: idmgiovanni@libero.it -------------------------| |------------------- http://santostefanogiovanni.blogspot.com -----------------| |==============================================================================| 1. INTRODUCTION 2. THE SYSTEM 3. CONCLUSION 1. INTRODUCTION This paper explain the theory of a steganography system that I've designed to allow an user to put in an image 3 ascii messages. Each message is stored in a color channel (R,G,B). To encode/decode the messages the user have to insert a password and the channel where he wants to store the message. 2. THE SYSTEM The Bliz Multifile Steganography System (BMS2) is a system that allow the user to insert in an image up to 3 ascii messages in a completely sthealt way. As you know each pixel of an RGB image is coded commonly in 24bit. These 24 bits are divided by the Red, the Green and the Blue channel. Each channel can contain a value from 0 to 255 or better from 0x0 to 0xff Fig.1 (pixel representation in bits) R G B |===============||===============||===============| |7|6|5|4|3|2|1|0||7|6|5|4|3|2|1|0||7|6|5|4|3|2|1|0| |===============||===============||===============| For each channel we take in consideration the bit 0 or 1. When the user decides to encrypt a message he selects the channel where he wants to store the message. Next he insert a password. The password is an ascii sequence like GENERIC PASSWORD: abc The password identify the next pixel to consider for encryption/decryption. Now there are 2 ways to find the next pixel. 1.ASCII CODE We search the next pixel to encode/decode by reading the ascii code of the i-th char of the password module the password length. The first element of the password is 'a' and the ascii code is 97. That means that the next pixel to evaluate is 97 pixels forward. Chars are taken position module length because we need a string abcabcabcabcabc... big as the lenght of the message to encrypt 2.BINARY SEQUENCE We take the password as a bit sequence. pwd="abc"=011000010110001001100011 The 0 means that the actual pixel is NOT evaluated. The 1 means that the actual pixel is evaluated. The sequence is read module its length because we have surely messages to encrypt bigger than the 1 of the binary sequence. We don't use this system because is designed only for reducing the image dimension needed to store the encrypted message. Now we know how to find the pixel to evaluate. We now take our ascii string to encode and consider it like a bit sequence: msg="This is our message"=01010101100100010001000100101001.... We set each bit in a pixel information. We assume to operate on the R channel. When we found the actual pixel with the password information we set the R channel first bit to the message bit if the password current char divide 2 otherwise we set the second bit of the R channel to the message bit. EXAMPLE (password is taken like char's ascii code. See line 44) { pwd="abc"; msg="hello"=0100101000100010010010010...; //this sequence is not the correct //hello bit sequence but is an example //The actual bit to compute is msg first bit msgbit=0x0; //The actual key char is the first password char actualkey='a'=97; //The actual image pixel is the first imagepixelposition=0; //Then we move 97 pixel forward imagepixelposition+=97; //And we take the R channel data of the imagepositionpixel pixel rchannel=GetRedChannel(imagepositionpixel); //Now we look to the key. If the (actualkey % 2 ==0) //we set the rchannel bit 0 to msgbit otherwise we set the //rchannel bit 1 to msgbit if(actualkey%2==0) rchannel=rchannel | msgbit; else rchannel=rchannel | (msgbit << 1); //now we take the next values msgbit=0x1; actualkey='b'=98; imagepixelposition+=98; ... and so on } In this way we can insert the bits of the message in the pixel of the image, changing only the first or second bit of each image channel. This can make a low variation in the image color. And what about the pixels that are not toutched by the encryption? This can make a problem because someone can compare the original and the encrypted image, discovering the differences between them and take the bits probably encrypted. The system avoids this situation by encrypt with random data the pixels of the shift between 2 pixels of encryption, following the encoding system. Now comparing the original image and the encrypted image is sensless because we can intercept differences that doesn't belong to the message hidden in it. The decoding system is the reverse operation aimed to taking each bit from the right channel of the right pixel and rebuild the message. Here follows the pseudocode of the encoding and deconding operations //we look at message not in the ascii representation "abcdef" //but in bit representation "010010101001001..." Encode(imagename, message, password, channel) { pixeldata=LoadImage(imagename); pixelindex=0; for i=0 to message.bitcount-1 { msgbit=message.GetBit(i); actualkey=ascii(password.GetChar(i%password.length)); //random change of pixels between 2 encrypted pixels //this is a security policy for j=1 to actualkey { selectbit=random(0 or 1); //can be 1 or 0 if(selectbit==1) //we set the first bit of the channel { //we set a random value 0 or 1 to first bit of the selected channel //of the actual pixel pixeldata.SetFirstChannelBit(pixelindex,channel,random(0 or 1)); } else //we set the second bit of the channel { //we set a random value 0 or 1 to the second bit of the selected channel //of the actual pixel pixeldata.SetSecondChannelBit(pixelindex,channel,random(0 or 1)); } pixelindex=pixelindex+1; } //end of security filling //now pixelindex point to the pixel that will contain the actual bit //of the message. //if actualkey mod 2 is 0 then we put the message bit in the first bit of //the selected channel of the current pixel //otherwise we place msgbit in the second bit of the selected channel of //the current bit if(actualkey mod 2 ==0) { pixeldata.SetFirstChannelBit(pixelindex,channel,msgbit); } else //actualkey mod 2 is 1 { pixeldata.SetSecondChannelBit(pixelindex,channel,msgbit); } pixelindex=pixelindex+1; } //end of "for i..." //now we have inserted the message bits in the image selected channel //we can overwrite the original image SaveImage(imagename, pixeldata); } //end of encoding procedure //The decoding routine ascii_string Decode(imagename, password, channel) { pixeldata=LoadImage(imagename); pixelindex=0; i=0; while a decoded character is not the termination character { //build a decoded char made by 8bit for j=0 to 7 { //we take tha actual key char actualkey=ascii(password.GetChar(i%password.length)); //we move to the next pixel containing the message information pixelindex=pixelindex+actualkey; //we take the bit of our message if(actualkey mod 2==0) { msgbit=pixeldata.GetFirstChannelBit(pixelindex,channel); } else { msgbit=pixeldata.GetSecondChannelBit(pixelindex,channel); } //we set the j-th bit of actualchar with msgbit actualchar.SetBit(msgbit,j); } //end build a decoded char //we append the decoded char to the decodedstring decodedstring.append(actualchar); } //end while //we have the decoded string and we can return it return decodedstring; }//end of decoding function As you can see in the pseudocode we can rapidly encode/decode the text message. To stop encoding/decoding we can use a termination character or a termination string (ex: !--END MSG--! ). When we found this string we stop the operations. To translate 01010101 string to ascii string I've written this function in C code /*convert binary string to ascii string*/ char* ConvertBinToAscii(char *bstr) { int count=0; char *astr=NULL; int i=0; count=(int)(strlen(bstr)/8); astr=malloc(count+1); memset(astr,0,count+1); for(i=0; i