BundlerでFizzBuzz

今年もFizzBuzzの季節がやってまいりました。

FizzBuzzを書くことのできない言語を使えると口にすることはとても恥ずかしいことらしいので、きっとFizzBuzzを書くことのできないライブラリを使ってることも恥ずかしいことなのだろうと思います。

私も、ほとんどのライブラリはFizzBuzzしたことがありませんでした。このままではソーシャル転職をすることができません!将来のキャリアプランが台無しです。

そういえば最近、Ruby on Railsの世界ではBundlerというツールが流行っているらしいので、これを使ってFizzBuzzすることにしてみました。

続きを読む

はてなブログの記事書きテスト

はてなブログの記事書きテスト

はてダからはてブロへと移行することの利益は何があるか、確認するために記事を書いてみる。

#include <stdio.h>

int main(int argc, char* argv){
  int i;
  for (i=0; i<100; i++){
    if (! i%15) {
      printf("hogefuga\n");
    } else if (! i%5){
      printf("fuga\n");
    } else if (! i%3){
      printf("hoge\n");
    } else {
      printf("%d\n", i);
    }
  }
}

fizzbuzz

条件分岐のやり方を忘れたネットワーク園児がなんかfizzbuzz書いてみました。ifと剰余演算子を使わない例。(http://bugrammer.g.hatena.ne.jp/nisemono_san/20111008 を見た)

#!ruby

class FizzBuzzer
  @@max = 1000

  def self.define_my_methods num, word
    num.step(@@max, num) {|n|
      define_method "to_#{n}" do
        word
      end
    }
  end

  def method_missing method, *args, &block
    method.to_s =~ /^to_(\d+)$/
    return $1 if $1
    super
  end

  define_my_methods 3, :fizz
  define_my_methods 5, :buzz
  define_my_methods 15, :fizzbuzz
end

(1..100).each do |n|
  puts FizzBuzzer.new.send("to_#{n}")
end

Rubyオブジェクト指向言語なので、オブジェクト指向で書けばこんな感じになると思います。上記だと一応1000までは対応しますね。

追記:よく見たらif文使ってた…orz if $1; super はなくてもfizzbuzzに関しては動くので、上記コードは簡単にifなしにできますが、method_missingでsuperしないのはとってもお行儀が悪いのでおすすめできません。

#!ruby

def fizzbuzz x
  begin
    x / (x % 15)
  rescue
    return :fizzbuzz
  end

  begin
    x / (x % 3)
  rescue
    return :fizz
  end

  begin
    x / (x % 5)
  rescue
    return :buzz
  end

  x

end

(1..100).each do |x|
  puts fizzbuzz x
end

こっちは剰余演算子は使う場合。とっても素直。

ECCの動作の現状

Apache22

Oops, no RSA or DSA server certificate found for 'YOUR.DOMAIN:0'?!

Holy shit! Apache2.2 doesn't support EC-based Server-Certificate yet!


http://www.jnsa.org/seminar/pki-day/2010/data/4_urushima.pdf
によると、ECDH/ECDSAの認証がApache2.3になるまで完成していないとのこと。
http://www.takeyellow.com/apachemirror//httpd/CHANGES_2.3
公式情報で見れば、2.3.3でECC鍵及びECDHのサポートを開始したとある。


http://mail-archives.apache.org/mod_mbox/httpd-dev/201012.mbox/%3CA418DE49-617A-45E2-9F6E-68642611773B@apache.org%3E
2010/12/22に2.3.10-alphaが出て、2011/3/7に2.3.11-betaが出た。2.4.0の正式版が出るのは2011年初頭とされていたけど、2.1-alphaから2.2が出るまでに9ヶ月かかったらしいし、まだ若干先のことになりそうだ。

Dovecot 2.0.9

起動まではOK。
Windows上のThunderbird3.1.9では ssl_error_no_cypher_overlap と怒られる。Outlook でも受信できず。サーバ上でのエラーはno shared cipherとのこと。もちょっと確認したい。
openssl s_clientで確認。ECDSA鍵ではSSLv3通信成立せず、RSA鍵に変えないと通信不能だった。どうやら未対応。

Postfix2.8.2

なにごともなく使える。
postfix2.6以降をopenssl1.0以降とリンクしてることが条件。
通常通りの設定に加え、smtpd_tls_cert_file の代わりにsmtpd_tls_eccert_file、 smtpd_tls_key_file の代わりに smtpd_tls_eckey_file の設定をすればok。
俺々CA(ECDSA signed)のcertを入れたところ、メールの送信まで確認できた。

OpenSSH 5.4 with OpenSSL 0.9.8n

上記バージョンの、FreeBSD 8.1-RELEASEについてきたやつは未対応っぽい。
http://slashdot.jp/~doda/journal/525952 によると、OpenSSH5.7 からECDH及びECDSAに対応しているそうな。
Windows上の端末エミュレータでは、PuTTY未対応・Tera Term 4.69(TTSSH 2.56) より対応・RLogin 2.10.0 より対応 というのが現状らしい。PuTTYから乗り換える良いタイミングかも知れない。

OpenSSL1.0.0で楕円曲線志向なサーバ証明書を作る

楕円曲線を用いた暗号方式でサーバ証明書を作ろう、というお話。

ユーザが証明書署名要求を作るまで

# openssl ecparam -genkey -name prime256v1 -out server.pem
# openssl ec -in server.pem -out server.des.pem -des

先ほどは知らなかったので書き損ねたけれど、openssl1.0.0ではecサブコマンドからec鍵対をDES暗号化することが可能。passphraseを使用/記述できる環境で使うのであれば暗号化しておいた方が安全になる。

# openssl req -new -key server.des.pem -out server.req.csr

で、これを署名してくれる人に送る。
一般的な注意として、Organization Nameに認証先と同じものを入力すること・Common NameにサーバのFQDNを入力すること、の二つがある。

CAが証明書をサインしてユーザに送り返すまで

ここの操作はecであろうと関係ないので、普通に。

# openssl ca -keyfile cakey.pem -cert cacert.cer -md sha256 -out newcert.pem -infiles server.req.csr

なお、-mdはhelpにsha1までしか載っていないが、実際にはsha256を指定できる模様。-mdを指定しないとsha1になる。設定ファイルでCA鍵対やsign用証明書を設定していれば-keyfileや-certのオプションは不要。

これまでCAがやるべきかどうかはわからないけど、証明書の部分だけを出力するためには、

# openssl x509 -in newcert.pem -out server.crt

とする。これでnewcert.pemから普通の公開鍵部分だけ取り出せる。

そしてserver.crtをサーバ証明書として活用する。

OpenSSL1.0.0で楕円曲線志向なCAを立てる

楕円曲線を用いた暗号方式でCAの証明書を作ろう、というお話。OpenSSLは1.0.0から楕円曲線暗号ECC)への対応がきちんとしてきているのだけど、ディストリ付属のOpenSSLは古い(0.9.8)ことがある。$ openssl version とコマンド打てば使っているopensslのバージョンが分かるので、古いようだったら新しいモノを入れると幸せになれる。

環境:FreeBSD 8.1-RELEASE, opensslはportsから入れる

準備

# cat /usr/ports/security/openssl/distinfo | head -1
SHA256 (openssl-1.0.0d/openssl-1.0.0d.tar.gz) = 92511d1f0caaa298dba250426f8e7d5d00b271847886d1adc62422778d6320db
# portinstall security/openssl
# cp /usr/local/openssl/openssl.cnf.sample /usr/local/openssl/openssl.cnf
# rehash
# openssl version
OpenSSL 0.9.8n 24 Mar 2010
# which openssl
/usr/bin/openssl

portsからインストールしてもopensslのバージョンは1.0.0dにならない。これは/usr/bin/opensslが使われているから。
そこで、/usr/bin/opensslの実行権限を落としてしまう。良い方法かは怪しいけど、ファイル名を変えるよかマシ。

# chmod -x /usr/bin/openssl
# rehash
# openssl version
OpenSSL 1.0.0d 8 Feb 2011

無事1.0.0dになりました。

CAの鍵対を準備する

# openssl ecparam -list_curves
(略)
  sect233r1 : NIST/SECG/WTLS curve over a 233 bit binary field
  sect239k1 : SECG curve over a 239 bit binary field
  sect283k1 : NIST/SECG curve over a 283 bit binary field
(略)
# openssl ecparam -genkey -name prime256v1 -out cakey.pem

曲線については、http://www.secg.org/download/aid-784/sec2-v2.pdfを参照するに、list_curvesにて出てくる曲線のだいたいがexplicitly recommendedらしい。ただしsect239k1などの一部の曲線は様々な標準に準拠こそしているがrecommendedではないので*1、鍵対を作る前に曲線の準拠具合をチェックしておくべき。
で、2011年2月現在の調査結果*2によると、現段階でWindowsにて実装されているのはprime256v1, secp384r1, secp521r1の三種類のみらしい*3
あとは、現在のところ楕円曲線の有効な攻撃法は見つかっていないはずなので、bit数を基準に選ぶ。160bitがRSA1024bitと同様の強度とされているので、2048bitに対応するのは224くらいだろうか、ということでprime256v1を選んでみる。


cakey.pemが鍵対ファイル。読むときはこんな感じ:

# openssl ec -in cakey.pem -text -noout

CAの自己署名証明書を作成する

# openssl req -new -x509 -days 1826 -sha256 -key cakey.pem -out cacert.cer
# openssl x509 -text -noout -in cacert.cer

0.9.8dではsha1しか対応していなかったが、1.0.0bではsha256でサインできるようになっている。1826日はだいたい5年。これで自己署名証明書ができた。
鍵対と証明書との対応を確認するさい、RSAのときにはmodulusを比較したが、ecdsaの場合は上記x509の出力結果のpubの部分とecの出力結果のpubの部分が同じになっていればok。

自己署名ではなくCSR(証明書署名要求)を作る場合は以下のようなコマンド。pkcs形式なのでverisignに送るときも安心*4

# openssl req -new -key cakey.pem -out careq.csr
# openssl req -in careq.csr -text -noout

それを自分でサインするなら:

# openssl x509 -req -in careq.csr -signkey cakey.pem -out cacert.cer -days 1826

CAの諸設定

  • openssl.cfgの初期設定ではCAの場所が./demoCAとなっていてとても怪しいので、まずこれをどこかの絶対パスに変更する(例:/var/ssl/CA)
  • 各種ディレクトリを作る
    • certs, crl, newcerts
  • ファイルをtouchする
    • index.txt, serial
  • ファイルの中身を作る
    • serialに「01」と書く
# vi /usr/local/openssl/openssl.cfg
(略; [CA_default]のdir項目を絶対パスにする等)
# mkdir -p /var/ssl/CA
# cd /var/ssl/CA
# mkdir certs crl newcerts
# touch index.txt serial
# cat > serial
01
^D(ctrl-Dで入力終了)

これで最低限動くようになる。より心地よい設計は今後の課題。

参考サイトさん:
http://webframe.sourceforge.jp/wiki/index.php?OpenSSL%A4%CB%A4%E8%A4%EB%C2%CA%B1%DF%B6%CA%C0%FE%B0%C5%B9%E6%A4%CE%CD%F8%CD%D1
http://researchmap.jp/index.php?action=cv_download_main&upload_id=11085
http://cro-pel.com/modules/penguin/content0103.html
http://www.fc-lab.com/network/server/pki/openssl.html

*1:IPSecにおいては準拠ですらない

*2:http://researchmap.jp/index.php?action=cv_download_main&upload_id=11085

*3:sect283k1で試したところ、確かにダメっぽかった

*4:https://www.verisign.co.jp/ssl/about/pem.html

プロトタイプチェーン

ふとJavaScriptに入門してみたところ、プロトタイプチェーンなるものが現れた。

var SomeObject = function(){};
SomeObject.prototype.someMethod = function() { print("some method!\n"); };
var AnotherObject = function(){};
AnotherObject.prototype = new SomeObject();

newしたものを入れることでワークするらしい。なんで?

通常のプロトタイプはこう。

var SomeObject = function(){};
SomeObject.prototype.someMethod = function() { print("some method!\n"); }; 
SomeObject.prototype.anotherMethod = function() { print("another method!\n"); }; 

あるいは、こういう書き方もある、と紹介されてる。

var SomeObject = function(){};
SomeObject.prototype = {
  someMethod : function() { print("some method!\n");},
  anotherMethod : function() { print("another method!\n");}
}; 

それがどうして唐突にnewに?と疑問を抱いた。

 
このままでは覚えられそうにないと思ったので、spidermonkeyを使って色々試してみた。

まずはコンストラクタの動作。

js> var Hoge = function(hoge){
  this.hoge = hoge;
};
js> Hoge
function (hoge) {
    this.hoge = hoge;
}
js> var hoge = new Hoge(2);
js> hoge;
[object Object]
js> new Hoge(2)
[object Object]
js> Hoge(2)
js>

コンストラクタは関数で、new + コンストラクタ によって返されるのは辞書(あるいは連想配列)。
で、コンストラクタに正しい引数を与えても何も返らない。これはコンストラクタを単に関数として判断しても何も返ってないから。return文を入れてれば対応したものが返る。

 

続いて生成されたオブジェクトについて見てみた。

js> var Hoge = function(hoge){
  this.a = hoge + " a";
  this.b = hoge + " b";
  this.print_it = function(){
    print (this.a + " " + this.b);
  };
};
js> Hoge
function (hoge) {
    this.a = hoge + " a";
    this.b = hoge + " b";
    this.print_it = function () {print(this.a + " " + this.b);};
}
js> hoge = new Hoge("wow");
[object Object]
js> for (key in hoge) {print(key)}
a
b
print_it
js> for (key in hoge) {print(key + " = " + hoge[key])}
a = wow a
b = wow b
print_it = function () {
    print(this.a + " " + this.b);
}
js>

オブジェクトは辞書だと納得。

 

で、最後に、辞書の宣言。

js> var dic = {
  "a" : "ahoge",
  "b" : "bhoge",
  c   : "choge"
}
js> dic["a"]
ahoge
js> dic.b
bhoge
js> dic["c"]
choge

辞書はオブジェクトと等価っぽい。

 

てわけで、

要は全部が辞書だからあんな書き方が許容されるみたいね。
prototypeの参照を追っかけるのは言語の仕様に入っちゃってるのかな、追いかけ方は今のところ見当もつかない。