phpをやり始めてから付き纏う問題で、ソースの暗号化や難読化についての話題があります。
結論から言うと、完全にプログラムの内容を秘匿する事ってのは出来ないんですが、まぁいろいろと前提条件有りでの秘匿化ツールというものが出回っているようです。
ただ、秘匿化するという事は自分とこのサーバに置けないという事であり、客先のサーバに置きたいから秘匿化したいのであり、そうなるといろいろと制約があり、「これをインストールしてください。」とは、なかなか言えない状況というのが大半ではないかと思われるのでありますです。
なので、「出来る限り」の難読化というのが関の山なんですが、今回ちょっとphpにおける難読化っつーものをやってみたので、日記してみます。
まず、「難読化」の方です。
基本的に行うのは、変数名や関数名を無意味な文字列に置き換えてしまうというもの。それと改行だとかコメントだとかを排除して、視覚的に読みにくくするという感じ。
いろいろとツールがあるようですが、今回はフリーという事もあり、Compressor.phpというのを使ってみました。
まぁド定番なんですかね。いろいろな所でオススメされているようです。
で、使い方も簡単なら、結果も単純という感じで、上記に書いたような変数名・関数名の変換とか改行・空白・コメントの排除をザザッとやってくれるだけ、みたいな。
require "compressor.php"; $c = new Compressor; $c->keep_line_breaks = false; $c->load(file_get_contents("hoge.php")); file_put_contents("hoge_comp.php", $c->run());
一つ気づいたのが、argvとかのコマンドライン引数については正常に判定してくれないみたい。これも適当な変数名に変換されてしまうので、後から手動で修正する必要がある。
あと、evalとかで変数名を文字列として記述すると、そいつは変換してくれない。
eval後にその変数を利用する場合は、これも手動で修正する必要がある。
まぁ、大した問題ではないかも知れない。そんなに巨大なプログラムを難読化するって事も無いと思うので。
で、出来上がったプログラムを見てみたんだが、普通に読める。
まぁ確かに読みにくくはなっているが、普通にphpやってる人なら;を改行入りで置換するとかやれば、何をやっているかは分かるレベルですね。
なんか、もうこの辺でそもそもphpで秘匿するっていう事自体が間違っているという事実を受け入れざるをえない心境になってきます。
Compressor.phpでできるのは、この程度って感じですね。
で、ここで終わっちゃうと、プログラム内にある定数的な固定の文字列とかが丸見えなので、焼け石に水ですが、暗号化してみます。
まぁ、暗号化の方はバリエーション豊富ですね。いろいろな方法があるようです。
ただ、言うまでもなく可逆暗号化でなければなりません。
そうなると、mcrypt_genericとか、openssl_encryptとかPEAR::Crypt_Blowfishとかでしょうか。
いずれにしても、keyとなる秘密鍵情報を保持する必要があり、それについてはベタ書きとなるので、あんまり意味が無い感じです。
まぁそもそもphpにおいては暗号化自体が難読化とほぼ同義なんだが…。
で、今回は上記関数ではなく、unpack、pack関数によるバイナリ文字列での暗号化?をやってみました。
暗号化というか、普通の文字列置換的な感じですね。
$data = file_get_contents("hoge_comp.php"); $unpack_data = unpack("C*",$data); print_r(implode(",",$unpack_data));
これなら、openssl_encryptとかの方が幾分マシなような気もしないでも無いが…、とりあえずこれで、ズラ~っと数字をカンマ区切りにした文字列が出来上がります。
Compressor.phpで難読化して、それを更にunpack関数で無意味なカンマ区切りの数字の羅列に変換するという感じ。
で、実行するときは、別にこの文字列をパースするphpファイルを用意して、packしつつ、その結果をevalする事で、動作させると。
要するに、最終的にはプログラムの内容は見られてしまうんだけど、出来るだけその意欲を削ぐ。という感じですね。
なんか、ものすごい徒労感が激しい作業ですが、素直にOCamlとかのコンパイル言語を習得した方が早いような気もする今日このごろであります。