【ステガノグラフィー】画像に文字を隠す方法

タグ:

最近ステガノグラフィーのライブラリを作ってみたのでそれの解説をします。

作ったもの: https://github.com/komayuki/ninja

ステガノグラフィーとは?

ステガノグラフィー(steganography)とは、データ隠蔽技術の一つであり、データを他のデータに埋め込む技術のこと、あるいはその研究を指す。 クリプトグラフィー(cryptography)がメッセージの内容を読めなくする手段を提供するのに対して、ステガノグラフィーは存在自体を隠す点が異なる。

作ったライブラリは画像に文字列を埋め込むものです。

仕組みとしては、画像1pxのRGB値それぞれの最下位bitに隠したい文字列のbitを埋め込むだけ。

1bitの変化は人間の目で判別できないので元の画像に変化を加えずにテキストを隠すことが出来ます。

すべてのpxにループして埋め込んでるのでパースするのは簡単になっています。

※jpegはクオリティに気をつけましょう。

 

ソースを読めば仕組みがわかるので簡単に解説します。

def hidden_keys(text): 
  codepoints = [hex(ord(t))[2:] for t in text] 
  keys = [] 
  
  for h1 in codepoints: 
    binary = bin(int(str(h1), 16))[2:].zfill(7) 
  
  for b1 in list(str(binary)): 
    keys.append(b1) return keys

埋め込む文字列を1文字ずつ分けて、コードポイントを16進数に変換しています。

そして16進数を2進数に変換して配列を作ります。

1度16進数に変換する理由は桁数を揃えるためです。

 

次にバイナリを埋め込む作業

from PIL import Image 
import os 
import sys import re

def generate(text): 
  keys = hidden_keys(text) 
  im = Image.open(img_path) 
  rgb_im = im.convert("RGB") 
  im_size = rgb_im.size im2 = 
  Image.new("RGB", im_size) 
  i_1 = 0 
  for x in range(im_size[0]): 
    for y in range(im_size[1]): 
      r, g, b = rgb_im.getpixel((x, y)) 
      rgb = [r, g, b] 

      for i_2 in range(len(rgb)): 
        c = rgb[i_2] 

        if i_1 < len(keys): 
          c_b = bin(c)[:-1] + str(keys[i_1]) 
          rgb[i_2] = (int(c_b, 2)) 
          i_1 = i_1 + 1 
      
        if i_1 == len(keys): 
          i_1 = 0 
          r = rgb[0] 
          g = rgb[1] 
          b = rgb[2] 
      im2.putpixel((x,y),(r,g,b,0)) im2.save(os.path.join(dir, "img/output.png"))

最初に説明したとおり、hidden_keysで取得した隠し文字をビットに変換した配列を最下位ビットに一つずつ埋め込むだけ。

1pxに3bit埋め込むことが出来ます。

これで画像に文字を隠すことが完了です。

 

解析したい時は、最下位ビットを取り出して繋げて2進数→16進数→コードポイント→文字列の順に変換していくだけ。

 

https://github.com/komayuki/ninja

お仕事の相談

フリーランスエンジニアをお探しでしたらこちらよりご連絡ください お仕事の相談