RubyのOpenSSLバインディングのOpenSSL::PKey::EC::Point#mulまわりがひどい(?)
Rubyは素晴らしい言語です(以下、自分でRubyに貢献もせずに好き放題言う上での事前の言い訳)
先日から、Bitcoinで遊んでいて、その関係でOpenSSLの楕円曲線(EC)暗号まわりをいじっていたが、RubyでOpenSSLのECDSAを使おうという人があまりいないのか、わりとひどい。
OpenSSLのECで、秘密鍵から公開鍵を生成するには一般にはEC_POINT_mulが用いられる(Satoshi Nakamotoのコードでもこれを用いて秘密鍵から公開鍵を生成している)が、Rubyには長らくmulすら存在していなかった。
EC_POINT_mul(ecdsa->group, new_public_key, private_key, NULL, NULL, ctx);
でも実際に過去にRubyでBitcoinクライアントを書いている人はいて、じゃあどうしているかというと鍵の再生成の時だけFFIで自前でOpenSSLのAPIを叩いていて、なんというworkaround…(そんなきたない事してないで後の人のためにRuby本体にコミットしてよ!!!)
で、2.0.0ぐらいで追加されたmulを使おうとするも、mulのコードを読んでも、どうやれば上のごく簡単なCコードと同等の記述ができるのかわからない(というかbn2だけ渡してbn1をNULLにする、ってことができない時点でAPIの引数のマップの仕方がおかしい気がする)。というか全体的にバインディングのコードが怪しい。
で、挙句の果てにかなり基本的なコードでセグフォすることを発見してしまった!
require 'openssl' OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new('secp256k1').group).mul([], [], OpenSSL::BN.new("00", 16))
Bitcoinの本質からは大脱線なので、「Bitcoinのしくみ」が書き終わってからバグレポートなりパッチなりをアレするなりしようと思いますが、かなりぐぬぬ…ってなりましたし、えっ、RubyでECDSAで電子署名したくなる、って現代においてそんなマイナーな行為なんですか…?