パスワードでページを保護したい!~暗号化編
パスワードでページを保護したいがCGIが利用できないサーバーをかりているのでJavaScriptやHTMLでできないか?というリクエストを何度か受けたことがあります。
そのリクエストに応じて、ファイル名をパスワードっぽく利用してそれらしい演出する手法を紹介しました(こちらです)。この手法はここだけでなく、割といろんなところで紹介されていて、ある程度ポピュラーなのでは、、、と思っているのですが、なにせ「もどき」なので、本当のパスワード保護というには程遠いものです。
パスワードで保護なんてサーバーサイドでCGIでも使わないと無理かな、、、と私も思っていたのですが、JavaScriptでページそのものを暗号化することでパスワードがかかればOKなのでは?という発想の転換で、この実験をしてみようと思いました。
もともと、パスワードを入れないと書かれている文字がちゃんと読めない掲示板を作ろうと思っていたのですが、それをHTMLレベルですればページにパスワードと同じことかな?と思ったのがきっかけです。
まず暗号化を考えるには、いかにして読めなくするか、また、その読めなくなった文書をいかにして元に戻すか、という仕組み(暗号化アルゴリズム)を考える必要があります。
ただ、一般的には自分のような個人がちょっと考えただけの暗号化は「簡単に破られる」ので使うべきではない、と暗号化の専門書などには載っています。そのとおりだと思いますが、暗号化とはこんなかんじ、、、という実験をする主旨なので簡単な暗号化アルゴリズムを考えてみることにしました。(そういう意味で、この方法で暗号化しても補償しないということです。)
暗号化とパスワード保護との違い
暗号化とパスワード保護との違いはなんなのでしょうか?暗号化された文書を読むときも当然それを解読するためのパスワードが必要です。そういう意味では暗号化もパスワード保護の一種なのかもしれません。
ただ、パスワード保護は一般に、そのファイルなどにアクセスするときのゲートみたいなもので、そこさえ通過すればそれ以降のファイルを自由にアクセスできる、ということだと思います。ですから、個々の保護したい内容そのものには手を加えられていません。
一方、暗号化の方は、内容そのものを読めないものに変更してしまい、なんらかの方法により元に戻す、という方式です。ですから、ここで実験する方法は一般的にパスワード保護と言われているものよりも、暗号化というべきなのでしょう。(暗号の場合にはパスワードではなく「鍵」という言い方をしますしね。)
暗号化の一般的解説
暗号化といっても様々な方式があります。
大きく分けると、やり取りしたい人で共通のパスワードを持ち、その共通のパスワードにより暗号化されたページを復号するもの、(共通鍵・秘密鍵方式という)と、暗号化する鍵は誰にでも公開し、復号する鍵だけ秘密にするという方式(公開鍵方式)があります。
ここでは、とりあえず簡単にプログラム化できる秘密鍵方式で実験してみることにしました。また、暗号化はいろいろと調べると大変面白く、別の機会にその一部を紹介できたら、、、と思ってます。
では、どのように暗号化を行うか?ということを簡単に考えたいと思います。暗号化の基本は元に戻せることです。(可逆性ともいいますが、、、)
例えば、、、
「JGNNQ」という暗号化された文字があったとします。 これは何を意味しているかわかるでしょうか。
ヒントは暗号化の鍵は「2」です。これでピンときた人もいると思います。
アルファベット26文字の並びを2文字づつ戻すと、、、
J << H
G << E
N << L
N << L
Q << O
となり、「HELLO」となるわけです。 この暗号化の鍵「2」は、アルファベットをいくつシフトするかという数字だったわけです。この数字を3にしたり5にしたりすることで、変更されたあとの文字は変わってくるので、この数字を知らないと復号できない、ということになります。
この「鍵でアルファベットの数字をスライドする」という暗号化の方法のことを「暗号化アルゴリズム」と言い、暗号化においては一番重要になります。
しかし今の場合だと、アルファベットを鍵の数だけスライドさせただけ、と簡単に推測できる可能性があるため、鍵を知らなくても26回程度全ての文字をスライドさせていけば鍵を知らなくても暗号を解読できてしまいます。
つまり、この状態で暗号が「破られた」ということになります。 暗号化については、強い弱いがあるだけで、「絶対」という言葉はありません。どんなに優秀な「暗号化アルゴリズム」があったとしても、「解読されるまでの時間が長いか短いか」だけのことなのです。
現在流通している公開鍵方式でRSAというものがありますが、この公式ページでも暗号化解読を一般の方々から募集して競わせています。(賞金付き)
http://www.rsasecurity.com/rsalabs/challenges/factoring/numbers.html
なぜ、わざわざこのようなことをしているかということですが、このように多くの人に解読に挑戦してもらうことで、その暗号化アルゴリズムの強度を公開し、強度のレベルを示す役目にもなっているのかなぁ、、、と思っています。
で、話を戻すと、先ほどの「アルファベットスライド方式」とでもいう方法では簡単に解読されてしまう、つまりそれほど暗号化強度は高くないということになります。
この程度の暗号化ならJavaScriptで簡単に出来そうです。全ての文字を2文字とか3文字とかずらす、、、という方法ですね。ただ、破られてはあまり意味がないので、ちょっとだけ工夫してみることにしました。
例えば、先ほどの「HELLO」を「2」という鍵で2個スライドさせただけの暗号化を、「524」とかいう数字に変えたらどうでしょうか?
つまり、HELLOという文字を出てくる順番に5個スライド、2個スライド、4個スライド、、、というようにです。すると、次のようになります。
暗号化前の文字「HELLO」
※524というパスワードを順番に一文字づつ繰返し摘要
H 「5」>>>>> M
E 「2」>> G
L 「4」>>>> P
L 「5」>>>>> Q
O 「2」>> Q
暗号化された文字「MGPQQ」
こうすることで、先ほどの方法よりもかなり解読しにくくなったはずです。そこで、JavaScriptでこのような方法を実装することで、そこそこ破られにくい暗号化ができるかな、、、と考えてJavaScript化することにしました。
具体的な方法について
基本的には上で書いたことを応用した仕組みを作っています。 ただ、暗号化される文字は数字や英語だけとは限りません。日本語などのいわゆる2バイト文字も入っています。
そこで、まず最初にする必要があることは、これらの文字列を英数だけの文字列に置き換えることです。
コンピュータの中ではこれらの文字列は全て「文字コード」と呼ばれる英数字の羅列で表現されており、文字をすべてこの文字コードに戻すことから始めることにしました。
そこで、割と簡単に英数化できる方法でJavaScriptの「Escape()関数」を利用しました。ただ、このEscape関数は実装しているブラウザのバージョンによっても変換される文字コードが違い、具体的には古いブラウザだとラテンコードに、最新のインターネットエクスプローラだとユニコードに変換されてしまいます。
よって、暗号化したときのブラウザでしか開けない、、、という状態が発生してしまいます。別な方法を使うことも考えましたが、とりあえず現段階のバージョンではこれでOKかな、、、ということで「Escape()関数」を利用することにしました。
この英数化されたコードを先ほどのような方法で暗号化してそのコードを吐き出しています。吐き出したコードには復号するためのJavaScriptを付属させているので、どのような方法で暗号化しているかは、わかる人が見ればバレバレです。ですが、やり方がわかってもパスワードが分からないと簡単には読めないはずです!
実は、このスクリプトの仕組みを一行づつ解説して公開しようかな、、、とも思ったのですが、暗号化する場合はこのサイトに来てもらってするようにしました。実験的に作ってますし(責任持たない旨は宣言してますが)、これを再配布されて面倒なことが起きるといやだなぁ、、、という自分の実力&自身のなさからです。(決して単純に内緒にしたい、ということではないのでご理解ください。)
ということで、具体的なソース解説はしないことにしました。この方法については別途変換用のページを作ってますので、下からお願いします。また、その利用方法に関する掲示板も作ってありますので、質問はそちらにお願いします。
追記:2008/1/7 パスワードでページ保護というのも、BlogやSNSという仕組みが一般化した今では、不要な知識になっているのかもしれません。自分でHTMLでページを作っている人というのは今はどれくらいいるのでしょうね。





