OpenPNEとPHPと暗号

運用に携わっている、OpenPNEベースのSNSのサーバを、入れ替えました。旧システムは、Fedora Core 3というおよそ、サーバで定常的に運用するのには不適切なチョイス。とはいえ、旧サーバがDELLのミラーリング有のサーバで、これが、当時は、FC3くらいしか、まともにインストールできなかったので、やむを得ないチョイスでもありました。

新サーバは、Vine5ベースの、ATOM330ベースのシステム。ミラーリングはやめて、旧システムの40GBx2から、1TBへとHDDの拡大を遂げました。まあ、これとATOM化による省電力が今回の目玉な訳ですが。

で、サーバのOSがVineに変わったことと、ディストリビューションが新しくなったこととで、様々なコンポーネントが新しくなりました。

MySQLが4から5へ、PHPが腐れ4.4.4から5.3へ、といった具合。MySQLは、バイナリのデータベース構造の互換性にかなり気を配っていて、PostgreSQLのように、ダンプしてからリストアしないとマイナーバージョンさえ上げられないのとは異なり、4から5へとアップグレードするのにも、バイナリのデータをまるっとコピーしてやれば終了。秀逸なモノです。

が、PHPの方は影響が甚大でした。まず、OpenPNEが多用している =& new が、5.3ではDepricatedになっているために、全面的に書き換えが必要。単に =& newを = newにするだけだけれど、コンストラクタ内でクラス変数よろしく参照しているものがあったらどういう副作用が生じるか判りません。ただ今のところ問題なく動いているので、多分、何も考えないで、サンプルかなんかの引き写しで=& newって書いていただけなのでしょう。

もう一点は、かなり致命的でした。OpenPNEは、暗号化に Blowfishを使っています。mcryptが入っていればそれを使うのですが、なければ、PHPで書かれた自前の関数で暗号化/復号化を行ないます。問題は、この自前の処理で、PHP 4.4.4以前にある丸め処理のバグ(<?php echo -2861207174 ^ 493813264; ?>を実行して1209765738が返れば問題なし。-1653670384が返れば、バグを抱えている。)にヒットしていて、バグ有りのPHPでエンコードしたモノはバグ有りのPHPでないとデコードできないのです。

結果、ログインID代わりに利用されるメールアドレスが抽出できず、誰もログインできない状態になってしまいました。新しいシステムは当然こんなバグはつぶされている。公式サイトの museumとかいうサーバに残されている Windows版のバイナリも 4.4.6で、これは問題のバグが修正されているのを発見。

仕方がないので、同じく museumの中にあった、4.4.4のソースを持ってきて、Vine上でビルド。出てきた sapi/cli/php を使って、強引に、バグ有り Blowfishによるデコードを強行。しかる後に、全てを、バグなしPHP+mcryptでエンコードしてDBを上書きしました。ことココにいたってようやく復旧にたどりつきました。ああ、疲れた oTL