Use the command line to create a new directory called lab26 in your labs directory. Make sure all of the .py files that you create for this activity are in that directory.
Cryptography can be used to make the contents of a message secret, but sometimes you want to hide that a message is even being sent. Steganography is one way to hide messages, and a common technique takes advantage of our inability to perceive small changes in colors. For example the image below consists of two boxes with different colors.
The left box has the RGB values (161, 187, 150). The box on the right has the RGB values (162, 188, 151). The two boxes appear to be the same color because the RGB values are similar. A message can be hidden in an image by making small changes to the RGB values of an existing image.
A common way of modifying an image is to change only the least significant bits of the RGB values. The least significant bit of a number is the right-most bit and represents the value 20, or 1. Therefore, the most a color value will change if the least significant bit is change is 1, which the above image demonstrates as imperceptible. The following whale image, for example, has a message encoded in it.
Details
Create a function called decode_image(ppm_file_name)
in
a file called steganography.py
. The program should
return the secret message that is embedded in the specified image
file. The message is encoded as 8-bit ASCII in the least
significant bit of the image's color data. Assume that the number
of color values in the file is a factor of 8. Once you have tested
your program on a simple example, you can test it on the
above
whale image.
Some things to keep in mind:
-
The first three lines of a PPM file specify header information for the image. You will have to skip these three lines.
-
Each subsequent line specifies one color value of a pixel (Red, Green, and Blue respectively). You need to extract the least significant bit of each of these values.
-
Once you have processed 8 color values, you will have to convert the binary sequence represented by their least significant bits into a single character. This is one character in the hidden message.
Example
>>> image_file = open("demo.ppm", "r") >>> print(image_file.read()) P3 1 8 255 122 101 215 42 2 128 200 13 64 203 155 130 36 172 91 180 88 77 55 22 44 66 33 99 >>> print(decode_image("demo.ppm")) abc
Hint
-
You are going to use the accumulator pattern here for strings, adding the least significant bit of the color values. A number that is odd has a 1 as the least significant bit, a number that is even has a 0 as the least significant bit.
-
You can convert a binary string to a base-10 integer by using the built-in
int
function. -
You can convert an integer to a character using the built-in
chr
function.
Challenge
Write a function that can embed messages into images. The function should take three parameters: a message, an input image file name, and an output image file name. It should read in the input image, modify the least significant bits of the color values to embed the message, and write the new image to the specified output file.
Many of the programs that you use on a daily basis all have some element of persistence to them. For example, Emacs can read and write text files that the user writes, or the Messages list on your phone keeps track of all the text-messages you have received. In fact, these programs would be worthless if they couldn't store this data.
Even programs that you wouldn't typically think of require a large
amount of stored data in order to accomplish their tasks. Mozilla
Firefox, for example, creates an entire directory to store the files
necessary to store the information that persists between browsing
sessions. It is located in a hidden folder in your home directory
called .mozilla/
.
In fact, if you have ever get an error opening Firefox because it claims there is already a browser instance open, you can solve the problem by removing one of these persistent files:
$ cd ~/.mozilla/firefox/<some random string of characters>.default/ $ rm lock .parentlock
Since (seemingly) all useful programs rely on files, today you will write such a program. Your program will allow the user to write and store some information using your program. The choice is up to you, but here are some ideas:
- To-Do List: Let the user store their current list of things to do.
- CD/DVD Collection: Allow the user to catalog their CD/DVD collection.
- Journal: Let the user dictate their deepest and darkest secrets to your program. No peeking!
- Travel Blog: Let the user keep track of everywhere they have been.
Details
Create a program called database.py
. This program
will allow the user to enter in their information, and have it saved
for later. This exercise is pretty open ended, but there are a few
restrictions:
-
Your program must read and store information that the user types in via the
input
function. -
Your program should ask the user which file they would like to use for this program at start-up.
-
The main portion of this program will allow users to add data to the users personal database. After every addition, the new entry should be written to the file, without overwriting the old data.
Example
$ python3 database.py Please enter the file you wish to load from and save to: cd_db.txt Welcome to the CD collection processor! Enter Album Title: The Wall Enter Album Artist: Pink Floyd **************Database************** The Wall - Pink Floyd ************************************ Add more? Y Enter Album Title: Physical Graffiti Enter Album Artist: Led Zeppelin **************Database************** The Wall - Pink Floyd Physical Graffiti - Led Zeppelin ************************************ Add more? N $cat cd_db.txt The Wall - Pink Floyd Physical Graffiti - Led Zeppelin
Hint
Create two functions: add_entry(database_file_name,
new_entry)
and read_entries(database_file_name)
.
-
The
read_entries
should print the current contents of the database file. -
The
add_entry
function should read the database file into a list, append the new entry to the end the list, and write the updated list back to the file.
Don't forget to close
your file objects when you
are done with them!
Challenge
It is possible to append to a file without having to first
re-write the current contents. Take a look at the documentation
for
the open
function, and see if you can figure out the mode necessary to
accomplish this.
Submission
Please show your source code and run your programs for the instructor or lab assistant. Only a programs that have perfect style and flawless functionality will be accepted as complete.