Download - 汎用性と高速性を目指したペアリング暗号ライブラリ mcl
汎用性と高速性を目指したペアリング暗号ライブラリ mcl
SCIS 2017
サイボウズ・ラボ株式会社
光成滋生
• ペアリング
• ベンチマーク
• mclの設計
• ベンチマーク詳細
• まとめ
概要
2 / 20
• 巡回群𝐺1, 𝐺2, 𝐺𝑇に対する双線形写像𝑒: 𝐺1 × 𝐺2 → 𝐺𝑇
• 𝑒 𝑎𝑃, 𝑏𝑄 = 𝑒 𝑃, 𝑄 𝑎𝑏 for 𝑎, 𝑏 ∈ ℤ
• それぞれの群の離散対数問題が困難
• IDベース暗号、属性ベース暗号、内積暗号などの応用
• ブロックチェーン関係でも注目されている
• Zcash ; 完全匿名可能な分散型暗号通貨
• ゼロ知識証明プロトコルzk-SNARKを利用
• DFINITY ; decentralized world compute cloud
• 検証可能な秘密分散機能を持つBLS署名を利用
ペアリング
3 / 20
• 𝐹𝑝上の楕円曲線 𝐸 ∶ 𝑦2 = 𝑥3 + 𝑏
• 𝑝 = 36𝑧4 + 36𝑧3 + 24𝑧2 + 6𝑧 + 1, 𝑛 = 𝑝 + 1 − (6𝑧2 + 1)
• 𝐺1 = 𝐸 𝐹𝑝 𝑛
• 𝐺2 = 𝜓−1(𝐸 𝑛 ∩ Ker 𝜋𝑝 − 𝑝 ) where 𝜓:𝐸′ → 𝐸 ; twist
• 𝐺𝑇 ; 𝐹𝑝12の1の𝑛乗根の部分群
• 𝑒: 𝐺2 × 𝐺1 → 𝐺𝑇
• 特徴
• 𝑝が256bit程度なら100bitのセキュリティ
• さまざまな高速アルゴリズム、実装が提案されている
BN曲線上のoptimal Ateペアリング
4 / 20
• ベンチマーク(単位 : msec)
• x64/x86 ; Inte Core i7-6700 3.4GHz(Skylake)
• ARM ; 900MHz quad-core ARM Cortex-A7 on Raspberry Pi2
• ARM64 ; 1.2GHz ARM Cortex-A53 on HiKey
• 問題点
• 高速なものは特定のCPU専用
• 汎用的なものは速くない
既存実装
software x64 x86 ARM ARM64
ate-pairing 0.21 - - -
NEON - - 16 -
RELIC 0.30 3.5 36 -
TEPLA 1.76 3.7 37 17.9
5 / 20
• 汎用性と高速性を目指したペアリングライブラリ
• https://github.com/herumi/mcl/
• x86/x64, ARM, ARM64 Linux, Windows, macOS対応
• LLVMがサポートするアーキテクチャで動作(するはず)
• ベンチマーク(単位 : msec)
• 詳細はhttps://github.com/herumi/mcl/#benchmark
mcl
software x64 x86 ARM ARM64
ate-pairing 0.21 - - -
NEON - - 16 -
RELIC 0.30 3.5 36 -
TEPLA 1.76 3.7 37 17.9
mcl 0.31 1.6 22.6 4.0
6 / 20
• メモリの動的確保をしない
• C++ templateによる使いやすいクラス
• Montogomery乗算などをLLVM bitcodeを用いて記述
• bitcodeは独自DSL on C++から自動生成
mclの設計
7 / 20
• 素体クラスFpの元(インスタンス)のメモリ配置
• ヒープ方式(GMPのmpz_class, TEPLAなど)
• インスタンスごとにメモリを確保し不要になったら解放する
• データサイズを自由に変更可能
• メモリ操作のオーバーヘッド
• 内包方式
• インスタンスにデータを保持する
• メモリ操作が不要
• データサイズは固定
• mclは内包方式を採用
メモリの動的確保をしない
256bitデータ
ポインタ サイズメモリ確保
インスタンス
インスタンス
256bitデータ
8 / 20
• 演算子オーバーロード
• Fpの元x, yに対してx + y, x *= yなどの表記を使いたい
• 問題点
• ‘x + y’にはpが明示されないが計算にはpの値が必要
• なんらかの方法でpを参照しなければならない
使いやすく高速な素体クラスFp
9 / 20
• 各元がpへのポインタを保持する(TEPLA)
• ポインタの分だけインスタンスサイズが増える
• クラス固定にする(mcl)
• コンパイル時に確定
• 各インスタンスはpへのポインタを保持しない
pの参照方法(1/2)
p
ポインタ
z
ポインタ
y
ポインタ
x
zyx
p
10 / 20
• ペアリング演算には複数の素体が登場する
• 楕円曲線の定義体𝐹𝑝, 巡回群の位数を扱う𝐹𝑟など
• 問題点
• pの参照方法をクラス固定すると決定すると素体は一つしか扱えない?
• 解決方法
• 素体をC++のtemplate classとしタグによる区別を行う
• インスタンスサイズをふやさずに複数の素体を共存可能
複数の素体の共存
zyx
p r
Fpの元 Frの元
11 / 20
• pへの参照はコンパイル時に解決
• 実行時の参照オーバーヘッドが少ない
• 複数の素体同士の計算はコンパイル時にエラー
• TEPLAでは素体は全て同じElementクラス
• 異なる素体の元を間違えて演算しても分からない
タグディスパッチによる実装の利点
struct FpTag; // 空定義でよいstruct FrTag;typedef FpT<fpTag> Fp;typedef FpT<frTag> Fr; // 好きなだけ定義できるFp x, y;Fr z;x += y;z *= z;x += z; // コンパイルエラー
12 / 20
• 素体クラスの演算性能はペアリングの演算性能に直結
• 高速なものが望ましい
• 標準C/C++では高速なコードは記述できない
• アセンブリ言語を使用する
• 特定のCPU・OSに依存しやすくなる
• LLVM
• プログラム言語開発に使われるコンパイラやツールチェインの開発基盤
• 独自の仮想機械とその表現(bitcode)を持つ
• 多様なCPUの専用命令への変換機能を持つ
• x86/x64/ARM/ARM64/MIPS/MIPS64/PowerPC/, ...
• LLVMのbitcodeを用いて素体クラスの演算を実装
LLVMを用いた素体クラスの演算実装
13 / 20
• LLVM bitcodeによる実装
• llcを用いて各CPU専用のアセンブリコードを得る
• この程度の簡単な関数はほぼ最速のコードが生成される
(例)192bit加算関数
define void @add(i192* %pz,i192* %px,i192* %py){%x = load i192, i192* %px%y = load i192, i192* %py%z = add i192 %x, %ystore i192 %z, i192* %pzret void
}
関数定義 関数名 192bitレジスタへのポインタ引数
192bitレジスタへの読み込み192bit整数加算
192bit整数の書き込み
14 / 20
• 素体クラス演算の実装方針
• 標数のサイズごとに専用演算関数を実装
• 固定長サイズになり高速化しやすい
• Montgomery乗算は32bitと64bitとそれぞれに必要
• 問題点
• よく似た関数のLLVM bitcodeを多数実装しなければならない
• その他のLLVMのテクニカルな問題
• LLVMは静的単一代入(SSA)なので多数の変数が必要
• 全ての変数名に型が必要なため記述が煩雑
素体クラス演算のLLVM bitcode実装
15 / 20
• 素体クラス演算のDSL / C++からLLVM bitcodeを生成
• 一つのDSLを記述するだけでよいので開発効率が向上
LLVM bitcodeを出力するDSLの開発
DSLでFp:mulを記述
64bit CPU用mul256
64bit CPU用mul320
32bit CPU用mul256
...
mul256-x64
mul256-ARM64
mul256-ARM
mul256-x86
for (uint32_t i = 1; i < N; i++) {y = loadN(py, 1, i);xy = call(mulPvM[bit], px, y);t = add(t, xy);if (i < N - 1) {storeN(trunc(t, unit), pz, i);...
16 / 20
• x64環境(Skylake)
• GMP ; メモリ確保を伴わないmpn_系関数を用いた
• Xbyak ; ate-pairingの最速実装で使われているサブルーチン
• 単位 : clock cycle
• mul ; 256bit Montgomery乗算
• mulPre ; 256bit x 256bit → 512bit乗算
• red ; 512bit → 256bit Montgomery reduction
• LLVM版mulはGMPの3倍程度, Xbyak版の90%程度の性能
LLVMの性能評価(1/3)
演算 add sub mul mulPre red
GMP 22.3 18.8 190.2 44.2 108.6
LLVM 8.6 7.7 63.1(x3.0) 27.6 48.2
Xbyak 9.4 9.4 56.6(x3.4) 24.8 41.9
17 / 20
• x86/ARM/ARM64環境の違い
• ARM64環境はmulがGMPの2倍程度
• x86環境は1.3倍程度, ARM環境はほとんど変わらない
• 32bit環境で256bit乗算は固定長演算の利点が相対的に低い
• LLVMはレジスタあふれの扱いが弱い
LLVMの性能評価(2/3)
CPU 演算 add sub mul mulPre red
ARM64 GMP 74.0 71.5 597.2 269.5 353.9
LLVM 42.6 44.9 300.6(x1.99) 172.2 185.2
x86 GMP 54.0 29.7 744.8 153.7 415.8
LLVM 29.0 23.8 553.4(x1.35) 229.1 316.7
ARM GMP 157 89 2054 749 1260
LLVM 143 105 2103(x0.98) 747 1244
18 / 20
• x64環境におけるビット長の違い
LLVMの性能評価(3/3)
ビット長 関数 mulPre red mul
256 GMP 42.75 114.76 191.65
LLVM 27.59 47.00 64.36(x2.98)
320 GMP 61.55 150.85 265.69
LLVM 45.18 69.93 88.97(x2.98)
384 GMP 78.59 192.57 355.33
LLVM 62.06 91.17 128.57(x2.76)
448 GMP 104.89 237.21 453.02
LLVM 82.63 130.96 179.41(x2.52)
512 GMP 130.33 286.51 554.50
LLVM 149.13 202.89 313.51(x1.77)
19 / 20
• 汎用性と高速性を目指したペアリングライブラリmclを開発した
• x86/x64/ARM/ARM64, Linux, Windows, macOS対応
• 64bit環境でTEPLAの4~5倍、32bit環境で1.4~1.6倍の性能
• x64, ARM版の既存最速実装の67~70%の性能を達成
• 今後の課題
• 実アプリケーションに向けた使いやすいAPI, ドキュメント
• よりセキュリティビットの高いペアリングの実装
まとめと今後の課題
20 / 20