Git Product home page Git Product logo

bpcs's Introduction

BPCS Steganography

The goal of steganography is to hide a message in plain sight. BPCS is a method to embed a message in an image by replacing all "complex" blocks of pixels in the image with portions of our message. It turns out that portions of the image with high complexity can be entirely removed (or in this case, replaced with our message) without changing the appearance of the image at all. Because most blocks of pixels are complex (i.e., with complexity above some threshold, alpha), you can usually replace around 45% of an image with a hidden message. Below, the 300x300 image on the right contains the text of an entire novel, while still looking virtually identical to the vessel image on the left.

vessel out

Note that with BPCS, the hidden message doesn't have to be text. It can be any file type, including another image.

You could upload a profile photo to a website that contains a secret image. Or you could embed an image of a turtle inside an image of a turtle inside an image...turtles all the way down.

This is an implementation of the method discussed in: Kawaguchi, Eiji, and Richard O. Eason. "Principles and applications of BPCS steganography." In Photonics East (ISAM, VVDC, IEMB), pp. 464-473. International Society for Optics and Photonics, 1999. (pdf)

Encoding and decoding

First, we want to embed a file in a vessel image. Here, we'll embed the text of an entire novel in a 300x300 image.

$ python -m bpcs.bpcs encode -i examples/vessel.png -m examples/message.txt -a 0.45 -o examples/encoded.png

Now, given the encoded image, we want to recover the message hidden inside it.

$ python -m bpcs.bpcs decode -i examples/encoded.png -a 0.45 -o examples/message_decoded.txt

The output, message_decoded.txt, should be the same as message.txt, which means we have recovered our original message.

Checking a vessel image's message capacity

Given a vessel image file and an alpha value, we can assess the maximum size message that we could encode.

$ python -m bpcs.bpcs capacity -i examples/vessel.png -a 0.45

The vessel image in the examples folder is 158 KB, and can store a hidden message of up to around 66 KB.

Customization

The goal of steganography is to hide things in plain sight. For this reason, BPCS doesn't use a secret key or password for encoding and decoding. However, aside from varying the alpha parameter, one way to customize the BPCS procedure is by adding custom encryption and decryption to the message before and after using BPCS.

Run as a module

import bpcs

alpha = 0.45
vslfile = '../examples/vessel.png'
msgfile = '../examples/message.txt' # can be any type of file
encfile = '../examples/encoded.png'
msgfile_decoded = 'tmp.txt'

bpcs.capacity(vslfile, alpha) # check max size of message you can embed in vslfile
bpcs.encode(vslfile, msgfile, encfile, alpha) # embed msgfile in vslfile, write to encfile
bpcs.decode(encfile, msgfile_decoded, alpha) # recover message from encfile

Running tests

$ python -m bpcs.bpcs test

bpcs's People

Contributors

mobeets avatar parthkolekar avatar speak2erase avatar yorlock avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

bpcs's Issues

AssertionError during decode if payload takes around more than 2 and less than 64 grids. Successful decodes could have null bytes at the end.

Hello once again.

I was experimenting around with this library, I found that the decoding part has quite a bit of issues.

Take the following 3 test payloads.

test1.txt

test

test2.txt

test test

test3.txt

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

test test

All these ran using the example image with 0.45 alpha.

test1.txt and test3.txt successfully encoded and decoded. However the decoded test1.txt and test3.txthas 3 and 5 null bytes respectively at the end of file.
test2.txt passed encoding but suddenly fails at decoding as it throws AssertionError. I tested around the length of message and found it always would fail if it takes up around more than 2 grids but less than 64.

Traceback (most recent call last):
  File "/usr/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/runner/BPCS-Test/bpcs_mobeets/bpcs/bpcs.py", line 55, in <module>
    decode(opts.infile, opts.outfile, opts.alpha)
  File "/home/runner/BPCS-Test/bpcs_mobeets/bpcs/bpcs_steg_decode.py", line 34, in decode
    write_conjugated_message_grids(outfile, grids, alpha)
  File "/home/runner/BPCS-Test/bpcs_mobeets/bpcs/array_message.py", line 190, in write_conjugated_message_grids
    messages, conj_map_grids, nbits_per_map = separate_conj_map_from_message(grids, alpha)
  File "/home/runner/BPCS-Test/bpcs_mobeets/bpcs/array_message.py", line 174, in separate_conj_map_from_message
    x = get_n_message_grids(nbits_per_map, ngrids)
  File "/home/runner/BPCS-Test/bpcs_mobeets/bpcs/array_message.py", line 154, in get_n_message_grids
    assert x > 0
AssertionError

I have setup a REPL.it workspace to show my test results:
https://repl.it/@Cerlancism/BPCS-Test#main.sh

I have reduced the size of image to 150x150 to speed up in REPL.it. Similar results shows for the provided example image.

Update

One of my friend catkane-doodles has forked this repo and he seemed to have fixed this. However, he did a complete revamp. Not sure if we could PR in.

Capacity is throwing TypeError: '>=' not supported between instances of 'float' and 'NoneType'

Encode and decode works fine. However when I tried to get the capacity from images, including the given example, it throws
TypeError: '>=' not supported between instances of 'float' and 'NoneType'

$ python -m bpcs.bpcs capacity -i examples/vessel.png -a 0.45

Output:

Slicing...
Graying...
Loaded image as array with shape (300, 300, 3, 8)
Creating histograms of image complexity...
Found 34656 grids
D:\Documents\GitHub\bpcs\bpcs\bpcs_steg_capacity.py:15: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.
  vals = [arr_bpcs_complexity(arr[dims]) for dims in get_next_grid_dims(arr, grid_size)]
Grid 10000 of 34656
Grid 20000 of 34656
Grid 30000 of 34656
Traceback (most recent call last):
  File "C:\Users\CHE-Main\AppData\Local\Programs\Python\Python38-32\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Users\CHE-Main\AppData\Local\Programs\Python\Python38-32\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "D:\Documents\GitHub\bpcs\bpcs\bpcs.py", line 62, in <module>
    capacity(opts.infile, opts.outfile, opts.alpha)
  File "D:\Documents\GitHub\bpcs\bpcs\bpcs_steg_capacity.py", line 96, in capacity
    histogram(infile, outfile, alpha, greater)
  File "D:\Documents\GitHub\bpcs\bpcs\bpcs_steg_capacity.py", line 76, in histogram
    hist = x.modify(alpha, comp_fcn)
  File "D:\Documents\GitHub\bpcs\bpcs\bpcs_steg_capacity.py", line 53, in modify
    hist, navail, ntotal = histogram_of_complexity(self.arr, grid_size, alpha, comp_fcn)
  File "D:\Documents\GitHub\bpcs\bpcs\bpcs_steg_capacity.py", line 21, in histogram_of_complexity
    navail = sum([n for n, bin in zip(ns, bins) if comp_fcn(bin, alpha)])
  File "D:\Documents\GitHub\bpcs\bpcs\bpcs_steg_capacity.py", line 21, in <listcomp>
    navail = sum([n for n, bin in zip(ns, bins) if comp_fcn(bin, alpha)])
  File "D:\Documents\GitHub\bpcs\bpcs\bpcs_steg_capacity.py", line 95, in <lambda>
    greater = lambda x,thresh: x>=thresh
TypeError: '>=' not supported between instances of 'float' and 'NoneType'

My Environment

Windows 10 2004 and Windows 10 1909
Python 3.8.3

Side note

This library also seem to need matplotlib but it is not stated in the requirements.txt

Cannot encode character

Hello sir,

Currently I am experimenting by combining AES file encryption (cryptography) and BPCS (steganography) for better data security on Jupyter Notebook. All went smooth, until i want to decode the encfile (image with encrypted file in it). It says :

UnicodeEncodeError: 'charmap' codec can't encode character '\x92' in position 309: character maps to

Can you help me fix this issue? i guess there is a problem in Notebook but i cannot figure it out

AssertionError if the grids are between 2 and 64 grids (refer to previous issue)

Good day Sir, sorry to bother you again. I am currently experimenting with both your repo and a repo i found on the previous (currently active) issue by Pekai-tan.

This repo is fine and working well if the message grids are either 1 grid or more than 64 grids, and repo by Pekai-tan only working if the message grids are between 2 and 64 grids and if more than that, the decoded message will be null.

I wonder if there is a way to make it work well without the message grids problem.

Again, sorry to bother you again Sir

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.