symfony で XCache の管理ページ認証が出る問題

XCache が有効な環境で symfony を使うと、時々(初回実行時やキャッシュクリア後等に)
XCache Administration というメッセージで HTTP 認証が出ます。
パスワードが違っていると勿論

XCache Auth Failed. User and Password is case sense

となります。
 
このままでは都合がとても悪いので原因と対策を調べてみたところ
symfony framework forum に、この問題についてコメントがありました。
http://www.symfony-project.com/forum/index.php/m/26145/

i tried XCache, APC and eAccelerator. What i discovered is, when the first hit occure (after symfony cc) there is a call for sfProcessCache::clear() in the checkConfig() method (line 201) of the sfConfigCache class. This happens even when using of ProcessCache is not enabled in the configuration.
 
All three of them require a user and password setting to use methods for clearing the cache. eAccelerator use ini settings, xCache require authentication. Thats bad, but not symfonys fault. The result is either a php ‘warning’ (eAccelerator) orthe authentication box popup (xCache) when you hit your app the first time.
 
I helped myself by rewriting the sfProcessCache::clear() and adding few lines. For eAccelerator i’m setting the proper ini settings right before the call of eA’s clearing method, and for xCache by setting $_SERVER[‘PHP_AUTH_USER’] and $_SERVER[‘PHP_AUTH_PW’] before calling xcache_clear_cache(). I read those settings out of the app config YAML, where i added them manually.

とのことで、
sfProcessCache::clear() で xcache_clear_cache() を呼ぶ際に xcache の管理権限が必要なことが原因のようです。
ここに書かれているように自分で

$_SERVER[‘PHP_AUTH_USER’] = ‘XCacheの管理ユーザ名’;
$_SERVER[‘PHP_AUTH_PW’] = ‘ XCache の管理パスワード’;

<pearディレクトリ>/symfony/cache/sfProcessCache.class.php の sfProcessCache::clear()

や、あるいは

<symfonyプロジェクトルート>/web/index.php

などに書き加える事で対処できます。
 
もう一つの解決方法として、XCache 1.2.1 RC1 からの新しい php.ini の設定で

xcache.admin.enable_auth = Off

とすれば XCache の管理認証なしで xcache のキャッシュクリアができるようになります。認証できなくして管理機能を使えなくするのではなく、認証なしで xcache の管理操作ができるようになる事に注意してください。
なお、セキュリティを考慮してなのか .htaccess で

php_flag xcache.admin.enable_auth off

としても無視されます。
 
– 前者はセキュリティ面で少しマシだが、管理面で手間
– 後者は XCache に関して内部のセキュリティを犠牲にするが、楽
 
なので、状況によって使い分けるのがよさそうです。

PHP5 MVC フレームワークの新スタンダード? symfony

http://www.symfony-project.com/
 
本日の「今更」その2。
 
CakePHPMojavi より symfony がいいかも。
 
と聞いていたので、とりあえずsymfony のインストールだけ。

$ pear channel-discover pear.symfony-project.com
$ pear install symfony/symfony

インストールの確認

$ symfony -V

と打てば

symfony version 1.0.3

のようにインストールしたバージョンが表示されます。
楽ちん。
 
なお、PHP ソースの configure 時に –enable-ctype をつけていないと
いざ使おうとした時に

PHP Fatal error: Call to undefined function ctype_alpha()

のようにエラーがでてしまいます。
(Windows の場合は ctype は標準で組み込まれているので問題ありません)
 
参考:
symfony.jp symfony の日本語情報 WiKi
CodeZine: symfonyで始めるPHPフレームワーク

Ruby on Rails はじめの一歩

今更ですが、最近ようやく Rails を触ってみました。
 
10分で作る Rails アプリ for Windows
– Ruby on Rails 公式 – [http://www.rubyonrails.org/]
 
10 分でできる Rails アプリは、本当に 10 分で Ruby on Rails の手軽さが分かるのでお勧めです。
10分で作る…が Windows + MySQL なので,とりあえず FreeBSD で DB を使わない Hello World を表示する場合のメモを残しておきます。
 
あまりまとまったものではないですが..
 

 
1.Ruby + RubyGems をインストール
 FreeBSD の場合、Ruby, RubyGems のいずれも ports からインストール可能です(RubyGems は lang/ruby-extensions に含まれる)。

# portinstall lang/ruby lang/ruby-extensions

 
2. RubyGems の gem コマンドで Ruby on Rails をインストール

$ gem install rails

上のコマンドで一発インストール。依存関係について聞かれるのが嫌なら

$ gem install -y rails

とすればプロンプトなしでインストールされるはずです。
 
3.$rails アプリケーションサーバの構築

$ rails foo

このコマンドひとつで、カレントディレクトリに以下のものをすべてふくむフォルダ foo/ を作成します。
– 管理用スクリプト(script/)
  たとえば script/server はスタンドアロンサーバであり、
  script/generate は目的に応じたクラスやフォルダの自動生成を行うスクリプトです。
– 公開ディレクトリ(public/)
  実際の URL マッピングは public/.htaccess および、public/dispatches.cgi で行われています。
  rails サーバのデフォルトのトップページは public/index.html です。
  
-コントローラ格納フォルダ(app/controllers)
  MVC の controller 格納先
  サンプルとして最初からコントローラの雛型(app/controllers/Application.rb)が含まれています。
  コントローラ作成時はコマンド(scriot/generate controller <コントローラ名>) で作成すると便利です。
 
-ビュー格納フォルダ(app/views)
  MVC の view 格納先。
  ここに .rhtml (eRuby) 形式のテンプレートファイルで view を記述します。
-モデル格納フォルダapp/models)
  MVC の model 格納先。
  script/generate model <モデルクラス名> 等で作成したモデルが格納されます。
 
– 設定ファイル(config/)、
コントローラと URL のマッピングを設定する config/routes.rb,
アプリケーション上のすべての Ruby スクリプトに影響する環境設定を行う config/environment.rb,
MySQL 等のデータベース接続用の設定(アカウント、接続先 DB 名等)を設定する config/database.yml 等があります。
 
– アプリケーションで利用する追加 ruby ライブラリ格納フォルダ(lib/)
  ここにいれておくと ruby スクリプトでのrequire でパス指定なしで参照できるようになります。
  例: lib/my_library.rb があれば、rails アプリケーションからの参照時は require ‘my_library’ とするだけでよい。
 
4. コントローラ作成

script/generate controller Foo

  デフォルトでは HTTP リクエスト URL の最初のディレクトリ表記がコントローラ、次が呼び出すメソッド(action)となっています。
  たとえば

http://localhost:3000/foo/edit

へのアクセスは、ファイル app/controllers/foo_controller.rb の

FooController#edit()

が実行されます。
また、

http://localhost:3000/foo

のように、アクションを省略した場合は、Foo#index メソッドが呼び出されます。
一般的な Web サーバにおける index.html が、コントローラでは index メソッドとなると考えれば分かりやすいと思います。
 
 
5. Hello world を出力する(view, model を使わない場合)
ActionController::Base#render() を使うのが基本です。
具体的にはコントローラのアクション定義メソッド(例: FooController#index)を以下のようにします。
app/controllers/foo_controller.rb

# 前略
def index
    render :text => “hello world!!”
end
# 後略

 
6.コントローラでテキストの出力を行う(view を使う場合)
まず以下のファイルを作成します。
app/views/foo/index.rhtml

<html>
 <head>
   <title>Hello Example</title>
 </head>
 <body>
 <%= @message %>
 </body>
</html>

次に、さきほどのfoo_controller.rb の def index を次のように書き換えれば自動的に index.rhtml を参照します。

def index
   @message = “Hello, world!”
   render
end

具体的には、参照される view のファイル名は

app/<コントローラ名>/<アクション名>.rhtml

です。

[Linux] メール自動受信処理のための procmail 入門

はじめに

procmail とはメール受信時の振り分け、フィルタリングなどを行うためのメール処理プログラムです。
Procmailが使える環境なら、レシピを書くだけでメール受信時に好きなプログラムで自動処理することができます。

たとえば、こんなことに使えます。

− メールが届いた時に、お礼メールを自動応答をする
– メールが届いた時に、自動で他の誰かに転送する
– スパムメールを自動で捨てる
– メモを書いたメールを送ったら、内容をデータベースに保存してくれるシステム
– 添付画像つきメールを送ったら、添付画像を自分のサイトで公開するシステム
– 問い合わせメールを管理画面で見えて、そのままメール返信ができるシステム
– などなど。

とにかく、

「メールを特定のメールアドレスに送ったら○○が✕✕する」

という処理のきっかけ(開始地点)として、procmailが使えます。

使ってみる

Procmailを使うには、メールサーバに Procmail が入っていることが前提です。

メールサーバ構築方法についてこの記事では省略します。
たとえばメールサーバとしてPostfixを使う場合は、以下の記事を参考にしてください。

この記事ではProcmailインストール方法はCentOS(RedHat Linux)、Postfixを使った場合の説明をします。
利用方法はOSによらず共通です。

procmailをインストールする

which procmail

とたたいて、 /usr/local/bin/procmail のように、パスがかえってくればOKです。

パスが何も結果がかえってこなければ、

sudo yum install -y procmail

と実行してインストールします。

インストールしたら、Postfixの設定ファイル main.cf の、mailbox_command設定を探して、以下のように追記します。
mailbox_commandが見つからなければ、main.cfのどこに入れてもOKです。

/etc/postfix/main.cf:

#mailbox_commandが並んでる最後の行に・・・
#mailbox_command = /some/where/procmail
#mailbox_command = /some/where/procmail -a "$EXTENSION"
#mailbox_command = /usr/local/mybin/procmail_wrap
#↓これを追記する!
mailbox_command = /usr/bin/procmail

/usr/bin/procmail は、自分の環境で

witch procmail

として出てきたパスを入力してください。

procmailを使う準備

procmail のルールを書くためには、まずメール受信ユーザのホームディレクトリに
以下の内容をもつ .forward ファイルを作成します(両端のダブルクォーテーションも必要)。

"|IFS=' '&&exec procmailのフルパス -f-||exit 75 #ログインユーザ名"

例:
/home/john/.forward を追加する場合…

"|IFS=' ' && exec /usr/local/bin/procmail -f-||exit 75 #john"

最初と最後のダブルクオーテーションが無いと正しく動かず、超ハマるので注意してください。

procmailのルールを書く

次に同様に .procmailrc ファイルを作成します。

MAILDIR=$HOME/Maildir
DEFAULT=$MAILDIR/
LOGFILE=$MAILDIR/procmail.log
LOCKFILE=$MAILDIR/.procmail.lock

<h1>--- 例1:未承諾広告を捨てる</h1>

:0 H
* ^Subject:.<em>iso-2022-jp
* ^Subject:.</em>\/.*
* ? echo "$MATCH" | nkf -me | egrep '※未承諾広告'
/dev/null

<h1>--- 例2:エイリアスによる script@example.org 宛のメールの内容(ヘッダ含む)を /usr/local/bin/dosomething.sh に渡して実行する</h1>

:0
* ^To:.*script@example.org
| /usr/local/bin/dosomething.sh

例1はメールフィルタリングの例です。
例2はメールをトリガとして任意のプログラムを実行する例です。この例では、/usr/local/bin/dosomething.shにメールの内容を標準入力で渡して、実行しています。
このように好きなプログラムにメールヘッダ・本文を渡して実行することで、自動応答メール等様々な用途で利用できます。

補足

~/.forward がない場合は、main.cf の mailbox_command 変数で指定されたコマンド, mailbox_cmmand も指定されていない場合は通常のメール配送を行います。

また、procmail を実行した時に ~/.procmailrc がない場合も(procmail が)単純にメール配送を行います。

仮想ドメイン・仮想ユーザを使っているPostfixでProcmailを使う方法

仮想ドメインのメールボックスでは .forward ファイルおよび main.cf での mailbox_command は参照されないため、 procmail 等コマンド実行は適用されません。
このため、仮想ドメインのメールアドレスで procmail を扱うためには virtual_alias_maps で、procmailを使いたいメールアドレスのみ、ローカルのリアルユーザにエイリアス(紐付け)する必要があります。

例: foo@example.org 宛のメールをリアルユーザ mailuser で受け取る場合…

/etc/postfix/main.cf:

#...略...

#@localhost のみリアルユーザとする(仮想ドメインを含めないこと)
mydestination = localhost

#...略...

#仮想メールアカウントのエイリアス
virtual_alias_maps = hash:/etc/postfix/viatual

#仮想メールアカウントのメールボックス
virtual_mailbox_maps = hash:/etc/postfix/virtual_mailbox_maps

/etc/postfix/virtual:

foo@example.com   mailuser@localhost

/etc/postfix/virtual_mailbox_maps:

#(エイリアスしたものは含めません)
#example.com
info@example.com         example.com/info
postmaster@example.com   example.com/postmaster
root@example.com         example.com/postmaster

#example.net
info@example.net         example.net/info
postmaster@example.net   example.net/postmaster
root@example.net         example.net/postmaster

設定ファイルの書き換えが終わったら、設定を反映するため以下のコマンドを実行します。

su - # root ユーザで行う
cd /etc/postfix
postmap hash:virtual_mailbox_maps
postmap hash:virtual
postfix reload

あとは前述のとおり mailuser のホームディレクトリ(例: /home/mailuser/ )に .forward, .procmailrc を作成すれば、
foo@example.com に対して procmail のルールが書けるようになります。

参考:
Advanced Email Forwarding
Manpage of PROCMAILRC(JM Project による和訳)
Postfix 設定パラメータ
.procmailrc の書き方
Virtual環境での.forward が有効になりません(postfix-jp: 425)
Postfix 設定パラメータ

IE6.0SP1以上で利用できるシステム制限

– Internet Explorer 6.0 SP1 で使用できる制限値(Microsoft)
http://support.microsoft.com/kb/823057/ja
 
Spybot の IE Tweaks 機能について気になって調べていて見付けました。
レジストリで設定すると、IE の機能の一部(例: メニューの項目等)を制限することが可能です。
例えば Spybot では

HKEY_CURRENT_USER\Software\Policies\Microsoft\Internet Explorer\Restrictions

キーで、NoBrowserOptions = 1 (REG_DWORD)とすることで
ブラウザからインターネットオプションを開こうとした時に

このコンピュータの制限により、処理は取り消されました。システム管理者に問い合わせてください。

と出し実行できなくする、という機能を実現しています。
 
その他

NoSelectDownloadDir : [ファイルのダウンロード] ダイアログ ボックスの [保存] ボタンを無効にします。
NoViewSource : [表示] メニューの [ソース] を無効にします。ただし、ユーザーがソースを完全に表示できなくなるようにするには、NoBrowserContextMenu 値を追加する必要があります。
AlwaysPromptWhenDownload : [ファイルのダウンロード] ダイアログ ボックスの [この種類のファイルであれば常に警告する] チェック ボックスを淡色表示にし、常にオンに設定されるようにします。
NoTheaterMode : F11 キー (全画面表示モード) を無効にします。
NoBrowserContextMenu : Web ページを右クリックしたときに表示されるショートカット メニューを無効にします。
NoOpeninNewWnd : Ctrl + N キーおよび [開く] を無効にします。
NoBrowserSaveAs : [ファイル] メニューの [名前を付けて保存] を非表示にします。

などなど。
作品展示用のコンピュータなどで機能制限したい場合に有用かもしれません。
 
なお、セキュリティのため Policies 以下については、(HKEY_CURRENT_USER においても)管理者権限がないと追加、削除、変更ができないようになっています。

国際化(i18n:他言語対応)の基本

まず文字列の外部化をし、言語ごとにプロパティファイルを作成し、Java のクラスパス直下に置きます。たとえば Eclipse の場合 src ディレクトリ、それ以外の場合 class ディレクトリなど。
 
filename.properties: (対応していない場合のデフォルト. 英語が望ましい)

message.greet = Hello!!
message.bye = Good bye.

 
filename_ja.properties:
  日本語ロケール ja_JP の時に利用されるプロパティ.
  マルチバイト文字を扱う場合 native2ascii でエンコードする必要があるため、参考欄で後述する Eclipse の PropertiesEditor プラグインを使うとよい.

message.greet = こんにちは!!
message.bye = さようなら。

 
filename_fr.properties:
  フランス語ロケール fr_FR の時に利用されるプロパティ.
  このように対応したい言語用のファイルを追加するだけで言語対応ができます.

message.greet = Salut!!
message.bye = Au revoir.

 
以下が国際化対応した外部文字列呼び出しと時刻整形の Java サンプルコードです。

import java.util.ResourceBundle; // 外部文字列取得用
import java.text.DateFormat; // 日付表示用
// その他 import 文省略
 
// 略
 
public void main(String[] args){
   // 実行環境のデフォルトのロケールのプロパティファイルを読み込む
   ResourceBundle bundle =
       ResourceBundle.getBundle(“filename”); // <filename>_<言語コード>.properties の <filename> を指定。
    
   // 現在のロケールの言語で挨拶
   System.out.println(bundle.getString(“message.greet”));
 
   // 現在のロケールで有効な書式で日付表示
   String sToday = DateFormat.getDateInstance().format(new Date());
   System.out.println(sToday);
    
   // 現在のロケールの言語で別れの挨拶
   System.out.println(bundle.getString(“message.bye”));
  
}

結果:

– ロケールが英語(en_USなど)の場合:
Hello!!
May 31, 2007
Good bye.
 
– 日本語(ja_JP)の場合:
こんにちは!!
2007/05/31
さようなら。
 
– フランス語(fr_FR)の場合:
Salut!!
31 mai 2007
Au revoir.

 

java.util.Locale.setDefault(Locale.ENGLISH);

のようにすることで、以降のコードのデフォルトロケールを任意の言語,国に変更することができます。
 
参考:
国際化プログラミングの常識(@IT)
Locale クラス(Javadoc)
DateFormat クラス
PropertiesEditor
  .properties ファイルで日本語を含むマルチバイト文字を扱う時に便利な Eclipse プラグイン.
これを使うことでいちいち native2ascii を実行する必要がなくなります.
なお、スタンドアロン版(PropertiesEdotor.jar)もあります.
詳しい導入方法はこちらの記事(@IT)が参考になります。

PHP 用デバッガ

PHP: Advanced PHP Debugger(PHP) (php.net)

(PHP 公式ドキュメントより引用)
APD は進化した PHP デバッガです。PHP コードのプロファイリングや デバッグの機能を提供すること、また完全なスタックトレースを出力する 機能を提供することを目的として作成されています。

 
インストール手順:

$ pecl install apd
 
$ cat >> /path/to/php.ini ← エディタ等で以下の内容を php.ini に追加
 
zend_extension = /path/to/apd.so ← APD モジュールのフルパス(zend_extention 指定の場合は相対パスは不可)
apd.dumpdir = /tmp/apd_log ← APD での解析結果の出力先フォルダ
apd.statement_tracing = 0 ← 行単位トレースをする場合 1 にする。これを有効にすると出力が冗長になります。

Windows 用のコンパイル済み PECL モジュールは http://snaps.php.net/win32/ からダウンロードできます(ファイル名 pecl からはじまるもの)。
 
 
利用方法:
デバッグをしたいスクリプトの一番始めに

apd_set_pprof_trace();

を呼ぶと PHP デバッガが利用できます。
 
PHP デバッガによる結果は php.ini の apd.dumpdir で指定したディレクトリに

pprof.<プロセスID>.<通し番号>

のような形式で保存されます。
 
そのまま読めなくはないですが、読みやすい形に整形するために pprofp コマンドを利用することができます(APD に付属しています)。
 
— かかった処理時間の多い関数順に並びかえて出力する

pprofp -R [ファイル名]

— コールツリー(関数の実行順序)を調べる

pprofp -t [ファイル名]

— (上の二つ)+(ビルトイン関数は含めない)+(コールツリーの横に経過時間を表示)

pprofp -Rtci [ファイル名]

 
その他のオプションについては「APD の pprofp 引数一覧(pprofp -h)」を参照してください。
  
Windows 用の pprofp についてはAPD のソースに含まれるものが使えるのですが、そのままの形では使いにくいため、実行用のバッチファイルを作成したものを置いておきます。
 
Windows 対応 pprofp をダウンロード
(APD 1.0.1 ソース付属のものから作成)
 
– pprofp
– pprofp.bat
– pprof2calltree
– pprof2calltree.bat
の 4 ファイルが入っています。
この4ファイルをそのまま php.exe と同じ場所など適当にパスが通る場所に置いてご利用ください。
 
参考:
APD(公式 PHP マニュアル)
cles::blog

PHP で OpenSSL

PHP で OpenSSL 関数を使ってみたので、定番のハローワールドを置いておきます。


OpenSSL 関数で暗号化、復号化を行うには、
暗号化、復号化に必要な鍵のペアを PEM 形式で生成する必要があります。
1. パスワード付き秘密鍵 private_password.pem を生成

$ openssl genrsa private_password.pem -des3 1024

2. (1)からパスワードのない秘密鍵 private.pem を生成

$ openssl rsa -in private_password.pem -out private.pem

3. (1)を削除

$ rm private_password.pem

4. (2)から公開鍵 public.pem を生成

$ openssl rsa -in private.pem -pubout -out public.pem

 


openssl_public_encrypt(), openssl_private
…公開鍵で暗号化し、秘密鍵で復号化します。
つまり、誰からでも暗号化して送れるが、内容を読めるのは秘密鍵を持っている人だけになるため、通信経路での傍受が不可能になり、内容が外部に洩れる心配がないので機密性が高くなります。
ただし誰でも暗号化できるので全く別の内容へのかいざんは可能であり、必ずしも信頼性はありません。
 

// 暗号化に使う公開鍵
$public_key = file_get_contents(“public.pem”);
 
// 暗号化する文字列
$message = “Hello, world!!”;
 
// 暗号化データの結果格納先
$encrypted = “”;
 
// 暗号化実行
if(!openssl_public_encrypt($message, $encrypted, $public_key)){
    echo “暗号化に失敗\n”;
    die;
}
 
// 暗号化結果を表示(そのままでは表示できないのでBASE64エンコードする)
echo “暗号化データ: \n “.base64_encode($encrypted) . “\n”;
 
$message = null;
// ———————
// 復号化
// ———————
// 暗号化に使った公開鍵に対応する秘密鍵
$private_key = file_get_contents(“private.pem”);
 
// 復号化結果格納先
$result = “”;
 
// 復号化実行
if(!openssl_private_decrypt($encrypted, $result, $private_key)){
    echo “復号化に失敗\n”;
    die;
}
 
// 結果出力
echo “復号化結果: \n ” . $result . “\n”
     “BASE64:\n” . base64_encode($result).”\n”; // 比較用

結果:

暗号化データ:
FmPaJ9jOmjl/mK249NqUPzYjPUHsmFkSuNyp0SMlgW1c9RRzmKXBjcRhXH/5fwTxItAcE8/
AlZkjYo27XvGR7a3hdXxgaXbk4VORdRRk8LJXKB+xlVzF48OlHJ5lKUrXUdfr2BFtx53/IH
431mBlYWDhf+KyW608eKAA0T34qRY=
復号化結果:
Hello, world!!
BASE64:
SGVsbG8sIHdvcmxkZmc=

 


openssl_private_encrypt(), openssl_public_decrypt() の例:
…秘密鍵で暗号化し、公開鍵で復号化します。
つまり、鍵の所有者しか暗号化できないので中身のかいざんも、経路での差し替えも不可能になり、内容についての信頼性が高くなります。
ただし誰でも読めるため、内容の機密性はありません。
 
秘密鍵、公開鍵の使い方を逆にする以外は上の例と全く同じです。

// 暗号化に使う秘密鍵
$private_key = file_get_contents(“private.pem”);
 
// 暗号化する文字列
$message = “Hello, world!!”;
 
// 暗号化データの結果格納先
$encrypted = “”;
 
// 暗号化実行
if(!openssl_private_encrypt($message, $encrypted, $private_key)){
    echo “暗号化に失敗\n”;
    die;
}
 
// 暗号化結果を表示(そのままでは表示できないのでBASE64エンコードする)
echo “暗号化データ: \n “.base64_encode($encrypted) . “\n”;
 
$message = null;
// ———————
// 復号化
// ———————
// 暗号化に使った秘密鍵から作られた公開鍵
$public_key = file_get_contents(“public.pem”);
 
// 復号化結果格納先
$result = “”;
 
// 復号化実行
if(!openssl_public_decrypt($encrypted, $result, $public_key)){
    echo “復号化に失敗\n”;
    die;
}
 
// 結果出力
echo “復号化結果: \n ” . $result . “\n”
     “BASE64:\n” . base64_encode($result).”\n”; // 比較用

結果:

暗号化データ:
CII4EW6LQBq0faVJxshUfk9VCdFsE66DnQPVdsLbvfq7tNCMzAIZbZA3GBxHu4cG2TqvOnn
xN9C9S9IgBIbulfj4c90IkrYtHQGt3RHAJBYiAgfmzCKbMr2cPJhZwkMUkjczXeaOD1htFJ
TL9e2RKsrWBVFIaiG1JgFk2Jyd928=
復号化結果:
Hello, world!!
BASE64:
SGVsbG8sIHdvcmxkZmc=


openssl_open(), openssl_seal() の例:
…同報メールのように、別々の公開鍵を持つ複数の相手に対して同じデータを暗号化して送る場合に使います
 
– 送信側(送信先1の公開鍵 user1_public.pem と送信先2の公開鍵 user2_public.pem を持っているとする. 自分の鍵は必要としない)

// 送り先の公開鍵一覧。
$pubkeys = array(
        file_get_contents(“user1_public.pem”),
        file_get_contents(“user2_public.pem”),
   );
 
// 送る内容
$real_message = “Hello, world!!”;
 
// 暗号化データの結果格納先
$encrypted = “”;
// 復号化に必要なエンベロープキーの格納先。$pubkeys の数だけ格納される。
$ekeys = array();
 
if(!openssl_seal($real_message, $encrypted, $ekeys, $pubkeys)){
    echo “暗号化に失敗しました\n”;
    die;
}
 
// 出力. エンベロープキーと暗号化データについてはバイトコードなので、表示のために BASE64 エンコードしています。
for($i = 0; $i < count($pubkeys); $i++){
    echo “送り先番号: $i\n” .
         “使った公開鍵: \n” .
         $pubkeys[$i] .”\n” .
         “対応するエンベロープキー: \n” .
         base64_encode($ekeys[$i]) .”\n” .
         “暗号化されたデータ: \n” .
         base64_decode($encrypted);
}

 
受信側(送信側からエンベロープキー $ekey と暗号化データ $encrypted を受け取っているとする):

// 送信側が暗号化に使った公開鍵(user1_public.pem)に対応する秘密鍵
$private_key = file_get_contents(“user1_private.pem”);
 
// 結果格納先。復号化した文字列が入る
$message = “”;
 
if(!openssl_open($encrypted, $message, $ekey, $private_key)){
    echo “復号化に失敗しました\n”;
    die;
}
 
// 結果表示
echo $message . “\n”;

 
送信側結果は次のようになります。


送り先番号: 0
使った公開鍵:


-BEGIN PUBLIC KEY—–
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzZFcKoXbuWzGvlv++7Y05/jBh
nYC+PM67v3H2I5pYV8tUz/6GqsG5afFgLJYoWPEd3KYXHb46B0GxEOydOTuTLEcv
+gVr6v4khgOgjxOcM1hlv+EvAThm1lIY1Y5lbTv+MEUyrGm7SDk8iUaHF6OBcQp3
NzkO6j3+YrsC8znXPwIDAQAB


-END PUBLIC KEY—–
対応するエンベロープキー:
lu4ON1xW2hrrS1jXfav6mjWD32+Iuz1Jk20vhDRmSsfEp3vXuij7Z0R/ClhpgE9MxDJADiU
LS/CCUPuiZ3wUDErccfUFGGgcBKFsoXOgcX/vSfhi8yCYu3BOD+h5fOMmg/ZVe6NMjCVq50
D8yce5gPoypg2LHijse+0R1bPil8o=
暗号化されたデータ:
0qf1eWjjaHkiqRFKijam


送り先番号: 1
使った公開鍵:


-BEGIN PUBLIC KEY—–
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzZFcKoXbuWzGvlv++7Y05/jBh
nYC+PM67v3H2I5pYV8tUz/6GqsG5afFgLJYoWPEd3KYXHb46B0GxEOydOTuTLEcv
+gVr6v4khgOgjxOcM1hlv+EvAThm1lIY1Y5lbTv+MEUyrGm7SDk8iUaHF6OBcQp3
NzkO6j3+YrsC8znXPwIDAQAB


-END PUBLIC KEY—–
対応するエンベロープキー:
Hpv4sE4M4RGnbEAPMqFKxOOPDJG0hpWBoIXCe8xUaIzx/dskUQ/a+T4jYyw+RRGh11wlzZt
CJOjzkP3pbafc0ymElAzS8RFAne7bVuCJh44UF55thAUo0nZVo1/2Wz9HuTDL23AYwc+jyh
U/k24bpGh81VJl5I7IkItoDeiS70Y=
暗号化されたデータ:
0qf1eWjjaHkiqRFKijam

受信側結果:

Hello, world!!

 
参考:
OpenSSL 関数(php.net)
 PHP マニュアルの OpenSSL 関数についての項目。
OpenSSL 公式サイトの日本語訳サイト
更新は不定期のようですが、openssl のマニュアルが参考になります。
公式はこちらです。

PHP の OpenSSL 関数で DSA(DSS) を使うとエラー

PHP で OpenSSL 関数を使って DSA 公開鍵での暗号化を行おうとしたところ

Warning: openssl_public_encrypt(): key type not supported in this PHP build!

のようにエラーがでてしまった。
 
PHP のソースを追ってみたところ、どうやら PHP では現在のところ DSA の秘密鍵/公開鍵についてはサポートされていないようです。
 
php-5.2.1/ext/openssl/openssl.c:

PHP_FUNCTION(openssl_public_encrypt)
{
// ** 省略 **
        switch (pkey->type) {
                case EVP_PKEY_RSA:
                case EVP_PKEY_RSA2:
                        successful = (RSA_public_encrypt(data_len,
                                                (unsigned char *)data,
                                                cryptedbuf,
                                                pkey->pkey.rsa,
                                                padding) == cryptedlen);
                        break;
                default:
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, “key type no
t supported in this PHP build!”);

        }
// ** 以下略 **

のように、
openssl_open(), openssl_seal(), openssl_private_decrypt(), openssl_private_encrypt(), openssl_public_encrypt(), openssl_public_decrypt()
など、暗号化/復号化を行う関数では RSA か RSA2 の時の処理しか実装されていないようです。
 
参考:
OpenSSL 関数(php.net)

他のアプリケーションのキーイベント等メッセージ監視

SetWindowsHookEx() という API を使うと、他のウィンドウに対するさまざまなイベントを監視することができます。
 
デフォルトの動作であるローカルフックだとそのアプリケーションに対するイベントしかとれません。他のウィンドウのイベントをとるキーロガー的な動作を実現するにはグローバルフックにする必要があります。
グローバルフックを行うには、DLL のハンドルを引数として渡さなければならないため、DLL で実装しなければなりません。
 
参考:
SetWindowsHookEx()(MSDN)
他のアプリケーションのメッセージを監視(doumo.jp)