AES-GCM 暗号が作れた
AESとGCMどちらも実装をしてみていたが、GCMの仕様が読みにくかったので進んでいなかった。
AESは前回からあまり変わらず適度に速いので、GCMの速度をどれくらいまで上げられるか、の前にGCMを実装できるのか? というところから。
GCMはほぼCTR Mode とハッシュ計算で認証コードの計算をするだけの組み合わせなので、CTRを若干修正したものとIVなどの初期化ができればやや完成、となる。
- やや難解な初期化
- CTRモード
- 認証タグの計算いろいろ
- AADの計算
- ガロアさんの計算をビット反転で
テストパターンをみつけてやる気を出して、なんとか完了。速度的には低下なし。本体のCTRっぽい計算のあと、認証タグの計算を別スレッドに分けてみた。2スレッドに分けることでAES-NIは使ってないのに1.5Gbpsくらいは出ていてJava標準のより速い。という結果が出てしまった。
GCM は CTRの拡張っぽい構造でストリーム暗号。本体の GCTR? とハッシュ値計算のGHASH に分けて作ったりすると楽か。スレッド分けは、本体データをハッシュ計算用にメモリに蓄積しながら本文の暗号を行う。ハッシュ計算用のスレッドが終わっていれば再始動する、くらいのものでうまく動く。スレッド間に挟むのはいつもの自作Packetなので読み書き別々にしても全読みしなければ多分問題なさそう。
基本的な高速化手法はAESもGCMも内部をlong型で64bit x 2 にすること。8bit x 16でやるよりXORが全然はやい。
GCTRとCTRの違いはIVのカウンタ部分が32bit固定になることぐらいでいいのかも。
IVの初期化は96bit 入力を使う、それ以外はGHASH で混ぜる、だがTLSでは96bit限定かもしれない。96bitの場合カウンタは乱数が入らないところからはじまる。計算された値はJ0っぽい値になる。
IVは最初の値をGHASH用に、次からGCTR用に使うのでCTRの初期値もひとつかふたつずれる。
GHASHの入力は内部で持つHから計算する、
ハッシュ計算用にAAD とかいう感じの暗号化しないヘッダ的なものを追加可能で本体は暗号化後の値で計算する。GHASHは2つを載せる前提の構造になっている。Paddingは単純な128bitまで0詰め。最後にAADと本体Cの2つのビット長を含める。ハッシュ値の計算はガロアっぽいGF(2^128)の掛け算だが一癖ありでビット列が逆の形で計算することになる。GHASHの初期値HだかLだかはAESで0を暗号化して作った値で毎回これを使い回すのでGCM初期化の段階で128パターンx2くり返したものを作成する。これを・Hで使うと高速化できる。まずデータと内部状態のxだかを⊕。これと掛け算 ・H していくことになるのでx2をくり返した128回分のものをあらかじめ作るとガロア体の再計算がなくなるので高速になる。
GCMのようなCCMもあるようなのでそちらも作ってみるか。
コメント
コメントを投稿