WordPressで数式を書くプラグイン MathJax-LaTeX を使って見る
[mathjax] 機械学習の各種アルゴリズムを読み解いていく際に、高頻度で確率統計に現れる数式が現れる。機械学習を習得していくにあたってWordPressに習得内容をまとめていきたいな、等と思うと、やはりHTMLで数式を書くことの限界は見えてくる。 MathJax-LaTeX 数式を書くツールといえば、今も昔もTeX(LaTeX)。WordPressのエントリにLaTeXスタイルで数式を記述するプラグイン(MathJax-LaTeX)を利用してみたので記事にしてみた。 エントリの先頭にショートコードmathjaxを書き、以下のような書式で文章を入力する。 $$x=frac{-bpmsqrt{b^2-4ac}}{2a}$$ 結果は以下の通りである。 $$x=frac{-bpmsqrt{b^2-4ac}}{2a}$$ うん。LaTeXのエスケープ文字はバックスラッシュだから、[option]+[¥]を打たないといけなくて面倒な以外はものすごく自然だ。フォントの再現性はこの際気にしなくても良いだろう。 数式サンプル いくつか数式を書いてみる。一番最初は正規分布の確率密度! $$p(x)=frac{1}{sqrt{2pisigma^2}}e^{-frac{1}{2sigma^2}(x-mu)^2}$$ $$p(x)=frac{1}{sqrt{2pisigma^2}}e^{-frac{1}{2sigma^2}(x-mu)^2}$$ 次、n次多項式。 $$ begin{eqnarray} f(x)&=&w_0+w_1x+w_2x^2+w_3x^3+cdots+w_Mx^M \\ &=&sum^M_{m=0}w_mx^m end{eqnarray} $$ $$ begin{eqnarray} f(x)&=&w_0+w_1x+w_2x^2+w_3x^3+cdots+w_Mx^M \\ &=&sum^M_{m=0}w_mx^m end{eqnarray} $$ 次、行列。 $$ A = left( begin{array}{ccc} a & b & c \\ d & e & f \\ g & h & i end{array} right) $$ $$ A = left( begin{array}{ccc} a & b & c \\ d & e & f \\ g & h & i end{array} right) $$ まとめ 使用感はまったくもってLaTexでした。フォントの表示を実現するために四苦八苦することも一切なくWordPressで数式を書けます。今までバカみたいにHTMLで数式書いてたのがマヌケでした。
FileMakerServer15の通信を無料でSSL化する方法
FileMakerServer15からデータベースの公開に関してセキュリティが考えられるようになった(本気になった感じ)。Windows VPSにFileMakerServerを配置することでお手軽クラウドが完成するので、割と重要なアップデートだと思う。 Rapid SSLは無理 CSRを作成し、証明書に署名してもらって、秘密鍵と一緒にサーバにインストールする流れはWebサーバと同じだが、RapidSSLなどドメイン認証式(かつファイル認証式)の証明書を作成する場合、FMSは80番で待っている訳ではないから「DocumentRootにファイルを配置してクロールしてもらう」という手続きを進められない。 じゃあ、簡易httpdを立てたらどうか。 RapidSSLのサイトには以下のような記述がある。 RapidSSL、PositiveSSLをお申込みの方へ ホームページが未完成、ホームページに運営者情報が掲載されていない場合、会員制など、ログインが必要なホームページの場合、審査を通過しないケースが増えております。 仮のWebサーバを立てて80番を開けてファイルを配置しても、そもそも怪しい署名リクエストはリジェクトされちゃうらしい!とりあえず、1日経っても来なかった。 一般的なフローではないのだから、仕方ないんじゃないかな。と納得する。そして無料SSLに触手を伸ばす。 Linuxであれば、Certbotを使って90日間の証明書を発行すれば良いが、2017年3月現在、WindowsServerで動作するCertbotが存在せず、Certbotは利用できなさそうである。Windows Serverにvagrant/virtualboxを立てて80番をそこに通すというやり方を思いついたが、それは相当に面倒くさい。 Zero SSL 世の中には便利なサービスがあるものだ。Certbot認証局側をやってくれるサービスが存在する。Zero SSLだ。手順はここのサイトが詳しかった。 サービスのWizardに従ってCSRとコモンネーム(ドメイン)を入力すると、サーバの80の指定URLにファイルを置いてくれ、と言われる。Wizardに従ってNextボタンを押下し続ければ、画面に署名済み証明書と中間証明書が表示される。 FMS15側で1)証明書、2)プライベートキー、3)中間証明書を入れてくれ、と言われるが、2)のプライベートキーはFMS15で生成したものをいれる。ZeroSSLで生成されるプライベートキーは利用しない。1),2),3)を安全な場所に保管しておくこと。 肝心のポート番号だが、80を閉じても繋がるようになった。しかし、443以外のwell knownでないFileMaker専用ポートは依然として使われるようだ。SSLをトンネルとして使うという訳ではなさそうだ。
機械学習 決定木 サンプルデータ(iris)をRのrpartに通してみた
教師有り学習の基本、決定木の動作を実データを使って確認してみた。 データの集合が以下の通り与えられていたとする。 (x,y)i = (x1,x2,x3,......,xk,y)i 決定木とは、従属変数x1,x2,x3.. が説明変数yにどの程度影響を与えているかを表すデータ構造を指す。説明変数yを予測するモデルであり、教師データ(x,y)iからこのモデルを生成することから「教師あり学習」に分類される。その素性がとても簡単なので教師有り学習の一番最初に出てくる。 中間ノードは根からそのノードに至るまでの質問を全て満たす説明変数xの集合に対応し、中間ノードから子ノードへの枝はその変数yiが取り得る個別の値に対応する。決定木のノードと枝はIF-THEN-ELSEに相当する。 中間ノードから子ノードへの分岐を繰り返すと、説明変数xが唯一に決まる時が来る。根から末端ノードまで辿るということは、従属変数に対応する質問を繰り返していったときの結論である。 なお、中間ノードから子ノードへ木を成長させていく際、従属変数の選び方が複数発生する。子ノードのバラつきを何らかの形で定量化し、バラつきが最も小さい従属変数を選択する。例えばバラつきの定量化手法としてエントロピーを採用する場合、親ノードの平均情報量と子ノード候補の平均情報量の差(情報利得)が最も小さい従属変数を選択する。バラつきを求める手法として\"ジニ係数\"を利用するものもあるらしい。 ということで、Rを使ってirisデータフレームについてSpeciesを説明変数、残りを従属変数として決定木を作成してみた。 > tree = rpart(Species~.,data=iris,method=\"class\") > tree n= 150 node), split, n, loss, yval, (yprob) * denotes terminal node 1) root 150 100 setosa (0.33333333 0.33333333 0.33333333) 2) Petal.Length=2.45 100 50 versicolor (0.00000000 0.50000000 0.50000000) 6) Petal.Width=1.75 46 1 virginica (0.00000000 0.02173913 0.97826087) * 出力にインデントがかかっているので何となく木構造が見えるのだが、Rのグラフ出力機能を使ってみる。 > par(xpd=NA) > plot(treem branch = 0.8, margin = 0.05) > text(tree, use.n = TRUE, all=TRUE) 見づらい...。rpart.plotを使う。 > install.packages(\"rpart.plot\") > library(\"rpart.plot\") > rpart.plot(tree, type=1,uniform=TRUE,extra=1,under=1,faclen=0) まだ見づらい...。partykitを使う。 > install.packages(\"partykit\") > library(\"partykit\") > plot(as.party(tree)) なんだか、rpart.plot だけ分岐の値が異なる気がしないでもないが...。partykitの奴は末端のラベルが全部setosaになってる気がしないでもないが...。この木の見方は以下の通り。 従属変数 Petal.Lengthが2.45未満のものは全て 説明変数が Speciesがsetosa 従属変数 Petal.Lengthが2.45以上のものは 従属変数 Petal.Widthが1.75未満のものは 説明変数 Speciesがversicolorのものが49個 説明変数 Speciesがvirginicaのものが5個 従属変数 Petal.Widthが1.75以上のものは 説明変数 Speciesがversicolorのものが1個 説明変数 Speciesがvirginicaのものが45個 従属変数 Petal.Length と Petal.Width がわかれば、この木を辿ることで 説明変数 Species が何になるか予測できる。決定木のエントリというよりRの使い方みたいなエントリになってしまったな。
Laravel Mutator Accessor
たぶん Delphi/C# が起源だと思うんだが、データに紐づく規則や処理をモデルに寄せるパターン(Microsoft:The Repository Pattern)と同等の機能がPHP FrameworkであるLaravelのORM(Eloquent)にあり、流石に超便利だったのでメモっておく。 setter側をMutator、getter側をAccessorという。Mutator, Accessorを簡単にまとめると以下のような感じ。 Eloquentインスタンスに対して値をセットする際に必ずあるメソッド(Mutator)を経由する機能 Eloquentインスタンスから値をゲットする際に必ずあるメソッド(Accessor)を経由する機能 本家のドキュメントは以下のように続く。 Accessors and mutators allow you to format Eloquent attribute values when you retrieve or set them on model instances. For example, you may want to use the Laravel encrypter to encrypt a value while it is stored in the database, and then automatically decrypt the attribute when you access it on an Eloquent model. データに紐づくルールや処理をモデルに寄せることでコントローラの肥大化を防ぐ機能の一つだが、コントローラとモデルの間の取り決めを規約によって定めることで、コントローラからもモデルからも扱いやすくなる。 例えば、usersテーブルにfirst_nameという名前のフィールドがあったとする。 フィールドには小文字で入力し、使うときは必ず先頭1文字を大文字として使う、というルールがある場合Userモデル側を以下のような規約に従って書く。 <?php namespace App; use IlluminateDatabaseEloquentModel; class User extends Model { /* * Get the user\'s first name. * * @param string $value * @return string */ public function getFirstNameAttribute($value) { return ucfirst($value); } /* * Set the user\'s first name. * * @param string $value * @return void */ public function setFirstNameAttribute($value) { $this->attributes[\'first_name\'] = strtolower($value); } } コントローラからfirst_nameフィールドの値を取るコードは以下の通りだが、必ずAccessorを経由し値が返る。フィールドの値が何であれ先頭は必ず大文字になる。ブラウザ等に表示する際に加工する必要がない。 <?php $user = AppUser::find(1); $firstname = $user->first_name; ブラウザ等からデータが入って来たとき、それをusers.first_nameフィールドに格納する処理を書く際、必ずMutatorを経由する。 「小文字にする」という処理を一切意識しないで良い。 <?php $user = AppUser::find(1); $user->first_name = \'Sally\'; コントローラより上は涼しい顔をして重い処理の記述を省略できる。データに紐づくルールが重ければ重いほどモデルに寄せる効果が大きくなる。 例えば、データを暗号化して格納するケースにおいては、暗号化/復号処理をModelに隠蔽しControllerより上からは透過的に平文として扱うなど。 Eloquentは流石に雄弁だ。
計量テンソルの物理的な意味
はじめに Tensor Flowを理解するために計量テンソルの物理的な意味の理解が不可欠なので数式を追ってみた。ちょっと時間かかったけど、計量テンソルまではOK。スカラー、ベクトルを説明するまではまだ理解できてない。しかし、Ad-HocなIT技術ばかり触っていると、数式の美しさは格が違うな。 計量テンソルが直感的に何を表しているのかは最後だけでOK 変換係数αik=gijって何?を理解するために共変ベクトル、反変ベクトルの定義を遡る必要がある ベクトルと変換 ある座標系の基底ベクトル(e1,e2,e3)を、別の座標系のベクトル(e1\',e2\',e3\')に変換することを考える。適当な係数αijを使って線形結合で表現すると、 e1\'=α11e1+α12e2+α13e3 e2\'=α21e1+α22e2+α23e3 e3\'=α31e1+α32e2+α33e3 αikを変換係数と呼ぶ。変換係数により基底ベクトルeから別の規定ベクトルe\'への座標変換を決定している。 まとめると以下のように表現できる。(HTMLじゃ厳しいです...) ei\'=Σk=13αiikek ダッシュ付きベクトルとダッシュ無しベクトルを入れ替えると ek=Σl\'=13αkl\'el\' 上の式に下の式を代入する。これはダッシュ無しベクトルをダッシュ付きベクトルに変換する式に、ダッシュ付ベクトルをダッシュ無しベクトルに変換する式を代入することを表す。もっと言えば、変換と逆変換を同時に行ってみる。 ei\'=Σk=13Σl=13αi\'kαkl\'el\' この右辺はeiiにならないといけないので、 Σk=l3αi\'kαkl\'=0 (i\'≠l\') Σk=l3αi\'kαkl\'=1 (i\'=l\') ダッシュ付きベクトルとダッシュ無しベクトルを入れ替えても同様に、 Σk\'=13αk\'lαk\'l=0 (i≠l) Σk\'=13αk\'lαk\'l=1 (i=l) 見事な感じで、Σk=13Σl=13αi\'kαkl\'は単位行列ということになる。話を戻すと変換、逆変換を同時におこなうと元に戻る、ということになる。 なお、クロネッカーのデルタを使うと、 Σk=l3αi\'kαkl\'=0 (i\'≠l\') Σk=l3αi\'kαkl\'=1 (i\'=l\') は、以下のように1つにまとめられる。 αi\'kαkl\'=δi\'l\' 同様に、 Σk\'=13αk\'lαk\'l=0 (i≠l) Σk\'=13αk\'lαk\'l=1 (i=l) は、以下のように1つにまとめられる。 αk\'lαk\'l=δk\'l 共変ベクトルと反変ベクトル ある基底ベクトルe=(e1,e2,e3)を別の基底ベクトルe\'=(e1\',e2\',e3\')ベクトルに変換する際の座標変換は以下のように表される。 ei\'=αi\'kek この時、変換係数αi\'kを用いて、基底ベクトルの変換式と同一の変換式に従うベクトルA=A1e1+A22+A33を共変ベクトルと呼ぶ。 Ai\'=αi\'kAk 一方、添字を上下逆にした変換係数αki\'ckに従うベクトルC=C1e1+C2e2+C3e3を反変ベクトルという。 C\'i=αki\'Ck ここで、eiを共変基底、eiを反変基底とよぶ。 共変基底、反変基底には次式が成り立つ。 ei・ej=δij 計量テンソル 共変基底ek,ekを用いたベクトルA=Akek=Akek。 それぞれに添字を上下反転させた基底ei,eiとの内積を取る。 ei・A=Akek・ei=Ak(ei・ek) ei・A=Akek・ei=Ak(ei・ek) 共変基底、反変基底の積 ei・ek=gikとする。 ei・A=Akgik ei・A=Akgik A=Aiei=Aieiであるから、 ei・Aiei=Akgik ei・Aiei=Akgik 整理すると、 ei・ei Ai=Ai=gikAk ei・ei Ai=Ai=gikAk つまり以下。 Ai\'=gikAk Ai\'=gikAk これは、ベクトルの共変成分、反変成分の変換式である。 共変成分、反変成分を相互変換する変換係数gij(=αij)の意味 ベクトルrの長さが微小に変化したとする。その微小変化をベクトルdr=dxiei=dxieiとする。 ds2 =dr・dr =dxiei・dxjej=gijdxidxj =dxiei・dxjej=gijdxidxj =dxiei・dxjej=gujdxidxj =dxidxi ei-ejを座標系として取ったとき、dxi、dxjを成分とすることを表す。 また、ei-ejを座標系として取ったとき、dxi、dxjを成分とすることを表す。 これらの座標系で各座標軸に沿った変化分の単純な積dxidxj、dxidxjと、本当の変化分の2乗ds2の比がgij、gijであることを表す。 gij、gijを計量テンソルと呼ぶ。
詐欺サイトを発見したので独自調査してみる
ある商品を探していたのだが、迂闊にも詐欺サイトのカートをポチってしまった。 届いた確認メールが突っ込みどころ満載だったのでそのサイトの模倣元に確認して事なきを得たが、住所と電話番号と氏名を抜かれてしまった。 あれ、自分はITで食ってるんじゃなかったか?詐欺サイトにハマるなんて...。 と疑心暗鬼になった。せっかくなのでブログのネタにしてみる。 実は技術的にこのサイトの秘密を暴いてみようと思ったのだが、 それ自体が不正アクセス禁止法に触れるため載せられないことが判明した。 詐欺サイト自体のセキュリティは緩かった。 サイトの特徴 アパレルのECサイトです。模倣元の子サービスという設定。 リテラシが比較的高くない女性向けだと思います。 市場価格から適度に格安。明らかにパチもんという設定ではない、 楽天との関係を装っています。 かなり精巧に模倣されているが、致命的な抜けがあります。例えば... ドメインが怪しい 特定商取引法の掲示がない 模倣サイトの子サービスの扱いなのに模倣サイトの電話番号がない スマホからだとポチるかも... 誤解を恐れずに言うならば詰めが甘い。もっとできるはず。 なお、情報の少ないスマホ経由だとかなりキワドい。 実質的にはスマホから流入して軽くポチッた人が被害にあっていそうだ。 確認メール おそらくチャイナだろう。日本語がメチャクチャ。詰めが甘いんだよな。 大多数の日本人はここで止まると思う。実質的には個人情報を抜く目的なのかもしれない。 ゆうちょ銀行の口座番号に振り込めと来た。 偽サイトを見つけたら 金銭的な被害がないので警察も動かないでしょう。 100円とか振り込んで相手方の様子を見て遊ぶのも面白いかもしれません。 七面倒臭い展開が待っていると思うのでやりませんがw 出来ることなんて以下ぐらい。 模倣元に偽サイトか否かの確認と事実の報告 振込先金融機関に口座番号が詐欺サイトに使われていることの報告 どういう仕組みで実行犯は金融機関の口座を取得し利用できているのだろうか。 恐らく善良な市民の口座がハックされ犯罪に使われているのだろうが、 そのあたりは知らない方が身のためだと思うので詮索は終わります。 もし実被害が出た場合、警察は指定口座から実行犯を割り出すことができるのだろうか。 公権力はどこまで力を持っているのか興味はあります。興味だけです。 実はもっと技術的に解析を試みたのだが、いくら相手が犯罪者とはいえ、 不正アクセス防止法を犯す行為をネットに晒すことは社会人として許されることはないから書かない。 セキュリティ的に無防備なサーバが存在し、どういう訳がそこで今回のような模倣サイトが運営されていた。 やり得な世界が広がっている事実に寒気がした。
Q-Lerningを試してみる(座学編)
そういえばQ熱って感染症があったな。不明の(Query)熱という意味だそうな。関係ないがQというパズルゲームがあって名作らしい。 食わず嫌いをしていても仕方がないのでちょっと調べてみた。割と単純な探索アルゴリズムの一種だった。自然界の~とか、脳内の~とか言うから胡散臭くなるだけで、コンピュータ上で動作させる他の探索アルゴリズムの一種だと思います。 結論は、枝コスト選択の難しさの解決を後回しにしたところで避けられない。というより、枝コスト選択を先にやらなくて良い、という事実が唯一にして最大のメリット。 アルゴリズムの概要 探索の際に選ぶ枝のコストを確率として予め求めておくのではなく、探索しながら更新していく。 前提は以下。 stは時刻tにおける状態。 atは時刻tにおける行動。 Q(st,at)は状態stにおいて行動atを選択する価値。 rt+1は環境の変化によって貰える報酬。 maxaQ(st+1,a)は 状態st+1のもとで最もQ値が高い行動aを選んだ場合のQ値。 γ(0<γ<1)は割引率。 α(0<α<1)は学習係数。 Q(st,at)を更新しQ(st+1,at+1)にする式は以下。 Q(st+1,at+1) := Q(st,at) + α(rt+1+γ maxaQ(st+1,a)-Q(st,at)) γ、rt+1の値によるが、Q(st+1,at+1)>Q(st,at)となるためには、Q(st,at)よりも、次の状態における最良の行動aを選択した価値Q(st+1,a)の方が大きい必要がある。 一般的にγ=0.9~0.99のように1に近い値を設定することが多いようなので、概ね最良の行動の選択maxaQ(st+1,a)による価値の増加分に報酬rt+1を加えたものがQ(st+1,at+1)となる。 アルゴリズムの設計 全ての状態とその時に取りえる行動の組(s,a)についてQ(s,a)の値をランダムに設定する。 t=0、s0にセットする。 状態stから行動atを選択し状態st+1とする。 状態の更新を一定回数行ったらt=0,s0に戻す。 グルグル回し、何回か終わったら終了。 状態の更新にはε-greedyアルゴリズムを用いる。状態stから状態st+1に遷移する際、常に最大のQ値となる行動を取るということは、最初にランダムで与えたQ(s,a)を教師として枝コストに確率を与えているのと同じになるからN.G.。定数ε(0<ε<1)を用い(1-ε)の確率で最大のQ値となる行動を選ぶようにする。 胡散臭くなってきた!結局枝コストの求め方の難しさに帰着する。たぶん確率密度とかの話ではなくエイヤっとεを決めるんだろう。
重回帰分析と教師あり機械学習
機械学習と多変量解析は本質的に同じ。 重回帰分析 観測された事象から目的変数と説明変数の関係をモデル化する。 目的変数 = a×説明変数1+b×説明変数2+c×説明変数3+d 機械学習 大量のデータを読み込ませることで、人が教えることなくデータの特徴量を導き出す。 機械学習により求められる特徴量は本質的に重回帰分析の係数に相当する。 時期的に、多変量解析(統計) << データマイニング < 機械学習。 要は多変量解析(統計)の理解がなければデータマイニング・機械学習の理解はおぼつかない。 多変量解析はExcelを使ったサンプルが多い。 Excelを使った重回帰分析のサンプル Excelを使うと簡単に重回帰分析の実行結果を得られる。試しに実行してみる。 SNS広告(Seg.1)、Web広告(Seg.2)、口コミ広告(Seg.3)と売上実績(Sales)の関係が以下のようになっているとする。単位は無し。各広告手段の売上実績に対する寄与度をモデル化する。 つまり、Sales=a×Seg.1+b×Seg.2+c×Seg.3+d の係数(a,b,c,d) を求める。 Seg.1Seg.2Seg.3Sales 4.93.11.50.1 5.43.71.50.2 4.831.40.1 4.331.10.1 5.841.20.2 5.74.41.50.4 5.43.91.30.4 5.13.51.40.3 5.73.81.70.3 5.13.81.50.3 回帰統計量 重回帰式 Sales=a×Seg.1+b×(Seg.2)+c×(Seg.3)+d の当てはまりの良さを表す統計量。 通常、重相関係数Rと重決定係数R2は説明変数の数が多いほど大きくなる傾向がある。 補正R2は説明変数の数を考慮した当てはまりの良さを表す。 そのため一般的に当てはまりの良さを見るためには補正R2を参照する。 重相関 R0.874912 重決定 R20.765472 補正 R20.648207 標準誤差0.06962 観測数10 分散分析表 回帰式の全ての係数が同時に0であることの分析。有意F値が0.05未満ならば、統計的に全ての係数が0でないといえる。 有意F値が0に近ければ近いほど重回帰式の信頼度は高いことを表す。 自由度変動分散観測された分散比有意F 回帰30.0949180.0316396.5277516380.025607 残差60.0290820.004847 合計90.124 以下より、a=-0.133596092、b=0.315699216、c=0.14050611、d=-0.403573178。係数の符号が正の場合、説明変数と目的変数に正の相関があることがわかる。係数の符号が負の場合は負の相関。絶対値は相関の強さ。 係数標準誤差 tP-値 切片-0.4035731780.281209521-1.4351334080.201255935 Seg.1-0.1335960920.110652276-1.2073506010.27272798 Seg.20.3156992160.1056493012.9881808270.024377448 Seg.30.140506110.1522815480.9226732460.391770244 下限 95%上限 95%下限 95.0%上限 95.0% 切片-1.0916680890.284521732-1.0916680890.284521732 Seg.1-0.4043524570.137160273-0.4043524570.137160273 Seg.20.0571846890.5742137430.0571846890.574213743 Seg.3-0.2321134140.513125635-0.2321134140.513125635
PythonでAES EncryptしてPHPでAES Decryptできなかった話
標題の通りなのですが。AESなんて枯れてるんだから鍵長と暗号モードを合わせれば出来るだろうと、軽く見積もってました。結果、無茶苦茶頑張ってみましたが出来ませんでした! 結論から先に書くと、以下の方法で逃げました。 PythonでEncrypt/Decrypt Classを書く Python側からは上記のClassをそのまま使う 上記のClassを叩くPythonスクリプトを書き、PHPからシェル経由でそのスクリプトを実行する。 もっと頑張れば道が見つかったかもしれませんが、本当にPython/PHPをクロスして暗号化/復号の対ができるのか心配になって、これに落ち着きました。 出来ない理由.. 正直出来ない理由もハッキリしません。 だいたいどちらでも以下ぐらいは設定できるものなのですが、以下を合わせたぐらいでは片方で暗号化したものを復号することができません。 鍵長=256bit Cypher Algorythm=Rijndael 暗号モード=ECB orCBC まともな暗号処理をするには暗号モードにECBは使えずInitialVector(IV)を与える必要があるのですが、乱数からIVを生成する箇所の共通性が怪しかったり、Python側では共通鍵の鍵長にAPIで制限がかかるものの、PHPでは任意に指定できたり、本当に実装すると突っ込みどころ満載になります。 Pythonのコードはだいたい以下のような感じになります(IVを共有するためにダイジェストにIVを含んでいるのは本質的でないので除いてみてください)。 PythonのCrypto.Cipherは Encryptした結果を自力でPaddingしてBase64エンコードしてますが、PHPのmdecryptはいきなりPrintableな文字列を要求します。普通に考えて、PHPのmdecryptがBase64デコードして同じようにPaddingを取り除くのを期待するのはナンセンスでしょ。 import base64 from Crypto import Random from Crypto.Cipher import AES class AESCipher(object): def __init__(self, key, block_size=32): self.bs = block_size if len(key) >= len(str(block_size)): self.key = key[:block_size] else: self.key = self._pad(key) def encrypt(self, raw): raw = self._pad(raw) iv = Random.new().read(AES.block_size) cipher = AES.new(self.key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(raw)) def decrypt(self, enc): enc = base64.b64decode(enc) iv = enc[:AES.block_size] cipher = AES.new(self.key, AES.MODE_CBC, iv) return self._unpad(cipher.decrypt(enc[AES.block_size:])) def _pad(self, s): return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs) def _unpad(self, s): return s[:-ord(s[len(s)-1:])] 気付いたこと 何か勘違いしているかもしれませんが、早々に別の道に進みました。
実践 PSR-4 クラスをspl_autoloaderを使ってautoloadしてみる最も簡単なサンプル
PSR-4の一次情報を読んだことだし、現在の理解でPSR-4 Autoloadに対応したクラスを作成し実際にAutoloadしてみる。composerもPSR-4に対応しているが、まずはPHP-Figがサンプルとして公開しているspl_autoloaderを使った例を試すことにする。 仕様は以下の通り。 Fully qualified class name ikutyexamplePsr4HelloWorld Namespace Prefix ikutyexamplePsr4 Base Directory ./src/ikuty/example/Psr4 Resulting file path ./src/ikuty/example/Psr4/helloworld.php サンプルクラスの作成 ./src/ikuty/example/Psr4/helloworld.phpを以下の通り作成する。 $ pwd ./src/ikuty/example/Psr4 vi helloworld.php <?php namespace ikutyexamplePsr4; class HelloWorld { public function __construct() { echo \"Hello World!\"; } public function say() { echo \"Hello World!\"; } } 呼出側の作成(PSR-0的) PHP Figにあるクロージャ版spl_autoloaderを使った実装例を試してみる。 ikutyexamplePsr4HelloWorldをnew()すると、spl_autoload_registerで登録したクロージャが評価される。 なお、名前空間の深さとBaseDirectoryの深さ等しくしている意味でPSR-0的なサンプル。 [sample.php] <?php 2 spl_autoload_register(function ($class){ 3 4 //project-specific namespace prefix 5 $prefix = \'ikuty\\example\\Psr4\\\'; 6 7 //base directory for the namespace prefix 8 $base_dir = __DIR__ . \'/src/ikuty/example/Psr4/\'; 9 10 //does the class use the namespace prefix? 11 $len = strlen($prefix); 12 if (strncmp($prefix, $class, $len) !== 0){ 13 // no, move to the next registerd autoloader 14 return; 15 } 16 17 //get the relative class name 18 $relative_class = substr($class, $len); 19 20 //replace the namespace prefix with the base directory, replace namespace 21 //separators with directory separators in the relative class name, append 22 //with .php 23 $file = $base_dir . str_replace(\'\\\',\'/\', $relative_class).\'.php\'; 24 25 //if the file exists, require it 26 if (file_exists($file)) { 27 require $file; 28 } 29 30 }); 31 32 $example = new ikutyexamplePsr4HelloWorld(); 33 $example->say(); 名前空間プレフィックスとBaseDirectoryの紐づけは結局人力でやっている。「名前空間プレフィックス」と「クラス名」の間にある「サブ名前空間」を読み飛ばしている。名前空間プレフィックスに続く「サブ名前空間」分をクラス側が自由に使えるところが興味深い。 実行結果 実行してみる。実行結果から分かりにくくて恐縮だが、new()してもHello World!は出力されず、say()メソッドを実行したときにHello World!が2回表示された。late-binding的な感じ。 $ php sample.php Hello World!Hello World! 名前空間の深さと関係なくBaseDirectoryを設定する(PSR-4的) 例えば、ikutyexamplePsr4HelloWorldの名前空間プレフィックスikutyexamplePsr4をBaseDirectory ./ikuty-example-psr4 に紐づければ、名前空間がどれだけ深くてもデプロイは影響を受けない。 Fully qualified class name ikutyexamplePsr4HelloWorld Namespace Prefix ikutyexamplePsr4 Base Directory ./src/ikuty-example-Psr4 Resulting file path ./src/ikuty-example-Psr4/helloworld.php <?php 2 spl_autoload_register(function ($class){ 3 4 //project-specific namespace prefix 5 $prefix = \'ikuty\\example\\Psr4\\\'; 6 7 //base directory for the namespace prefix 8 //$base_dir = __DIR__ . \'/src/ikuty/example/Psr4/\'; 9 $base_dir = __DIR__ . \'/src-ikuty-example-psr4/\'; 10 11 12 //does the class use the namespace prefix? 13 $len = strlen($prefix); 14 if (strncmp($prefix, $class, $len) !== 0){ 15 // no, move to the next registerd autoloader 16 return; 17 } 18 19 //get the relative class name 20 $relative_class = substr($class, $len); 21 22 //replace the namespace prefix with the base directory, replace namespace 23 //separators with directory separators in the relative class name, append 24 //with .php 25 $file = $base_dir . str_replace(\'\\\',\'/\', $relative_class).\'.php\'; 26 27 //if the file exists, require it 28 if (file_exists($file)) { 29 require $file; 30 } 31 32 }); 33 34 $example = new ikutyexamplePsr4HelloWorld(); 35 $example->say(); 結論 PHP-Figがサンプルとして提供しているspl_autoloader(クロージャ版)をお試し実装してみた。 PSR-4は名前空間プレフィックスのベースディレクトリの関連を記述する仕様であり、ベースディレクトリの物理的な配置が名前空間プレフィックスに直接影響を受けない。 ベースディレクトリが深くならなくて良い