Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
86
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

@MATS-Electric-Blue-Industries

画像の複製・拡散を防ぐ方法(1)

0. はじめに

 この投稿では最新の技術の紹介ではなく、いかにシンプルに社会にある課題のひとつを解消できるかを書く。話の中心にあるのは「インターネットにある画像」で、ブラウザで画像が表示できるようになった1990年代前半からあるものである。

 次々にインターネットに関する新しい技術や考え方が脚光を浴び様々な利便性を提供してきたと同時に、多くの課題ももたらしてきたことも事実である。全て挙げればキリがないのだが、インターネットと不可分な社会の課題のうち、この10年ほど変わらずもっとも多くに関与しているのは「画像」のように思う。

 私自身、インターネット上での画像の扱いにつき元から漠然とした課題意識は持ってはいたのだが、インターネット上の画像がもっと洗練された使い方をされれば防げたかもしれない様々な課題の中でも「幼い子供や女性に対する卑劣な犯罪」が一向に無くならないことを口惜しく思い、これをまとめた。実現方法の策定にあたっては、せっかくならできるだけ多くの課題解決に使えればと多くの課題に適用できる案を目指し、結果としてある程度の課題範囲を包括する案ができたように思う。

 この投稿は、1部にまとめると長くて読むのが困難なので、要点に絞ってコンパクトにしたうえで下記の3部に分けてする。なお、私はプログラミング能力はプロのレベルにはなく、理念が発端になって本提案をまとめたので、追って記載するコードが美しくないことはあらかじめご容赦いただきたい。アドバイスも喜んで伺いたい。私と同じ社会貢献の意図を持ってのご質問があれば喜んで個別に具体的にお答えします。

第一部 問題の整理(←イマココね)

 どのような理念に基づいてどのような課題を解消すべきか、要因とアプローチの整理をする。

第二部 具体的なアプローチ

 課題と技術的制限を照らし合わせ、どのような落とし所が適切か整理する。

第三部 実際に作成したプロトタイプ

 実際に作成したプロトタイプを見せながら、皆さんのご意見やアドバイスを期待する。

1. 解消すべき課題

この数年間だけを振り返っても、インターネットと画像に関わる社会的問題は枚挙にいとまがない。SNSが悪いとか、スマホが悪いとか十把一絡げな議論もあるが、それらをブレイクダウンして分類しながら本質的要因が何かを考えてみよう。よく耳にするものだけでも課題を分類をすると下記の4つに分類できると思う。

1.1. コンテンツ要素としての画像のパクリ(労力のタダ乗り)

  • 自身が書いたブログ・記事・論文の画像を無許可で転用される
  • 自分で撮った販売製品の画像を他人が無許可で使う
  • 作品として販売している画像をコピー共有され商機を失う

今年に入ってからも某IT系企業が人様が苦労して作ったブログ記事や画像を無断で拝借して稼いでいたことが露見し社会問題になりましたね。ネット売買サービスを見ればなぜか同じ製品写真が別の人に使われていたり。これは転売屋さんに多いようですね。中には落札してもいないものの製品画像を勝手に使って、落札前に販売するなんていうツワモノもいるそうです。また、プロのカメラマンさんやイラストレーターさんが時間と労力をかけて形にした作品を、そのままお金も払わずにネットで使っているのも目にします。有料画像サイトで販売した画像がネットでばら撒かれたりしてビジネスにならずに消え去ったサイトも多々あります。

1.2. 人物に関する画像が本人の意図・意思に反して利用(肖像権の侵害)

  • 無断で顔写真等を利用されアイデンティティーを無断利用・剽窃される(偽造・背乗り)
  • 過去の人間関係を示す現在は不都合な画像が不祥事発覚後も閲覧される(過去の恋人関係)
  • 判断ミスで他人に送った恥ずかしい画像が拡散される(リベンジポルノ・デジタルタトゥー)
  • 子供や女性の画像が不特定多数に見られ犯罪の対象選定に利用される(性犯罪への巻き込まれ)
  • 有名人がクラウドに不正アクセスされて個人的な写真を勝手に閲覧される(プライバシー)
  • メールやクラウドサーバーにある画像が採取され個人の思想分別に使われる(プライバシー)

ここがこの提案がもっとも解決したい分類です。私も一昨年、LinkedIn経由で某企業から転職のお誘いを受けたのですが、そのアカウントのプロフィール画像(欧米系女性)なのに文章が男性的なので調べたところ、プロフィール画像を勝手に拝借して作った詐欺アカウントでした。クレジットカードや銀行口座の情報を盗み取る「フィッシング・サイト」も健全なサイトの画像を無断拝借して似せて作られます。私はLineはしませんが、Lineでもそういう詐欺アカウントはあるのでしょうか?で、私が非常に危機感を持っている「性犯罪」ですが、よく知られるようにSNSなどに子供や女性の写真が掲載されて不特定多数に閲覧されてターゲットにされることがあるといいます。最近の事件ではベトナム人の女の子を毒牙にかけたのが保護者会の人物の可能性が高いという。もう誰を信じていいのかわからない状態です。この事件にネット画像が関与したかは不明ですが、インターネットが人を見つけるのに有効な手段である以上、危機感を持っておいた方が良さそうです。また、この一週間でもありましたが、朝ドラ出演の女優さんのクラウド画像保存サービスに他人が不正ログインしてプライベートな写真を見ていたという事案がありました。

1.3. 有効期間がある画像が期間満了後も使用(情報の時間的制御不能)

  • 広告の契約期間満了後のタレントの画像が事務所や代理店の許可なく利用され続ける
  • 不祥事を起こしたタレントの広告画像がネット上に存在し続け、スポンサー企業のブランドを損なう

画像は情報量が多いので多くの情報発信に用いられるわけだが広告もそのひとつ。広告にタレントさんを起用する場合、タレントさんの事務所と企業の間で一定期間の契約を交わしてタレントさんが映った画像を広告に使う。タレントさんには個々にブランド価値があるので、そのブランドと製品を紐つけて広告する。以前、ある携帯電話会社の顔として広告に出ていたタレントが、その契約終了後にライバル会社の広告の顔になった事があったが、ネットを見ると両方の広告画像が見つかる。こういう場合、元の契約の会社の広告画像は契約切れなので、存在を消してしまいたいだろう。しかし今の画像データではこれはできない。また、清廉潔白で売っていたタレントさんが実は不倫をしていて、それが発覚した直後に広告契約が打ち切りになることも多い。企業としてはその広告自体の存在を抹消してしまいたいだろうが、現状の画像データではこれができない。

1.4. 守秘義務情報を含む画像が持ち出され組織に不利益(情報の漏洩)

  • 社外秘資料が持ち出されて社外で閲覧される

組織や企業がイントラネット内限定で守秘義務情報を共有している場合、これが外部に持ち出されて彼らの社会的信用を低下させるばかりでなく、組織・企業としての存続の危機に立たされる場合がある。多くの組織・企業ではイントラネットに接続できる端末を管理・制限し、USBを接続できないようにしたり、外部とのメールのやりとりを監視したり、機密情報だらけの場所では携帯電話・スマートフォンの持ち込みも禁止したり。非常に気を使って対応している分野であるが、なぜか情報漏洩は止まらない。

2. 課題の本質とアプローチ

上に列挙した課題の本質的原因は、インターネットでは「著しい劣化を受けずにデータの複製が容易にできること」と「拡散が容易にできること」と「他人の管理下にあるデータは作成者の制御が及ばないこと」という3要因に起因すると考える。画面に表示されるページ構成情報がクライアント(ブラウザ)側にすべて渡されるというHTTPの特性を根拠にして、「ウェブサイトでページに表示された画像は容易に複製されるのはしょうがなく、また作成者の意向を十分に反映せずに勝手に拡散されるのは仕方ない」という認識が不幸にも常識となっているが、前章に挙げた現存する深刻な課題を前に、私はその諦めにも似た認識を素直に受け入れるつもりは毛頭ない。もし、これら3要因への対応が適切になされた場合、「解消すべき課題」にあげた現存する多くの課題の解消・軽減が期待できると考え、これら3要因の発生を完全に阻止することはできないとしても、画像の取得に技術や手間がかかるようにすることで費用対効果的に採算が合わないようにし、また許可なく複製・拡散することのリスクを顕在化することで問題の発生を減らすというスタンスに立つ。以下にこれら3要因の本質とアプローチにつき述べる。

2.1. 複製について

「既知の手順で容易には複製できず、複製できても拡散を抑制する」という、拡散防止と合わせたスタンスを取る。スマホ及びPCで画像データを複製保存される主な方法は「1. UIの機能を使っての保存」「2. htmlソースを分析して画像のURLを特定し保存」「3. ページを丸ごとローカル保存」「4. スクリーンショット保存」である。1についてはJava ScriptやCSSを用いた方法が知られるところであり、これを踏襲し拡張した方法を提案する。2については「ブラウザ画面には表示されるがHTMLを見ても取得はできない」というトークンと暗号化を用いた新たな方法を提案する。3と4については技術的に封じることが現状で困難であることに加え、個人としての画像の閲覧の利便性というそもそものインターネットの存在意義の観点からその実施可能性を残し、後述する「拡散を防止する」ことに実被害の発生を防ぐ対応を期待するものとする。

2.2. 拡散について

「技術的に阻止ではなく、拡散により社会的制裁を受けることを示唆する」というスタンスを取る。現状で多くの画像が「Watermark(画像に著作権者のトレードマーク等を被せた半透明のマーク)」を用いているが、これが十分に拡散を防げているとは思えない。というのは、対象の画像をデータ保存もしくはスクリーンショット保存できた場合、保存した画像は任意に拡散することは可能であり、誰が拡散し始めたのかを特定できない以上、匿名性が高いインターネットでは拡散し始めた人物が適切かつ迅速に制裁を受けることは過度に期待できない。しかしながら、保存した画像に保存した端末を特定する情報(時刻やホスト名)を動的に記載し、拡散が発生した場合にはその画像を見れば拡散の出元がわかるようにした場合、自身が保存した画像を拡散開始させることを踏みとどまらせることができると考える。

2.3. 制御について

インターネット上に送り出した画像はその送り出した先が他者が管轄するサーバー上である場合、多くの場合、管轄者が特段の権限を付与しない場合にはその画像を自力で消すことも出来ない。この提案では、他者が管轄するサーバーにあっても画像と所有者を紐つけておき、画像を表示することを許可するかを画像が他者の管轄下にあっても画像の所有者が一方的に決められる余地を残すスタンスを取る。

3. 目指す状態の実現にあたり

前章で挙げた3つの「複製」「拡散」「制御」に関する施策を実現するにあたり、実際に多くの人々の役に立つためには以下が担保されるべきと考える。

3.1. 利用者にとって煩わしくないこと

画像の所有者及び閲覧者の双方にとって容易に理解できる方法で実現する必要がある。HTMLやJava Script等の知識が無ければ導入できないものであれば導入できない人も多くなるし、閲覧者にとって従来のウェブサイトの使い勝手から逸脱したものであれば、ウェブサイトの本来の目的である「知らせる」という目的にそぐわなくなる。

3.2. 実現する技術が従来の基本的な技術を逸脱しないこと

例えば、新たなプラグインのインストールを求めたりした場合にはそれをためらう人もいるだろうし、また、CMSで動的にページを生成している人々が多い実情を考えると、コードに大幅な修正を必要とする場合は導入をためらうだろう。最新のライブラリが無ければ導入できなかったりもNG。できれば、既存のページやコードにコピペ中心で1分以内に終わるような工数で実現できれば多くの人は実施できると考える。

3.3. 仕組みの有効性が客観的に評価できること

仕組みを秘密にすることで安全性を担保しようとすれば、その秘密が露見した時点で安全性は完全崩壊する。実現する仕組みは、多くの人がその便益を確信を持って享受できるためには、彼ら自身が有効性を客観的に評価できる機会がある仕組みにすべきである。これを踏まえ、本提案では仕組みを秘密にすることで安全性を担保するのではなく、データの暗号化技術の適用により「計算量的安全性」を提供する。

4. ブラウザに表示された画像はどのように複製保存されるか

まず、ブラウザに表示された画像がどんな手順で閲覧者のローカル端末に保存されるかを洗い出してみよう。下記の4パターンがある。

4.1. ブラウザに備わった機能を用いて

・画像を右クリック(PC)
・長押しして表示されるメニューを使用(スマホ)
・画像をドラッグ&ドロップして保存
・ページを丸ごと保存(画面上で右クリックして出るメニューを使用)
・ページを丸ごと保存(ブラウザ画面外のメニューを使用)

4.2. HTMLのソースを見て画像のURLを特定して

・ソースコードのimg src=xxxxを見て、その画像のURLに直接アクセスして保存

4.3. スクリーンショットや画面の撮影によって

・OSに装備されたスクリーンショット保存機能を使用
・画面に別のカメラを向けて撮影
・スクリーンショット用アプリケーションを使用

4.4. ブラウザ自体以外のアプリケーションを用いて

・ブラウザのアドオンを使ったページの丸ごと保存
・ページ巡回収集アプリケーションを用いたページの丸ごとの保存

5. 複製保存された画像はどのように拡散されるか

 HTTPで配信される多くのウェブサイトに転載される他、メールで人に送られたり、FTPやファイル共有によって人から人、システムからシステムに拡散されていく。様々な方法で画像は拡散していくが、ひとつ確かなのは、「自分が見られない画像は拡散しない」です。何が写っているかわからない画像を拡散することはまずない。なので、「画像を閲覧できる場所(ドメイン等)を制御する」ことが拡散自体を防ぐ。この制御については後述する。

6. 画像の複製保存を防ぐ対応案

 画像の保存の目的は「画像がほぼ劣化せずに保存できて初めて意味があるケース(商用画像など)」と、「ある程度劣化しても被写体が判別可能であれば良いケース(情報漏洩・リベンジポルノなど)」の2種類がある事に注意したい。つまり、単純に「画像の一部分を隠したり、画質を劣化すればいいだろう」という考えでは役に立たない後者のケースがあるという事を実際の対策を検討する際は忘れないようにしたい。なお、以下にIT技術的な視点で対応策を記載するが、それを実現する技術はどれも目新しいものではなく、レベルも高くない。

6.1. 対象画像にCSSで透明PNGを被せる

 この方法は特にスマートフォンでの閲覧者に画像の保存をさせない方法として知られた方法である。スマホのブラウザ画面に表示された画像を長押しするとメニューが開いて保存ができるが、保存されるのは被せた透明PNG画像であるため、目的の画像は保存できない。しかしながら、PCで閲覧している場合は「ChromeのInspectモード」や「FirefoxのFirebug」を用いてCSSで被せた透明PNG画像をひっぱがすことができてしまうという弱点がある。(後述するサービス化では不採用とした)

6.2. 対象画像の上でマウス右クリック及びドラッグ&ドロップを継続的に無効化する

 上記の透明PNGを弱点を突いて剥がされた場合を考慮し、被せた透明PNGの下にある画像にJavaScriptで「右クリック無効」と「ドラッグ&ドロップ無効」の属性を与える。そして、この無効化をPNG画像の時と同じくInspectモードで剥がされないよう、JavaScriptのsetIntervalを用いて継続的にかけ続ける。こうして高橋名人の毎秒16連打のようにかけられた無効化は、Inspectモードで外されても一瞬で元に戻る。しかしこれにも弱点があり、ページを丸ごとローカル保存して、JavaScriptのインクルードを外したり、JavaScript自体を外されたら無効化がされなくなる。そこで、後述する6.4.及び6.5.の施策により、ページのローカル保存やJavaScriptの改造をすると画像自体が見られなくなる方法を導入する。

6.3. キーとウィンドウの状態の検出で見分ける

 煩わしいのが「スクリーンショット」「画面の別カメラでの撮影」である。結論から言うと、コードや仕組みでこれらを完全に防ぐことは現状でできない。なので、撮影されることを完全に防ぐのではなく、撮影された後の拡散を防ぐようにする。なお、だからと言ってあまりにも簡単に撮影されるのは癪なので、OSに装備されたスクリーンショット機能を使おうとすると画像が消えるようにJavaScriptでキーとウインドウの状態を監視する仕掛けをする。なお、スマートフォンにおいてスクリーンショットを撮影する際に押すキー(電源+ホーム)をブラウザ上で動いているJava Scriptが検出することはできない。

6.4. 対象画像をエンコードし、特定の条件を満たす場合のみサーバー側でデコードする

 6.1.と6.2.で述べたように、これまで共有されてきたCSSとJSによるブロックは外す方法が現実的にある。このあたりの実情を鑑みて「ブラウザに表示された画像はパクられるのは仕方ない」と言われている気がする。私の提案では、ここを乗り越える。画像をあらかじめ「とあるアルゴリズム」でエンコードしておいて、ページが表示されるときにJavaScriptでサーバーと通信してデコードするのだが、「そのJavaScriptを改造されたら終わりじゃん」と言う声が聞こえる。ノンノン。チッチッ。そのJavaScriptを改造すると今度は画像がデコードされなくなる方法が次の6.5.である。

ちなみに、画像を表示(つまりデコード)しても良い条件をエンコード時に画像に属性として付加しておけるようにし、「自分のサイトでは画像は表示されるが、その他のサイトでは表示されない」などの制約を画像の所有者がかけられるようにしておく。

6.5. 上記のデコードは動的に生成されたトークンを持つJavaScriptで行う

 上記のデコードを行うJavaScriptはページからインクルードで呼び出されるたびに動的に生成し、その中に記述された動的に生成されたトークンで、ページが読み込まれた瞬間しかサーバーはデコードを受け付けないようにする。こうすると、読み込まれたページの上にはデコードされた画像が表示されるが、JavaScriptを改造してデコードだけ行わせようとしても、改造する前にすでにトークンが無効になりデコードが受け付けられなくなる。htmlソースを読んで画像のURLに直接アクセスしてもデコードするためのトークンがないので画像は表示されない。

補足)検討したが却下した他の方法

上記の6.1.から6.5.を対応案とする過程で他の案も検討したが採用には至らなかった。それらと却下理由を記載する。

却下案1:ページ上全体でのマウス右クリックでのメニューを非表示にし「ページを保存」が選べないようにする( → 画像が貼られるページのユーザビリティーに制約を起こすため「やりすぎ」と判断)

却下案2:ブラウザのクライアント領域からマウスのポインタが出たら画像を隠す( → マウスの動きが早い場合はポインタの位置を正確に捉えられないため実効性が薄いと判断)

却下案3:CSSの機能を用いて画像をbackground imageとして貼る( → ページを保存しても保存されたデータの中に画像は含まれないが、HTMLソースを調べられたら容易に画像URLを知られることは何も変わらない)

却下案4:画像をピクセルや行に分解して画面上で並べて1枚の画像のように見せる( → 手間がかかる割にはスクリーンショットに弱いしコードが煩雑になる)

7. 実装の感じ

上記を実際に加味して作ったJavaScriptの概要がこちら。実際のURLなどを記載しておくとかえって紛らわしくてご迷惑なので、サンプルっぽくシンプルにしました(これをこのまま使っても動きません。動くものは次回お見せします。)。JavaScript書きの方は雰囲気がお分りいただけると思う。このJavaScriptをHTMLのheadタグの中にjQueryと一緒に

<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<script type="text/javascript" src="https://somedomain.com/js/eclips-image.js"></script>

のようにインクルードし、保護したい画像に

<img src="image.jpg" class="protect-image">

のように protect というクラスを付ければ実装できる。そんだけ。なので、Wordpressへの適用も容易(JetPackのように画像に対して複雑な処理をするアドオンとは共存できない場合があるが)だし、既存のFacebookのようなSNSへも(彼らがその気があれば)容易。数秒のコピペで実装が可能です。

eclips.js

var server_root_url = "http://chomechome.ne.jp/eclips/";

//繰り返し継続的に画像に右クリック禁止とドラッグ&ドロップ禁止をかけ続ける
var setIV = setInterval('checkWindow()',250);

function checkWindow() {

    $('.protect').attr({
        onSelectStart: "return false",
        oncontextmenu: "return false",
        onMouseDown: "return false",
        onMouseUp: "return false",
        onMouseOver: "return false",
        onMouseOut: "return false"
    });

}

// Windowがfocusされているか否かで画像を見え隠れする
window.onblur = function() {

    jQuery('.protect').css({opacity:"1"}).animate({opacity:'0.05'}, 250);

};

window.onfocus = function() {

    jQuery('.protect').css({opacity:"0.05"}).animate({opacity:'1'}, 250);

};

//MacとWindows標準のスクリーンショットのためのキーを押された時に画像を見えなくする
document.addEventListener('keydown', (event) => {

    if (event.shiftKey == true || event.ctrlKey == true || event.altKey == true) {

        jQuery('.protect').css({opacity:"1"}).animate({opacity:'0.05'}, 250);

    }

}, false);

document.addEventListener('keyup', (event) => {

    if (event.shiftKey == false && event.ctrlKey == false && event.altKey == false) {

        jQuery('.protect').css({opacity:"0.05"}).animate({opacity:'1'},250);

    }

}, false);

// サーバにエンコードされた画像のurlを送りデコードする処理
window.onload = function() {

    // このJavaScriptを動的に生成し、デコードリクエストに必要な瞬間的に有効なトークンを持たせる
    var token = "LS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tClZlcnNpb246IEdudVBHIHYyLjAuMTQgKEdOVS9MaW51eCkKCmhRSU1BOE5UMi92QmxjTTFBUS8vWkwvRXc4dlNGbmRmbll6VXp6KzBGdWJOSWJ0ZlpsNWZjeUNocDVIVDJ0L2oKbzl4WWQ2Tk8rYngyNkdHM29ibkRyaWJYQU14UDR5Mk1Venlielh4Q1F1Y0IxV0NhWEdsYjBKQk5iblZjL1dERgpnVGFwOWo0ZnJ5Y2plc3dQSnNGNUo3djBFQUNkc05ETG10K2laTklRcXpBdXpHTGpib3A2Vng2ZWVnTzNwZ2ZBCkV2V2RPckFIMU9pQ1B4VkNYbWdMdjZkekFCTE1ndDlNekpmUVhtTWdmV25tSXZ0YnVTaTdnMm1kUVc2UEFLRGgKTU1HT1pPWmlxOWduMWtpV1N0ZXVUalFTRWpzbHdKZFhwR1o1Y0pUL2FxenVsbWIwUmVJTVlqZ05yOUNXaWdxQgpnbmpMdUVVR3o1WWdWNmI3NkdpVzNmbWQ1eWRXY3ZvaHhYWWd0SjVzbEdabi94aXF4QVhFTmdjc1FYTy9Gcnc5CmpMakl2bnhrRXVkSGtGR0FlelhLS3pZaHZFYk9LMUVsYnpCaEVQNWo4RzZYbFdHZzBiMGdBMnVFMzFWb3YvaC8KUkU5VVNTbGt0MWR6dmZrODg5NG03QzUxSnlaamtHYWJGZEN3SmRvZmtYRmJrM2JJUlk5YkFjWGpwZUVHSWNBdgpBeXYrM3NVaUlxd3hKc2xyOERscnBKeGFZai9JV0ZnSEE3d3J2Y2xRL0F2cG5RaktPVkhsWXBZN25pd3p4OGpQCkRNSHlIa21tWnJXTjdSQ21NOHhzcWN0TGo4SGd5NHg3V28xdkcrVFkvSml0eDlkanVLYng5cUxBcGZ3cDFoVDkKTjczNi9qdEpJeHBOTXZhYzdEN0xmT09UYndZcGRMdm92ZUNRbDkwZnpWQVhJNU5iL3VzcGRBWVRzcmhMSjdmUwpTZ0ZlZUJwcGpZWGdLSlZURWsvWFhOSUJoOUJGeWphTzg1SkRyd2xWcXVsTERaVGQ1akptS0dZWlJ2U1g1NXlBCjVqZGM3SlhaZHQ5K211MDMwVU5aLzJnVEw0eGVOYm1VRVlOMgo9WlMwcwotLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tCg==";

    // 画像を表示しようとしているページのurl(動的生成)
    var page_url = "hogehoge.ne.jp/test.html";

    // 画像を表示させようとしているクライアントのホスト名(動的生成)
    var client_hostname = "g7.124-44-19.ppp.hogehoge.ne.jp";

    var img = new Array();
    img = document.getElementsByClassName('protect');

    for (var i = 0; i < img.length; i++){

        var srcImage = img[i].getAttribute('src');

        var imgFullUrl = jQuery('img.protect')[i].src;

        var decodedImageUrl = 
                server_root_url + 'decode.php?token=' + token
                + '&src=' + encodeURIComponent(imgFullUrl)
                + '&page_url=' + encodeURIComponent(page_url)
                + '&client_hostname=' + encodeURIComponent(client_hostname);

        var image = new Image();

        img[i].setAttribute('src', decodedImageUrl);

    }

};

そして、実際にエンコードした画像が下記。改造等の手を加えられていない上記のJavaScriptがサーバーにデコード依頼をし、画像の所有者がエンコードした際に設定した条件(表示しても良いドメインや時間など)を満たしている場合のみに画像は表示される。これらの条件情報は全て画像内部に埋め込んであり、デコードするサーバーには画像は保存されていない。なお、このように「特定の条件が揃った場合のみに見られる」ということが皆既日食みたいだなと思ったので、この仕組みの名前を「ECLIPS(エクリプス:皆既日食)」と呼ぶことにした。

エンコードしていない画像:
01.jpg

エンコードされた画像:
02.jpg

なお、エンコードされた画像はエンコード前の画像と同じようにシステムには画像として認識され、サムネイルがある場合はOSのファイル縮小表示では画像が表示される。だけども実寸大表示ができない。JPEGのバイナリーデータ構造に詳しい方はバイナリー・エディタで開いて見てみてほしい。どこのマーカーがエンコード前後で変わっているか。


ということで、今回は実際にどのような施策を行うかを技術的制限を加味しながらまとめた。次回は実際に動くサービスとしてお見せし、みなさんからのアドバイスに耳を傾ける。

(次回の投稿は2017年5月3日です。) → こちら

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
86
Help us understand the problem. What are the problem?