wiki:PythonCamellia

Camellia暗号Python版

 NTTと三菱電機が開発したCamellia暗号がオープンソースになったので、Pythonに移植してみました。

  • BSD風ライセンス。
  • APIはほぼオリジナルどおりです。若干、Python風に変更しました。
  • Pure Pythonの実装と、C版を呼び出す拡張モジュール版とがあります。
  • Pure Python版は、オリジナルのC版から移植しました(Java版は鍵長が128ビットに固定なんです)。
  • 鍵長は128、192、256ビット。
  • 対象はPython 2.3および2.4です。
  • オリジナルどおりのAPIなので、単に128ビット(16バイト)ブロックの暗号化復号化ができるだけです。
  • Pure Python版は遅いです。
  • ベンチマークやってません。
  • Python 2.3および2.4対応のため、やむなく長整数の演算を行っています。不効率です。

NTTさん、 逆リンクありがとうございます。

ダウンロード

すみません。パッケージはこれから準備します。

最近の更新

使い方

説明文書ありません。最低限の__doc__文字列を書いておきましたので、Pythonのシェルからhelpでご覧下さい。

if __name__ == '__main__':の部分には簡単なテストを書いてあります。何かいじった場合は、このテストを実行してみてください。

Camelliaそのものについて

詳しくは Camelliaのサイトをご覧下さい。

  • NTTと三菱電機が開発し、特許を保有している。
  • 2006/4/13より、特許使用契約不要、リファレンス実装がオープンソースに。
  • ブロック暗号。ブロック長は128ビット。鍵長は128、192、256ビットから選べる。
  • 速い、らしい。
  • AESと同等の速度、安全性。
  • S/MIME、XML、SSL/TLS、IPsec用標準暗号

ライセンスについて

BSD風ライセンスです。当社が記述した部分については当社に著作権があります(いちおう)。詳しくはソース自体をご覧下さい。オリジナルはBSD風、GPL、MPL風、OpenSSL風から選べるという贅沢ななものですが、今回はBSD風版のCのソースを見ながら書いたので、BSD風に固定です。オリジナル、なぜかライセンスごとにソースファイルが別々なんですよ。コード自体は同じ物のようなんですが。1つのソースの頭に複数のライセンスを書いておけばいいのに。

このあとやること

  • 暗号化モード(CBCとか)
  •  PyCrypto互換API
  • チューニング
  • C版をそのままネイティブモジュール化してみる
  • __doc__文字列をもう少しまともにする。

感想など

作業時間は5時間程度。32ビットのシフト、ローテート演算で悩んでしまいました。初歩的…と言われるかもしれませんが、Pythonは32ビットのビット演算が苦手なんです。苦手というか、intが32ビットである、あるいは32ビットでの演算が効率的ということを仮定するのはPython流ではない。いろいろ悪あがきをしましたが、結局、わりきって全部長整数で演算するのが一番速かったです。

Python 2.3では、

>>> 0x80000000
<stdin>:1: FutureWarning: hex/oct constants > sys.maxint will return positive va
lues in Python 2.4 and up
-2147483648
>>> 1<<31
__main__:1: FutureWarning: x<<y losing bits or changing sign will return a long 
in Python 2.4 and up
-2147483648
>>>

Python 2.4では、

>>> 0x80000000
2147483648L
>>> 1<<31
2147483648L
>>>

特にこのように、Pythonの2.3と2.4とでは、32ビット整数の場合のMSB1であるような整数の取り扱いが異なります。2.4では、小さい整数(32ビット整数)と長整数の区別が無く、必要に応じて使い分けられるそうです。アセンブラとかCとかからこの業界に入った者としては、どうも居心地が悪いですが、仕方ありません。ごちゃごちゃ考えてややこしい計算で高速化しようという悪あがきは、Pythonでは無駄というより逆効果です。具体的な対策は、全ての定数にLをつけるだけです。Python 2.4では無意味ですが、Python 2.3では必要です。

鍵生成(Ekeygen())での、定数表を使ったループ演算は、べた書きに変更しました。この方が見通しが明るい。ただ、タプルの足し算をたくさんやっているのが、効率の点で気になります。たぶん、タプルのオブジェクトを作っては壊すを繰り返してるんですよ。鍵生成はそんなにたくさんやることではないから、許してください。

暗号化と複合化のややこしいループも、べた書きに展開しました。かなりわかりやすくなったはずです。暗号の仕組みがちょっと見えた気がします。feistelの「-2オフセット」なんてのはCならではであって、Pythonではできないので、feistel1()feistel2()の二つを作って使い分けています。

開発の過程でJava版も読みましたが、Java版は作りがいまいちな気がします。C版を逐語訳した感じです。鍵長128ビットにしか対応していませんし。個人的にはJavaは得意ではないので憶測ですが、もう少しJavaらしい書き方があるんじゃないでしょうか。ただ、もしかしたら、携帯電話のJavaなど、ライブラリやリソースに制限がある環境で使用することを考えてのことかもしれませんね。NTTの方々は、タブ=4のようです。タブ=8で見ると、タブと空白の混在でインデントが壊れてます。タブ=8にするか、全部空白に変換しておいて欲しかった。

リンク

作った人

たいしたことはやっていませんが、いちお、連絡先。sgk あっとまーく accense.comです。