Click here to Skip to main content
Click here to Skip to main content

A Stegano-Framework for .NET Developers

By , 2 Aug 2006
 

Introduction

This article is about turning a collection of hardly reuseable classes into a handy framework. My series of simple proof-of-concept applications and tutorial articles here on CodeProject left me with a heap of functionality. To make it useful, I have built a framework that you can plug into your applications as a black box. There also is a demo application that shows all the framework can do.

The Back End: Workers and Helpers

First I made up a list of properties and methods that all *Utility classes from the existing applications already supported, in order to define an interface from them. Then I realized that some methods (for example GetMessagePart()) appeared in several classes or were implemented somewhere else in the application. So I decided to create an abstract class FileUtility instead of an empty interface and place the common code there.

Why should an application care about which FileUtility to use? I wanted the framework to take a filename and find the right utility from the extension or content. That's what the FileType singleton is there for. It decides which type a given file is, then the concrete *FileType returns the utility object plus some information about what can be done with the carrier file. That means, a framework user retrieves a file type object and a utility object via the filename and can start hiding or extracting data right away.

The result were two base classes, each with a couple of derived classes, and a couple of specialised classes which are being used only by certain utilities. FileUtility actually is abstract. FileType does not represent a concrete type, therefor it should have been abstract, but to avoid "static dirt" I implemented it as a singleton with a few public factory methods.

SteganoDotNet.Action Class Diagram

All these classes are the namespace SteganoDotNet.Action which does the actual steganography. The other framework namespace is SteganoDotNet.UserControls; it makes the configuration of carriers comfortable, but it's not essential. For example, with the Action namespace it is possible to waterwark a song without telling the framework that it's a standard MIDI file:

string originalFileName = @"C:\Somewhere\music.mid";
string resultFileName = @"C:\Somewhere\result.mid";

FileType fileType = FileType.Current.GetFileType(originalFileName);
FileUtility fileUtility = fileType.CreateUtility(originalFileName);
fileUtility.CountBytesToHide = watermarkText.Length;
fileUtility.CountUsedBitsPerUnit = watermarkText.Length/fileUtility.CountUnits;
fileUtility.OutputFileName = resultFileName;

using (Stream message = streamboxMessage.Stream)
{
 Stream formattedMessage = fileUtility.GetMessagePart(message);
 fileUtility.Hide(formattedMessage, new MemoryStream());
}

The Front End: Forms and Boxes

Every file utility needs some basic information like input data stream (not every carrier must be stored in a file!), and output file name. Depending on the file type's stegano-abilities, additional properties need to be configured. For example, a bitmap file utility has to know which regions of the image to use, or a wave file utility needs the count of bits to change per sample. But don't worry, a framework user does not need to know everything about every file type: The namespace SteganoDotNet.UserControls contains GUI parts for every kind of carrier. You don't even have to choose which control to use. Every FileUtility has got a property CarrierConfigurationControl which returns a UserControl with a complete configuration GUI. That control raises the event CancelSettings, when the user cancels the configuration and the file utility is not ready to hide data. When the user has entered and confirmed all settings, the file utility raises its SettingsChanged event.

The following example creates a FileUtility for a bitmap and displays the configuration control. If the user clicks the control's cancel button, the control gets removed and nothing happens. If the apply button is clicked instead, FileUtility_SettingsChanged embeds a message in the bitmap. All configuration information like output file name, whether or not to add random noise, the image regions to use, are collected by the CarrierConfigurationControl. As long as you don't have any cool ideas about the perfect carrier configuration GUI, you can rely on the framework instead of messing with the forms designer.

FileUtility fileUtility = <BR>          BitmapFileType.Current.CreateUtility(@"C:\Somewhere\original.tif");
fileUtility.SettingsChanged += new EventHandler(fileUtility_SettingsChanged);
fileUtility.CarrierConfigurationControl.CancelSettings += <BR>                                     new EventHandler(config_CancelSettings);
fileUtility.CarrierConfigurationControl.ExpectedMessageLength = <BR>                                                     sbMessage.Stream.Length;
((BitmapConfiguration)<BR>             fileUtility.CarrierConfigurationControl).PercentOfMessage = 100;
panelConfig.Controls.Add(fileUtility.CarrierConfigurationControl);

[...]

private void CarrierConfiguration_CancelSettings(object sender, EventArgs e)
{
    panelConfig.Controls.Remove(fileUtility.CarrierConfigurationControl);
}

private void FileUtility_SettingsChanged(object sender, EventArgs e)
{
    FileUtility fileUtility = (FileUtility)sender;
    panelConfig.Controls.Remove(fileUtility.CarrierConfigurationControl);
    Stream fullMessage = fileUtility.GetMessagePart(message);
    fileUtility.Hide(fullMessage, sbKey.Stream);
    fullMessage.Dispose();
}

The prefix sb in sbMessage.Stream stands for StreamBox. This little control encapsulates a GUI part that I needed quite often. No matter how the user decides to enter a piece of content, by filename or plain text, the StreamBox returns the content as a Stream.

StreamBox control

Lossy Sound: The End of Comfortable Controls

The FileType/FileUtility/CarrierConfiguration architecture worked fine for all carrier types, except for the loss resistant audio stuff. I wanted to keep the framework free from third party components, but without support for reading/writing audio discs, the GUI would not seem complete. That's why TapeWaveFileUtility.CarrierConfiguration returns a TapeWaveConfiguration, but as soon as you place it on a form, the utility raises its OpenTapeForm event. Then the application has to show its own modal configuration dialog and copy the settings into the file utility. Take a look at WaveHideForm in the demo application for a complete example. That form reads tracks from an audio disc, allows you to configure each track in a dialog you might know from an older article ^, distributes a message over these audio tracks and finally burns a new audio CD. WaveExtractForm also reads tracks from an audio CD, then it shows a quite equal configuration dialog to make TapeWaveFileUtility find the frequency markers:

TapeForm dialog

Those wave processing dialogs are so complex and user-unfriendly that they did not become parts of the framework. The task of filtering the wave with a bandpass filter before calling TapeWaveUtility.FindAnything() is up to the application itself. FindAnything() is the first step of data extraction: It finds the frequency markers. The application is informed about every single Beep with the BeepFound event. In the demo, WaveDisplayControl handles those callbacks to give the user a last chance for manual corrections (which means, removing false positives). Finally, WaveExtractForm uses the (maybe manually fixed) result to fill TapeWaveFileUtility.Seconds and extract the actual message.

I assume you have not read the entire last preceding paragraph. You're right. Preparing a wave for message extraction is a little too complicated and I'll try to make things easier in the next version. Until then, I suggest you copy TapeForm and WaveDisplayControl into your own application, if you want to use loss resistant audio steganography.

Back to the Roots

At this point, I had a useful framework and a huge demo application which I called S4U (Steganography for You). I presented it as my exam project at evening school and got top grades. Then school was over and I had too much spare time. Why not turn the whole thing into an open source project? Nice idea, but three components I integrated for audio features are not published under GPL: The wave recorder^ and the CD ripper^ are samples from CodeProject, Steve McMahon's IMAPI-Wrapper ^ is a Creative Commons library.

I did not really solve that problem. That means, i did - if you call deletion of features a solution. When I had removed all CD ripping/burning and wave live recording dialogs, the framework and the demo application were free from third party code. Both still call Sound Exchange^, but this one is not compiled into or referenced by my assemblies, and anyway, it is GPL software.

Now that my steganography framework was ready to become a GPL licensed open source project, I needed a version control system, a bug tracker, a place for documentation, releases, forums and feature request ... in short words: I registered a SourceForge^ account and a project called SteganoDotNet^. The next day my project was accepted and I could check in all my files. Well, that's the way my steganography tutorials will go from now on: You have great ideas? Come to SourceForge and code them into the framework! Especially I'd be very happy about anybody who added JPEG support, or a new audio CD ripper/recorder ... welcome to my first open source project, feel free to join and make it the stegano-framework for the .NET world. :-)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Corinna John
Software Developer
Germany Germany
Member
Corinna lives in Hannover/Germany (CeBIT City) and works as a Delphi developer, though her favorite language is C#.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionGPL = useless licensememberloizzi2 Aug '06 - 19:45 
Hello,
 
I already read some articles from you but this is the best. Sadly you decided for the useless GPL license so I can't use this framework for commercial applications. How about the LGPL?
 
Die meisten Quellen sind hier entweder frei oder unter der LGPL, GPL ist eher was für open source Apostel... Roll eyes | :rolleyes:
 
Ciao
 
Frank Loizzi
Dortmund
Germany
Answeruseless for you, protection for mememberCorinna John2 Aug '06 - 19:56 
Hallo Frank,
 
you considered using it in a commercial app? You wanted to make money from my free work?! That's lazy of you, is it? Roll eyes | :rolleyes:
 
It's your right to analyse the code, learn from it, write your own library and then sell it. But you won't make your customers pay for code I gave you for free. That's my reason for GPL. Poke tongue | ;-P

GeneralRe: useless for you, protection for mememberloizzi2 Aug '06 - 20:47 
Hallo Corinna,
 
I do not want sell your code, I only want to use it in a commercial application for copy protection purpose. So I want use it in the manner of its state of aggregation, as library. I don't talk about selling your library as Stegano-Framework.dll.
 
Bye
 
Frank Loizzi
Dortmund
Germany
 

GeneralRe: useless for you, protection for mememberCorinna John3 Aug '06 - 1:23 
Hey Frank,
 
as I found out, you actually can use GPL licensed components in commercial software. You only cannot use it in closed source software. If you ship the source code with every copy of your application, it's perfectly fine. The only problem you might run into is that the users are allowed to copy the application and give it to other people who would otherwise have to buy it from you.
 
Look here: http://www.gnu.org/philosophy/free-sw.html[^]
 
"A program is free software if users have all of these freedoms. Thus, you should be free to redistribute copies, either with or without modifications, either gratis or charging a fee for distribution"
 
That means, you may charge a fee for your free program.
 
"You should also have the freedom to make modifications and use them privately in your own work or play, without even mentioning that they exist."
 
Ain't that great? You can even enhance the framework to make it embed real StirMark-safe watermarks! (Usually it creates LSB messages, that's not good for copyright protection...)
 
"You may have paid money to get copies of free software, or you may have obtained copies at no charge. But regardless of how you got your copies, you always have the freedom to copy and change the software, even to sell copies.
'Free software' does not mean 'non-commercial'. A free program must be available for commercial use, commercial development, and commercial distribution. Commercial development of free software is no longer unusual; such free commercial software is very important.
"
 
I couldn't have said it in better words.
 
"The freedom to redistribute copies must include binary or executable forms of the program, as well as source code, for both modified and unmodified versions."
 
Yes, your commercial application must be distributed with source code. Anyway, you may also charge some money that that process (and for the CD, for the service, for ... )
Look at SUSE Linux: Novell earns money by selling distributions, even though every customer can copy his copy. It actually seems to work. Smile | :)
 
Have Fun
coco
 

 

GeneralRe: useless for you, protection for mememberloizzi3 Aug '06 - 4:25 
Hallo Corinna,
 
thanks for the explanations but I already knew about the meaning of GPL license. Thats the reason why I wrote GPL = useless license. You have to deliver your source with your software and I can't do that, because the source is my intellectual property and that is the only reason why I can sell software. If I deliver my work with my applications I deliver my work to thousands of plagiarist and there is no more to sell. Smile | :)
 
Furthermore I can't deliver source code from libraries that are closed source and which I bought and which I use in the same application. So the GPL license is a very useless license, thats the reason why mainly the LGPL license is used. What about your problem with the LGPL license?
 
My target group is the private customer not the industrial audience. So I can't provide only support services and live from that. I have to make money to pay my bills like any other.
 
If you don't change your mind, I unfortunately can't use your work. But it is indeed a nice article and you are indeed cute as a button. Wink | ;-)
 
Grüße aus Dortmund...
 
Frank Loizzi
Dortmund
Germany
GeneralRe: useless for you, protection for mememberJohn Rayner3 Aug '06 - 8:38 
loizzi wrote:
If I deliver my work with my applications I deliver my work to thousands of plagiarist and there is no more to sell

 
Don't you think that's a bit rich? You're trying to use someone else's source code for free, but you don't want other people to use your work for free. It's more than a little bit hypocritical.
 
loizzi wrote:
My target group is the private customer

 
This means that they will generally not know how to program. In other words, they are unlikely to actually do anything with your source code.
AnswerRe: useless for you, protection for mememberloizzi3 Aug '06 - 10:33 
John Rayner wrote:
loizzi wrote:
If I deliver my work with my applications I deliver my work to thousands of plagiarist and there is no more to sell
 
Don't you think that's a bit rich? You're trying to use someone else's source code for free, but you don't want other people to use your work for free. It's more than a little bit hypocritical.

 
Yes. So what? I really don't understand what you mean? Do you know SourceForge or even Codeproject? Do you think this is a source stock exchange? Most projects exist for fun, for learning purpose, for beta testing and so on. Can you explain whats exactly your problem?
 
loizzi wrote:
My target group is the private customer
 
John Rayner wrote:
This means that they will generally not know how to program. In other words, they are unlikely to actually do anything with your source code.

 
Thats simple-hearted. Do you really think that? First (I guess you have not read my post exactly) every competitor is able to produce an own version of my work. Thats something really bad. Dead | X|
 
Second, there is a massive security problem for people they do nothing (like you said) with the source code.
 
And finally I have no motivation to produce sophisticated software if I can't earn money from this work.
 
I don't want to discuss this anymore, because this is to self-evident and I don't depending on this framework. So I simply work for my own or look for another project.
 
Bye
 
Frank Loizzi
Dortmund
Germany
 

GeneralWhat about a second license?memberttoni664 Aug '06 - 2:08 
So, why don't you offer Corinna some money to give her code to you under some other license, like LGPL or something even more commercial? A lot of free software projects do this and it seems quite sensible to me. Both sides win.
AnswerRe: What about a second license?memberloizzi4 Aug '06 - 2:57 
Hello,
 
yes, you are right. But I don't essentially need her framework to build applications. It would only be a nice extension to some kind of application. So I have no motivation to pay for it. Mainly I was simply telling her that the GPL license is a kind of viral license and has nothing to do with freedom or protection. Unfortunately she isn't telling us whats wrong with the LGPL and what kind of protection offers the ideological GPL license for her. So I think she has decided to stop responding and I look for something different.
 
Bye
 
Frank Loizzi
Dortmund
Germany
GeneralRe: What about a second license?memberlolocmwa15 Aug '06 - 23:46 
So no motivation to pay for it ! But still motivation to get paid for it ? Indeed you lose so much time to get something free, maybe we shoud pay you to help you getting what you want Smile | :)
 


General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 2 Aug 2006
Article Copyright 2006 by Corinna John
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid