serialize/unserialize vs json_encode/json_decode 速度比較
テストデータとして 金沢市オープンデータ から取得した JSON 形式で 351 KB になるデータを使用した。PHP 5.4.17 (cli) でそれぞれ 1000 回実行したときの実行時間を以下に示す。
エンコード
実行時間 [s] | 比 | |
---|---|---|
serialize (array) | 2.06 | +26% |
serialize (stdClass) | 2.06 | +26% |
json_encode (array) | 1.58 | - |
json_encode (stdClass) | 1.58 | - |
配列でも stdClass でも速度は変わらない。
PHPソースコード難読化・暗号化ツール所感
2014年7月1日追記:この記事は情報が古い可能性があります
PHP ソースコードの難読化・暗号化ツール php-compressor, ibLind, プラセンス SPHP, ionCube PHP Encoder を試してみた。
php-compressor
php-compressor はコード実行に必要のない空白や改行、コメントを削除し、変数名を短縮してくれる。フロントエンドで行う JavaScript や CSS の圧縮と同じ状態のものが得られる。
このプログラム自体も PHP で書かれているので、PHP が動作すれば環境を問わず使える。構文解析に PHP の標準関数 token_get_all を使っているところが面白い。
クラスの変数定義を書く場所によってうまく変換できないことがあるのを修正したものがこちら。
ibLind
php-compressor と似たツールとして ibLind という Windows 用のアプリがある。ライセンスは PC 1台につき9800円 (2013年6月10日現在)。体験版ではファイル数 3、ファイルサイズ 10 KB までの制限がある。
設計思想は次のように書かれている。
『こんなものを解読するくらいなら自分で一から同じ仕様のものを作った方が早い』と思わせる程度に難読化できれば良しというコンセプトの元に開発しました
http://apps.ibyte.jp/iblind.html
php-compressor, ibLind と次で紹介する SPHP に関してはこの程度の認識が妥当であろう。
ibLind では出力されるコードはクラス名やメソッド名も短縮されるため、ライブラリ部分だけを難読化することはできない。public メンバ名が短縮されたり、private メンバ名がそのまま残ったり、ロジックが不安定と思われる個所がある。
<?php class _1 { private static $_2 = false; public static function _3($_4, $_5, $_6 = array()) { if (self::$_2) return; if ($_SERVER['REQUEST_METHOD'] !== 'GET') return; self::_18($_4, $_5, $_6); } public static function _7($_4, $_5, $_6 = array()) { if (self::$_2) return; if ($_SERVER['REQUEST_METHOD'] !== 'POST') return; self::_18($_4, $_5, $_6); } public static function _8($_4, $_5, $_6 = array()) { if (self::$_2) return;
値段や使い勝手も考えると、今のところ ibLind を選ぶメリットはないだろう。
プランセス SPHP
難読化、使用期限の設定、サーバのドメインによる制限、コード改変の検出など、機能が盛りだくさんの SPHP。
有償で1万2600円の買い切り型。難読化ツールを動かすには Windows 2000/XP/7/8 で Internet Explorer 6 以降と Flash Player 10 以降がインストールされている必要がある。
ライトユーザ向けに作られているためか、多少お節介とも思える画面が特徴である。またディレクトリごとにまとめて処理するなどのバッチ処理は行えないため、今後の改良が望まれる。
このプログラムを使うと次のようなコードが出力される。unSS_sh2b 以前が復号用のコード、それ以降がユーザのコードである。
<?php $fMOz1404_sh=6983;eval(urldecode(str_replace(chr(40),chr(37).chr(54), str_replace(chr(41),chr(37),"(9(6)28 ... )3b"))));eval(urldecode(str_replace(chr(35), chr(37).chr(54),str_replace(chr(96),chr(37),"#9#6`28`21#9`73`5f ... `7d")))); unSS_sh2b("=`6649fe0=======`5eb)90 ... bda"); ?>
一見するとコードが読めないようになっているが、難読化されたコード内でエラーを発生させることで、スタックトレースに元のコードを表示することができる。eval() を使用したツールに共通の問題だ。変数名を短縮しないぶん、php-compressor より読みやすい。
実行時にコードを復号するためコード量が多いと遅くなるかもしれない。また使用期限が設定されている場合、PHP 5.1 以降で mktime() に関する notice が発行される問題がある。
ionCube PHP Encoder
ionCube PHP Encoder は PHP の拡張モジュールを読み込んで、暗号化された独自のバイトコードを実行するタイプの難読化ツールである。
日本の代理店アシアルから購入すると8万4800円(Pro, ダウンロード版)だが、開発元の ionCube から直接購入すると同じものが234米ドルと、約6万円も安い。違いは翻訳されたマニュアルと日本語によるサポートだけで、ソフト自体は英語版しか提供されない。
動作も高速で非常によくできたエンコーダだが、サーバに拡張モジュールをインストールする必要があるため、PHP のコードのみを納品する場合には使えない。
以下の記事も参照されたい。
セキュリティ上の理由で preg_replace が制限されている環境での代替関数
preg_replace 関数は使い方によっては任意のコードを実行できる脆弱性を生むことがあるため、php.ini の disable_functions によって使用を禁止されている場合がある。
しかしライブラリ中でも preg_replace が使われる機会は多い。そこで次の関数を定義する。(PHP 5 >= 5.3.0)
<?php function preg_replace2($pattern, $replacement, $subject, $limit = -1, &$count = '__preg_replace2_args_4') { if ($count === '__preg_replace2_args_4') { unset($count); } return preg_replace_callback($pattern, function() use($replacement) { return $replacement; }, $subject, $limit, $count); } // test echo preg_replace2('{/usr\b}', '/opt', '/usr/local/bin/php:/usr/local/bin/ruby', -1, $count); echo '<br>', $count;
ToDo
- “\1” などによる参照を展開する
cURLでアクセスできるサイトとできないサイト
MacPorts で入れた php5 (5.3.12) と php5-curl でテスト。
接続 | ドメイン | 接続方式 | 暗号化方式 | ビット数 | digest | 鍵交換 | 認証局 |
---|---|---|---|---|---|---|---|
OK | twitter.com | TLS 1.0 | RC4_128 | 128 | SHA1 | RSA | VeriSign Class 3 Extended Validation SSL CA |
OK | account.edit.yahoo.co.jp | TLS 1.0 | AES_256_CBC | 256 | SHA1 | RSA | Cybertrust Japan Public CA G1 |
OK | admin.shop.pro.jp | TLS 1.0 | AES_256_CBC | 256 | SHA1 | DHE_RSA | Alpha CA |
NG | mainmenu.rms.rakuten.co.jp | TLS 1.0 | AES_256_CBC | 256 | SHA1 | RSA | VeriSign Trust Network |
NG | glogin.rms.rakuten.co.jp | TLS 1.0 | RC4_128 | 128 | SHA1 | RSA | VeriSign Trust Network |
NG | card.rakuten.co.jp | TLS 1.0 | RC4_128 | 128 | MD5 | RSA | VeriSign Trust Network |
* About to connect() to glogin.rms.rakuten.co.jp port 443 (#0) * Trying 203.190.60.32... * connected * Connected to glogin.rms.rakuten.co.jp (203.190.60.32) port 443 (#0) * successfully set certificate verify locations: * CAfile: /opt/local/share/curl/curl-ca-bundle.crt CApath: none * Unknown SSL protocol error in connection to glogin.rms.rakuten.co.jp:443 * Closing connection #0
Windows でも非同期で exec()
<?php function exec_async($command) { if (PHP_OS !== 'WIN32' && PHP_OS !== 'WINNT') { exec($command . ' >/dev/null 2>&1 &'); } else { $fp = popen('start "" ' . $command, 'r'); pclose($fp); } }