stepic 0.3 は、画像のステガノグラフィに対して最も単純なアプローチを使用します。モジュールから直接引用:
def decode_imdata(imdata):
'''Given a sequence of pixels, returns an iterator of characters
encoded in the image'''
imdata = iter(imdata)
while True:
pixels = list(imdata.next()[:3] + imdata.next()[:3] + imdata.next()[:3])
byte = 0
for c in xrange(7):
byte |= pixels[c] & 1
byte <<= 1
byte |= pixels[7] & 1
yield chr(byte)
if pixels[-1] & 1:
break
秘密データのすべてのオクテットと、それが最後のバイトであるかどうかのフラグは、3 つの連続するピクセルに隠されています。より正確に言うと、stepic は各ピクセルの最初の 3 つのコンポーネント (通常は RGB) の最下位ビットを使用します。コンポーネントごとに 4 ビットの RGBA ストリームについては、この非常に醜い図を参照してください (D
はデータをE
意味し、ストリームの終わりを意味します)。
| pixel 0 | pixel 1 | pixel 2 |
image viewer sees: | rrrr gggg bbbb aaaa | rrrr gggg bbbb aaaa | rrrr gggg bbbb aaaa |
stepic sees: | ___D ___D ___D ____ | ___D ___D ___D ____ | ___D ___D ___E ____ |
この変更によって導入されたノイズは、既に「ノイズが多い」画像 (256 分の 1) では小さいため、多くの場合、これを実際に視覚的に検出することはできません。これは、この手法の目的が達成されたことを意味します。自然に発生するノイズと誰も区別できないため、データは目に見えないところに隠されています。
これは機能します。少なくとも、PNG などのロスレス形式では機能します。残念ながら、JPG は無損失ではなく、その圧縮によってエンコードされたビットの少なくとも 1 つが変更される可能性が非常に高くなります。隠しデータが 1 バイトに切り捨てられるため、9 番目のビットを変更してこのメソッドをほとんど役に立たなくするだけで十分です。
JPG 画像のステガノグラフィーは多くの形式でまだ可能ですが、デコードされたピクセル値を微調整するだけでは十分ではありません。より良い (しかしより複雑な) 方法は、コンプレッサーによって推定されたパラメーターにデータを隠すことです。