2010/12/20

hg push basic-auth web push_ssl

調べるの 2 回目だったので書いとく。入門Mercurialにも書いてあったら御免なさい。


Mercurial を web ui 経由で push するには
[web]
allow_push = blooper
push_ssl = false
とか書けばいいって
PublishingRepositories - Mercurial
に書いてありました。

つーかその他、複数の repository をまとめて提供する方法とか
色々書いてあるからまた後でよーく読もうと思います。

hgweb.wsgi とか hgwebdir.wsgi とかあるけど
hgwebdir.wsgi がどこで提供されてるのか良く分からん。
と思ったらmodwsgi - Mercurial書いてあった。
WSGI さえ使えればあとは
from mercurial import demandimport; demandimport.enable()
from mercurial.hgweb.hgwebdir_mod import hgwebdir

application = hgwebdir('/var/www/vhosts/hg.example.net/cgi-bin/hgweb.config')
っての用意して
hgweb.config に提供したいもの書けばいいらしい。
楽チンだ。

2010/11/25

bash 変数 改行

情弱なので shell script とか書けません
コマンドの結果とっといて調べて必要なら出力しようと思いました
$ diff=`diff -u a b`
$ if [ $diff != '' ]; then echo $diff; fi
みたいなね
そしたら結果が
--- a 2010-11-25 01:07:18.017333910 +0900 +++ b 2010-11-25 01:07:29.313422799 +0900 @@ -1,4 +1,4 @@ a -b c d +e
って感じで改行無くなっちゃったの

どーすんだかなー、と思ってググりました
bashなどのシェル変数の値に改行を含める事は可能でしょうか? - Linux系OS - 教えて!goo
教えて!goo かぁ、情弱にはぴったりな感じです

つわけで、変数を "" で括って解決してしまいました
切ない

2010/11/03

django file download

ひさ〜しぶりに Django で作ってあったものをいじりました。
str で持ってるデータをダウンロードしてもらいたくって
どうするのかな〜と思ってググってみると

Generating file to download with Django - Stack Overflow
もぉほんと、Stack Overflow と結婚しちゃえばいいのに

上のページは
「Zip file を実ファイル作らずに何とかしたい」
っつー話だったようですが
def download(request):
zip_string = (何か zipped なデータ)
response = HttpResponse(zip_string, content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename=myfile.zip'
return response
みたいにすればいいみたいでした。
みたいってのは content_type を HttpResponse の引数に渡して
Content-Disposition で filename など指定してあげること。

なんか、今更そんなこと調べてるのか! って感じですね、

2010/10/26

getpass python username

Google History は便利ですねぇ。
以前は Firefox の履歴から Google で検索したものを、
じゃなかった、ググったものを抜いてネタ探してたんですが、
今ではすっかり Google History です。

で、暫くサボってたんで記憶も曖昧になってるんですが
getpass python username で検索してるんですよね

何したかったかっつーとそれは覚えてて
getpass は key input 隠して入力取ってくれるけど
入力見せつつ prompt 出して入力取ってくれるの無いの?
って思って

でね、あるわけですよ、raw_input って関数が、だから、
import getpass

print "%s\t%s" % (raw_input('user: '), getpass.getpass('passwd: '))
こんなことすりゃいいんですよ

でね、これは覚えてるんだけどどのページ見て raw_input に辿りついたのか
もしかしたら何か適当にソースを読んだのかもしれないし
どっかページを見たのかもしれないし
それが思い出せんのです

いや〜、こまった
歳が

2010/10/10

tokyocabinet

Tokyo Cabinet を使ってみよー、と思ったんですが
ググってみても
データベースマネージャ Tokyo Cabinet
まぁご本家が一番お詳しいわけですよ

と思ってインストールしようとしたら若干はまりまして
  • 32bit 環境だったら --enable-off64 付けましょう
というのが教訓でした

で、どうせならこれを TokyoTyrant からと思って
ディスク多めだった FreeBSD のサーバから、と思ったらまたはまって
  • FreeBSD だったら gmake 使って build

というのが結論でした

更に、データほ他マシンに移動させると
5: invalid meta data
って怒られたりするの。
  • --enable-swab っていう configure option もあるぞ
まじでー

dbm かわいいなぁ

メモリが 16GB くらいあるマシンが欲しいっす

2010/10/05

cryptoapi aia windows-98

cryptoapi というのはここでは Windows API の暗号のやつを想定
AIA は Authority Information Access の略
Authority Information Access は X.509 などの機能拡張
X.509 は公開鍵証明書の規格の名前
で Windows 98 は Microsoft の OS の名前

で、やっぱ AIA ですよね、何それ? っていうの
http://www.ipa.go.jp/security/rfc/RFC5280-04JA.html#042201 見ると
その証明書の認証局の証明書が入ったりするみたいです。

で、ここで我らが Microsoft さんの登場です。
いつも知らないところで色々してくれてる Microsoft さん。
CryptoAPI で証明書を検証するときにも AIA をちゃんと見てくれて
手元に指されてる証明書が無かったら取ってきてくれたりするんです。

えー、まじでー

っていうのを検索した結果の「暗号と PKI の基本」には書いてあります

にしても「RFC 5280」にしても「暗号と PKI の基本」にしても
長い
引用しようと思ったけど必要なとこ含ませると長くなっちゃって
そんなダラダラ引用しても仕方ないから引用しませんでした
なんかもーこっとさっくり言えないもんすかねぇ

で、Windows 98 ですよ、検索語句にも含めた
Windows 98 でもそうなのかどうか? が良く分からず
検索自体は空振りに終わってしまいました
実機検証でもできたらいいんですが...

Windows 98 ってどうやったらいま動かせるの??
CD はあるんですが boot disk が見当たらず
FreeDOS と仮想化技術で何とかならないのかなぁと思うんですが
面倒ですね、Windows 98 までそこまでするか??

いかん、Microsoft の話してるのに愚痴が多くなってしまった

2010/09/23

diffie-hellman dhe

なんか、質問受けてたんですよね、きっと
DH と DHE って何が違うの? って話になったんで検索しました

夜でもアッサム: SSL(TLS)のDHとDHEの違い
なんかもぉ、しっかり書いてありましたよ
  • DHEのEは、EphemeralのE。
  • DHEは、DHパラメータを通信時に動作に作成する。
  • DHは、DHパラメータは証明書に書かれている物を使う。よって、static DHとも呼ばれる。
  • DH-RSAは、証明書にCAがRSAで署名したという事。証明書にRSA鍵が入っているわけではない。
  • DHE-RSAは、証明書にRSA鍵が入っている。


でね、気になるので原典をあたるわけですよ、
英語だと辛いから和訳ですけど
The TLS Protocol Version 1.0
DH は、認証局(CA)によって署名されたサーバー証明書に含まれているDiffie-Hellman パラメータを使用した暗号スイートを示すものである。DHEは、CA によって署名された DSS またはRSA証明書により署名されたDiffie-Hellmanパラメータを使用した一時的 Diffie-Hellman を示すものである。使用される署名アルゴリズムは、DHまたは DHEパラメータの後に指定される。
おぉ、なるほど、これだ

この前後に、大量の CipherSuite が記載されています。
抜粋すると
CipherSuite TLS_RSA_WITH_RC4_128_MD5 = { 0x00,0x04 };
CipherSuite TLS_RSA_WITH_RC4_128_SHA = { 0x00,0x05 };
CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x0A };
CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00,0x0D };
CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x10 };
CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00,0x13 };
CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x16 };


SSL/TLS って何をしてるかってーと
  • サーバ(とクライアント)の認証
  • 通信の暗号化
  • 通信の改竄検知
でした。で、それぞれ
  • 証明書(=身元情報+公開鍵+それらの認証局による署名)と公開鍵に対応する秘密鍵を持ってること
  • 外部とは秘密に交換した情報を鍵とした暗号化
  • 外部とは秘密に交換した情報を鍵とした HMAC
で実現してました。

何が大切かっていうと「信頼できる相手」と「鍵交換」できるってことね

TLS_RSA_WITH
鍵交換に使える RSA 証明書があるんで、秘密鍵持ってることを確認して認証して、証明書の鍵で鍵交換
TLS_DH_???_WITH
DH 証明書があるんで、鍵交換で同じもの共有できると秘密鍵の所有も確認できるんで認証もできる。??? ってのは証明書の署名。
TLS_DHE_???_WITH
鍵交換には使えないかもしれない? RSA/DSS 証明書があるんで、秘密鍵持ってることを確認して認証して、公開鍵で署名した DH の鍵なら信頼できるんでそれを使って鍵交換。??? は、何だ? 証明書の公開鍵か? 署名か?


かな、ちょっと想像入ってるけど。
分からない部分もあるけど。

っていうか鍵交換に使える RSA 証明書しか見たことないし
TLS_RSA_WITH だけで許してもらえるよね、きっと。

2010/09/02

pkcs7 openssl create

Windows はダブルクリックで
X.509 な証明書の中身を見せてくれるのでいいですよね
PKCS#12 も PKCS#7 も中身見せてくれたりします
何で CSR は見せてくれないんでしょう、ここだけちょっと残念

PKCS#7 ってのは「PKCS - Wikipedia」に書いてありますが
メッセージの暗号化や証明書の配布に使われる形式だそうです
Windows だと複数の証明書をまとめて PKCS#7 にしておくと
一辺にインポートできたりして便利です

で、作り方が分からない、OpenSSL ならできるんじゃないの!?
でもそれっぽいコマンドがないヨ!!
と思って検索しました

Creating a PKCS7 (P7B) Using OpenSSL | langui.sh
おぉぉ、
$ openssl crl2pkcs7 -nocrl -certfile cert.pem
なのか。crl2pkcs7 なのに -nocrl ってそのセンス!!

PEM が連なってる 1 つのファイルを突っ込んでみて
できたファイルがちゃんと Windows で読めました、沢山入ってました
ちなみに拡張子は .p7b です

2010/08/30

linux 音楽cd コピー

数日車に乗る用事があったので
聴きたい CD をコピーして車で聴くかと思いました
で、Mac mini でコピーしようと思ったんですが方法が良く分からず
ググったり何なりした結果 iTunes に一旦読み込まないとダメと結論
なにそれ面倒くさい

本当は OS X 用のライティングソフトも持ってるんですが
インストールしてなくてどっか仕舞っちゃってたのでやっぱ面倒
なので Linux で何とかならないの? と思いました

Linux:コマンドラインで音楽CDをコピー - miyapiのひとりごと
これだ!

cdrdao ってソフトがあって、それなら音楽 CD も扱ってくれるみたいで
# cdrdao copy
でも適当にデバイス見付けてよきにはからってくれます
ドライブが複数繋がってたら指定したらいいと思う

cdrdao で使いそうなコマンドは copy の他に scanbus と write くらいかな?
copy のときに --keepimage って付けると .toc と .bin って拡張子のファイルが保存され
write で .toc なファイルを指定すると .bin を焼いてくれます
コピーを複数枚複製する場合にはこれが良さそうでした

2010/08/24

conservative powersave ondemand userspace performance

暑い日が続いています
熱いの嫌なのでノートパソコンの CPU も最低周波数で稼働してました
でも何だかそれって、寂しいですよね

CPU の速度ってどーしたかなーと思ってちょっと /etc/init.d 見てみると
/etc/init.d/cpufrequtils ってのが入ってました
$ dpkg -S /etc/init.d/cpufrequtils 
cpufrequtils: /etc/init.d/cpufrequtils
まんまだな
もちっと調べると /etc/default/cpufrequtils で設定してたみたいで
$ cat /etc/default/cpufrequtils 
GOVERNOR="powersave"
powersave と設定してました。

こいつをちょいと変えてみようかと思ったわけですが
そもそもどんな選択肢があるか覚えていません
/sys 以下のどっかに書いてあったよなー、と思って探すと
$ cat /sys/devices/system/cpu/cpu?/cpufreq/scaling_available_governors 
conservative powersave ondemand userspace performance
conservative powersave ondemand userspace performance
つわけでこいつらで検索

動的にCPUクロックや電圧を変更するcpufreqの概要とcpufreqdデーモンについて - 試験運用中なLinux備忘録
説明してくださってました。
更に conservertive に関してのチューニングまで
cpufreqの「conservative」governorについての覚え書き - 試験運用中なLinux備忘録

まぁ、powersave の次は conservative かな、
気が向いたらちょっとだけがんばってくれればいいかな、
と思ったのでチューニングなどせずとりあえず conservative にだけしました
ちょっと様子みてみます

2010/08/01

lxml html

日本に割りあてられてる IP address が分かると嬉しいですよね
国内からならアクセスできるようにするとかできるようになります

ちょっとググると APNIC が日本に割りあててる IP address は
http://ftp.apnic.net/stats/apnic/delegated-apnic-latest
に書いてあるもののようでした
IPv4 についても IPv6 についても書いてあります

で一方で国内っつったら APNIC よりは JPNIC でしょってことで
ちょっと JPNIC のページを探っていたんですがこんなのあったりして、ん〜、なんだこれはどうなってるんだ

で、何か違いがあるのかしら、と思って調べようと思ったんですが
JPNIC の方は table でこんなのどうしようかと
使ったことない lxml 使ってみることにしました
4 TopCoder: lxmlでHTMLスクレーピング
を見ながら

まぁだいたい 256 コ単位で割り振られてるんでしょうから
頭の3オクテット部分を列挙して diff 取ることにしましたよ
import math
import re
from urllib import urlopen

from lxml import html

def ip2int(ip):
return sum(
[256**x*int(y) for (x, y) in enumerate(reversed(ip.split('.')))])

def int2ip(n):
result = []
for i in range(4):
result.insert(0, str(n % 256))
n = n / 256
return ".".join(result)

classCs = set(())

for line in urlopen('http://ftp.apnic.net/stats/apnic/delegated-apnic-latest'):
rows = line.rstrip().split('|')
if len(rows) >= 4 and rows[1] == 'JP' and rows[2] == 'ipv4':
for i in range(int(rows[4])/256):
classCs.add(ip2int(rows[3])+256*i)

for url in ('http://www.nic.ad.jp/ja/dns/jp-addr-block.html',
'http://www.nic.ad.jp/ja/dns/ap-addr-block.html'):
root = html.fromstring(urlopen(url).read())
for (start, _, end) in [ [b.text for b in a.xpath('td')]
for a in root.xpath('//tr') ]:
tmp = ip2int(start)
end = ip2int(end)
while tmp < end:
classCs.add(tmp)
tmp += 256

for num in sorted(classCs):
print re.sub(r'\.[0-9]+$', '', int2ip(num))
使い捨てもいいところだ

で、こんな感じで2つ差分とってみましたところ
$ diff -u a.txt b.txt 
--- a.txt 2010-08-17 12:20:53.976666937 +0900
+++ b.txt 2010-08-17 12:14:20.992660340 +0900
@@ -554716,6 +554716,7 @@
203.190.61
203.190.62
203.190.63
+203.191.2
203.191.136
203.191.137
203.191.138
203.191.2?
そりゃいったい日本なのよどうなのよ
と思って上の delegated-apnic-latest を grep しみると
apnic|AU|ipv4|203.191.2.0|256|20060615|assigned
AU? オーストラリア??

まぁあとは WHOIS とか引いてみればいいわけですが
なんでオーストラリアかなぁ???

2010/07/29

chrome "missing-plugin"

google chrome を使っているんですが
extension なんて普段全然使っていないものですから
【レポート】Google Chromeのチームが使っているエクステンション19 | エンタープライズ | マイコミジャーナル
これがちょっと気になったりして
Google Docs/PDF Viewer - PDFやPowerPointプレゼンテーションデータなどをGoogle Docsビューアで閲覧するためのエクステンション。
これも入れてみました

でもね、
PDF 見るのはローカルで viewer 使った方が快適だ!
PPT なんて普段見ないや!
という理由からやっぱり削除することに

で、削除したら PDF クリックしたときに
"missing plug-in" とだけ出た画面になるようになっちゃった
昔はダウンロードしてくれてたのに、困った

ググりましたよ、困ったから
そしたら about:plugins を見ろって言われました


おぉ、Disable にできる

確かにね、ありました、PDF の plug-in
近頃の chrome は PDF viewer 持ってるはずなんですよね
Linux だとどうなってるんだか知りませんが
Adobe Reader 辺りから何かもってきて入れとくのかな??

まぁ、ここで有効/無効が選べるのが分かったので
無効にしてあげたら無事ダウンロードしてくれるようになりました

ちなみに右の方に details って詳細見せてくれるボタンあって
それ開いたら上から三つめの名無しさんは Java でした

2010/07/24

ssl-v3

今まで OpenSSL/GnuTLS/Java のライブラリを使って証明書取ってきました
そろそろ SSL のこと詳しく知ってもいいんじゃない?
でも暗号とか難しそうだしどうしようかなぁ

手元に「マスタリングTCP/IP SSL/TLS編」はあったので
つらつらと眺めたり wireshark のログを見て分かってきたので
更に原本にあたろうと思い SSLv3 の仕様を眺めることに
The SSL Protocol Version 3.0
SSLv2 はもぉ使わない方がいいらしいですしね
TLSv1 でもいいんですが、何となく SSL の方を選択

すげー簡単に SSL の手順書くと
  • client hello で使える暗号スイートリストと client random 送信
  • server hello で使う暗号スイートと server random 送信
  • server certificate でサーバの証明書送信
  • client key exchange で pre-master secret 送信
  • 両者で鍵作って finish
細かいことは解説してるサイトを見るということで

よーし、とーさん Python で実装しちゃうぞー、と思いますよね
データのやりとりは TCP などの上で SSL Record とかいう
version と type と length だけ頭に付ける単純な入れ物に入れて行われて
中身もまぁ大体似たようなもんでした、type と length くらい

client hello は random とか送るんだけど決め打ちで
時間を入れるとこがあるんでそこだけ真面目に入れてみました

server hello done まではまだ暗号とか使ってないんで
パースして証明書を取り出してみました

ここまでで力尽きました
標準ライブラリだけでガンバりましたヨ!!
def bin2int(b):
return sum(256**e*x for (e, x) in enumerate(reversed([ord(x) for x in b])))

def recv_server_hello_from(s):
messages = []

received = ''
while True:
while len(received) &lt; 5:
bytes = s.recv(1024)
if len(bytes) == 0:
raise socket.error(&quot;0 bytes received&quot;)
received += bytes

header, received = received[:5], received[5:]
content_type = ord(header[0])
version_major = ord(header[1])
version_minor = ord(header[2])
if not (content_type == 22
and version_major == 3 and version_minor in range(3)):
raise socket.error(&quot;not SSLv3/TLS&quot;)
content_length = bin2int(header[3:5])

while len(received) &lt; content_length:
bytes = s.recv(1024)
if len(bytes) == 0:
raise socket.error(&quot;0 bytes received&quot;)
received += bytes

content, received = received[:content_length], received[content_length:]

class ServerHelloDone(Exception):
pass
try:
while content:
msg_type = ord(content[0])
if msg_type == 14:
raise ServerHelloDone
if msg_type not in (2, 11, 12, 13, 14, 15, 16, 20):
raise socket.error(&quot;not SSLv3/TLS msg_type = %d&quot; % msg_type)
msg_length = bin2int(content[1:4])
msg = content[4:4+msg_length]
messages.append((msg_type, msg_length, msg))
content = content[4+msg_length:]
except ServerHelloDone:
break

return messages

def parse_server_certificate(data):
certs = []

length, data = data[:3], data[3:]

while data:
length = bin2int(data[:3])
certs.append(data[3:length+3])
data = data[length+3:]

return certs

if __name__ == '__main__':
import socket
import struct
import time

client_hello = (b'\x16\x03\x00\x00`\x01\x00\x00\\\x03\x00'
+ struct.pack('&gt;I', int(time.time()))
+ 'L?\xac\xc8\xc5lw?\xa8\x1a\xce\xdf\x8d\xc0\x96'
+ '\t\x97\xab\xa1dv\xc1\xec\x9aj\xc8\x0f(\x00\x004\x00'
+ ':\x009\x008\x005\x004\x003\x002\x00/\x00\x1b\x00\x1a'
+ '\x00\x19\x00\x18\x00\x17\x00\x16\x00\x15\x00\x14\x00'
+ '\x13\x00\x12\x00\x11\x00\n\x00\t\x00\x08\x00\x06\x00'
+ '\x05\x00\x04\x00\x03\x02\x01\x00')

s = socket.socket()
s.connect(('www.google.com', 443))
s.send(client_hello)

for (msg_type, msg_length, msg) in recv_server_hello_from(s):
if msg_type == 11:
for cert in parse_server_certificate(msg):
print '-----BEGIN CERTIFICATE-----'
print cert.encode('base64'),
print '-----END CERTIFICATE-----'
これ動かすと
$ python sslv3.py 
-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQG
EwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhh
d3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0xMTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVT
MRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApH
b29nbGUgSW5jMRcwFQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jNgtXj9xVo
RaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L05vuuWciKh0R73mkszeK
9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAMBgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0w
K6ApoCeGJWh0dHA6Ly9jcmwudGhhd3RlLmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYI
KwYBBQUHAwEGCCsGAQUFBwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzAB
hhZodHRwOi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0ZS5j
b20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUFAAOBgQCfQ89bxFAp
sb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5u2ONgJd8IyAPkU0Wueru9G2Jysa9
zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqA
ibAxWEEHXw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDIzCCAoygAwIBAgIEMAAAAjANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJVUzEXMBUGA1UE
ChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlm
aWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNTEzMDAwMDAwWhcNMTQwNTEyMjM1OTU5WjBMMQswCQYD
VQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMN
VGhhd3RlIFNHQyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1NNn0I0Vf67NMf59HZGh
PwtxPKzMyGT7Y/wySweUvW+Aui/hBJPAM/wJMyPpC3QrccQDxtLN4i/1CWPN/0ilAL/g5/OIty0y
3pg25gqtAHvEZEo7hHUD8nCSfQ5i9SGraTaEMXWQ+L/HbIgbBpV8yeWo3nWhLHpo39XKHIdYYBkC
AwEAAaOB/jCB+zASBgNVHRMBAf8ECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjARBglghkgBhvhCAQEE
BAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFByaXZhdGVMYWJlbDMtMTUwMQYDVR0fBCow
KDAmoCSgIoYgaHR0cDovL2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwMgYIKwYBBQUHAQEEJjAk
MCIGCCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMDQGA1UdJQQtMCsGCCsGAQUFBwMB
BggrBgEFBQcDAgYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEBBQUAA4GBAFWsY+re
od3SkF+fC852vhNRj5PZBSvIG3dLrWlQoe7e3P3bB+noOZTcq3J5Lwa/q4FwxKjt6lM07e8eU9kG
x1Yr0Vz00YqOtCuxN5BICEIlxT6Ky3/rbwTRbcV0oveifHtgPHfNDs5IAn8BL7abN+AqKjbc1YXW
rOU/VG+WHgWv
-----END CERTIFICATE-----
証明書が出てきます

つづく (のか!?)

2010/07/15

imap4 login list

telnet と openssl s_client があれば大抵のことはできるよね!
って思いませんか?

まぁそこまでするつもりはないんですが

IMAP4 の確認がしたかったんでそりゃ telnet だろと思い
ググってみたところ
IMAPプロトコルの流れを学ぶ
おぉ、すごい、各クライアントの挙動が!!

まぁ古い記事なので近頃はまた違うかもしれませんが
IMAP4 に関しては IMAP4rev1
RFC 3501 - INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1
これとか見たらいいのかなと思っています
subscribe ってコマンドなんかが増えているのです

2010/07/09

postgresql graphviz

PostgreSQL の DB がありまして
どんなことになってるか把握したいと思ったんですが
可視化だよ、世の中可視化だよと思い
可視化といえばと GraphViz で何とかならないの
って検索してみました

http://www.graphviz.org/Resources.php
GraphViz のページがヒットして良く見てみると
PostgreSQL Autodoc
このページへのリンクがありました

で、適当に apt-get で Perl の module 入れて
db に接続したら dot ファイルとか html ファイルとか生成してくれて
見事なグラフが書けました

備忘備忘

2010/06/25

header_logo trac

Ubuntu を入れたんで Trac + Mercurial でも作ってみようかと
最近 build ばっかしてて疲れてきたので package でサクサクいきたいです

package をまず探したいんですがファイルから探したいので
auto-apt とか apt-file とか入れようと思って
auto-apt 入れようとしたら凄い依存関係が攻めてきたので apt-file で
でも、apt-file 遅いんだよなぁ
$sudo aptitude install apt-file
(略)
$ sudo apt-file update
(略)
$ apt-file search bin/tracd
trac: /usr/bin/tracd
お前はそこまでしないと trac という package みつけられないのか!

trac を入れようとすると沢山依存関係で入ります。apache とか。
まぁ apache でいいですよね。
あと mercurial にしたいので trac-mercurial も入れます。

で、ここからググると思うでしょ?
でも Debian ならググらなくてもいいんです。
/usr/share/doc の下にドキュメント揃っていますの。
  • /usr/share/doc/apache2/README.Debian.gz
  • /usr/share/doc/trac/README.Debian.gz
  • /usr/share/doc/trac-mercurial/README.Debian
みたいに README に Debian って付いてるのが
Debian 系の設定方法が書いてあったりするファイルになります

/usr/share/doc/trac/README.Debian.gz に trac 環境の作り方細かに書いてあって
  Trac can work without vcs repository, but you may want to create
one for you project before creating a Trac environment. With
Subversion this can be made with:

$ mkdir /path/to/repos
$ svnadmin create /path/to/repos

A new Trac environment is created with trac-admin:

$ trac-admin /path/to/projectenv initenv
なんかレポジトリ作ってそれ使って trac を initenv しろと
今回は mercurial でいきたいので svn? って聞かれるところを hg と答えます

で、apache で使えるようにするには
Configuring as CGI, WSGI, FastCGI
---------------------------------

For trac >= 0.11 the *gi scripts have to be generated using the deploy command:

trac-admin /path/to/env deploy /path/to/www/trac
deploy しろと
WSGI がお薦めらしいので
#Trac as WSGI on Apache
#extra info on http://trac.edgewall.org/wiki/TracModWSGI
#info about daemon mode http://code.google.com/p/modwsgi/
# http://code.google.com/p/modwsgi/wiki/IntegrationWithTrac
WSGIScriptAlias /trac /path/to/www/trac/cgi-bin/trac.wsgi
WSGIScriptAlias を設定しろと
なんでまぁ例えば /etc/apache2/sites-available/default なんかに
WSGIScriptAlias 設定すればいいのかー

で、apache 再起動したら動かなかったんですが
そういえば mod_wsgi を入れた覚えがなく
$ apt-file search wsgi.conf
libapache2-mod-wsgi: /etc/apache2/mods-available/wsgi.conf
なので libapache2-mod-wsgi を入れました

で、最後に /usr/share/doc/trac-mercurial/README.Debian を見て
  [components]
tracext.hg.* = enabled

(略)

[hg]
# -- Show revision number in addition to the changeset hash
show_rev = yes

# -- Changeset hash format
node_format = short
# hex: Show the full SHA1 hash
# short: Show a shortened hash for the changesets
って設定を trac.ini にコピりました

これで http://192.168.0.1/trac とかにアクセスしちゃうと
mod_wsgi 経由で trac が動いちゃってるという素敵

で、動いたんだけど左上のロゴが壊れてたのでググったら
Tracサイトのロゴを変えたい - hack my life
src = site/your_project_logo.png
ってあるので、
trac の下の htdocs に your_project_logo.png って画像置けば OK だそうでした

2010/06/24

lucid xen domu

定期的に何かを更新するとか面倒ですよね
放っておくといつの間にか VM image も熟成しています
フレッシュなのが欲しいね! ということで作ることにしました

流行りには乗る方向で今回は Ubuntu

Debian 系である Ubuntu には debootstrap っていう
最小構成なシステムをネット経由で構築してくれるツールがあるので
debootstrap_1.0.23_all.deb を拾ってきて
$ ar -x debootstrap_1.0.23_all.deb
$ tar xfz data.tar.gz
みたいなことすると中身が取り出せます
usr ってディレクトリができてて中に色々ありますが
usr/share/debootstrap ってのが debootstrap のシステムみたいなもんなので
$ export DEBOOTSTRAP_DIR=(前は色々あるでしょうけど)usr/share/debootstrap
ってしときます

で、root_dir ってディレクトリ作っといて
おもむろに
$ ./usr/sbin/debootstrap --arch i386 lucid root_dir ftp://ftp.riken.go.jp/Linux/ubuntu
と打てばダウンロードと展開が始まります

で、以下は ext4 な file が root_dir にマウントされてると思って読んでね

終わったらデータは揃ってるんですけどまだ設定ができてないので
root_dir/etc/fstab に
/dev/hda1      /       ext4    errors=remount-ro       0       1
なんて書いて
root_dir/network/interfaces に
auto eth0
iface eth0 inet static
address 192.168.0.2
network 192.168.0.0
netmask 255.255.255.0
broadcast 192.168.0.255
gateway 192.168.0.1
dns-nameservers 192.168.0.1
みたいなの追加したらいいと思います
ほんとは Network の設定は NeworkManager とか使うんでしょうけど
まぁ、いつか覚えましょう

で、kernel ですよね
Xen 用の kernel で準仮想化といきたいところなんですが
Ubuntu の場合は server 用の kernel 使うんだったかなーと思いながら調べると
Xen: Debian Lenny Dom0 with Ubuntu Lucid Guest — Agile Web Operations
linux-image-ec2 を入れろと書いてある!! そんなのありますか
おどろいた

インストールするには chroot しましょう
$ chroot root_dir
$ apt-get update
$ apt-get install linux-image-ec2
$ apt-get install libc6-xen
的なことをしまして chroot を抜けます

root_dir/boot に initrd と vmlinuz ができてるんで
こいつらをコピーして Xen に登録してやったら完成です
簡単だよ Ubuntu! 簡単だよ Debian!!

2010/06/05

python "クラス変数"

やっぱりクラス変数のこと良く分かってませんでした
クラス変数?インスタンス変数? - Ponsukeの日記
これこれ

例えば
class A(object):
n = 0
l = []

def __init__(self):
print self.n, self.l

self.n = self.n + 10
self.l.append(10)

print self.n, self.l

A()
A()
こんなの実行すると
0 []
10 [10]
0 [10]
10 [10, 10]
ってなって
「なんで self.n が 0 に戻るんだYo!!」
とか思うわけですが
  • 変数を参照するときはインスタンス変数探して無かったらクラス変数も見にいく
  • 代入するときはインスタンス変数で無かったらインスタンス変数作る
というわけで
    self.n = self.n + 10
この右辺はクラス変数を見てるけど左辺はインスタンス変数なのでした。

クラス変数もインスタンスから self.xxx でアクセスできるとあるけれど
何か混乱しそうなので注意するか別の方法をとるかした方がいいなぁ
と思いました

2010/05/20

"unicode-1-1-utf-7"

なんか、メールでエラーが、っつーことで調べようと良く見ると
unicode-1-1-utf-7 って何だよって思ってググってみたんだけど
や、UTF-7 か、そうか、ASCII で見れちゃうのかとやっとこさ気付き
In [1]: print('+ayEwblPXT+GABTB4MG6RTU/hMGtZMWVXMFcwfjBXMF8wAg-'.decode('utf7').encode('euc-jp'))
次の受信者への配信に失敗しました。
で読めたっていう
それだけの話なんですけどね。

特に Exchange 2000 Server を恨んだりはしていません。

2010/05/13

sni

ことの始まりは
http://twitter.com/k4403/status/13880245576
このつぶやき

Google Reader で証明書に関する警告が出るということで
画像を見てみると FQDN が www.google.co.jp になっていました
ほぉ、www.google.co.jp でもアクセスできるのか、なんて思いつつ
Firefox でアクセスしたら www.google.com にリダイレクトされてしまった
あらら

とりあえず引いてみると
$ host www.google.co.jp
www.google.co.jp is an alias for www.google.com.
www.google.com is an alias for www.l.google.com.
www.l.google.com has address 66.249.89.99
www.l.google.com has address 66.249.89.104
まぁこの辺は色々な仕組みで IP address 渡されてるんだろうけど
でもまぁ、www.google.com の CNAME ってことになってるようで

で、他のブラウザでも、と思って w3m で繋いでみると
Bad cert ident www.google.com from www.google.co.jp: accept? (y/n)
むむむ?
何故 Firefox と結果が違うのだ?
ちなみに https://www.google.com/reader はちゃんと見れるの

で、どうやら 1 IP address で複数の証明書を利用しようとしてるみたいで
それには
  • マルチドメインな証明書 (CN とか SubjectAlternativeName に沢山書く)
  • ワイルドカードな証明書 (* 使う、ホスト名部分だけウマー)
  • Server Name Indication (SNI)
で、google はこの SNI っぽい

SNI?
そもそも何でそんな小細工しないといけなかったかというと
SSL/TLS の handshake の際に IP address だけ使ってたんですって
でも、Virtual Host 的なことは色々なサービスで使いたいのでこれは不便
マルチドメインとかワイルドカードもあったけど根本的に解決しようということなのか
登場したのが SNI だと思うの多分
Server Name Indication - Wikipedia, the free encyclopedia

でまぁ、どうしてるかというと、client hello に繋ぐ先の FQDN 入れるの
そうよね、伝えちゃえばいいのよね
で、Firefox で www.google.co.jp に繋いだところを wireshark で見てみたら
しっかり www.google.co.jp って名前を伝えているようでした
Google は SNI を使っている!!

SNI には 1 つだけ悲しいところがありまして
Windows XP がサポートしていません。2003 もかな。
Windows は CryptoAPI とかいう API で暗号回りを処理してるんだけど
多分それが古いのかな?
で、それを使ってる IE とか chrome が SNI 使えないみたいです。
(chrome はそのうち TLS まわりを自分でもってくるかもしれないけど)

例えば Google App Engine の Roadmap に
App Engine For Business Roadmap - Google App Engine - Google Code
独自ドメインで SSL 使えるようにって書いてあったりしますけど
ワイルドカードはダメだからマルチドメインか SNI かと思い
(IP address をしこたま用意してあるってのもあると思うんですが)
SNI だったら XP 切るのかなぁ〜、と思いました

でも Google だったら証明書も用意してくれるかなって思ったりもしたけど
審査があるんだよなぁ、やっぱ、証明書は自前で用意かなぁ
秘密鍵と CSR を作成してくれて、証明書と中間が用意できるようになるのかなぁ
や、アプリ部分と同様に upload するのかなぁ

ちょっと楽しみ

2010/05/07

property python

gnutls を使って SSL な server から証明書を取りたい話

gnutls python でサーバーの証明書は取ってきていましたが
python-gnutls にはその上の証明書を取る関数がありませんでした
で、とりあえずソース見てみると connection.py に
    @property
def peer_certificate(self):
if gnutls_certificate_type_get(self._c_object) != GNUTLS_CRT_X509:
return None
list_size = c_uint()
cert_list = gnutls_certificate_get_peers(self._c_object, byref(list_size))
if list_size.value == 0:
return None
cert = cert_list[0]
return X509Certificate(string_at(cert.data, cert.size), X509_FMT_DER)
とありました。
サーバの提示する証明書全部取って、頭だけ出している!!

で、何か decorator 付いてるけどその辺り慣れていないのでググりました
Pythonでプロパティ - crazy()for(;;)you();
なるほど! () を省略したいんだな!!

というわけで書いてみました
from gnutls.connection import (
ClientSession, GNUTLS_CRT_X509, X509Certificate, X509_FMT_DER,
byref, c_uint, string_at,
gnutls_certificate_type_get, gnutls_certificate_get_peers,
)

def peer_certificate_chain(self):
if gnutls_certificate_type_get(self._c_object) != GNUTLS_CRT_X509:
return []
list_size = c_uint()
cert_list = gnutls_certificate_get_peers(self._c_object, byref(list_size))
ders = []
for i in range(list_size.value):
cert = cert_list[i]
ders.append(X509Certificate(string_at(cert.data, cert.size), X509_FMT_DER))
return ders

ClientSession.peer_certificate_chain = property(peer_certificate_chain)

if __name__ == '__main__':
import socket
from gnutls import connection

cred = connection.X509Credentials()
sock = socket.socket()
session = connection.ClientSession(sock, cred)

session.connect(('www.google.com', 443))
session.handshake()

for i in session.peer_certificate_chain:
print("%s <- %s" % (i.subject, i.issuer))
で、動かすと
$ python chain.py
C=US,ST=California,L=Mountain View,O=Google Inc,CN=www.google.com <- C=ZA,O=Thawte Consulting (Pty) Ltd.,CN=Thawte SGC CA
C=ZA,O=Thawte Consulting (Pty) Ltd.,CN=Thawte SGC CA <- C=US,O=VeriSign\, Inc.,OU=Class 3 Public Primary Certification Authority
$
うん、動いた

でも場当たりでメソッド足したりだなんて Python 的と言えないのでは?
と悩んだりもしました
う〜ん

2010/05/04

rfc kindle

Kindle DX を借りることができました
考えていた用途に「RFC をゴロゴロしながら読む」というのがあったので
ここぞとばかりに、と思って思考停止しました

Kindle DX は mobi/azw/html/txt/pdf などの format が読めるそうです
RFC は txt で配布されています

txt はブラウザで見るような感じで表示されるのですが
RFC は等幅フォント? monospace? で表示されることを前提としている風で
若干文章ががちゃがちゃするうえに
ページのヘッダとフッタが定期的に入ってきて少し憂鬱になります

pdf は 1 ページ毎に文字がある領域めいっぱいに最大化して表示してくれます
といっても Kindle だったら小さくて「もっと大きくしてくれよ!」と思うところ
Kindle DX であれば大きいのでそれなりに読めるようになります
がしかしどうも IETF の pdf はフォントが薄い
Courier で表示されてると思うのですが何だか薄くてちょっと辛い感じでした
pdf で無理矢理フォント入れかえ? ん〜

Kindle で RFC や Internet Drafts を読む: 日誌
なるページをググって見つけてみましたが
RFC 2629 な形式で書かれた RFC に関するもので全てがというわけではありません
多分、これはちょっと試してみたんですが良く分からず
若しかしたらどれでも読めるのかもしれません

txt である RFC を今から色々と編集するというのも手間で嫌なので
HTML やら epub -> azw という手順を踏むのも嫌だったので
pdf で何かフォントを入れかえてやれば良いのではないかと思いました

a2ps/a2psj/u2ps/enscript など txt を ps にしてくれるのはあるんですが
どうもこいつらは Courier やその Bold 辺りで決め打ちらしく
というかどのフォントに変更すればいいのか決めていませんでした
ワードパッドか? ワードパッドでフォント変えて pdf にしたらいいのか??

とここで、LaTeX を思いだしました
LaTeX なら色々と等幅フォントがあるに違いなく
少なくとも Computer Modern に Typewriter がある!!
txt に関しては verb な何かで囲んでやればいいと思ったので
簡単な tex soucre 生成スクリプトを作成
import fileinput

print r'''\documentclass[12pt,a4paper]{article}

\addtolength{\topmargin}{-4cm}
\addtolength{\textheight}{100cm}
\addtolength{\textwidth}{3cm}
\addtolength{\oddsidemargin}{0cm}
\addtolength{\evensidemargin}{0cm}
\pagestyle{empty}

\begin{document}
\begin{verbatim}'''

lines = fileinput.input()
lines.next()
lines.next()

for line in lines:
line = line.rstrip("\n")
if line.find("\x0c") > -1:
print (r'''\end{verbatim}
\newpage
\begin{verbatim}''')
else:
print(line)

print r'''\end{verbatim}
\end{document}'''
プリアンブルとか出して
^L の度に verbatim を閉じて開いてるだけです

こんなのに rfc の txt 通してみたら
少なくとも IETF のよりは見易い pdf を得ることができました
ほんとは mobi とかで欲しいけど!
これでゴロゴロしてみようかと思います

2010/05/03

"chirpstream.twitter.com"

最新のTwitter API「ChirpUserStreams」をPythonから使う - ctrlshiftの日記
なんかそんな API 聞いたことある!
と思ってサンプルを動かそうとしたら上手くうごきませんでした

json の解釈に失敗してるっぽいんだけどそもそも
何が返ってくるかも分かってないので何だか良く分かりません
コピペに失敗したのかもしれません

で、楽な方向に流れてしまってそもそも何なのその API は、
とか調べようと思ったんですがとりあえず繋いでみました
http://chirpstream.twitter.com/2b/user.json
なんか、色々流れてくるじゃない

というわけで、とりあえず流れるものを書いてみた
import simplejson
import urllib2
import time

auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password(
realm='Firehose',
uri='http://chirpstream.twitter.com/',
user='あなたの id を入れるところ',
passwd='あなたの password を入れるところ')

opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
u = urllib2.urlopen('http://chirpstream.twitter.com/2b/user.json')
u.readline()
u.readline()

while True:
try:
j = simplejson.loads(u.readline())
print "[%s] %s".encode('utf-8') % (j['user']['screen_name'], j['text'])
except:
time.sleep(0.5)
とりあえずダラダラと TL が流れはじめたので良しとします
これは便利そうだ!

もう少しググってみた
Twitterの新しいStreaming API「ChirpUserStreams」がすごすぎる件 - すぎゃーんメモ
あ、なるほど、TLよりも豊富な情報が流れてるのか、それは凄い
Twitter API Wiki / ChirpUserStreams
まだ beta だからあんま本気で使うなと、なるほど
"In Q3 2010, launch User Streams at scale." ということなので楽しみに待ちます

と、こんなもの書いてる間にもどんどん情報が流れてました
アイコン無いと誰だか認識するの難しいなぁ
おかしいなぁ、CUIの世界の人だったはずなんだけどなぁ...

2010/05/01

"self.__class__"

クラス変数へのアクセス方法すら忘れていました
Python って何ですか? というレベルです
7.7 クラス定義
self.??? で良かったんですけどね

最初 method の外で定義されてるから何も付けずに OK かと思ったらダメで
ん〜、class って self.__class__ に入ってるな〜とか思って
調べてみたら
Python/codepiece/継承(2) - Glamenv-Septzen.net
ってページがひっかかったんですが、ここからリンクされてる
Effective Python Programming
が面白そうなんだけど長くて、あと少し古くて
最近の流行りとかもまとまってるの何かないかなぁ〜と思いました

でも初心者なのでこれ読むだけでも勉強になるに違いありません

2010/04/26

python octet

\110\145\154\154\157\054\040\127\157\162\154\144
ってあったらこれを string に直したいと思われるのではないでしょうか
私は思います
でもどうすればいいか直ぐには思いつきません
そこでグーグル先生に聴いてみました

octet string conversion
何か色々話されていますが斜めに読みます
コードしか読みません
>>> ''.join([chr(int(x,8)) for x in r'\110\145\154\154\157\054\040\127\157\162\154\144'.split('\\')[1:]])
'Hello, World'
あれ、なんかこれ、どっかの求人ので見たな
学習能力が無いようだ

python ssl

何か私、勘違いをしていたみたいでして
Python 2.6 だと ssl って module がありました
17.3. ssl — SSL wrapper for socket objects — Python v2.6.5 documentation
ssl.SSLSocket.getpeercert とかあるの

というわけで簡単にいじってみました
import socket
import ssl

sock = socket.socket()
ssl_sock = ssl.wrap_socket(sock)
ssl_sock.connect(('www.google.com', 443))
der = ssl_sock.getpeercert(binary_form=True)
print ssl.DER_cert_to_PEM_cert(der)
として実行してみると
$ python get_cert.py 
-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x
MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN
gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L
05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM
BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5
u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6
z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==-----END CERTIFICATE-----

$
何だこの変な改行は
まぁ、動いた

あ、や、こんなことしなくても
ssl.get_server_certificate(("www.google.com", 443))
でいいのか

Python 2.6 だったらサーバー証明書取るだけならまぁいける
裏で動いてるのは OpenSSL だから OpenSSL は要るけど
うん、覚えておこう、っていうかもぉ、忘れられないわ

2010/04/23

ocaml open as

Python やら Haskell だと
import XXXX as Y
みたいなことできますので
OCaml だったらどうするんじゃらほいと思いました

ググったんだけど良く分からず
id:camlspotter さんに聴いちゃいました
答は
module Y = XXXX
でした
なるほど!

というわけで少し試してみることに
$ rlwrap ocaml 
Objective Caml version 3.11.2

# #load "unix.cma";;
# module U = Unix;;
module U :
sig
type error =
Unix.error =
E2BIG
| EACCES
| EAGAIN
| EBADF
| EBUSY
(略)
val setsid : unit -> int
end
# U.connect;;
- : U.file_descr -> U.sockaddr -> unit = <fun>
#
おぉ〜、できてる

gnutls python

悪ノリも大概にしなさいという気がしないでもないですが
どうせならと思って gnutls も使ってみようと
Python であれば python-gnutls というのがあります
easy_install でも pip でも使えば入ってしまいます

example とかも揃っているので良く分かってなくても使えてしまいましたが
from gnutls import crypto

x509 = crypto.X509Certificate(open("google.crt").read())

print "version: %d" % x509.version
print "serial number: %s" % x509.serial_number
print "issuer: %s" % x509.issuer.title()
print "not before: %s" % time.ctime(x509.activation_time)
print "not after: %s" % time.ctime(x509.expiration_time)
print "subject: %s" % x509.subject.title()
とか
import socket
import time

from gnutls import connection

cred = connection.X509Credentials()

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
session = connection.ClientSession(sock, cred)

session.connect(('www.google.com', 443))
session.handshake()
x509 = session.peer_certificate
session.bye()
session.close()

print "version: %d" % x509.version
print "serial number: %s" % x509.serial_number
print "issuer: %s" % x509.issuer.title()
print "not before: %s" % time.ctime(x509.activation_time)
print "not after: %s" % time.ctime(x509.expiration_time)
print "subject: %s" % x509.subject.title()
とかすると
version: 3
serial number: 205024093581220934167709006090448199471
issuer: C=Za,O=Thawte Consulting (Pty) Ltd.,Cn=Thawte Sgc Ca
not before: Fri Dec 18 09:00:00 2009
not after: Mon Dec 19 08:59:59 2011
subject: C=Us,St=California,L=Mountain View,O=Google Inc,Cn=Www.Google.Com
こんなのが出ました

gnutls.constants.X509_FMT_DER とかあるので DER も読めたり
gnutls.library.functions ってのがあるんでガリガリ書いたり
できるのかな? 試していません

とりあえず証明書は読めました

2010/04/21

scala cast

Jython でできたら Scala でもできるべ JK、と思ったら失敗しやんの
というお話

同じようにしようと思ったんですね、Scala で
scala> import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.SSLSocketFactory

scala> val fc = SSLSocketFactory.getDefault
fc: javax.net.SocketFactory = com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl@10c6406

scala> val sock = fc.createSocket("www.google.com", 443)
sock: java.net.Socket = 17aa961[SSL_NULL_WITH_NULL_NULL: Socket[addr=www.google.com/66.249.89.99,port=443,localport=57185]]

scala> sock.startHandshake
<console>:8: error: value startHandshake is not a member of java.net.Socket
sock.startHandshake
^

scala>
java.net.Socket には startHandshake なんて無いと

あれー、と思って調べてみたら
Java の場合は Socket 作るときにキャストしてたんです
なんで調べてみましたところ
型キャスト - うなの日記
.asInstanceOf でキャストするらしい

とわけで仕切り直し
scala> import javax.net.ssl.SSLSocket                                 
import javax.net.ssl.SSLSocket

scala> val ssl_sock = fc.createSocket("www.google.com", 443).asInstanceOf[javax.net.ssl.SSLSocket]
ssl_sock: javax.net.ssl.SSLSocket = 5b55a9[SSL_NULL_WITH_NULL_NULL: Socket[addr=www.google.com/66.249.89.104,port=443,localport=51395]]

scala> ssl_sock.startHandshake

scala> val session = ssl_sock.getSession
session: javax.net.ssl.SSLSession = [Session-1, SSL_RSA_WITH_RC4_128_SHA]

scala> session.getPeerCertificates
res3: Array[java.security.cert.Certificate] =
Array([
[
Version: V3
Subject: CN=www.google.com, O=Google Inc, L=Mountain View, ST=California, C=US
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

Key: Sun RSA public key, 1024 bits
modulus: 16360039926653679142684174795487342200966220249542631283272411000230225514996552443305086682233800494025854567816692732625...
scala>
取れた!!

Scala の方が Java に対して素直なんですかね
何故 Jython でキャストが不要なのか良く分からず
どのくらい手を加えているのかっつーことなんでしょうか

2010/04/20

sslsocketfactory session getdefault

Jython で Java を使って SSL 張って証明書を取ろうとしました

色々ググったりして SSLSocketFactory ってのがあるということで
java.net パッケージの仕組み
を見てふんふんとする
で、socket を作って getSession したらそこに getPeerCertificates という method が!
In [63]: soc = factory.createSocket('www.google.com', 443)

In [1]: from javax.net.ssl import *

In [2]: sock = factory.createSocket('www.google.com', 443)

In [3]: session = sock.getSession()

In [4]: certs = session.getPeerCertificates()
---------------------------------------------------------------------------
SSLPeerUnverifiedException Traceback (most recent call last)

/tmp/<ipython console> in <module>()

SSLPeerUnverifiedException: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

In [5]:
うぎゃぁ!!

何か足りないのみたいなのでググり直すと
HTTPS通信にはまる - TNET日々のメモ
そうですよね、handshake してませんでした

ということで
import sys
from javax.net.ssl import SSLSocketFactory

host = "www.google.com"
port = 443

factory = SSLSocketFactory.getDefault()
sock = factory.createSocket(host, port)
sock.startHandshake()
session = sock.getSession()
certs = session.getPeerCertificates()

for c in certs:
print '-----BEGIN CERTIFICATE-----'
print c.getEncoded().tostring().encode('base64').rstrip()
print '-----END CERTIFICATE-----'
Certificate を PEM で出したかったんですが
DER を array で取り出す方法しか分からなかったので
Jython str にして encode してしまいました
てゆーか array なんてあったんだー使ったことないよー

でどうなるかというと
$ jython get_certs.jy www.google.com
-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQG
EwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhh
d3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0xMTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVT
MRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApH
b29nbGUgSW5jMRcwFQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jNgtXj9xVo
RaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L05vuuWciKh0R73mkszeK
9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAMBgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0w
K6ApoCeGJWh0dHA6Ly9jcmwudGhhd3RlLmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYI
KwYBBQUHAwEGCCsGAQUFBwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzAB
hhZodHRwOi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0ZS5j
b20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUFAAOBgQCfQ89bxFAp
sb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5u2ONgJd8IyAPkU0Wueru9G2Jysa9
zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqA
ibAxWEEHXw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDIzCCAoygAwIBAgIEMAAAAjANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJVUzEXMBUGA1UE
ChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlm
aWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNTEzMDAwMDAwWhcNMTQwNTEyMjM1OTU5WjBMMQswCQYD
VQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMN
VGhhd3RlIFNHQyBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1NNn0I0Vf67NMf59HZGh
PwtxPKzMyGT7Y/wySweUvW+Aui/hBJPAM/wJMyPpC3QrccQDxtLN4i/1CWPN/0ilAL/g5/OIty0y
3pg25gqtAHvEZEo7hHUD8nCSfQ5i9SGraTaEMXWQ+L/HbIgbBpV8yeWo3nWhLHpo39XKHIdYYBkC
AwEAAaOB/jCB+zASBgNVHRMBAf8ECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjARBglghkgBhvhCAQEE
BAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFByaXZhdGVMYWJlbDMtMTUwMQYDVR0fBCow
KDAmoCSgIoYgaHR0cDovL2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwMgYIKwYBBQUHAQEEJjAk
MCIGCCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMDQGA1UdJQQtMCsGCCsGAQUFBwMB
BggrBgEFBQcDAgYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEBBQUAA4GBAFWsY+re
od3SkF+fC852vhNRj5PZBSvIG3dLrWlQoe7e3P3bB+noOZTcq3J5Lwa/q4FwxKjt6lM07e8eU9kG
x1Yr0Vz00YqOtCuxN5BICEIlxT6Ky3/rbwTRbcV0oveifHtgPHfNDs5IAn8BL7abN+AqKjbc1YXW
rOU/VG+WHgWv
-----END CERTIFICATE-----
$
ありゃ、1行が76文字に...

まぁいいや、Java で証明書が取れました

InputStream 文字列

色々ググっていたら
Java(TM) PKI API プログラマーズガイド
ってのを見付けました
こりゃいいや、これに違いない

で、先ず証明書読みたいと思いまして読み進めると
java.security.cert.CertificateFactory
を使うと良いらしく、サンプルも
Java 暗号化アーキテクチャー (JCA)
に書いてありました
FileInputStream fis = new FileInputStream(filename);
BufferedInputStream bis = new BufferedInputStream(fis);

CertificateFactory cf = CertificateFactory.getInstance("X.509");

while (bis.available() > 0) {
Certificate cert = cf.generateCertificate(bis);
System.out.println(cert.toString());
}


でも file を Java で読みたくないなぁ
でも Jython で file 開いた後どうするんだろう
中身を str にしたら何とかならないかな
つわけでググってみると
String文字列をInputStreamに変換する方法 - Java入門
そうそう、こういうの

というわけで簡単に証明書の中身を出してみました
from java.security.cert import CertificateFactory
from java.io import ByteArrayInputStream

pem_file = open("google.pem", "r")
cf = CertificateFactory.getInstance("X.509")
pem_stream = ByteArrayInputStream(pem_file.read())
x509 = cf.generateCertificate(pem_stream)

print x509.version
print x509.sigAlgName
print x509.issuerDN
print x509.notBefore
print x509.notAfter
print x509.subjectDN
これがこうなります
$ jython read_cert.jy
3
SHA1withRSA
CN=Thawte SGC CA, O=Thawte Consulting (Pty) Ltd., C=ZA
Fri Dec 18 09:00:00 JST 2009
Mon Dec 19 08:59:59 JST 2011
CN=www.google.com, O=Google Inc, L=Mountain View, ST=California, C=US
$

Python で開いた file をそのまま InputStream? にする方法もある気がする
今度調べよう

2010/04/18

java http socket

Jython っつっても Java を触りたく
Java のことなんて何も分かってないのを思いだしました
こまった

でもグーグルがあるじゃないか!
インターネット世代だし先ずは 80 番ポートじゃないか!!
教えてグーグル先生!!!

先生優しいので何でも教えてくれます
Java で HTTP クライアントを作ってみよう (1)
Java 関連はグーグル先生特に詳しいみたいでいくらでも出てきます
Java を使うことによるメリットの1つはグーグル先生が詳しいからかっ

で、これを Jython に写経です
import java.net as net
import java.io as io

host = "www.google.com"
port = 80
path = "/"

sock = net.Socket(host, port)
reader = io.BufferedReader(io.InputStreamReader(sock.getInputStream()))
writer = io.BufferedWriter(io.OutputStreamWriter(sock.getOutputStream()))

writer.write("GET %s HTTP/1.0\n\n" % (path,))
writer.flush()

while True:
line = reader.readLine()
if line:
print line
else:
break
で、実行
$ jython get_google.jy
HTTP/1.0 302 Found
Location: http://www.google.co.jp/
Cache-Control: private
Content-Type: text/html; charset=UTF-8
(後略)
動いてしまいました、あっさり

これは、既にどこかに Java -> Jython translator があるに違いない

jython ipython

OpenSSL ばっかりでは飽きてきたし
GNU TLS とかでもいいんだけど
Java のライブラリとか素敵なんじゃないのかしら
でも Java を今からって、private? public? static??

そこで Scala か Clojure かと思ったんですが Jython があるじゃないですか
先ずは Jython から初めようと思いダウンロードしてインストールしてみました
$ time /usr/local/jython-2.5.1/bin/jython /dev/null

real 0m2.870s
user 0m2.844s
sys 0m0.124s
立ち上がりは遅い。このパソコンが重いのか?
未だに EUC-JP 環境にいるので LANG=C とか ja_JP.UTF-8 とかしないと
string なリテラル打ったが最後帰ってこなくなったりしました

さて、Python だったら IPython とかで happy になってるわけなので
補完とかがある Jython が欲しいと思ってとりあえずググると、あるある
How to use IPython with Jython
作業日誌/2010-03-04 - Go's WikiLog

最初書いてある通りにしてるつもりができてなかったので動かず
読み直してちゃんと動きました
$ jython
Python 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54)
Type "copyright", "credits" or "license" for more information.

IPython 0.9.1 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object'. ?object also works, ?? prints more.

In [1]: import java

In [2]: java.
java.__name__ java.awt java.io java.math java.nio java.security java.text
java.applet java.beans java.lang java.net java.rmi java.sql java.util

In [2]: java.
Tab で補完もできました
さて、何して遊ぼう

2010/04/14

"GetOcspSignerCertificate"

失効されてるはずなのに OCSP が教えてくれないな〜
Windows でそんなことが起きた場合にはイベント ビューアーを見ましょう
Windows 7 であればイベント ビューアーを開くを参考

[アプリケーションとサービス ログ] -> [Microsoft] -> [Windows] -> [CAPI2]
と進みます
この CAPI2 は CryptoAPI 2 の略で、1 は XP とか 2003 までのものなのかな?
Vista/2008 移行の色々機能が強化された CryptoAPI が CAPI2 です

デフォルトだとログが無効化されているので右の方にある [ログを有効化] を押せば
SSL なページを見にいったときの証明書の検証のログなどをガシガシ保存してくれます

例えばエラーが出てるところを見て
GetOcspSignerCertificate なんて書いてあったとしますと
検索することによって
Windows Vista での PKI に関する問題のトラブルシューティング
というページがひっかかりますので探しますと

OCSP 応答には署名が必要であり、OCSP 署名者の証明書には OCSP 署名 EKU が含まれている必要があります。この EKU がないと、エラーが発生します。このエラーは、"CertRejectedRevocationInfo" イベントの操作 "GetOCSPSignerCertificate" で示されます。OCSP 署名者の証明書の内容でその他のエラーが発生した場合も、同じ操作がログに記録されます。このようなエラーには、次のものがあります。

  • 期間が無効な証明書

  • CDP 拡張機能または OCSP URL は含まれていても "Revocation_No_Check" 拡張機能が含まれていない証明書

これらのエラーの場合、CAPI2 では、OCSP 署名者の証明書に関する情報もログに記録されます。

ほぉほぉ

Revocation_No_Check というのは RFC2560 の 4.2.2.2.1 に
id-pkix-ocsp-nocheck OBJECT IDENTIFIER ::= { id-pkix-ocsp 5 } と記載が
1.3.6.1.5.5.7.48.1.5 ですね
OCSP はオンラインでやりとりをするので MITM などの対応をしなくてはいけません
OCSP Responder が信頼できるかどうかの判断はとても大切です

ちなみに OpenSSL の場合 man x509v3_config を見れば
   OCSP No Check
The OCSP No Check extension is a string extension but its value is ignored.

Example:

noCheck = ignored
という記述が見付けられます

やぁ、Google って便利ですね

"mod_rewrite" "%2F"

mod_rewrite で飛んでほしかったんですが
何故だか "%2F" が URL に入ってると飛べなくて
別にこんなリクエスト受けつけなけりゃという話もありますが
投げてくる人がいるんですから仕方がありません

GET で ? も使わずに base64 されたデータが飛んでくるんですが
これは mod_rewrite で query に回すとかで正しいんでしょうか
http://sample.com/ だけ公開したいサーバがあって
http://sample.com/Z2d1dHRlcg%3D%3D みたいなリクエストが来るんで
これを処理して返事したかっただけなんですが
なんか、大鉈振ってる気がします...

でまぁ、検索しましたら
PHPプロ!TIPS+
AllowEncodedSlashes On を設定しなさいと教えて頂き
無事に動くものができました

よかったよかった

2010/04/12

"ocsp" "-rsigner"

OCSP は Online Certificate Status Protocol の略です。
証明が失効されてるか有効かをオンラインで調べる為のものです。
例えば
$ openssl s_client -connect www.google.com:443 </dev/null | openssl x509 -noout -text
(前略)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 CRL Distribution Points:
URI:http://crl.thawte.com/ThawteSGCCA.crl

X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication, Netscape Server Gated Crypto
Authority Information Access:
OCSP - URI:http://ocsp.thawte.com
CA Issuers - URI:http://www.thawte.com/repository/Thawte_SGC_CA.crt
(後略)
のように http://ocsp.thawte.com が OCSP サーバだと分かります

openssl も ocsp というコマンドを持っているので
例えば
$ openssl s_client -connect www.google.com:443 -showcerts < /dev/null
などで google と thawte の証明書を取ってくれば
$ openssl ocsp -issuer thawte.crt -cert google.crt -url http://ocsp.thawte.com -resp_text -CAfile thawte.crt 
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: C = ZA, O = Thawte Consulting (Pty) Ltd., CN = Thawte SGC OCSP Responder
Produced At: Apr 12 11:09:20 2010 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 1E9209AA713C794BCA1E931A0A61AD3FD0BA6083
Issuer Key Hash: 3B349A709173B28A1B0CF4E937CDB370329E1854
Serial Number: 2FDFBCF6AE91526D0F9AA3DF40343E9A
Cert Status: good
This Update: Apr 12 11:09:20 2010 GMT
Next Update: Apr 19 11:09:20 2010 GMT

Certificate:
Data:
Version: 3 (0x2)
Serial Number:
7c:ec:c6:3e:2b:8d:3e:ad:f6:ba:ce:11:13:1a:b7:73
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=ZA, O=Thawte Consulting (Pty) Ltd., CN=Thawte SGC CA
Validity
Not Before: Feb 13 00:00:00 2010 GMT
Not After : May 14 23:59:59 2010 GMT
Subject: C=ZA, O=Thawte Consulting (Pty) Ltd., CN=Thawte SGC OCSP Responder
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:d3:2f:7e:60:63:4c:bb:b9:98:84:91:23:d8:f0:
e9:d9:0f:35:42:40:dc:d5:75:d5:cf:4e:a0:3b:50:
e6:85:fa:38:27:bc:cb:8f:7e:34:8d:ed:8d:19:27:
9a:cb:9c:84:82:3c:3a:ed:7a:ba:2b:75:b1:74:c9:
32:7d:7d:11:bb:d2:7d:8b:c4:3c:03:7d:4f:22:c0:
03:82:26:b9:8e:ce:4a:21:0e:9c:ef:b8:e7:81:af:
a7:0a:14:c6:04:a0:94:05:44:e2:e2:fc:b0:71:2a:
98:f3:6f:d2:1c:46:ab:af:7d:ea:22:ab:3e:a1:94:
28:eb:91:67:61:a3:58:4b:ed
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Extended Key Usage:
OCSP Signing
X509v3 Key Usage:
Digital Signature
OCSP No Check:

X509v3 Subject Alternative Name:
DirName:/CN=OCSP5-TGV-4-109
Signature Algorithm: sha1WithRSAEncryption
b7:7e:90:32:f5:5e:73:86:d3:3a:f9:27:ea:95:0c:70:b8:80:
e4:8e:83:9e:36:f5:8a:c4:c2:5f:a3:df:01:ed:24:03:dd:de:
c1:41:56:5a:92:48:0b:8e:cc:67:9a:53:a5:9c:ea:e5:36:7f:
4b:07:cc:9e:40:9a:fb:d3:cd:b2:df:de:87:f6:89:cf:5b:94:
80:06:d7:d8:aa:db:35:8c:7b:46:84:e6:37:41:e7:d9:07:1e:
7d:79:34:e1:18:91:b0:e8:fd:40:1b:eb:63:ef:6b:3a:2a:30:
ad:48:0e:9e:8e:de:61:92:c1:c2:0d:d1:f3:6d:d5:db:4b:e5:
82:25
-----BEGIN CERTIFICATE-----
MIICkjCCAfugAwIBAgIQfOzGPiuNPq32us4RExq3czANBgkqhkiG9w0BAQUFADBM
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0xMDAyMTMwMDAwMDBaFw0x
MDA1MTQyMzU5NTlaMFgxCzAJBgNVBAYTAlpBMSUwIwYDVQQKExxUaGF3dGUgQ29u
c3VsdGluZyAoUHR5KSBMdGQuMSIwIAYDVQQDExlUaGF3dGUgU0dDIE9DU1AgUmVz
cG9uZGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTL35gY0y7uZiEkSPY
8OnZDzVCQNzVddXPTqA7UOaF+jgnvMuPfjSN7Y0ZJ5rLnISCPDrterordbF0yTJ9
fRG70n2LxDwDfU8iwAOCJrmOzkohDpzvuOeBr6cKFMYEoJQFROLi/LBxKpjzb9Ic
Rquvfeoiqz6hlCjrkWdho1hL7QIDAQABo2kwZzAJBgNVHRMEAjAAMBMGA1UdJQQM
MAoGCCsGAQUFBwMJMAsGA1UdDwQEAwIHgDAPBgkrBgEFBQcwAQUEAgUAMCcGA1Ud
EQQgMB6kHDAaMRgwFgYDVQQDEw9PQ1NQNS1UR1YtNC0xMDkwDQYJKoZIhvcNAQEF
BQADgYEAt36QMvVec4bTOvkn6pUMcLiA5I6Dnjb1isTCX6PfAe0kA93ewUFWWpJI
C47MZ5pTpZzq5TZ/SwfMnkCa+9PNst/eh/aJz1uUgAbX2KrbNYx7RoTmN0Hn2Qce
fXk04RiRsOj9QBvrY+9rOiowrUgOno7eYZLBwg3R823V20vlgiU=
-----END CERTIFICATE-----
WARNING: no nonce in response
Response verify OK
google.crt: good
This Update: Apr 12 11:09:20 2010 GMT
Next Update: Apr 19 11:09:20 2010 GMT
good と言われてるので有効な証明書であることが確認できます

また、-index というオプションがあり
これで openssl ca コマンドで利用する index file を指定してやると
OCSP Responder としても動作させることができます
-rsigner ってのは response に署名する証明書を指定する為のものでした。

-reqin -reqout で OCSP のリクエストフォーマットのデータの入出力
-respin -respout で OCSP のレスポンスフォーマットのデータの入出力
ができるので、個別にリクエスト・レスポンスを作成・保存したりもできます。

2010/04/10

再帰 継続 末尾

再帰なら継続渡しで書き直して末尾再帰にできるヨ!!
そんなことを耳にしていたんですが
どうも継続というものが良く分かっていません
まぁ、関数渡すらしいな、程度の認識

再帰といえば fold なわけですが
Haskell だと foldr、OCaml だと List.fold_right です
まぁ、何でもいいんですが
foldr f v [] = v
foldr f v (x:xs) = f x (foldr f v xs)
とか
let fold_right f lst init = match lst with
| [] -> init
| x::xs -> f x (fold_right f xs init)
とかそういうのです
要するに
fold [] = v
fold (x:xs) = f x (fold xs)
みたいなことになってればいいんです

で、これ末尾再帰にはなってないわけですよ
することに意味があるかは知らないんですよ
したいんですよ、末尾再帰に
できないんですよ、まだ継続とか関数渡すとかの理解浅いから

ぐぐりました
反復的プロセス、末尾再帰、継続渡しスタイル : torus solutions!
append が末尾再帰の刑に処せられていますがまぁ fold も同じようなもんです

fold f v [] k = k v
fold f v (x:xs) k = fold f v xs (\y -> k (f x y))

let rec fold f lst v k = match lst with
| [] -> k v
| (x::xs) -> fold f xs v (fun y -> k (f x y))
でもね、
continuation(継続)は末尾再帰の最適化手段ではない : メカAG
飽くまで「継続を使うと再帰が末尾再帰に直せる」というだけなので
このままでは「継続」の入口にも立っていないのでした

付録:

で fold には left もありましてこっちは最初から末尾再帰でしたが
(最近 Haskell ご無沙汰なので Haskell だけにしよう、もぉ面倒だ)
foldl f v [] = v
foldl f v (x:xs) = foldl f (f v x) xs
こんなだったか
これは例えば
foldl (+) 0 [1,2,3]
= (((0+1)+2)+3)
= (\k -> k.(+1)) ((\k -> k.(+2)) (+3)) 0
= (\x k -> k.(+x)) 1 ((\x k -> k.(+x)) 2 (+3)) 0
= (\x k -> (\y -> k (y+x))) 1 ((\x k -> (\y -> k (y+x))) 2 (\x k -> (\y -> (y+x))) 3 id) 0
= (foldr (\x k -> (\y -> k ((+) y x))) id [1,2,3]) 0
ははは、欺瞞にも程がある
でもまぁ
foldl f v lst = (foldr (\x k -> (\y -> k (f y x))) id lst) v
と書けないこともないということで
何が嬉しいのかは分かりません

2010/04/05

openssl 接続 bio

SSL で証明書を取ってくるシリーズ
今回は何と C with OpenSSL
C なんて学部の頃に「独習 C」を友達に薦められ
読んだというか眺めた憶えはありますがそれっきりで
一生のうちで使うことは無かろうかと思っていたのですが

で、OpenSSL の各種 binding は散々いじってるので
  1. socket 用意する
  2. SSL Centext 用意する
  3. socket と Context で SSL 作る
  4. 繋ぎにいって証明書もらう
というのは分かっちゃいるんですが
そもそも C で socket 叩いたことないよボク!!

というわけでググるわけです
良い sample code でも無いものかと探してみました

OpenSSLライブラリを使ってプログラミング(1) - 再帰の反復
このページは OpenSSL や SSL に関する詳しいまとめが
Geekなぺーじ : getaddrinfo(単純な例)
getaddrinfo の使い方とか socket の張り方とか

で、ついでなんで getopt とか構造体のこともググりながら
どうにかとりあえず動くものは作れました。
でもあれだからね、素人が作ったからどこに穴があるか分からないからね。
#include <stdio.h>
#include <getopt.h>
#include <sys/socket.h>
#include <netdb.h>
#include <openssl/ssl.h>

typedef struct {
unsigned char *data;
int length;
} der_data;

char* x509_as_pem(X509 *x509) {
BIO *bio;
BUF_MEM *bptr;

bio = BIO_new(BIO_s_mem());
PEM_write_bio_X509(bio, x509);
bptr = BUF_MEM_new();
BIO_get_mem_ptr(bio, &bptr);

return bptr->data;
}

der_data* x509_as_der(X509 *x509) {
int len;
int i;
unsigned char *buf, *p;
der_data *data;

len = i2d_X509(x509, NULL);
buf = OPENSSL_malloc(len);
if (buf == NULL) {
printf("error\n");
exit(1);
}
p = buf;
i2d_X509(x509, &p);

data = (der_data *)malloc( sizeof(der_data) );
data->data = buf;
data->length = len;
return data;
}

int main(int argc, char *argv[]) {

int der = 0;
int c, s;
char *cmd = argv[0];

struct hostent *host;
char *service = "443";
struct addrinfo hints;
struct addrinfo *result;
int fd;

SSL_CTX *ctx;
SSL *ssl;
int ret;
X509 *x509;
BIO *bio;

void help() {
fprintf(stderr, "usage: %s [-d] hostname\n", cmd);
exit(1);
}

while ((c = getopt(argc, argv, ":d")) != -1) {
switch (c) {
case 'd':
der = 1;
break;
case '?':
help();
}
}
argc -= optind;
argv += optind;
if (argc < 1) {
help();
}

memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if ((s = getaddrinfo(argv[0], service, &hints, &result)) != 0) {
printf("error %d : %s\n", s, gai_strerror(s));
exit(1);
}

fd = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (fd < 0) {
perror("open socket error");
exit(1);
}

if (connect(fd, result->ai_addr, result->ai_addrlen) != 0) {
perror("connection error");
return 1;
}

free(result);

SSL_load_error_strings();
SSL_library_init();

ctx = SSL_CTX_new(SSLv23_method());
if ( ctx == NULL ){
ERR_print_errors_fp(stderr);
exit(1);
}

ssl = SSL_new(ctx);
if ( ssl == NULL ){
ERR_print_errors_fp(stderr);
exit(1);
}

ret = SSL_set_fd(ssl, fd);
if ( ret == 0 ){
ERR_print_errors_fp(stderr);
exit(1);
}

ret = SSL_connect(ssl);
if ( ret != 1 ){
ERR_print_errors_fp(stderr);
exit(1);
}

x509 = SSL_get_peer_certificate(ssl);
if (x509 == NULL) {
ERR_print_errors_fp(stderr);
exit(1);
}

if (der == 0) {
char *data;
data = x509_as_pem(x509);
printf("%s", data);
} else {
der_data *data;
int i;

data = x509_as_der(x509);
for (i=0; i < data->length; i++) {
printf("%c", (data->data)[i]);
}
}

return 0;
}
セキュリティーとか何も考えてないというか
セキュリティーの考え方を知らないので
それは誰か教えてくれると嬉しいヨ!!

で、
$ gcc -lssl -o get_cert get_cert.c 
$ ./get_cert www.google.com
-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x
MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN
gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L
05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM
BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5
u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6
z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==
-----END CERTIFICATE-----
$ ./get_cert -d www.google.com | od -t x1
0000000 30 82 03 21 30 82 02 8a a0 03 02 01 02 02 10 2f
0000020 df bc f6 ae 91 52 6d 0f 9a a3 df 40 34 3e 9a 30
0000040 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 4c
0000060 31 0b 30 09 06 03 55 04 06 13 02 5a 41 31 25 30
0000100 23 06 03 55 04 0a 13 1c 54 68 61 77 74 65 20 43
0000120 6f 6e 73 75 6c 74 69 6e 67 20 28 50 74 79 29 20
0000140 4c 74 64 2e 31 16 30 14 06 03 55 04 03 13 0d 54
0000160 68 61 77 74 65 20 53 47 43 20 43 41 30 1e 17 0d
0000200 30 39 31 32 31 38 30 30 30 30 30 30 5a 17 0d 31
0000220 31 31 32 31 38 32 33 35 39 35 39 5a 30 68 31 0b
0000240 30 09 06 03 55 04 06 13 02 55 53 31 13 30 11 06
0000260 03 55 04 08 13 0a 43 61 6c 69 66 6f 72 6e 69 61
0000300 31 16 30 14 06 03 55 04 07 14 0d 4d 6f 75 6e 74
0000320 61 69 6e 20 56 69 65 77 31 13 30 11 06 03 55 04
0000340 0a 14 0a 47 6f 6f 67 6c 65 20 49 6e 63 31 17 30
0000360 15 06 03 55 04 03 14 0e 77 77 77 2e 67 6f 6f 67
0000400 6c 65 2e 63 6f 6d 30 81 9f 30 0d 06 09 2a 86 48
0000420 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02
0000440 81 81 00 e8 f9 86 0f 90 fa 86 d7 df bd 72 26 b6
0000460 d7 44 02 83 78 73 d9 02 28 ef 88 45 39 fb 10 e8
0000500 7c ae a9 38 d5 75 c6 38 eb 0a 15 07 9b 83 e8 cd
0000520 82 d5 e3 f7 15 68 45 a1 0b 19 85 bc e2 ef 84 e7
0000540 dd f2 d7 b8 98 c2 a1 bb b5 c1 51 df d4 83 02 a7
0000560 3d 06 42 5b e1 22 c3 de 6b 85 5f 1c d6 da 4e 8b
0000600 d3 9b ee b9 67 22 2a 1d 11 ef 79 a4 b3 37 8a f4
0000620 fe 18 fd bc f9 46 23 50 97 f3 ac fc 24 46 2b 5c
0000640 3b b7 45 02 03 01 00 01 a3 81 e7 30 81 e4 30 0c
0000660 06 03 55 1d 13 01 01 ff 04 02 30 00 30 36 06 03
0000700 55 1d 1f 04 2f 30 2d 30 2b a0 29 a0 27 86 25 68
0000720 74 74 70 3a 2f 2f 63 72 6c 2e 74 68 61 77 74 65
0000740 2e 63 6f 6d 2f 54 68 61 77 74 65 53 47 43 43 41
0000760 2e 63 72 6c 30 28 06 03 55 1d 25 04 21 30 1f 06
0001000 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 05
0001020 07 03 02 06 09 60 86 48 01 86 f8 42 04 01 30 72
0001040 06 08 2b 06 01 05 05 07 01 01 04 66 30 64 30 22
0001060 06 08 2b 06 01 05 05 07 30 01 86 16 68 74 74 70
0001100 3a 2f 2f 6f 63 73 70 2e 74 68 61 77 74 65 2e 63
0001120 6f 6d 30 3e 06 08 2b 06 01 05 05 07 30 02 86 32
0001140 68 74 74 70 3a 2f 2f 77 77 77 2e 74 68 61 77 74
0001160 65 2e 63 6f 6d 2f 72 65 70 6f 73 69 74 6f 72 79
0001200 2f 54 68 61 77 74 65 5f 53 47 43 5f 43 41 2e 63
0001220 72 74 30 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05
0001240 00 03 81 81 00 9f 43 cf 5b c4 50 29 b1 bf e2 b0
0001260 9a ff 6a 21 1d 2d 12 c3 2c 4e 5a f9 12 e2 ce b9
0001300 82 52 2d e7 1d 7e 1a 76 96 90 79 d1 24 52 38 79
0001320 bb 63 8d 80 97 7c 23 20 0f 91 4d 16 b9 ea ee f4
0001340 6d 89 ca c6 bd cc 24 68 d6 43 5b ce 2a 58 bf 3c
0001360 18 e0 e0 3c 62 cf 96 02 2d 28 47 50 34 e1 27 ba
0001400 cf 99 d1 50 ff 29 25 c0 36 36 15 33 52 70 be 31
0001420 8f 9f e8 7f e7 11 0c 8d bf 84 a0 42 1a 80 89 b0
0001440 31 58 41 07 5f
0001445
$
という感じに der とか pem とかで取れるようになりました。

openssl s_client の劣化版じゃん!!
や、そうなんですけどね。

ocaml ssl

SSL で繋いで証明書を取ってこようシリーズ
今回は OCaml でいってみようと思います
OCaml に関してはプログラミング in OCaml など見ると良いのかも

とりあえずググりますと
http://sourceforge.net/projects/savonet/files/ocaml-ssl/
こちらに OpenSSL の binding があったのでこれを使おうかと思いまして
っていうかね、
OCamlで簡易SSLクライアント - komamitsu.log
こんな素敵なまとめページが見つかってしまいました

OCaml-SSL をインストールしようとすると
「findlib が無いよ」
って言われたので findlib から入れました
で、使い方は上記ページを参考にしつつ試して動いた感じです

OCaml-SSL のソースをザザっと眺めてみたんですが
証明書をいじる関数があまり用意されていないらしく
というか subject と issuer を抜くものしかありませんでした
あらら

とりあえず minimal かと思われる証明書取ってくるのがこれ
open Unix;;

Ssl.init ();;
let hostent = gethostbyname "www.google.com";;
let addr = hostent.h_addr_list.(0);;
let sockaddr = ADDR_INET(addr, 443);;

let sock = Ssl.open_connection Ssl.SSLv23 (ADDR_INET(addr, 443));;
let cert = Ssl.get_certificate sock;;
Printf.printf "%s%!" (Ssl.get_subject cert)
っていうか何というコード
変数に欲しいもの列記して実行してるだけです
って OpenSSL をいじってるわけだから仕方ないのかな?

でまぁこんなのを show_subject.ml として用意して
ocamlfind c -package ssl -thread -linkpkg -o show_subject show_subject.ml
と打つとコマンドができました

findlib っていうのがあるのだというのを知ったのが
今回の最大の成果となっております

2010/03/31

erlang foldl

日本語で読める Haskell の入門書といえば今では
@kazu_yamamoto訳のプログラミングHaskellなわけです
何が素晴らしいって
オーム社の方曰く「ソフトカバーなのに、ハードカバーのように平たく開ける特殊な製本」だそうです。
もぉこれが気になって気になって買ってしまいました
や、無いんです、近所に、立ち読みとかできそうなところが

原著も素晴らしいんですが訳も素晴らしくって
付録に「訳者による関数の解説」とかまで付いてて至れりつくせり

で、Haskell っつったらモナドですよモナド
この本だと第8章「関数型パーサー」、第9章「対話プログラム」で
モナドっぽいものをすこーしずつ見ながら
第10章「型とクラスの定義」で「モナド型」の説明が出てきます。

でもね、(>>=) とかはもぉ第8章から出てるの
type Parser a = String -> [(a, String)]

parse :: Parser a -> String -> [(a, String)]
parse p inp = p inp

(>>=) :: Parser a -> (a -> Parser b) -> Parser b
p >>= f = \inp -> case parse p inp of
[] -> []
[(v, out)] -> parse (f v) out
みたいな感じで

原著のサポートページみたいのでは第8章で使ってるコード載せてるんだけど
> instance Monad Parser where
> return v = P (\inp -> [(v,inp)])
> p >>= f = P (\inp -> case parse p inp of
> [] -> []
> [(v,out)] -> parse (f v) out)
インスタンスにしてる!!
なんでもぉあれですよ、本を写経してみても実行しようとしたら
*Main> :t (>>=)

<interactive>:1:0:
Ambiguous occurrence `>>='
It could refer to either `Main.>>=', defined at ggutter.hs:7:2
or `Prelude.>>=', imported from Prelude
みたいなこと言われて
「>>= あいまいだからちゃんとモジュール指定すれ」って怒られちゃうの

むきー!! ということで Erlang で写経し直してみました
-module(parser).
-compile(export_all).

return(V) -> fun(Inp) -> [{V, Inp}] end.

failure() -> fun(_) -> [] end.

item() ->
fun(X) ->
case X of
[] -> [];
[H|T] -> [{H,T}]
end
end.

parse(P, Inp) -> P(Inp).

bind(A, F) ->
fun(Inp) ->
case parse(A, Inp) of
[] -> [];
[{V, Out}] -> parse(F(V), Out)
end
end.

l_or_r(P, Q) ->
fun(Inp) ->
case parse(P, Inp) of
[] -> parse(Q, Inp);
[{V, Out}] -> [{V, Out}]
end
end.

sat(P) ->
bind(
item(), fun(X) ->
case P(X) of
true -> return(X);
false -> failure()
end
end).

is_digit(X) -> (X >= $0) and (X =< $9).
is_lower(X) -> (X >= $a) and (X =< $z).
is_upper(X) -> (X >= $A) and (X =< $Z).
is_alpha(X) -> is_lower(X) or is_upper(X).
is_alphanum(X) -> is_digit(X) or is_alpha(X).
is_space(X) -> X =:= $ .

digit() -> sat(fun is_digit/1).
lower() -> sat(fun is_lower/1).
upper() -> sat(fun is_upper/1).
letter() -> sat(fun is_alpha/1).
alphanum() -> sat(fun is_alphanum/1).

char(X) -> sat(fun(Y) -> X =:= Y end).
string([]) -> return([]);
string([H|T]) ->
bind(char(H), fun(_) ->
bind(string(T), fun(_) ->
return([H|T])
end) end).

many(P) ->
l_or_r(many1(P), return([])).
many1(P) ->
bind(P, fun(H) ->
bind(many(P), fun(T) ->
return([H|T])
end) end).

ident() ->
bind(lower(), fun(H) ->
bind(many(alphanum()), fun(T) ->
return([H|T])
end) end).

nat() ->
bind(many1(digit()), fun(X) ->
{Nat, _} = string:to_integer(X),
return(Nat)
end).

space() ->
bind(many(sat(fun is_space/1)), fun(_) ->
return({}) end).

token(P) ->
bind(space(), fun(_) ->
bind(P, fun(V) ->
bind(space(), fun(_) ->
return(V)
end) end) end).

identifier() -> token(ident()).
natural() -> token(nat()).
symbol(X) -> token(string(X)).

int() ->
l_or_r(
bind(char($-), fun(_) ->
bind(space(), fun(_) ->
bind(nat(), fun(N) ->
return(-N)
end) end) end),
nat()).

integer() -> token(int()).
見所は do notation っぽく見せようとしているところ

パーサーの部品とかは関数として定義しようかと思ったところ
token(fun nat/0)
みたいに
fun って付けてアリティーもどうにかしなきゃいけないのが面倒なので
関数返す関数にしてみた

で、8.8 で簡単な数式計算するのを作りましたので
-module(expr).
-compile(export_all).
-import(parser, [parse/2, item/0, symbol/1, l_or_r/2, bind/2, return/1, integer/0, l_or_r/2, many/1]).

eval(X) ->
case parse(expr(), X) of
[{N, []}] -> N;
[{_, out}] -> throw("unused input " ++ out);
[] -> throw("invalid input")
end.

expr() ->
bind(term(), fun(T) ->
l_or_r(
bind(
many(
bind(l_or_r(symbol("+"), symbol("-")), fun(Bin) ->
bind(term(), fun(T1) ->
case Bin of
"+" -> return(T1);
"-" -> return(-T1)
end
end) end)
), fun(List) ->
return(lists:sum([T|List]))
end),
return(T)
)
end).

term() ->
bind(factor(), fun(F) ->
l_or_r(
bind(
many(
bind(l_or_r(symbol("*"), symbol("/")), fun(Bin) ->
bind(factor(), fun(F1) ->
return({Bin, F1})
end) end)
), fun(List) ->
{P, D} = lists:splitwith(fun({X, _}) -> X =:= "*" end, List),
TMP = lists:foldl(fun({_,X},Y) -> Y*X end, F, P),
return(lists:foldl(fun({_,X},Y) -> Y/X end, TMP, D))
end),
return(F)
)
end).

factor() ->
bind(atom(), fun(A) ->
l_or_r(
bind(symbol("^"), fun(_) ->
bind(factor(), fun(F) ->
return(math:pow(A,F))
end) end),
return(A)
)
end).

atom() ->
l_or_r(
bind(symbol("("), fun(_) ->
bind(expr(), fun(E) ->
bind(symbol(")"), fun(_) ->
return(E)
end) end) end),
integer()).

で、動かしてみると
1> expr:eval("1-2/9-3/2^3^2-4").
-3.2280815972222223
Haskellで検算
Prelude> 1-2/9-3/2^3^2-4
-3.2280815972222223
おぉ、なんか、動いてるみたい

左再帰なんて始めてググったので何か色々間違ってるかもしれないけど動いたヨ!!

Erlang で Parsec っぽいことしようとしている
freesourcecode - Erlang Parsec library とか
Erlang 付属のパーサジェネレータ Yecc を使ってみた - muddy brown thang とか
まぁ、色々あるんだと思うんですが
lists:foldl とかやっとこさ使ったんでちょっと楽しかった

教訓: do notation は便利

2010/03/29

erlang now

Erlang で現在時刻を取りたい!!

Erlang Community - Dates and Time - Trapexit
このサイトはちょくちょく見るんだけど素敵だなぁ
1> erlang:localtime().
{{2010,3,29},{18,10,54}}

他にも色々載ってるので上のページ見てね

erlang resolve

名前の解決の間にも色々したい!!

Erlang ならどんどん名前の解決をしてくれるに違いありません。
プログラミングErlangには
inet:gethostbyname/1 とかあるみたいですけど
1> inet:gethostbyname("www.google.com").
{ok,{hostent,"www.l.google.com",
["www.google.com"],
inet,4,
[{66,249,89,147},
{66,249,89,106},
{66,249,89,104},
{66,249,89,105},
{66,249,89,103},
{66,249,89,99}]}}
そんなことでは飽きたりません

で、ググったら inet_res ってのがありました
2> inet_res:gethostbyname("www.google.com").
{ok,{hostent,"www.l.google.com",
["www.google.com"],
inet,4,
[{66,249,89,147},
{66,249,89,106},
{66,249,89,104},
{66,249,89,105},
{66,249,89,103},
{66,249,89,99}]}}
いっしょやん
いやいや
3> inet_res:lookup("www.google.com", in, a). 
[{66,249,89,147},
{66,249,89,106},
{66,249,89,104},
{66,249,89,105},
{66,249,89,103},
{66,249,89,99}]
4> inet_res:resolve("www.google.com", in, a).
{ok,{dns_rec,{dns_header,2,true,'query',false,false,true,
true,false,0},
[{dns_query,"www.google.com",a,in}],
[{dns_rr,"www.google.com",cname,in,0,315339,
"www.l.google.com",undefined,[],false},
{dns_rr,"www.l.google.com",a,in,0,22,
{66,249,89,147},
undefined,[],false},
{dns_rr,"www.l.google.com",a,in,0,22,
{66,249,89,106},
undefined,[],false},
{dns_rr,"www.l.google.com",a,in,0,22,
{66,249,89,104},
undefined,[],false},
{dns_rr,"www.l.google.com",a,in,0,22,
{66,249,89,105},
undefined,[],false},
{dns_rr,"www.l.google.com",a,in,0,22,
{66,249,89,103},
undefined,[],false},
{dns_rr,"www.l.google.com",a,in,0,22,
{66,249,89,99},
undefined,[],false}],
[],[]}}
色々細かく指定できるみたい
例えば
5> inet_res:lookup("www.google.com", in, a, [{nameservers, [{{8,8,8,8}, 53}, {{8,8,4,4}, 53}]}]). 
[{66,249,89,147},
{66,249,89,104},
{66,249,89,103},
{66,249,89,106},
{66,249,89,99},
{66,249,89,105}]
てな感じで nameservers も指定できます

あと、メモ (inet とか inet_parse とか)
6> inet_parse:ntoa({8,8,8,8}).
"8.8.8.8"
7> inet_parse:address("8.8.8.8").
{ok,{8,8,8,8}}

2010/03/25

"-import" erlang

@higepon さんは言いました:
Erlang の import 使ってなかった。コード短くなる。

プログラミングErlangをちゃんと読めということなのかもしれません
でも、検索しました。

Erlang for Python programmers: Part II « Ruslan’s Blog
-import(lists, [foreach/2, map/2]).
とかすればいいみたい
確かに一々書くの面倒だよな〜と思ってたんですが
@voluntas さんは言いました:
@higepon 名前空間重要って事で使ってないです import ... 。

イライラしてきたら使ってみようと思いました

2010/03/22

X11 debian nice

debian だと X11 の nice 値をどっかで適当に設定してくれてるはずなんですが
もーそんなのどこだったかなんて憶えてないよ教えて○○えもーん
というわけでググえもんに聴いてみました

XWindowの起動に失敗する。 Debian SargeからEtchへの移行 - 後編 - | 日記
dpkg-reconfigure x11-common すればいいそうです
何て基本的

で、実際にやってみると
  • 誰が X を立てられるか (root・console user・誰でも)
  • X の nice 値 (-10 から 0 推奨)
を聞かれました
debconf の設定次第でもっと色々聞かれるに違いありません

で、-10 で grep してみたところ
/etc/X11/Xwrapper.config:nice_value=-10
って出たのでこいつをいじればいいみたい

-10 にしてみました

2010/03/05

"-newkey ec"

楕円曲線暗号 (Elliptic Curve Cryptography, ECC) ってのがあります
公開鍵暗号の1つです
暗号使いたいといったら OpenSSL
OpenSSL なら ECC もばっちりに違いないと思い適当にコマンド叩きはじめました

Debian Lenny は OpenSSL 0.9.8g だそうです

とりあえず CSR 作る辺りの話ってのは幅広い暗号の話が? と思い
$ openssl req -help
unknown option -help
req [options] <infile >outfile
where options are
-inform arg input format - DER or PEM
(中略)
-newkey ec:file generate a new EC key, parameters taken from CA in 'file'
(後略)
"unknown option -help" とか言われてますが
"-newkey ec:file" で ECC な CSR が作れるっぽい!

そこで、ググってみましたところ
OpenSSLによる楕円曲線暗号の利用
え〜と、変な検索語使わなくても良かったんじゃないの?

楕円曲線暗号ってのは、楕円曲線の上で掛け算をするんですが
楕円曲線っての自体が沢山あるので先ずどれを使うか決めないといけません
どれでもいいかというとそういうわけではなく
ものによっては暗号としての強度が落ちてしまうそうなので
「これ使ってこうぜ!!」ってのが定められています

http://www.ietf.org/rfc/rfc4492.txt
http://www.ietf.org/rfc/rfc5480.txt
http://www.ietf.org/rfc/rfc5639.txt
あれ、なんか、一杯あるな、どれだ

で、最初にどの曲線使うか決めるわけですが
openssl に ecparam ってのがありまして
$ openssl ecparam -list_curves
secp112r1 : SECG/WTLS curve over a 112 bit prime field
secp112r2 : SECG curve over a 112 bit prime field
secp128r1 : SECG curve over a 128 bit prime field
secp128r2 : SECG curve over a 128 bit prime field
secp160k1 : SECG curve over a 160 bit prime field
secp160r1 : SECG curve over a 160 bit prime field
secp160r2 : SECG/WTLS curve over a 160 bit prime field
(後略)
と、扱える曲線のリストが出ます
で、実際にパラメータを出すには
$ openssl ecparam -name secp224r1
-----BEGIN EC PARAMETERS-----
BgUrgQQAIQ==
-----END EC PARAMETERS-----
とすると base64 された形で出てきます
これをファイルに入れといたりすれば OK

で、次に鍵を作りたいということで
$ openssl ecparam -name secp224r1 -genkey
-----BEGIN EC PARAMETERS-----
BgUrgQQAIQ==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MGgCAQEEHFaQDqPQ8x4NAr5Bz67BZcgqZurwgy4UGdlQ2OegBwYFK4EEACGhPAM6
AASNeby2ALikGQghKhN1a1SSvi1J+y1l55kE3AH1c4y+6LcesqdYKtkLt0P303p+
IH1Tj0J9MxqEJA==
-----END EC PRIVATE KEY-----
のように parameter と鍵が一緒に出せます

鍵だけ ecc.key というファイルに入れておいて
$ openssl ec -in ecc.key -param_out
read EC key
writing EC key
-----BEGIN EC PARAMETERS-----
BgUrgQQAIQ==
-----END EC PARAMETERS-----
と parameter を取り出すことも可能

じゃぁパラメータだけ出しても仕方なくない?
というとそうでもなくて、最初の req で出てきた -newkey で使えます
parameter の base64 を ecc.param ってファイルに入れといて
$ openssl req -new -newkey ec:ecc.param -nodes
Generating a 224 bit EC private key
writing new private key to 'privkey.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
や、まぁ、作っといて req に食わしてもいいんですが

CSR は CSR なんで、
あとはこれを RSA で署名してもいいし、ECC で署名してもいいし、
煮ても焼いても美味しく頂けます

2010/02/13

python epoll

「イベント〜?」「ドリブ〜ン!」

なんか、すっかり放置していました
私は GUI でチャットなどを作るはずだったのです
しかし全く着手せぬまま現在に至っています、ごめんなさい

そこで、少しだけ epoll 触っとこうと思うことにして調べました
How To Use Linux epoll with Python
何とも丁寧な説明がありました

とりあえず
  • select.epoll.register で file descriptor と何を監視するかを登録
  • select.epoll.poll で active なやつをとってくる
ってのだけ把握

というわけで、少し試してみることに
import socket
import select
from OpenSSL.SSL import Connection, Context, SSLv23_METHOD

fqdn = 'www.google.com'

s = socket.socket()
s.settimeout(0)

epoll = select.epoll()
epoll.register(s.fileno(), 2**11-1)

print epoll.poll(1)
s.connect_ex((fqdn, 443))
print "connect"
print epoll.poll(1)
ctx = Context(SSLv23_METHOD)
print "make Context"
print epoll.poll(1)
c = Connection(ctx, s)
print "make Connection"
print epoll.poll(1)
c.set_connect_state()
print "set connect state"
print epoll.poll(1)
c.do_handshake()
print "do handshake"
print epoll.poll(1)
x509 = c.get_peer_certificate()
print x509.get_subject()

で、結果がこちら
$ python test1.py 
[(3, 276)]
connect
[(3, 260)]
make Context
[(3, 260)]
make Connection
[(3, 260)]
set connect state
[(3, 260)]
Traceback (most recent call last):
File "test1.py", line 26, in <module>
c.do_handshake()
OpenSSL.SSL.WantReadError
non-blocking のまま handshake しようとして怒られました

select.EPOLLOUT = 4, select.EPOLLHUP = 16, select.EPOLLWRNORM = 256
みたいなんですけど、まぁ、OUT だけ見りゃいいのかな、この場合

教訓:「OpenSSL の handshake を呼ぶんなら blocking にしよう」
え、そこなの?

2010/02/09

ekrn.exe

パソコンが遅いんだけど何でかなと言われて調べました
taskmgr を開いてみるとプロセスが 2 つ暴走しています
1 つは Firefox でもう 1 つは ekrn.exe というもの

ウイルス!? と思って検索してみたところ
「ekrn.exe のCPU使用率が100%になるのは?」
NOD32 のエンジンらしい

にしても何故 Firefox とコンビで
Firefox はこの前 3.6 にしてみたんですが
自分の環境でも Google Apps で暴走してしまうようだったので
3.5 に戻してみたばかりでした
今回の環境も試しに 3.5 に戻してみたら一先ず解決しました

その後 NOD32 も version up されてたので更新
これでちょっと様子見てみることにしました

NOD32 はまぁいいんだけど Firefox が暴走するのがちょっと心配です
しかも Google Apps とは
「ちょっと人柱過ぎだから気をつけろ」
ということかもしれません

2010/02/05

erlang ssl_esock

HTTPS サーバーから証明書を取ってこようシリーズ
今回は Erlang です

Erlang の SSL な module はこちら
Erlang -- SSL Reference Manual
ざっと見ると getpeercert という関数があるのでこれっぽいです

左のコラムに ssl と ssl_new というのがありますが、これは
以前は SSL 関連でも全て OpenSSL を利用していたようで
connection を張ろうとしたりすると ssl_esock という subprocess が立ち
そいつに色々と仕事を任せていたようです
でも Erlang 的にはそこに C が入ってしまうので嬉しくありません

そこで cryptographic primitive な部分だけ OpenSSL を使って
connection の部分なんかを Erlang で実装したのが ssl_new のようです
cryptographic primitive は crypto って application を使います

で、application とか良く分かってないんですが
とりあえず start とかしといたらいいんでしょ、というのが次
-module(get_cert).
-compile(export_all).

get_cert(Host) ->
application:start(crypto),
application:start(ssl),
{ok, Sock} = ssl:connect(Host, 443, [{ssl_imp, new}]),
{ok, Der} = ssl:peercert(Sock),
{ok, Cert} = public_key:pkix_decode_cert(Der, otp),
ssl:close(Sock),
application:stop(ssl),
application:stop(crypto),
Cert.
ssl:connect の option に ssl_new を使うと伝え
ssl:peercert で証明書を DER で取り
public_key:pkix_decode_cert でそれを parse しています
otp ってあるのは parse の形式で、あと plain があります
それぞれ
-include_lib("public_key/include/public_key.hrl").
-include_lib("public_key/include/OTP-PUB-KEY.hrl").
的なことをしておけば読み易いです
かんたんなことしかしていませんね

で、動かしてみると
$ erl
Erlang R13B03 (erts-5.7.4) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.4 (abort with ^G)
1> get_cert:get_cert("blogger.com").

=INFO REPORT==== 15-Feb-2010::01:34:14 ===
application: crypto
exited: stopped
type: temporary

=INFO REPORT==== 15-Feb-2010::01:34:14 ===
application: ssl
exited: stopped
type: temporary
{'OTPCertificate',
{'OTPTBSCertificate',v3,134060097170805708820381,
{'SignatureAlgorithm',{1,2,840,113549,1,1,5},'NULL'},
{rdnSequence,
[[{'AttributeTypeAndValue',{2,5,4,6},"US"}],
[{'AttributeTypeAndValue',
{2,5,4,10},
{printableString,"Google Inc"}}],
[{'AttributeTypeAndValue',
{2,5,4,3},
{printableString,"Google Internet Authority"}}]]},
{'Validity',
{utcTime,"091222015844Z"},
{utcTime,"101222020844Z"}},
{rdnSequence,
[[{'AttributeTypeAndValue',{2,5,4,6},"US"}],
[{'AttributeTypeAndValue',
{2,5,4,8},
{printableString,"California"}}],
[{'AttributeTypeAndValue',
{2,5,4,7},
{printableString,"Mountain View"}}],
[{'AttributeTypeAndValue',
{2,5,4,10},
{printableString,"Google Inc"}}],
[{'AttributeTypeAndValue',
{2,5,4,3},
{teletexString,"*.blogger.com"}}]]},
(あと長いんで略)
こんな感じで X.509 を parse してくれてます

ちなみに public_key の Reference は
Erlang -- public_key
にあって
例えば pem_to_der ってのを使えば PEM の PATH 与えて
DER で返してくれるなんてのも分かります

2010/01/25

pdf 署名

PDF に署名したいなーって思いました
ググりました

Adobe Acrobat 使えばいいみたいなんですが
手元にあるのが弱いバージョンだからなのか
Reader と上手く連携してないからなのか
何だか良く分かりません

っていうか Linux とかでしたいじゃん

で、これですね
MOONGIFT: » PDFに署名をする「PortableSigner」:オープンソースを毎日紹介
Java で書かれてるようなので Linux でもいけそうだ!
と言いながらとりあえず Windows XP で試してみたんですが
インストールして Readme を参照して JCE というのを入れてみたら
しっかり署名することができました
簡単!
まぁ、きっと Acrobat を使うともっと凄いこと色々できるんだろうなぁ

で、Acrobat で開くと
「文書の証明の完全性が不明です。作成者が検証できませんでした。」
って出ます。
これはルート証明書から署名した証明書まで辿れなかったってことだろう
と思ったんでちょっと仕組みを調べてみました。

といっても、メニューの「文書」に「信頼済み証明書」ってのがあって
それ開いて表示を「証明書」にすれば良かっただけなんですが。
で、そこには Adobe Root CA ってのしかありません。
ん〜? と思って他のも調べてみると Reader の 8 までは Adobe Root CA のみ
9 になると色々と第三者機関の証明書も入っていました。

全ての信頼の起点はこれなの? と思いもう少し調べてみると
Windows であれば
[編集] -> [環境設定] -> [セキュリティ] -> [詳細環境設定]
と進んで [Windows 統合] ってところで
片っ端からチェックすればいいみたい。
Windows で信頼されているルートを Reader でも信頼することになります。

んでは、信頼済みな証明書ってのは何のことなの? って思ったので
更にしつこくググってみたら
Adobe - Certified Document Services (CDS)
に辿り着きました。

なるほど、Microsoft の場合は
Microsoft Root Certificate Program
Firefox の場合は
Mozilla CA Certificate Store Information
で採用されていないといけないわけですが
Adobe Reader に関してもそういうのがあるってことですね。
でも Adobe の少なくないの?

PDF の方が色々用途があったり署名が頻繁だからなのか
商品ラインナップも個人用とか法人用とかあったりして
署名できる回数も決まってたりで複雑そうでした。
タイムスタンプとかその辺良く分かってないんですが。
同じ Adobe でも Air 用の Code Signing とかとは勝手が違うみたい。
ビジネスとか法律の香がしてきました。