Differences between revisions 2 and 3
Revision 2 as of 2011-03-10 18:17:59
Size: 6085
Editor: SimonMarsden
Comment:
Revision 3 as of 2011-03-11 10:02:22
Size: 6114
Editor: SimonMarsden
Comment:
Deletions are marked like this. Additions are marked like this.
Line 10: Line 10:
|| PUT PHOTOS HERE!!! || {{attachment:photo.bmp}}
{{attachment:modified.bmp}}

Studio

Fun With secret messages hidden in pictures

Page under construction

A previous Wiki article discussed how to hide a secret message in a block of apparently random text, a 500-year old technique known as a Grille Cypher. For a bit of fun, let's look at the modern equivalent - how to hide a message inside a photograph. In the example below the first picture is unmodified, but the second one has a 1000 word secret message hidden in it. Can you spot the difference?

photo.bmp modified.bmp

Modern computers typically use a 24-bit encoding for colours. Each of the Red, Green and Blue components of a pixel is represented using 8 bits, so a modern graphics card can display (2*8)*3 or 16777216 different colours. In fact the colour value is often encoded in a 32-bit word; the high byte is either unused or represents a transparency value.

A person looking at a colour image is very unlikely to notice if we make very slight changes to the pixel values. For example we can flip the bottom bit of the pixel colour, and it's almost certain to pass undetected. We can use this to hide a secret message inside a picture.

For the demonstration which follows I'll assume that the photograph has already been read into an APL variable, and that it takes the form of an M x N matrix, where M and N correspond to the dimensions of the photo. Each value is an integer representing the 32-bit encoded colour of a single pixel. (At the end of this article I've included a brief description of how to read in a picture using APLX).

Random Numbers

APL is able to generate random numbers using the ? function. For example to get 10 random numbers in the range 1 - 20 you could type:

      10?20
10 9 13 3 20 11 6 16 5 8

Normally if we type 10?20 again we will get a completely different sequence of random numbers. However by re-setting the Random Link ⎕RL we get a repeatable sequence:

      save_rl←⎕RL      
      10?20
20 6 10 7 4 2 14 18 15 19
      ⎕RL←save_rl
      10?20
20 6 10 7 4 2 14 18 15 19

We can use this information when hiding the message in the picture. First we choose a random sequence of pixels to modify, so that the tampering is less likely to be noticed. Provided that the person receiving the modified picture knows the value of ⎕RL we used and the sequence length, they will be able to reconstruct the random sequence so they will know which pixels contain the message.

For simplicity the example below hides⎕RL at the start of the picture, together with the length of the secret message. If you care about security you could use a pre-agreed value instead!

Converting a value to Binary

We want to hide the secret message by only modifying the bottom bits of randomly selected pixels, which means that we can only store 1 bit of information per pixel. This means that we need to convert the secret message to binary, which can be done using APL's Encode primitive . Here is an example of an encode and a corresponding decode:

      encoded←2 2 2 2 2 2 2 2⊤1 2 3 4 5
      encoded
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 1
0 1 1 0 0
1 0 1 0 1
      2⊥encoded
1 2 3 4 5

Modifying the bottom bit of a number

We're now ready to insert our binary-encoded message into some randomly chosen pixels. One way to do this would be to convert the pixel values to binary, replace the bottom bits with values from our message, and convert back to integers. However, there's an easier way which doesn't require conversion to binary. We compare the current value of the bottom bit to the desired value, and flip it if it's wrong.

For example, imagine you want to insert the binary message 1 0 1 1 0 1 1 0 into the bottom bits of pixels with the values 5012853 1921862 1858884 5282424 9758136 7981975 9492903 6200428. The current values of the bottom bits are given by:

      vals←5012853 1921862 1858884 5282424 9758136 7981975 9492903 6200428
      2|vals
1 0 0 0 0 1 1 0

In some cases the current bit already equals the desired bit. In other cases it's a 0 and needs to be a 1; and in other cases it's a 1 and needs to be a 0. We can handle this as follows:

      encoded←1 0 1 1 0 1 1 0
      vals ← vals + (encoded > 2|vals) - (encoded < 2|vals)

Finally we can recover the secret message:

      2 | vals
1 0 1 1 0 1 1 0

The Final Functions

We're now ready to put the steps into two functions as follows:

∇  R←bitmap EncodeText text;length;encoded;bm;vals;idx;⎕RL
   ⍝ Takes text and encodes it into least significant bits
   ⍝ of bitmap, where it will be embedded without affecting the
   ⍝ visual appearance of the bitmap

   bm←,bitmap

   ⍝ Each character of text will give 8 binary digits
   length←8×⍴text

   ⍝ Encode the value of ⎕RL and the text length
   encoded←,(32⍴2)⊤⎕RL,length

   ⍝ Encoded the text message too
   encoded←encoded, ,(8⍴2)⊤⎕av ⍳ text

   ⍝ Choose random positions to modify, except for ⎕RL and the length,
   ⍝ which we'll put at the start of the bitmap so the decoder can find them
   idx←(⍳64),64+length?¯64+⍴bm

   ⍝ Modify the bottom bits
   vals←bm[idx]
   bm[idx]←vals + (encoded > 2|vals) - (encoded < 2|vals)

   ⍝ Reconstruct bitmap with secret text embedded
   R←(⍴bitmap)⍴bm

∇ R←DecodeText bitmap;bm;rl;random;vals;⎕RL

   ⍝ Regenerate the sequence of random numbers
   bm←,bitmap
   (rl length)←2⊥(32 2)⍴2|64↑bm
   ⎕RL←rl
   random←64+length?¯64+⍴bm


   ⍝ Extract the binary representation of the text
   vals←2|bm[random]

   ⍝ Reconstitute the secret message
   R←⎕av[ 2⊥(8,length÷8)⍴vals]

Working with images in APLX

WRITE THIS BIT!!!

Author: SimonMarsden

Studio/SecretMessages (last edited 2017-02-16 18:44:54 by KaiJaeger)