リスト1●プログラムのコード(PHP)
リスト1●プログラムのコード(PHP)
[画像のクリックで拡大表示]
図1●暗号化プログラムはコマンドラインで動かす
図1●暗号化プログラムはコマンドラインで動かす
[画像のクリックで拡大表示]
図2●暗号化前のテキスト
図2●暗号化前のテキスト
[画像のクリックで拡大表示]
図3●暗号化されたテキスト
図3●暗号化されたテキスト
[画像のクリックで拡大表示]
レシピ
■ PHP 4.xまたは5.x
http://www.php.net/
別途モジュールは必要ありません

 今回はファイルの暗号化に挑戦です。個人情報保護が声高に叫ばれるご時勢です。ファイル内容を秘密にしておきたいというニーズも,そこはかとなく静かなブームになってます。今回のサンプルはそんなニーズにお応えすべく,ファイルの中身を意味不明の内容に暗号化してしまいます。

 今回のサンプルも前回同様にPHP(PHP:Hypertext Preprocessor)を使用します。バージョンは4.xでも5.xでもかまいません。Windowsにデフォルト設定でインストールされているもの(C:\PHPにインストール済)としてお話を進めさせてください。

 暗号化にはいくつかの方法があります。単純なものでは「aを1にする。bをXにする」のように対応表を使った置換暗号ですね。ただこの方法は英数程度ならともかく,漢字を含めると膨大な数になる日本語文章では非現実的な作業になります。簡単な方法なら「URLエンコード」という方法もあります。これは2バイト文字をURLとして使用できないので,URLとして理解される文字列に置換するというものです。例えば「日経ソフトウエア」は「%E6%97%A5%E7%B5%8C…」のようになります。しかしURLエンコードは2バイト文字は変換してくれるものの,半角文字は変換がかかりません。プログラマ的には日本語コメントを暗号化できても,ソース本体(思いっきり英数だけ)が暗号化できなければまったく意味がないでしょう。ですからURLエンコードは却下です。

 そこで今回採用したのは,ビット演算子の論理和による暗号化です。XOR暗号化ともいい,暗号化アルゴリズムとしては比較的有名なものですが,暗号化されたファイルをぱっと見ただけでは復号方法の見当がつきにくく,XOR暗号だとわかってもシード値(暗号化の種)がわからなければ復号できません。またXOR演算はPHPだけでなくC言語,Java,Visual Basic系,Delphi,Perlなどの他言語でもサポートされているので,理屈がわかっていれば言語間移植も楽々というわけです。

暗号/復号化を
一つのプログラムで実行する

 まずは実行して動作を確認してみましょう。Cドライブにsampleというディレクトリ(フォルダ)を作ります。暗号化したいテキスト・ファイルを用意してsrc.txtという名前で保存してください。リスト1[拡大表示]のプログラムをxorenc.phpという名前で,このsampleディレクトリに保存します。スタート・メニューから[アクセサリ]→[コマンドプロンプト](Windows 9xの場合は[MS-DOSプロンプト])を起動します。

php C:\sample\xorenc.php
と打ち込んでEnterキーを押してください(図1[拡大表示])。これでsampleディレクトリにsrc.txtを暗号化した「src.txt.encode」というファイルが作成されます。間違って操作してしまうと大変なので,元のファイルを上書きしないように作ってあります。生成された暗号化ファイルはテキスト・エディタで中身を確認できますが,制御コードが入ってしまうこともあり,エディタでの表示もおかしくなるかもしれません。まあそれくらい完全に暗号化されているというわけです。

<?php

$src_file = "c:\sample\src.txt";
$dist_file = "c:\sample\src.txt.encode";
$fh = fopen($src_file,"r");
if(!$fh){
    echo "暗号化するファイルが開けません";
    exit();
}

//ファイルの内容を読み込みます
$src_text = fread($fh, filesize($src_file));
fclose($fh);

$len = strlen($src_text);

for($i=0;$i<=$len;$i++){
    $seed .= "1";
}

//ビット演算XOR(排他的論理和)で暗号化
$enc_text = $src_text ^ $seed;

//echo "暗号化結果: ".$enc_text."\n";

//復号化したテキストを保存
$fh = fopen($dist_file,"w");

//ファイルを開けない場合は終了
if(!$fh){
    echo "復号化記録ファイルが開けません";
    exit();
}

fwrite($fh,$enc_text);

//ファイルを閉じる
fclose($fh);

echo "暗号化した文字列をファイルに記録しました";

?>

 プログラムではsrc.txtという固定のファイルを暗号化する仕組みになっていますが,暗号化するファイルそのものはexeやjpgのようなバイナリ・ファイルでもかまいません。暗号化したファイルは元がexeでも実行できません。バイナリ構造そのものも暗号化されているというわけです。任意のファイルを開いて,任意の名前で保存できるように改造すれば,かなり使えるソフトになります。

 さて復号化です。実は復号化は同じリスト1[拡大表示]のプログラムを使います。まったく同じルーチンを再度通してやるだけです。つまりsrc.txtを削除(あるいはリネーム)して,生成されたsrc.txt.encodeをsrc.txtに名前を変更します。この状態で再度xorenc.phpを実行すると,復号化されたファイルがsrc.txt.encodeの名前で作られるというわけです。src.txt.encodeは常に上書きされるので,特に削除などする必要はありません。

 ところで,暗号化にはシード値と呼ばれる文字列が必要と述べました。今回のサンプルでは,読み込んだ元ファイルのバイト数と同じ長さの1の連続する文字列(11111…)を,シード値として生成して使っています。このシード値の生成をより複雑化すれば,暗号化は強固になりますが,毎回ランダムな数値を使うと暗号と復号でシード値が変わって復号できなくなりますから注意してください。

 さて,このサンプルに限らず,本連載でご紹介しているサンプルはあくまでも“種(シード:seed)”です。皆さんの手でしっかりと世話をして,立派な実用ルーチンに育ててあげてくださいませ。