Apelog

ウノウラボ Unoh Labs: PHPで暗号化・復号あれこれ
に暗号化の話が出ていたので、追記する形で他にいくつか。

同じ記事を書いていた前のBlogが消えてしまったので流し書き程度に。

gnupg 関数

PHPからOpenPGPであるgnupg 関数を利用して鍵方式の暗号化がおこなえます。

gnupg関数を使用する為にPECLのgnupgモジュールが必要。

速度的にも以降の方法に比べて早い。PGP暗号化では一番最初に検討したい。

PEAR::Crypt_RSA

PEAR::Crypt_RSAパッケージで公開鍵暗号がおこなえる。

GMP, BigInt, BCMathの3種類が使え、速度は(GMP>BigInt>BCMath)でGMPを基準として(1倍>5倍>250倍)遅い。暗号化するものが少なければ問題無いものの、多くなると速度以外でも色々と問題がある。

動作環境はDebian / PHP5.2.0 / Crypt_RSA 1.2.0bで確認。

  • GMPを使うと暗号化時にメモリリーク(PHP自体)、復号は大丈夫。
  • BigIngを64bit環境で使うと暗号化できない(空文字になる)。

PEAR::Crypt_RSAを使うしか選択肢が無い状態で、3000レコード(1レコード1M)ほどのデータを各行暗号化してDBに入れ、しばらくして復元した時、テスト環境が32bitの本番環境が64bitで泣いた記憶があるので(結局分割してバックグラウンドでGMPで暗号化した)、そもそも環境が違うなんて・・・というのはおいておき、もしかしたら特有の問題かもしれませんが似たような環境で使う人は注意

exec()でgpgコマンドを叩く

http://www.alt-php-faq.org/local/65/

もしかすると幾多もの外的要因によりこういった方法を選択せざるを得ない時もあるかもしれない。GnuPGが必要なのでインストールしておく。

とても重いので頻度が少ないならまだしも、多くなると実用には耐え切れない。既にGnuPGが入っている状態なら何も必要無いのでそういう点で利用は出来るかもしれない。

PEAR::MDB2のmysqliドライバを使用してキャラクタセットにSJISを使う時の注意。

SET NAMES sjis;

上記SQLの発行だけだと(cp932でも)プレースホルダのエスケープが上手く行われない場合がある。問題が起こるのはプレースホルダの引数に渡した文字の最終文字が特定の文字の場合。

以下の文字が該当し共通点は2バイト目が0×5c(ASCIIコードのに該当)なのでSQLのエスケープ処理で「’」によって囲まれても「’」自体がエスケープされてしまいsyntax errorになる。

― ソ Ы ? 噂 浬 欺 圭 構 蚕 十 申 曾 箪 貼 能 表 暴 予 禄
喀 媾 彌 拿 杤 歃 濬 畚 秉 綵 臀 藹 觸 軆 鐔 饅 鷭 ? 薌 硃 菑

mysqliにはmysqli_set_charset系のクライアントキャラクタセットを変更する関数・メソッドが用意されていて、それを利用しキャラクタセットを変更すればmysqli_real_escape_string関数が正しく2バイト目を判別するようになる。

変更にはmysqli接続オブジェクトが必要になるので取得して変更。

/**
 * @var $mdb2 MDB2
 */
$mdb2->getConnection()->set_charset('sjis');

これで上の文字列が通れば大丈夫。MDB2.phpの読み込み重い・・・。