moth/puzzles/steg/100/encode

60 lines
1.4 KiB
Python
Executable File

#! /usr/bin/python
## Fetch some public domain images, make a PNG of the key, and encode
## that in the Exif.Image.OriginalRawFileData tags of the images
import os
import glob
import random
import shutil
import md5
import sys
import zipfile
def system(cmd):
ret = os.system(cmd)
if ret:
raise OSError('return value %d: %s' % (ret, cmd))
# Read in key image
key_png = sys.stdin.read()
# Duplicate two photos, give them a chance to bindiff
jpegs = sys.argv[1:]
random.shuffle(jpegs)
for fn in jpegs[:2]:
root, ext = os.path.splitext(fn)
jpegs.append(fn)
random.shuffle(jpegs)
bytes_per_photo = len(key_png) / len(jpegs)
zipf = zipfile.ZipFile(sys.stdout, 'w')
for i in range(len(jpegs)):
fn = jpegs[i]
cmd1 = 'set Exif.Canon.0x0019 %d' % i
offset = i * bytes_per_photo
if i == len(jpegs) - 1:
bytes = key_png[offset:]
else:
bytes = key_png[offset:offset + bytes_per_photo]
bytes_str = ' '.join(str(ord(c)) for c in bytes)
cmd2 = 'set Exif.Canon.0x0018 "%s"' % bytes_str
# Now apply our devious stuff
system('exiv2 -M\'%s\' -M\'%s\' %s' % (cmd1, cmd2, fn))
# Read it in
contents = open(fn, 'rb').read()
# Find the new file's md5 checksum
checksum = md5.new(contents).hexdigest()
# Make a new zip file entry
zi = zipfile.ZipInfo(checksum + '.jpg')
zi.compress_type = zipfile.ZIP_DEFLATED
zi.external_attr = 0644 << 16L
zipf.writestr(zi, contents)