How I solved the Secret Announcement
Lord_Poseidon (158)

A Detailed Solution to Secret Announcement


You are most likely busy creating a game for the game jam and you probably know that an announcement came 2 weeks before the jam as a secret message using steganography I was one of those chaps who actually solved the secret, but didn't do anything.
The challenge can be found here. There was a solution, but that was not very explanatory.This post will explain how ~I~ solved the announcement. This post assumes basic knowledge of the binary system.

The first thing I did after seeing the newsletter was to read up on steganography.I found this on wikipedia:

Concealing messages within the lowest bits of noisy images or sound files


Reverse Engineering:

Then, I looked at the code.Apart from imports and loops to go through all pixels,this was the crux of the code:

 secret_red = secret_pix[0] >> shift_amt
 secret_green = secret_pix[1] >> shift_amt
 secret_blue = secret_pix[2] >> shift_amt

 public_red = public_pix[0] & all_except_LSB_mask
 public_green = public_pix[1] & all_except_LSB_mask
 public_blue = public_pix[2] & all_except_LSB_mask
 final = (
      secret_red + public_red,
      secret_green + public_green,
      secret_blue + public_blue

>> and & are binary operators.shift_amt was 7 and all_except_LSB_mask was 254
What does the >> operator do? It shifts the bits towards towards right.For example:
11100010101 >> 6 outputs 11100 i.e. the last 6 bits are removed.
In our case, all the 8 bit data(because 255 is the maximum in RGB color format and 255 is 8 bits) is shifted by 7 bits so that would leave only the highest bit as one or zero. This would also imply that anything greater than 127.5 (255 / 2) would leave 1 while anything lesser would leave zero.
10101010 >> 7 == 1
01010000 >> 7 == 0
So that's our secret pixel
Then, we see the & operator with all_except_LSB_mask as 254.The & operator is called bitwise and. Basically, it returns one only if both expressions are one.Like
1&1 == 1
1&0 == 0
0&0 == 0
An important property of the & operator is that something & all 1s = something another one is that something & 0 = 0
254 in binary is 11111110
So,all the bits except the last one would remain intact
10011011 & 11111110 ==10011010
So,this would turn all public pixels into even numbers as the last bit is 2**0=1 and if it is absent, the number must be even. The final pixel is secret_pix + public_pix.We know that public pix is either 0 or 1.Since the last bit of public pix is always zero,The last bit of final pixel must reflect the secret image.
So here's my code:

from PIL import Image'out.png').convert('RGB')'RGB',(600,600))
for x in range(600):
    for y in range(600):
        secret.putpixel((x,y),tuple((i%2)*255 for i in public.getpixel((x,y))))'secret.png')

All the juicy stuff is in one line:(i%2)*255 for i in public.getpixel((x,y) What this does is:

  • take the public pixel
  • compute modulo two (returns 1 if odd and 0 if even)
  • multiply that by 255 because 00000001 or 00000000 show no visible difference but 11111111 and 00000000 do
  • put this in the secret image, pixel by pixel
    And Heres my output:

waow indeed

You are viewing a single comment. View All