aspose file tools*
The moose likes I/O and Streams and the fly likes DataOutputStream / WAVE steganography Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » I/O and Streams
Bookmark "DataOutputStream / WAVE steganography" Watch "DataOutputStream / WAVE steganography" New topic
Author

DataOutputStream / WAVE steganography

Stephen Longville
Greenhorn

Joined: Mar 25, 2010
Posts: 15
didnt know where else to put this (as i am using the DataOutputStream to write a text file)

first off let me say i am aware of javas non unsigned types issue.
im trying to make a stego tool to hide simple .text files inside WAVE files.

the Attachment shows what i decode from the .wav file and the origonal text next to it

i'l post code if need be, i was just wondering if anyone knew offhand why it starts to work then trails off.

as it stands, i am reading one byte at a time and converting them to a BitSet(8), do i need to be reading in 2 bytes at a time or prhaps a bigger BitSet?
im also using System.arraycopy() to copy the changed byte into a new byte array (for writing).

Audio info:

Format: WAVE / PCM
Size: 55.78449630737305MBChannel Type: Sterio
Sample Rate: 44100Hz
BPS: 16
Byte Rate: 176400

i should also probably mention im using lsb technique, and at this moment the hidden bits are placed in the first x bytes of the Data Chunk of the WAVE file (x being the number of bits the .txt file is made up of)

Cheeres.
Java Greenhorn Stig.


[Thumbnail for decoded.jpg]

Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2861
    
  11

Hi Stephen, welcome to JavaRanch!

It sounds like a fun project, but you're not really giving us enough information to go on. How are you adding the text to the wav without corrupting it? In any case, I think you would need to get the text in a byte array, which is fairly easy because it looks like simple ASCII. Then I'd guess you'd read some data from the wav file, manipulate some bits, and then write it back to your "stego" wav file. I'm not clear why you're using a DataOutputStream though, since I think all you need to do is write bytes to a file, which you can do with a simple FileOutputStream. I'm also not clear how Java's integer types being signed affects you in any way. I assume it trails off the way it does because you're doing something wrong, but I can't guess what that would be without some more detail.
Stephen Longville
Greenhorn

Joined: Mar 25, 2010
Posts: 15
hi greg thanks for the warm welcome.

im not currently sure what the difference between file / data or even audio input stream (i origonaly started out using the audio input stream to read the bytes of the wav file but this didnt go too well)

this is how im encoding the wav file:



and my decoder;



theres also an issue with endians (big/small) the WAVE file is apparently little but i read somewhere most things use big (like .txt files) but i think iv encoded little endian LSB (farthest left).
its all alot to get my head arround and mabey not the best of choices for my project but yes it is fun none the less.

Cheeres.
Stig.
Stephen Longville
Greenhorn

Joined: Mar 25, 2010
Posts: 15
ok im now using a File input / output stream directly, tried a number of things such as changing my byte to bit and vice versa methods making sure they work.

doesnt matter what txt file i use the first 31 characters display fine and the rest is along the lines of "ol}lyèýÿïî¯ëï.ÿïï¾çï"

this is realy wierd, any ideas anyone?
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2861
    
  11

Hi Stephen,

Sorry, I've been traveling for the past week, so I haven't had a chance to get back to you.

I looked up WAV format and found this:

Offset Contents
(hex)
0000 'R', 'I', 'F', 'F'
0004 Length of the entire file - 8 (32-bit unsigned integer)
0008 form type (4 characters)

000C first chunk type (4 character)
0010 first chunk length (32-bit unsigned integer)
0014 first chunk's data
... ...


So, I assume you want to take a character from your text file and store it in lowest order bit of each of eight (or sixteen if you allow Unicode) bytes of the WAV's data chunks. If you store it in the metadata areas (chunk type or chunk length), you will probably corrupt the WAV file. The big-endian / little-endian comes into play for you because you have to know how to interpret the length. So your algorithm is going to be something like:

ENCODE:
< Skip past RIFF header
> Write RIFF header into new file
< Read length of entire file (and maybe confirm it's long enough for your text)
> Write length into new file
while you still have chunks left
< Read chunk type
> Write chunk type into new file
< Read chunk length
> Write chunk length into new file
< Read chunk into byte array
while you have eight bytes left in chunk
get a character from your text
set low order bit of next eight bytes to the eight bits of the character
> write byte array to new file

Done! Note that when you run out of characters, you're going to want to change gears a bit and just copy the rest of the input file directly to the output file.


DECODE:
Skip past RIFF header
Skip past length of entire file
while you still have chunks left
Skip chunk type
Get chunk length
Read chunk into byte array
while there are still eight bytes left in chunk
build up a character from low order bits of the next eight bytes
add the character to a string

Done!

Actually, you will still get gibberish at the end since there's no way to check how long the original text was. Maybe you want to encode the text length into WAV file first. That's just some extra polish though.


Stephen Longville
Greenhorn

Joined: Mar 25, 2010
Posts: 15
thanks for the reply greg:

if slightly changed the code since my last post, i now write as soon as each byte is ready, as for your advice, unless im mistaken i belive i'v already done this

within my gui i type the size of the file to be extracted (and how many(for now just one)) just to make sure its working but i still get gibberish when i extract anything past 32 characters (or bytes).

e.g. encoding the text file with: "This is my secret message" (25 bytes) works as its short, but iv been trying it with a script of hamlet i found somwhere in .txt format (201789 bytes)

to avoid any confution heres my encoding / decoding up to date:



encoder writes new WAVE header info, then begins to loop through the file data taking each byte converting it to bits and changes it aquordingly




also heres how i convert to and from bits to bytes:





could it be a memory problem? something which makes me think so is that it gives memory errors when i try and run it in university (on holiday at the moment) so i can only run it at home.

Phew...

cheres.
Stephen Longville
Greenhorn

Joined: Mar 25, 2010
Posts: 15
P.s. if i convert the byte to a char and add it to a string (or even print it out) it still comes out the same (first 31 characters are ok and the rest is nonsence)

cheers.
Stephen Longville
Greenhorn

Joined: Mar 25, 2010
Posts: 15
i dont wanna jump to conclutions but...WOOOOOHOOOOOO i think i did it, if ya intrested i re wrote the encoder seeming doing everything the same and it didnt work then i added the else statement in this little chunck of code...

...and hey presto it workes, now i gotta tidy it up a bit...looks like a bomb hit my IDE

thanks for trying to help greg.
i'll be sure to post if it turns sour >.< (fingers crossed)

still odd though how the first 30 or so characters came out fine without this little fix
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2861
    
  11

Congratulations! Yep, little things like that can really trip you up. Incidentally, I'd guess the first 31 characters worked because the chunk of audio data started with a bunch of zeroes (or less likely a bunch of even values), so it didn't matter you weren't clearing the lsb. Once you got to audio data that had some of those bits set, you were seeing problems.
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42612
    
  65
Stephen Longville wrote:

As an aside, this can be shortened to

bit.set(0, bit1.get(j));

Ping & DNS - my free Android networking tools app
Johnny Harrows
Greenhorn

Joined: May 16, 2011
Posts: 1
Sorry to post in old thread. Where is the v object declared in your code and how is it defined?

My guess is it is a Vector, but where does it get its data from in your code? Could you explain or show?

Thanks.



Also, where does this little bit of info go? I don't see it at all in your encode.

-
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
Stephen Longville wrote:...


where is the getSubchunk() and getDataChunk located?
I cannot find one.
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42612
    
  65
Possibly from http://code.google.com/p/esn-android/source/browse/trunk/?r=138#trunk%2Fsrc%2Fesn%2Fclasses or http://www.javadocexamples.com/java_source/apo/io/fields/WaveStructure.java.html. (I know nothing about these, I found them via a quick Google search.)
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
It's working! but the variable v is of what type?
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
totalFileData = new byte[(int)v.elementAt(0).getFile().length()];

I'm getting an error here.
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42612
    
  65
Impossible to say, as we don't know the code where that snippet is taken from.
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
It;s actually taken from [ the above code ].

cheers.

[ UD: removed duplicated code - see the code posted above ]
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2861
    
  11

V isn't declared anywhere in that code, which is either a mistake or it's declared as a member variable of the class. Given its name and the elementOf() method, I guess it is meant to be a Vector, which is a class we don't use much anymore.
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
So with what code do I substitute then?
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42612
    
  65
From the context I would guess that it's a list of WAV files to be processed.
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
Can you help me with the code?I'm not quite sure how to go about it.
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2861
    
  11

ArrayList is the normal substitution for Vector. It also is basically a growable array, but it's not synchonized like Vector, so it performs better in single-threaded contexts.

What help do you need with the code exactly? Don't just say it doesn't work, but what doesn't work, where in the code the problem happens, and what the error message is. Something like that we can help with.
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
totalFileData = new byte[(int)v.elementAt(0).getFile().length()];

This is where the error actually happens.
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
I'm actually tryin' to read the dataChunk into the audio data array but I don't exactly know how to go about it.
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2861
    
  11

Kordor Pyrbot wrote:totalFileData = new byte[(int)v.elementAt(0).getFile().length()];

This is where the error actually happens.


Again, please tell us what the error is. Is it a compile error or a runtime error? Do you get an error message? If not, how do you know it's an error?
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
Stephen Longville wrote:thanks for the reply greg:

if slightly changed the code since my last post, i now write as soon as each byte is ready, as for your advice, unless im mistaken i belive i'v already done this

within my gui i type the size of the file to be extracted (and how many(for now just one)) just to make sure its working but i still get gibberish when i extract anything past 32 characters (or bytes).

e.g. encoding the text file with: "This is my secret message" (25 bytes) works as its short, but iv been trying it with a script of hamlet i found somwhere in .txt format (201789 bytes)

to avoid any confution heres my encoding / decoding up to date:



encoder writes new WAVE header info, then begins to loop through the file data taking each byte converting it to bits and changes it aquordingly




also heres how i convert to and from bits to bytes:





I'm not quite sure what's happening in line number 39 & 40.please help & what packages is the coder using?
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
Hey there helper.Down below is how my encoding code is.now how do I exactly append the encrypted message into the audioBytes array?kindly help.
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
Hey Ulf can you help me with the insertion of text into a wave file datachunk?
Tony Docherty
Bartender

Joined: Aug 07, 2007
Posts: 2366
    
  50
Please don't keep asking for help, PatienceIsAVirtue (← click). We are all volunteers here and will help as soon as we can.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18904
    
    8

Kordor Pyrbot wrote:Hey Ulf can you help me with the insertion of text into a wave file datachunk?


Is that related to the chunk of code you posted earlier? If so you're going to have to explain how the code is relevant. I couldn't figure out how the original question was relevant to that code -- for example I didn't see anything which looked like an encrypted message there. And now you're asking about inserting text, presumably into the byte array which that code fills? That requires explanation too.
Kordor Pyrbot
Greenhorn

Joined: Dec 15, 2013
Posts: 13
Is that related to the chunk of code you posted earlier? If so you're going to have to explain how the code is relevant. I couldn't figure out how the original question was relevant to that code -- for example I didn't see anything which looked like an encrypted message there. And now you're asking about inserting text, presumably into the byte array which that code fills? That requires explanation too.


Thank you for the response.I've posted the code earlier.That was just to insert the wav file to a byte array.Let's analyze the code again.

this code is executed when my 'Encode' button on my GUI is clicked.I've extracted the audio data and it's stored in the audioBytes array.The text will be extracted from a text file chosen by the user or from a TextArea where the user may enter the text manually.Then the text will be encrypted using DES algorithm.The variable that holds this text is named 'enctext'.
Now,how do I append this text to the wave file bits contained in the audioBytes array?Do I have to convert the encrypted text 'enctext' to bits or to bytes?Kindly help me with the code to accomplished this.
 
jQuery in Action, 2nd edition
 
subject: DataOutputStream / WAVE steganography