2012
12
04
12
04
ステガノグラフィ: CodeIQの第一回目
CodeIQの第一回目の問題を解いてみた(https://codeiq.jp/ace/kogai_dan/q124)。こういうのを解くのはインスタグラムのやつ以来だ。
ステガノグラフィというものにかんする問題らしい。こういうのは、ウィキペディアよりIBMのほうがしっかり解説してくれていることがある。というわけで参考:http://www.ibm.com/developerworks/jp/web/library/wa-steganalysis/index.html
出題ページに、例示として情報が埋め込まれた画像がある。この画像を拡大して一番上の行を見てみると、たしかに不自然な色の変化があり、ここに情報が埋め込まれてることを察することができる。
Pythonで実装してみた。エンコードとデコードを実装して70行程度。最初はアルファチャンネルの1バイトに文字1バイトを対応させた。これだと画像に与える変化が大きかったので、RGBAのそれぞれ下位2ビットを集めて、文字1バイトに対応させた。
埋め込み済みの画像 - 見た目として画像に不自然さがないが、この画像に文が埋め込まれている


ソース


埋め込んだ文(2nd law - museより引用)
”All natural and technological processes proceed in such a way that the availability of the remaining energy decreases. In all energy exchanges, if no energy enters or leaves an isolated system, the entropy of that system incre,cre,cre,cre,c,c,creases. Energy continuously flows from being concentrated, to becoming dispersed, spread out, wasted and useless. New energy cannot be created and high grade energy is being destroyed. An economy based on endless growth is...Unsustainable”

stegano.py
おまけ
ステガノグラフィをやるとき、BMPかPNGを使いなさいという注意書きがあった。JPGは駄目? なぜ? JPGはその圧縮率の高さから、今やもっともポピュラーな画像フォーマットである。だがその圧縮率の高さと引き換えに、元画像の完全な復元は不可能になっているため色情報にほかの情報を埋め込めない。他方でBMPは1ピクセルごとの色をRGB値で完全に記録しているので元画像の完全な復元ができる。PNGも圧縮処理をしているが、復元可能な処理になっているので情報を埋め込んでも問題がない。
ステガノグラフィというものにかんする問題らしい。こういうのは、ウィキペディアよりIBMのほうがしっかり解説してくれていることがある。というわけで参考:http://www.ibm.com/developerworks/jp/web/library/wa-steganalysis/index.html
出題ページに、例示として情報が埋め込まれた画像がある。この画像を拡大して一番上の行を見てみると、たしかに不自然な色の変化があり、ここに情報が埋め込まれてることを察することができる。
Pythonで実装してみた。エンコードとデコードを実装して70行程度。最初はアルファチャンネルの1バイトに文字1バイトを対応させた。これだと画像に与える変化が大きかったので、RGBAのそれぞれ下位2ビットを集めて、文字1バイトに対応させた。
埋め込み済みの画像 - 見た目として画像に不自然さがないが、この画像に文が埋め込まれている


ソース


埋め込んだ文(2nd law - museより引用)
”All natural and technological processes proceed in such a way that the availability of the remaining energy decreases. In all energy exchanges, if no energy enters or leaves an isolated system, the entropy of that system incre,cre,cre,cre,c,c,creases. Energy continuously flows from being concentrated, to becoming dispersed, spread out, wasted and useless. New energy cannot be created and high grade energy is being destroyed. An economy based on endless growth is...Unsustainable”

stegano.py
# coding: utf-8
#################################################################
#encode: python stegano.py inputImage string
#encoded image is generated in current directory "embedded.png"
#
#decode: python stegano.py inputImage
import sys
from PIL import Image
def encode(file, word):
try:
sr = Image.open(file)
except:
"image not found"
return
newImg = sr.convert('RGBA')
width, height = sr.size
string = word + "\xff"
im = newImg.load()
x, y = 0, 0
for value in string:
pixel_data = [0, 0, 0, 0]
binary = bin(ord(value))[2:].zfill(8)
for num in xrange(4):
bin_val = bin(im[x, y][num])[2:].zfill(8)
manipulated = bin_val[0:6] + binary[2*num: 2*num + 2]
new = int(manipulated, 2)
pixel_data[num] = new
im[x, y] = tuple(pixel_data)
x += 1
if x >= width:
x = 0
y += 1
if y >= height:
print "too small image. FAILED"
break
newImg.save(r"embedded.png")
print "complete"
def decode(file):
try:
sr = Image.open(file)
except:
return
if sr.mode != "RGBA":
return
width, height = sr.size
x, y = 0, 0
im = sr.load()
string = ""
while 1:
pixel_data = ""
for num in xrange(4):
bin_val = bin(im[x, y][num])[2:].zfill(8)
pixel_data += bin_val[6:8]
if int(pixel_data, 2) == 255:
break
string += chr(int(pixel_data, 2))
x += 1
if x >= width:
x = 0
y += 1
if y >= height:
break
print string
if __name__=='__main__':
if len(sys.argv) == 3:
encode(sys.argv[1], sys.argv[2])
elif len(sys.argv) == 2:
decode(sys.argv[1])
おまけ
ステガノグラフィをやるとき、BMPかPNGを使いなさいという注意書きがあった。JPGは駄目? なぜ? JPGはその圧縮率の高さから、今やもっともポピュラーな画像フォーマットである。だがその圧縮率の高さと引き換えに、元画像の完全な復元は不可能になっているため色情報にほかの情報を埋め込めない。他方でBMPは1ピクセルごとの色をRGB値で完全に記録しているので元画像の完全な復元ができる。PNGも圧縮処理をしているが、復元可能な処理になっているので情報を埋め込んでも問題がない。