しーぱんおーさーになってみた

いわゆるCPAN Authorデビューしたのでその記録。

何作ったのか

RNCryptorというAESのベストプラクティス的なファイルフォーマット及びiOSライブラリがあるのですが、

The primary target is Objective-C, but implementations are available in C++, C#, Java, PHP, Python, Javascript, and Ruby.

RNCryptor/RNCryptor · GitHub

Perl版が無い…ということでRNCryptorフォーマットを取り扱うためのPerlモジュールを作りました。その名もCrypt::RNCryptorです。



余談:暗号化の面倒くさいお話

何故にこんなものを作ったのかというと、最近、PerliOSAndroid共通鍵暗号のAESを扱う機会があったのですが、AESもとい暗号化というものは想像以上に面倒ということが分かり、いい感じのライブラリを探していたらRNCryptorに辿り着いたものの、Perlの実装がなかったというわけです。

もっとも、実際の所、Perlだけで暗号化・復号する分にはそれ程面倒ではないです。
AESであれば、Crypt::CBC-cipher => 'Crypt::OpenSSL::AES'を指定すれば後はライブラリがよしなにやってくれます。

ですが、これを別のプラットフォームに送るとなるとこれが結構厄介で、色々取り決めが必要となります。

例えばAESの場合、暗号化を行う際に考慮すべきファクターは、ざっと思いつくだけでも以下のようになります。

  • 暗号利用モードをどうするか
    • 上でCrypt::CBC使えば簡単なんて書きましたが、そもそもCBCというのは所謂「暗号利用モード」の1つでしかなく、他にもECBなど色々あります。
    • 今はCBCが主流っぽい?
  • 鍵の長さをどうするか
    • 今は32文字*1のAES256が主流っぽい?
  • 鍵をどう取り扱うか
    • 最初から32文字で生成し、やりとりするのか。
    • 適当な文字列からハッシュで32文字にするのか。
      • Saltは付けるのか。付けるならどうやって渡すのか。
    • ハッシュ化のアルゴリズムはHexなMD5?SHA256?PBRDF2?Bcrypt?
      • ストレッチング(ハッシュの繰り返し)する場合、その回数は?
  • IVをどうするか
    • 使わない(全部0固定にする)のか、使うならどうやって渡すのか。
    • (そもそもIVとか初耳だった…)
  • paddingをどうするか
  • 等々

いやはや面倒ですね。

てなわけで、RNCryptorはこの辺りをトレンドを踏まえつついい感じに決めてくれています。

実は、OpenSSLも独自の取り決めを作っており、

'Salted__' + Salt(8 byte) + CipherText(16 x n byte)
OpenSSLの暗号文をJava/Perl/Rubyで開く - mixi Engineers' Blog

というヘッダを暗号化データに付けるようですが、それ以外についてはストレッチング1回とか、ある程度決めの部分があるようです。詳しくは以下の記事をば*2

RNCryptorはOpenSSLより汎用的*3で頑強な*4設計になっています。
そしてなによりObjective-CJavaのライブラリが既にあるのが一番大きな強みです。

閑話休題

CPANモジュールの作り方

モジュールの作成には、tokuhirom氏謹製のMinillaを使いました。

この手の支援ツールはExtUtils::MakeMakerやShipItなど色々あるようですが*5、Minillaはその中でも最も新しい統合的なオーサリンツールといえるかと思います。

Minillaの基本はこんな感じです。

# インストール
cpanm Minilla
# 大枠作成
minil new Crypt::RNCryptor
cd Crypt-RNCryptor
# 好みのエディタでコード書く
atom .
# テスト
minil test
# リリース
minil release

Minilla Tips

慣れるまで戸惑う点が結構あったので記録しておきます。

README.mdは直接いじらない

メインモジュール(例えばCrypt::RNCryptor)のPODが自動でREADME.mdとして出力されます。

Travis CIを使う

シンプルなモジュールなら自動生成の.travis.ymlで問題無いです。

README.mdにバッジを表示したい場合は、minil.tomlに

badges = ["travis"]

を追記します。ここを変えればcoverallsのバッジも置けます。

テスト

minil testはgitリポジトリの今の状態をサンドボックス環境へ持ってきて、その中でテストしてくれます。そのためか、新規ファイルはgit addしておく必要があります。

サンドボックスが必要ないのであれば、普通にproveしても問題無いです。

余談ですが、proveする際には、Test::Prettyを入れて、.provercを以下のようにすると幸せになれます。

--lib
--color
--failures
--trap
-P Pretty
--verbose
$VERSIONは触らない。

Minillaが勝手にインクリメントとかするようなので、手動での変更は必要ありません。

gitでバージョンのtagは付けない

minil release時に自動的に付けられるので、必要ありません。

Changesの編集

この辺りの仕組みはよくわかっていないのですが、ChangesというのはCPANのSpecial Filesの1つで、CPANにアップする際には、Changesファイルに変更内容を記述するのが慣例のようです。

この時、タイムスタンプを入れる必要がありますが、これをMinillaが自動的に入れてくれます。
minil relase前に{{$NEXT}}の下に色々書くよう習慣づければ良さそうです。

{{$NEXT}}

    - write something
minil release時の"missing user argument ... UploadToCPAN.pm"エラー

よっしゃ書いた書いた公開しちゃうぜー、というノリでminil releaseしたら出てきたエラーです*6

結論から言えば、~/.pauseファイル(PAUSEに関しては後述)が無いor記述が足りない場合に出ます。

minil releaseするには、以下のような~/.pauseを作成しておく必要があります。

user sshin
password himitsu

しかし、生のパスワードを書くのは抵抗があるのですが、何とかならないのでしょうかね。今のところ対応策が見つけられてないのですが…仕方ないので、releaseの時だけ書いて、終わったら消してます。

PAUSEに登録

gemsとかnpmにはモジュールを公開するのにユーザ登録が必要ですが、CPANにももちろんあります。それがPAUSE(The [Perl programming] Authors Upload Server)*7です。

少し驚きだったのは、歴史が長いからかアクティブユーザ数が少ないからかは分かりませんが、何かと人によるチェックが入るところです。そして登録フローもまたアナログです*8

人が絡む最大のメリットは世界のPerl Mongers達がdisってくれることらしいです。

DISられるということは、それだけドキュメントやコードをを読んでいただいている証拠...だと思うので、DISには感謝しましょう。

何事からも学び、そして感謝するのです。謙虚な姿勢が大事なのです。アザマス!!

「CPAN Author になったよ」のつづき - hayajoのはてなブログ

cpan disられる - Google 検索

Minilla使えば、コード関係ない所でdisられることはなくなるんじゃないかな(汗。

モジュール公開までの流れ

一応、公開までの流れを簡単に書いておきます。

参考:[Perl] 作成したモジュールをCPANで公開する手順

  1. PAUSE登録。人のチェックが入るっぽいが、完了までそんなに時間はかからなかった。
  2. パスワード変えたり、プロフィール変えたり。
  3. tarballのアップ。minil releaseでサクッと。PAUSE上でもできるみたい*9
  4. ネームスペースの申請。 これが通過して初めてCPAN上で閲覧可能になる。待ち時間は半日ほど?

感想

Minilla様々です。
開発・公開のフローもこういったツール使うことで、他の言語と大差無いように思います。

CPAN登録するとハッカー気取りになれるので、2日ぐらいでちゃっちゃと作ってアップしてみると良いんじゃないかと思いました(適当)。

以上。

*1:正確には32バイト。ASCIIである必要ないので。

*2:必読

*3:v3で10000回のストレッチング、v3.1では調整もできる。これらの値はヘッダに入る

*4:HMACでとったハッシュを末尾に付ける等

*5:参考:http://gihyo.jp/dev/serial/01/modern-perl/0026

*6:依存関係のエラーも何度か出ました

*7:何をpauseするの?みたいな感じで最初意味が分かりませんでした

*8:というかサイトが既にアレゲPerlらしいといえばPerlらしいですが。初見うぉっとなります。

*9:というかこっちが正式な方法