Pythonでなんちゃってステガノグラフィを作ってみた。画像データにテキストを埋め込んで、メッセージを隠してしまうというわけだ。お遊びで適当に作っただけなので、本格的な使用に耐えうるものではないことをお断りしておく。
上に示す画像は何も埋め込まれていないもの。下に示す画像にはPython: PaSoRiでSuicaの履歴を読み出すの全文が埋め込まれている。
これなら変更したことを誰にも気づかれないだろう。使用したソース(covgraph.py)は下に示す。使い方は、
covgraph.py cover.png stego.png input.txt
とする。cover.pngにinput.txtの中身を埋め込み、stego.pngとして出力する。input.txtに代えて直接文字列を指定することもできる。
covgraph.py cover.png stego.png "hello, world"
とすれば、stego.pngには"hello, world"が埋め込まれることになる。
埋め込まれた画像からテキストを取り出す場合は、
covgraph.py stego.png
もしくは、
covgraph.py stego.png output.txt
とする。前者は標準出力、後者はファイルに書き出す。
追記: 今回のソースは書き殴りで汚いしアルゴリズムとしてもよくないと思うので、修正版のPython: 続・簡単ステガノグラフィ…画像を画像に埋め込むの方がましだと思う。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""covgraph.py by nox, 2008.4.15"""
import sys, os, bz2, base64
from PIL import Image
def cover(input_image, output_image, text_data):
"""テキストデータを画像ファイルに埋め込む.
input_image: 入力画像ファイル.
output_image: 出力画像ファイル(PNG等、アルファ画像が扱えること).
text_data: 埋め込むテキストもしくはテキストファイル.
"""
if os.path.isfile(text_data):
text = file(text_data).read()
else: text = text_data
bz2_text = bz2.compress(text)
b16_text = base64.b16encode(bz2_text)
im = Image.open(input_image).convert("RGB").convert("RGBA")
data = list(im.getdata())
if len(data) < len(b16_text) * 4:
print >>sys.stderr, "Error: text too large."
sys.exit(1)
for i in range(len(b16_text)):
for j in range(4):
n = i * 4 + j
data[n] = (data[n][0], data[n][1], data[n][2], 255 - (int(b16_text[i], 16) >> j & 1))
data[n+1] = (data[n+1][0], data[n+1][1], data[n+1][2], 253)
im.putdata(data)
im.save(output_image)
def uncover(image_file):
"""画像ファイルからテキストデータを抜き出す.
image_file: テキストが埋め込まれた画像ファイル.
戻り値: テキストデータ.
"""
im = Image.open(image_file)
data = list(im.getdata())
end = [d[3] for d in data].index(253)
data = [hex((255 - a[3]) + ((255 - b[3]) << 1) + ((255 - c[3]) << 2) + ((255 - d[3]) << 3)).upper()[-1] for a, b, c, d in zip(data[:end:4], data[1:end:4], data[2:end:4], data[3:end:4])]
b16_text = "".join(data)
bz2_text = base64.b16decode(b16_text)
text = bz2.decompress(bz2_text)
return text
def main(args):
if len(args) < 2 or len(args) > 4:
print >>sys.stderr, u"画像ファイルにテキストを埋め込む:"
print >>sys.stderr, u"Usage: %s <input image> <output image> <text or text-file>" % os.path.basename(args[0])
print >>sys.stderr, u"input image: 入力画像ファイル"
print >>sys.stderr, u"output image: 出力画像ファイル(PNG等、アルファ画像が扱えること)"
print >>sys.stderr, u"text: 埋め込む文字列"
print >>sys.stderr, u"text-file: 埋め込むテキストファイル"
print >>sys.stderr
print >>sys.stderr, u"画像ファイルからテキストを抜き出す:"
print >>sys.stderr, u"Usage: %s <input image>" % os.path.basename(args[0])
print >>sys.stderr, u"Usage: %s <input image> <output text-file>" % os.path.basename(args[0])
print >>sys.stderr, u"input image: 入力画像ファイル"
print >>sys.stderr, u"output text-file: テキストの出力ファイル"
sys.exit(1)
# 画像ファイルにテキストを埋め込む.
if len(args) == 4:
cover(args[1], args[2], args[3])
# テキストが埋め込まれた画像からテキストを取り出す.
elif len(args) == 3:
# テキストをファイルに書き出す.
file(args[2], "w").write(uncover(args[1]))
elif len(args) == 2:
# テキストを標準出力に書き出す.
print uncover(args[1])
if __name__ == "__main__": main(sys.argv)
2008年4月16日水曜日
Python: 簡単ステガノグラフィ…テキストを画像に埋め込む
登録:
コメントの投稿 (Atom)
0 コメント:
コメントを投稿