You are on page 1of 13

4/20/2019 Steganography - Java Tutorials | Dream.In.


Dream.In.Code> Programming Tutorials> Java Tutorials

(6 Pages)


Last »
Steganography Rate Topic: 10 Votes
William_Wilson Follow & Share General Discussion
Posted 11 May 2007 - 06:19 PM
Caffeine Lounge

Corner Cubicle
Steganography Student Campus

Software Development
Steganography is a complex subject, please note that although it involves hiding messages, it is not
cryptography. The definitions are as follows: Java Tutorials Industry News

Cryptography: “The discipline which embodies principles, means and methods for the transformation of 2048 Game in Java Introduce Yourself
data in order to hide its information content, prevent its undetected modification, or prevent its
unauthorized use” Swing Nightmare.In.Code
Steganography: “A method of hiding a secret message inside of other data.” Avoiding
Essentially the difference is that, while both hide a message, steganography is meant to make the NullPointerExceptions Programming Help
message invisible, while cryptography changes the message’s form, by means of replacement and/or
algorithm. by using Optional<T>
C and C++
This code is written in Java, and the following topics will need to be understood, before properly I need help with this
understanding how this method works: VB.NET
Bytes: individually as integers and as arrays Array Question
Bit Operations: Logical AND (&), OR(|) and how they work Java
Images: BufferedImage specifically Dijkstra's Algorithm
ImageIO: how image files are opened and saved C#
Graphics2D: accessing user space image properties Book Review: Murach's
Raster: specifically WritableRaster allows access to the buffer Python
DataBufferByte: Buffer used with BufferedImage Beginning Java with
*These are the major topics needed to understand Steganography, but there are others used and PHP
assumed to be understood, as this topic is not meant for those inexperienced with the Java language. NetBeans
Mobile Development
Graph Data Structure
Bytes: ASP.NET
Bytes are the elementary data source of most applications, and many programmers will never use them Tutorial
in any source code, but that is beside the point. A byte is made of bits, 1s and 0s, 8 of them to be exact. .NET Framework
And the 8 0s and 1s have a decimal value, it is simply a case of transforming the binary (base 2) into Swing, Passive Model-
decimal (base 10). Ruby
Value by position: 128 64 32 16 8 4 2 1 (and all positions with a 1 are added together) View-Presenter in 5
Examples: Game Development
00000000 = 0 minutes.
00000010 = 2 Assembly
00000111 = 7 1/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code
00001011 = 11 Databases
And so on… Book Review: Murach's

A byte can be transformed from an int in java by simple casting:

Java Servlets and JSP ColdFusion
Byte b = (byte)7;
Most classes in java have a method for returning the byte[] of an object, either as a section of the object Phobos - A JavaFX VB6
or the entire object.
String Class Example: Games Engine: Part 2 - Other Languages
JavaFX Scene API and 52 Weeks Of Code
1 String w = “William”;
2 Byte[] b = w.getBytes(); the FSM

Maven Tutorial 2 -
Web Development
Where b[0] will now contain the ascii value for ‘W’ 87 if printed. Though it is good to remember that Adding Dependencies
although it appears as an int, when displayed, it is in fact a byte, which is stored as 8 bits, in this case:
01010111. Web Development
225 More Java
Bit Operations:
There are simple operations which most computer users have either heard of, or even used: JavaScript
The AND(&) bit operator, will AND 2 bytes together. The same rules apply as when using true and false Reference Sheets Graphic Design
values, where 1 = true, and 0 = false. If both bytes have a 1 in the same position, then the result for
that position is a 1, otherwise the result is a 0. Flash & ActionScript

Example: Blogging
01010111 = 87
01100101 = 101 SEO & Advertising
01000101 = 69
Web Servers & Hosting
Byte b = 87 & 101; //69: 01000101
Site Check
The OR(|) bit operator, will OR 2 bytes together. The same rules as with AND where 1 = true, and 0 =
false, only when using OR, as long as one of the bits in the position is a 1, then the result is a 1. Only if
both bits are 0, is the result a 0.
01010111 = 87
01100101 = 101 Code Snippets
01110111 = 119 C Snippets
Byte b = 87 | 101; //119: 01110111
C++ Snippets
On top of these basic operations, we can also shift bits:
Left Shift: Java Snippets
An important thing to remember when left shifting bits, is if the first bit is not a 1, a single left shift will
essentially double the value. What actually happens, is a 0 is added on the right hand side of the bits, Visual Basic Snippets
then the far left bit is removed thus leaving a new set of 8 bits. Also, when shifting in Java, a number of
positions to shift must also be supplied. If the value is greater than 1, the process is simply repeated C# Snippets
that many times each time beginning with the result of the previous shift. Thus any value will become 0
if shifted 8 times.
VB.NET Snippets
(single shift) ASP.NET Snippets
01010111 = 87
<< 1 PHP Snippets
10101110 = 174
(double shift)
Python Snippets
01010111 = 87
<< 2 Ruby Snippets
01011100 = 92
ColdFusion Snippets 2/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code
1 Byte b1 = 87 << 1; //174: 10101110
SQL Snippets
2 Byte b2 = 87 << 2; //92: 01011100
Assembly Snippets

Right Shift:
A right shift is the opposite of a left shift in the sense that a 0 is added to the left side of the bits, and Programming Snippets
the far right bit is removed, once again leaving a set of 8 bits.
Perl Snippets
(single shift)
01010111 = 87 HTML/CSS Snippets
>>> 1
00101011 = 43 Javascript Snippets
(double shift) Flash/ActionScript
01010111 = 87
>>> 2 Snippets
00010101 = 21
ASP Snippets
1 byte b1 = 87 >>> 1; //43: 00101011 Linux, Unix, and Bash
2 byte b2 = 87 >>> 2; //21: 00010101

These are the bit and byte operations which are used to effectively create this steganography Other Languages
application, I will provide some more complex examples, breaking down the steps of adding the data to Snippets
the image, a little later.
BufferedImage: Regex
A bufferedImage is something to be comfortable with when dealing with images. They are easily used
with the newly introduced ImageIO class of Java 1.5.0 as well as containing methods for accessing the
raster and buffer of the image, which makes image editing much easier. The basic actions for creating a
new image are:
DIC Chatroom
Join our IRC Chat
1 BufferedImage img = new BufferedImage(int, int, int);
3 File file = new File(String); Bye Bye Ads
4 BufferedImage img =;

A useful class to handle IO operations on images. This class has much to offer, but as far as this program
is concerned, the read() and write() methods will be sufficient.
A class which has been around for a long time as far as Java is concerned, and allows access to some of
the more in depth aspects of graphics/images. Allows for creating editable areas in a new image or an
image which already exists. As well as allowing a way to reach the renderable area of the image. This
class also allows for an easy switch from image space to user space, which is necessary when modifying
or reading certain bytes of an image.
This by definition is the process of rendering an image pixel by pixel, which comes in handy when you
need to access the bytes of an image, that are representing pixels. WritableRaster is a sub-class of
Raster itself, which has methods to access the buffer of an image more directly.
The form of a byte[] buffer for an image.
*These topics/classes will be useful to know and have experience with as you attempt to modify this
application, or create similar applications of your own. 3/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code

The Program: Dream.In.Code

There are a few specific methods that should be gone over, including the complex bit operations to add 88,000 likes
the data seamlessly into the image to properly understand the how and why behind this code.
User Space:

1 private BufferedImage user_space(BufferedImage image)

2 { Like Page Sign Up
3 BufferedImage new_img = new BufferedImage(image.getWidth(), image.getHeight(),
4 Graphics2D graphics = new_img.createGraphics(); Be the first of your friends to like this
5 graphics.drawRenderedImage(image, null);
6 graphics.dispose();
7 return new_img;
8 }

-To make the switch into user space (this is the actual term) a new image is created the same size as
the original, and a graphics area is created in it.
-The original image is then rendered/drawn onto the new image
-As an added memory benefit, the resources used by the new image are released
That’s it, the new image is now completely in user space, this means that all of the data is created and
thus can be modified in Java. There are issues with trying to modify an image directly, the changes are
not always applied. It is also advisable to create this user space as a new copy of the original image,
thus ensuring there is no resource sharing between the original and user space version which may
impede the saving of your changes.
Bit Conversion:

1 private byte[] bit_conversion(int i)

2 {
3 byte byte3 = (byte)((i & 0xFF000000) >>> 24);
4 byte byte2 = (byte)((i & 0x00FF0000) >>> 16);
5 byte byte1 = (byte)((i & 0x0000FF00) >>> 8 );
6 byte byte0 = (byte)((i & 0x000000FF) );
7 return(new byte[]{byte3,byte2,byte1,byte0});
8 }

I thought it important to explain this operation. This method could just as easily be written as:

1 private byte[] bit_conversion(int i)

2 {
3 return(new byte[]{0,0,0, (byte)(i & 0x000000FF));
4 }

Because a byte holds a max value of 127, all shifts of 8 and higher, will remove all bits and replace them
with zeros, but to be proper, to save each set of bits, the implementation is left as calculating each byte.
*Note that hex FF = 11111111 in binary this is important, because, if there were more than 8 bits, say
16 and let i = 287:

0000000100011111 = 287
0000000011111111 = 255 or 0x00FF
0000000000011111 = 31 4/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code

The result has the last 8 bits matching I, but the first 8 bits were all removed to 0s due to being AND
with 0s in all positions, but the last 8. The thing to take from this, is we can force a value to 0, by
ANDing with 0, and leave a value alone, by ANDing with 1.
Encode Text:

01 private byte[] encode_text(byte[] image, byte[] addition, int offset)

02 {
03 if(addition.length + offset > image.length)
04 {
05 throw new IllegalArgumentException("File not long enough!");
06 }
07 for(int i=0; i<addition.length; ++i)
08 {
09 int add = addition[i];
10 for(int bit=7; bit>=0; --bit, ++offset)
11 {
12 int b = (add >>> bit) & 1;
13 image[offset] = (byte)((image[offset] & 0xFE) | b );
14 }
15 }
16 }

At first this can appear overwhelming, the task of doing it nearly drove me insane, until I had read on
countless websites and forums about classic implementations of steganography and how to split up and
place the bits.
In a byte, the bits have a rank, the left most bit is the most significant and right most, least significant.
This gives us the key, if we need to change some data in this image, we want it to be as unobtrusive as
possible, or even invisible. Thus we want to apply our changes to the least significant bit of some of the
bytes. In this way we change each byte, a maximum of 1 in value.
Here is how this code accomplishes that:
for(int i=0; i<addition.length; ++i) – loops through each byte of the addition array
int add = addition[i]; – assigns add to be the current byte
for(int bit=7; bit>=0; --bit, ++offset) – loops through the 8 bits of the byte stored in add
int b = (add >>> bit) & 1; – b is assigned the value of the byte add shifted right bit positions AND 1
This may look complicated, but the end result is a loop which systematically assigns b the next single bit
value of the byte add, either 0, or 1. This is best seen in a set of examples:
We will start with int b = (add >>> bit); only, Say:
add = 87 = 01010111
First loop through, bit = 7:
01010111 = 87
>>> 7
00000000 = 0
Next time, bit = 6:
01010111 = 87
>>> 6
00000001 = 1

Next time, bit = 5:

01010111 = 87
>>> 5
00000010 = 2

Next time, bit = 4:

01010111 = 87 5/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code
>>> 4
00000101 = 5
… and so on.
*Notice how the right bits match the left bits of add, in a growing number based on how many positions
we shift add.
Now to apply the & 1:
First loop:
00000000 = 0
00000001 = 1
00000000 = 0 = b

00000001 = 1
00000001 = 1
00000001 = 1 = b
00000010 = 2
00000001 = 1
00000000 = 0 = b
00000101 = 5
00000001 = 1
00000001 = 1 = b

Note the pattern, b is assigned the value 0 or 1, based on the last bit of the shifted add byte. We
accomplish the same as above, by ANDing by 1, which clears all bits to 0, except the last which is left as
it was. This means that b’s value represents the bit at position bit in the for loop.
image[offset] = (byte)((image[offset] & 0xFE) | b );
This line of code works in a similar way. 0xFE is hex, which represents 11111110 in binary. By reasoning
above, this will leave the first 7 bits as is, and clear the least significant bit to 0. Then with the last bit 0,
we OR it with b, which is either: 00000000 or 00000001. This will set the last bit to match the value
stored in b. As the OR operation with 0s will not change any of the first 7 bits, and thus knowing the last
bit is a 0, the value in this position of b, is guaranteed to be placed into this position, whether it be 0 or

*The code advances the offset value as the loop continues as well, thus the 8 bits of a single byte of
addition are separated across the 8 least significant bits of 8 separate and sequential bytes of the image.
**Also it is important that we encode the length first, and do it in a static way, eg. It is saved in 4 bytes,
or the first 32 least significant bits. Thus we know how many least significant bits to read after the
length to retrieve the entire message.
Decode Text:

01 private byte[] decode_text(byte[] image)

02 {
03 int length = 0;
04 int offset = 32;
05 for(int i=0; i<32; ++i)
06 {
07 length = (length << 1) | (image[i] & 1);
08 }
09 byte[] result = new byte[length];
10 for(int b=0; b<result.length; ++b )
11 {
12 for(int i=0; i<8; ++i, ++offset)
13 { 6/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code
14 result[b] = (byte)((result[b] << 1) | (image[offset] & 1));
15 }
16 }
17 return result;
18 }

The process may seem straight forward, but I will explain how each step works to retrieve the bits we

int offset = 32; – The length of the message is stored as a 4 byte number, or 32 bits, thus the message
starts after 32 bytes of image.
for(int i=0; i<32; ++i) – Since the first 32 bytes contain 1 bit each of our length, we must loop all 32 bytes
to retrieve the length.
length = (length << 1) | (image[i] & 1); – We shift the bits of length left by 1, then OR it with a result of the
least significant bit of the image byte. (& 1) will clear all bits, except the last bit, which will be left as is.
Thus as bits are added, they are moved along and placed into the newly empty least significant slot of

*For the same reason as the bit conversion array being {0,0,0,byte0}, this for loop could use i=24, and
will still work. Both of these things have not been placed into the final code, as leaving the larger ranges,
allows for expansion and much larger text to be hidden in the image.

for(int b=0; b<result.length; ++b ) – Now that we have a length and have created a byte array to hold the
bits, we loop through that many image bytes.

for(int i=0; i<8; ++i, ++offset) – Again we must loop through the 8 bits of a byte to be collected.

result[b] = (byte)((result[b] << 1) | (image[offset] & 1)); – the resulting array of bytes is made up of the least
significant bit of each sequential byte. This is retrieved in the same way as we retrieved the length, now
that the loops are properly setup.

That explains the magic of how Steganography works. Of course there are other ways to implement it,
and in fact, most often the text is encrypted before it is hidden to decrease it’s chances of being
detected and/or broken. The more randomness there is in the image, the easier it is to add data to the
image without any detection, but even so, the following 2 images are an original(left) and a
modified(right). Without knowing there was a message in the second, you would be hard pressed to
figure it out on your own. Also most often the recipient of a steganographic image would never see the
original to compare.

(2.62KB) 7/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code



Code Statistics:
-Fully commented in JavaDoc format.
-File size is not increased greatly.
-Output file is of type .png
-Both .jpg and .png input files have been tested successfully.
-The image is not distorted in any visible way.
-Due to the complexity of the encoding, the message cannot be viewed by simply looking at the image in
a text editor, such as Notepad.

This program is done in a Model, View, Controller style. The Controller file is the one which contains a
main method, but all 3 files are necessary to use the application.


001 /*
002 *@author William_Wilson
003 *@version 1.6
004 *Created: May 8, 2007
005 */
007 /*
008 *import list
009 */
010 import;
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;
018 import javax.imageio.ImageIO;
019 import javax.swing.JOptionPane;
021 /*
022 *Class Steganography
023 */ 8/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code
024 public class Steganography
025 {
027 /*
028 *Steganography Empty Constructor
029 */
030 public Steganography()
031 {
032 }

View (GUI):

*It is a very simple GUI, no threads, and no fancy options, feel free to add elements such as opening
text files, and other useful items.
app=core&module=attach&section=attach&attach_id=4456&s=409afd949184eafee167a74575c4f7dc) (
app=core&module=attach&section=attach&attach_id=4456&s=409afd949184eafee167a74575c4f7dc) (6.64K)
Number of downloads: 26840

Image Filter:

app=core&module=attach&section=attach&attach_id=4454&s=409afd949184eafee167a74575c4f7dc) (
app=core&module=attach&section=attach&attach_id=4454&s=409afd949184eafee167a74575c4f7dc) (1.45K)
Number of downloads: 20301

Controller (Main Method):

app=core&module=attach&section=attach&attach_id=4455&s=409afd949184eafee167a74575c4f7dc) (
app=core&module=attach&section=attach&attach_id=4455&s=409afd949184eafee167a74575c4f7dc) (7.41K)
Number of downloads: 21680

Text Version of the Entire Tutorial: (

Steganography_Tutorial__no_tags_.txt (
app=core&module=attach&section=attach&attach_id=4448&s=409afd949184eafee167a74575c4f7dc) (39.62K)
Number of downloads: 16317

Replies To: Steganography

Posted 12 May 2007 - 07:33 AM
Wow, this is really cool. I studied cryptography for a (brief) while and made some (simple) encryption
and decryption programs, but this is something else. Very awesome. Thanks for the tutorial!
Posted 12 May 2007 - 02:24 PM
No problem, i've always enjoyed all forms of encryption and cryptography, but i don't always have time
to pursue it. I will admit the idea of modifying the least significant bit is not really my idea, it has been
used in many programs over the years, and it is the most logical choice if you understand the
importance of each bit. 9/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code

*I also wanted to take the opportunity to properly describe how the GUI works, as it is simple and not
explained anywhere, lol.
Menu Options:

Encode: type or paste the text to encode into the textarea, and press "Encode Now!", this will prompt
you with a jfilechooser, which is to pick your image to encode, then you are prompted for an output file
name (this does not include the extension, as it will always be .png). If the image is encoded correctly,
the end result image will be saved, and then displayed in the decode view.
Decode: will prompt to choose an image, .jpg are available, but it will not work, so select a .png. Once
open, select "Decode Now!" and if the image has a hidden message it will be displayed in the textarea of
encode view.

I have also been adding some encryption abilities to the text, before it is encoded, both encryptions thus
far are bit shifting operations. If there is a demand for it, i can post .jar files of any newer versions i
Posted 28 May 2007 - 05:56 AM

Just awesome work, the "science of secrecy" is entering a new and better world.

On a similar note, there has been "watermarking" available in some graphic programs for some time, I
am guessing this is a type of Steganography?
Looks like you will be in big demand for this sort of work, well done :D

Posted 28 May 2007 - 10:17 AM
watermarking is a similar technique for sure. In fact some theaters even use an invisible watermark on
their movies viewable with correct filters, to help catch people filming them and releasing the
"screeners" online.
This particular method would be the most common hiding spot, the last bit of course, but this technique
can be applied to nearly any media file, i currently have both wav and mp3 correctly embedding. Care
needs to be taken to watch for IDs and other tags used to describe the file, type, and data.

I am working on a way to copy the header of an mp3, while extending the frame length beyond what the
header describes. Thus embedding data within the file, in pieces, but the mp3 header does not know the
data is there. This is instead of using the available storage an ID3 tag allows which is accessible to most
audio players.
*Note that although most english characters only use 7 bits, there is no such thing as a signed char in
java, so the first bit is not available.

The real secret behind making this more useful, is compressing the data, as the media needs to be ~8
times larger than the data being hidden. I have 2 algorithms which will work on standard characters
reducing to 7/8 the original length, but anything smaller seems too hard to retrieve, but I continue to
pursue a better algorithm.
Posted 03 June 2007 - 03:02 AM
I have been trying to study steganography since quite some time now and have searched for resources
on the net. Some have been pure code with no explanation while most of them been techniques with no
proper implementation. But today I think my search ends here on this tutorial. I have no words to
express my thanks to you for this wonderful tutorial. Its just today that I registered and introduced
myself in the forum and this is just what I had been looking for. Thanks alot!
Posted 03 December 2007 - 10:26 AM
This was an extremely detailed and well written article. I've read up on stegonagraphy before on HTS,
but the article was nothing compared to this. Thumbs up! 10/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code

Posted 29 January 2008 - 08:44 PM
Do we need to write a separate interface to run the above code?
Posted 12 February 2008 - 06:09 AM

William_Wilson, on 11 May, 2007 - 06:19 PM, said:
EDIT: Tutorial quote removed to save space W^2

can you give me some basic idea to hide the message behind the audio file plz i am using the java for
that and getting the message through input dialog box and encrypt it and then i want to hide that
encrypt message behind the audio file and send through internet
Posted 12 February 2008 - 06:22 AM
Ouch! Don't quote the entire tutorial! :)

Posted 24 February 2008 - 10:22 AM
I have been completely swamped with school and such lately, but I will consider writing a follow up
tutorial explaining how to handle other files. I currently have code working for wav, mp3, and a couple
more, but i forget at the moment. It is not excessively complicated, but it does include knowing how to
determine if ID3 or ID2 tags exist.
Posted 29 February 2008 - 07:46 AM
U have done an excellent job... But, why didnt you apply any encryption of the text message and use
any keys for decryption n encrytion process... Then only it will be a steganographic system..I mean it
would be more secure with multiple layer security...U just embedded data into the image... Can u
implement it using RSA algorithm for encryption and decryption to the above code... i tryed but not able
to implement. Please help me out.
Posted 05 April 2008 - 02:02 PM
This tutorial was only intended to describe the "basics" as complicated as they are of Steganography.

This method applies the process to text, thus any encryption process you know of could be applied
before hand and then insert the modified text into an image. It would be a simple addition to have a
buffer or stream inserted byte by byte instead of using copy and pasted text.

To implement something like RSA you would want to implement it on its own first, before trying to
combine it with this code.
Posted 11 April 2008 - 04:00 AM
:) Thanx william.this code has helped me a lot,you have done an xcellent job

Thanx again :^:

Posted 06 June 2008 - 06:06 AM
Great post Indeed , Thanks a lot William. The tutorial does enlight the basics of stego. I have just
registered on dreamincode and was reading this topic. I am working on a steganography project
currently supporting wav and bmp (Uncompressed) formats without changing the quality or size. I was
glad to see a true quality post as such that i couldnt find when i was beginning my project lol , I had to
look on lots of websites to understand mechanics of it. Great Work Indeed. about the mp3 format
however i searched yet did not find much of things regarding its format, hoping to see something
regarding it from you in future. Thank you once more 11/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code

Mihir Pandya
(6 Pages)


Last »

Related Java Topicsbeta

Audio Steganography - Coding For

Audio SteganographyAudio Steganography

Steganography Algorithm - What Is The

Algorithm For Developing Steganography?

Steganography - How To Implement The

Steganography In Java

Audio Or Video SteganographyAudio Or

Video Steganography

Steganography - I Need Help In

Steganography Using Java

Code For Audio Steganography - Code For

Audio Steganography For Embed Data
Through Character To Audio

Video Steganography - How To Implement

Video Steganography

Steganography - Actually I M Workin On My

Final Year Project Steganography... I Need

Steganography - Explanation Of Phase Shift

In Audio Steganography

Steganography - Steganography Using Vedio

File 12/13
4/20/2019 Steganography - Java Tutorials | Dream.In.Code

FAQ | Team Blog | Feedback/Support | Advertising | Terms of Use | Privacy Policy | About Us

Copyright 2001-2019 MediaGroup1 LLC, All Rights Reserved

A MediaGroup1 LLC Production - Version
Server: secure3 13/13