2009/04/25

client-hello ie firefox RSA SHA1 MD5

SSL の暗号スイートは誰が決めてるのよ? って話になって
この話するの 2 度目なはずなんだけど曖昧な記憶
なので SSL について検索したらサーバが決めてました
client hello でクライアントが使えるリストを提示して
server hello で「じゃぁこれね」ってサーバが選んでるそうです

「じゃぁ、ブラウザは何を提出してるわけ?」って知りませんよねぇ
まぁパケットキャプチャーすれば分かるしサーバいじってもいいのかと思ったら
wireshark で全て解決ということが分かってはいおしまい

というわけにもいかなかったのですが
まぁこんだけ道具揃ってれば絶対誰か調べてるはずなので
ググったらちゃんといらっしゃいました
Tatsuyoshi tech diary
やぁ、すばらしい

ブラウザによってバラバラですね
勉強になりました

2009/04/24

csv python

csv から tsv にしようと思いました
たまに csv だとダメだけど tsv なら平気っていうことに出会ったり
そもそも csv より tsv の方が好きです
ググりました
一杯出てきます

object 指向だと思うともう少しちゃんと書いた方がいいのかしら?と思いつつ
import csv
import fileinput
import sys

tsv = csv.writer(sys.stdout,csv.excel_tab)

for row in csv.reader(fileinput.input()):
tsv.writerow(row)
まぁ簡単でいいや、という気分。
ほんとに変換すればいいんなら
tsv.writerows(csv.reader(fileinput.input()))
でいいのかもしれないけど自重

mod_wsgi

mod_wsgi を使って Django の project を deploy しようとしました
でも WSGI のことは
WSGIとPythonでスマートなWebアプリケーション開発を:第1回 WSGIの概要|gihyo.jp … 技術評論社
で復習しないと曖昧にしか理解できてません、middleware とか
昔一度読んでるのであとは勘が頼りです

apache に mod_wsgi を読ませると wsgi-script という Handler が登録されるみたい
ConfigurationGuidelines - modwsgi - Basic configuration guide for mod_wsgi. - Google Code によると
The WSGI application contained within the code file specified should be called 'application'.

なので
wsgi-script として呼ばれた file に application という関数が定義されていれば
あとは server に渡して動かしてくれます

どうやって wsgi-script だと認識させるかというと
AddHandler, SetHandler, WSGIScriptAlias などを用います
WSGIScriptAlias は ScriptAlias と同じだと思えば OK なはず
これさえ設定してやれば
mod_wsgiでDjangoを動かすまでを淡々と記録する - スコトプリゴニエフスク通信
にあるような sample script はもぉ動くはず
あとは urls.py とか settings.py いじると Django も動く、tryl & error で

でも、これ 1 つの url で動くようになるけど
urls.py にある沢山の URL には対応しない??
試しに沢山ファイル作ったら動いたけどそれじゃ格好悪いし
1 つのファイルで全部受けることにしてあと PATH_INFO っぽい感じでっていうと
AddHandler だと /mysite/index.wsgi/vote/3 とかなるし、格好悪いし
(つうか本当は PATH_INFO ではないと思うんだけど、PATH_INFO って何だ?)
で〜、沢山検索しました
あー、何で ".htaccess" なんて入ってるかっていうと
どうも最初に system の設定 file をいじってるような説明があったので
local で何とかならないかなと思ったからなんですけど

で、結局どうしたかっていうと
SetHandler で拡張子無しで wsgi-script と思わせることにしました
え〜
でもまぁ、仕方ないですよね
Rails のときは lighttpd をサーバにして apache からそれを呼んだんだけど
Django でもそういうのできるのかな?
何かそっちの方がシンプルな気がしてきてるんだけど
また後日ググりましょう

2009/04/23

new.instancemethod

Python で既存クラスに instance method 足せないの? と思ったので
調べてたら結局 new.instancemethod に辿りつきまして検索すると
クラスの挙動まとめ #2 - 大カフェインに辿りつきました
やぁ、ありがたい

#1 があるので #1 から読むと良いですよね
とりあえず、function が class とか instance に対応付けられると (これも束縛と言うの?)
instance method に返信するっていうのが分かりました
あと、class の定義に新旧あるのも知れたので良かったです

小学生の日記みたいになってるな

"recompile with -fPIC" mod_python

Django も勉強したのでデプロイだーと思って
Django のデプロイを見てみたら mod_python を使ったらと
コンパイルしちゃうぞーと思ってコンパイルしてみたら通らない

"recompile with -fPIC" って言われたから検索してみたら
Agile Testing: Compiling mod_python on RHEL 64 bit を発見
Python の Makefile をいじって make install してからやり直したら無事にコンパイルできました
CFLAGS に -fPIC 足しました

mod_wsgi も同様にエラーが出たのだけど同様の方法で解決

にしても blog の記事が 2007/10 なら
何か対応しといてくれても良い気がするんだけど
これは 64bit RHEL 固有の問題なんでしょうか

2009/04/22

数字 変換 python

昨日せっかく n 進表示な str を int に変換したのに
今日はそれをもう一度 str に戻したくなりました
ググりました
とりあえず 16 進でいいよ、と思ったら結局
3.6.2 文字列フォーマット操作でいけました
$ python
Python 2.5.2 (r252:60911, Jan 4 2009, 17:40:26)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "%o %x %X" % (59, 59, 59)
'73 3b 3B'

Python 2.6 以降? なら
$ python
Python 2.6.1 (r261:67515, Apr 19 2009, 02:16:57)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print format(59, 'b')
111011
>>> print format(59, 'o')
73
>>> print format(59, 'x')
3b
>>> print format(59, 'X')
3B

こんなんもいけるみたい
でも、int みたいな柔軟さのあるのは無いのかなぁ

2009/04/21

16進数 python

Python の OpenSSL のバインディング? っていうと
OpenSSLの本にも載っている M2Crypto
でもこれ SWIG を入れなきゃいけなかったりしてちょっとインストールが面倒
他にも SWIG 使ってる package 使いたいってんならいいんだけど、そうでもないし
SWIG 使ってる何か良いパッケージあるんでしょうか

で、簡単にインストールできるのが pyOpenSSL
これは easy_install でサクっと入ってくれたりするんだけど非力
何が例えば困ったかっていうと
  • X.509 の署名アルゴリズムが取れない
  • SSL で繋いだときのサーバが提示するサーバ証明書以外の証明書が取れない
  • 公開鍵のパラメータが取れない
とかまぁ、ニッチな要望なんですけど

で、patch でも書くかと思っていじっていたんですが
RSA っていうと大きな素数を使います、2 つ
しかも掛け算して 1024bit とか 2048bit でないと表現できないような数字を使うので
OpenSSL は BIGNUM とかって多倍長? って言うんでしょうか、型が用意されていて
その型で計算しています、桁溢れちゃうからね!!
で、pyOpenSSL はどうも BIGNUM をバインドしてくれていない、ひどい

ひどい! と思ったんですがそこで諦めてはいかんと思い
かといって BIGNUM を実装というのは踏み込んではいけない世界な気がして
OpenSSL: Documents, bn(3) を良く眺めてみると
char *BN_bn2hex(const BIGNUM *a);
とある、これは BIGNUM を char で 16 進表示してくれるようでした
string までもってったら Python の int にもできるだろうと思って検索
2-36進数の文字列をint型に変換する - スコトプリゴニエフスク通信にありました
>>> int("0101", 2)
5
>>> int("nishio", 36)
1422284208
おぉ〜

で、これを C で書かないといけないので include/python2.6/intobject.h をチェック
PyAPI_FUNC(PyObject *) PyInt_FromString(char*, char**, int);
名前からして何かこれっぽいけど、何だこの第二引数は、ということで更に "PyInt_FromString" で検索
7.2.1 (通常)整数型オブジェクト (plain integer object)
素晴しい、日本語だ
で、どうも NULL で良いらしいので NULL にしたら無事大きな数字が出てきました

NULL ってのはアドレス 0 を挿すポインタのことらしい
要するに 0?

結局どうなったかっていうと
static PyObject *
crypto_PKey_params(crypto_PKeyObj *self, PyObject *args)
{

PyObject *params;

if (!PyArg_ParseTuple(args, ":params"))
return NULL;

params = PyDict_New();

if (self->pkey->type == EVP_PKEY_RSA) {
if (self->pkey->pkey.rsa->n != NULL)
PyDict_SetItem(params, PyString_FromString("n"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->n), NULL, 16));
if (self->pkey->pkey.rsa->e != NULL)
PyDict_SetItem(params, PyString_FromString("e"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->e), NULL, 16));
if (self->pkey->pkey.rsa->d != 0)
PyDict_SetItem(params, PyString_FromString("d"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->d), NULL, 16));
if (self->pkey->pkey.rsa->p != NULL)
PyDict_SetItem(params, PyString_FromString("p"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->p), NULL, 16));
if (self->pkey->pkey.rsa->q != NULL)
PyDict_SetItem(params, PyString_FromString("q"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->q), NULL, 16));
if (self->pkey->pkey.rsa->dmp1 != NULL)
PyDict_SetItem(params, PyString_FromString("dmp1"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->dmp1), NULL, 16))
;
if (self->pkey->pkey.rsa->dmq1 != NULL)
PyDict_SetItem(params, PyString_FromString("dmq1"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->dmq1), NULL, 16))
;
if (self->pkey->pkey.rsa->iqmp != NULL)
PyDict_SetItem(params, PyString_FromString("iqmp"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->iqmp), NULL, 16))
;
} else if (self->pkey->type == EVP_PKEY_DSA) {
if (self->pkey->pkey.dsa->p != NULL)
PyDict_SetItem(params, PyString_FromString("p"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.dsa->p), NULL, 16));
if (self->pkey->pkey.dsa->q != NULL)
PyDict_SetItem(params, PyString_FromString("q"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.dsa->q), NULL, 16));
if (self->pkey->pkey.dsa->g != 0)
PyDict_SetItem(params, PyString_FromString("g"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.dsa->g), NULL, 16));
if (self->pkey->pkey.dsa->priv_key != NULL)
PyDict_SetItem(params, PyString_FromString("priv_key"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.dsa->priv_key), NU
LL, 16));
if (self->pkey->pkey.dsa->pub_key != NULL)
PyDict_SetItem(params, PyString_FromString("pub_key"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.dsa->pub_key), NULL
, 16));
}

return params;
}
こんなんになっちゃったんだけど、何か格好悪くない?
誰かに直して欲しい、あと、unittest の書き方も教えて欲しい
つか先ず BIGNUM をバインドしてほしい

あ、ちなみに、Ruby の source を中々参考にしました。