Unicodeステガノグラフィ with JavaScript

概要

ゼロ幅文字を使ってUnicodeのプレーンテキストにステガノグラフィを施す、 ブラウザのJavaScriptで動作するライブラリを書いてみた。 参考にしたのは以下のサイト

特徴としては以下の通り。

  • デフォルトではゼロ幅文字として4種類を使用(U+200C, U+200D, U+202C, U+FEFF)し、2種類の時よりもエンコード後の文字数を減少(それでも1文字埋め込むために8文字増える)
  • 使用する文字種はライブラリの使用者側で指定可能
  • 使用する文字種に応じて自動的にコード長を変更(例: 2種類のときは1字(16bit)が16字になり、8種類のときは6字になる)
  • 漢字とひらがな、カタカナの間や英単語間にゼロ幅文字を埋め込むことで、できる限り単語検索を邪魔しない(厳密には異なるUnicodeブロック間に挿入する。非英語の欧州の言語や、サロゲートペアを使用する文字の前後には単語内でも挿入される)
  • 埋め込む位置は毎回ランダム
  • 元の文章、隠しテキストともに多言語対応(全部UTF-16としてJavaScriptで扱っているため)
  • GitHubのものは任意のバイナリデータにも対応

ダウンロードや、サイトに使用する際は以下のURLからどうぞ。

https://330k.github.io/misc_tools/unicode_steganography.js

ライセンスはMITライセンス。

使い方は https://330k.github.io/misc_tools/unicode_steganography.html に書きました(英語です)。

動作サンプル:

デフォルトで使用する4種の文字(U+200C, U+200D, U+202C, U+FEFF)は、 GmailやOutlook 2010、iPhoneの標準メールアプリにおいて

  • ゼロ幅として表示
  • 文字化けしない(豆腐にならない)
  • コピー&ペースト時に保存されるもの

として選定した。

U+200B(ZERO WIDTH SPACE)はブラウザからGmailで送信するときに削除される。 ただ、メーラを使ってSMTPサーバ(smtp.gmail.com)から送信するときは削除されない。

Bidiを考慮せず左横書きに限定すれば、U+200E(LRM)やU+202B(LRO)などを追加できる。 FacebookやTwitterなど各アプリやウェブサイトの対応状況は参考サイトの2番目に詳しい。

GitHubにアップロードした方はバイナリデータにも対応。 これは通常のステガノグラフィとは逆に、画像などのバイナリデータをプレーンテキスト中に埋め込むことになる。 ただサイズがバカでかくなって存在がバレるので、ステガノグラフィとしての意味はなさないかも。

動作確認ブラウザ

  • Chromium 45 (Ubuntu 14.04 LTS)
  • Firefox 42 (Ubuntu 14.04 LTS)
  • Edge (Windows 10)
  • Internet Explorer 11 (Windows 10)
  • Safari (iOS 9.1)
  • Chrome (Android 4.2)

更新点

  • デコードに致命的なバグがあったため修正 (May 27 2016)
  • バイナリデータ対応版をGitHubにアップロード (May 30 2016)

ゼロ幅文字の対応状況

  • U+200B (ZERO WIDTH SPACE) : ブラウザGmailで送信時に取り除かれる
  • U+200D (ZERO WIDTH JOINER) : iOSメッセージアプリにて豆腐化
  • U+2062 (INVISIBLE TIMES) : Outlookで空白扱い
  • U+2063 (INVISIBLE SEPARATOR) : Outlookで空白扱い
  • U+200E (LEFT-TO-RIGHT MARK), U+202A (LEFT-TO-RIGHT EMBEDDING), U+202C (POP DIRECTIONAL FORMATTING) : カーソルが行末に行かなくなる