stegosaurus

    0.1.2 • Public • Published

    Build Status

    About Stegosaurus

    A very, very basic steganographic device for storing a payload in a (png) image.

    The resulting image (with the hidden payload) should appear to the human eye the same as the original image.

    For a somewhat realistic use-case, you might find it useful to watermark images.

    Unless you're James Bond, then, maybe you'll find another use.

    You'll find a sample original & encoded image near the bottom of this readme.

    Caveats

    • Currently, it only supports png files.
    • I haven't tried it with binary (just ascii text), be a guinea pig, try it.
    • Regarding watermarking: If the images are compresed or resized, it will lose this invisible watermark.

    See future plans, near the bottom.

    Installation

    Just install with NPM, it's that easy.

    npm install stegosaurus
    

    Basic CLI Usage

    CLI Install note For command-line usage, you might want to install it with sudo npm install -g stegosaurus. Otherwise, you'll have to run it with the full path to it. Or add it to your path.

    You can always get some help out of it:

    $ ./stegosaurus.js --help
    
    Usage: node stegosaurus.js [options]
    
    Options:
       -e, --encode                       [mode] Set to encode a TARGET file.
       -d, --decode                       [mode] Set to decode a TARGET file.
       -t FILE, --target FILE             [both modes] Target steganographic file
       -i FILE, --inputmessagefile FILE   [encode mode] A text file with the message to encode (used instead of -m)
       -o FILE, --outfile FILE            [encode mode] Output filename
       -m "STRING", --message "STRING"    [encode mode] A string to encode into the resulting png
       -s NUMBER, --size NUMBER           [decode mode] Number of bytes to decode
    

    Example CLI Usage

    Encoding

    Here we use samples/barn.png as our source, and we encode into the contents of the file samples/dogood.txt (A letter from a series written as a prank by Benjamin Franklin)

    $ ./stegosaurus.js -e -t samples/barn.png -i samples/dogood.txt -o out.png
    File encoded as: out.png
    

    Decoding

    In this version, we need to know how many bytes are in the encoded message. So I use the tool wc (wordcount) to see how many characters are in the text file. Which I use in my command. (If you don't specify how many characters, it will do 128 by default)

    $ wc -c samples/dogood.txt 
    3945 samples/dogood.txt
    $ node stegosaurus.js -d -t out.png -s 3945
    To the Author of the New-England Courant [...]
    

    Usage as Node.js module

    Naturally, you can use this guy as a node module. Essentially three methods you can call.

    Methods

    stegosaurus.encodeFile(original_png, generated_png, message_file_path, [callback(err)])

    • original_png is the path to your source image file (in PNG format)
    • generated_png is the path to the output file that you're generating
    • message_file_path is the path to the message file you'll hide / use as a payload in the generated png.
    • callback when finished encoding, returns if there was an error (as boolean)

    stegosaurus.encodeString(original_png, generated_png, message_string, [callback(err)])

    • original_png is the path to your source image file (in PNG format)
    • generated_png is the path to the output file that you're generating
    • message_string is a string to hide / use as a payload in the generated png.
    • callback when finished encoding, returns if there was an error (as boolean)

    stegosaurus.decode(generated_png, message_size_bytes, [callback(decoded_string)])

    • generated_png is the path to a png with a hidden message
    • message_size_bytes is how many bytes you want to decode from the generated png
    • callback returns with the decoded payload as a string.

    Samples

    Encoding (and then subsequently decoding) a text from a file into a PNG:

    var stego = require("stegosaurus");
    var fs = require("fs");
     
    var original_png = "samples/barn.png"; // The original png file.
    var generated_png = "out.png"; // The resulting file.
    var message_file = "samples/dogood.txt"; // The message we're going to use as our payload.
     
    stego.encodeFile(original_png,generated_png,message_file,function(err){
        if (err) { throw err; }
        console.log("Wrote png to: ",generated_png);
     
     
        // How long was the message?
        fs.stat(message_file, function (err, stats) {
     
            // Now let's decode that.
            stego.decode(generated_png,stats.size,function(payload){
                console.log("Decoded message: ",payload);
            });
     
        });
     
    });

    Encoding (and then subsequently decoding) a text from a string into a PNG:

    var stego = require("stegosaurus");
    var fs = require("fs");
     
    var original_png = "samples/barn.png";  // The original png file.
    var generated_png = "out.png";  // The resulting file.
    var message_string = "Drink more Ovaltine."; // The message we're encoding.
     
    stego.encodeString(original_png,generated_png,message_string,function(err){
        if (err) { throw err; }
        console.log("Wrote png to: ",generated_png);
     
        // Now let's decode that.
        stego.decode(generated_png,message_string.length,function(payload){
            console.log("Decoded message: ",payload);
        });
     
    });

    Sample Images

    Original png image:

    Original image

    Image encoded with first of the Silence Dogood letters

    Image with encoding

    Don't be shy, check out the fullsize original and the full-sized image with encoded message.

    Unit tests

    Run the unit tests by issuing:

    grunt nodeunit

    You'll find the tests in the /test/ folder, for now, just a regression test.

    Node.js version support

    Requires 0.10 or later. Namely due to the dependencies this carries. See .travis.yml for currently supported versions.

    Future Considerations

    In the future, I'd like to expand this module to:

    • Better handle binary using typed arrays
    • This was originally written in an afternoon, and I did somethings to quickly work out the algo. It could be done more efficiently, beautifully.
    • Encrypt the data. (That'd be nice.)
    • Obscure where the data is hidden in the image by using a pre-shared key which defines where it is. Or, compare vs. original (one or both)
    • Determine size of image by packing the size of the message into the encoded message, a la, a header in the stored data.

    Install

    npm i stegosaurus

    DownloadsWeekly Downloads

    2

    Version

    0.1.2

    License

    none

    Last publish

    Collaborators

    • dougbtv