🧮

準同型暗号CKKSその2 エンコードとデコード

2023/08/02に公開

初めに

前回、多項式環とベクトル空間の同型対応を紹介しました。今回はそれを使ってCKKSの平文空間、およびエンコード・デコードという処理を紹介します。

前回の復習

Mを4以上の2のべきの形の整数、\xi:=e^{2\pi i/M}, N:=M/2としたときσ:ℂ[X]/(X^N+1) \rightarrow ℂ^Nσ(f):=(f(\xi), f(\xi^3), \dots, f(\xi^{2N-1}))で定義し、それが環同型となっていることを示しました。ℂ[X]/(X^N+1)N-1次以下の多項式の集合と同一視しておきます。

複素共役

複素数z=a+bia,b \in ℝ)に対して、複素共役(きょうやく)をconj(z):=a-biと書きます。複素共役は複素平面のx軸に対する線対称の操作です。markdownでチルダ\tilde{z}は表記しづらいのでconjを使います。
複素数z, wの和や積の複素共役はそれぞれの複素共役です。

\begin{align*} conj(z+w)&=conj(z)+conj(w),\\ conj(zw)&=conj(z)conj(w). \end{align*}

実数aの複素共役は変化しません。

conj(a)=a.

さて、\xiについてconj(\xi)=\xi^{M-1}です。よってconj(\xi^u)=\xi^{M-u}です。
前回の1の8乗根の例を見ても、

\begin{align*} conj(\xi)&=\xi^7,\\ conj(\xi^2)&=\xi^6,\\ conj(\xi^3)&=\xi^5,\\ conj(\xi^4)&=\xi^4 \end{align*}

を確認できます。

実数係数多項式環

fが実数係数多項式ならconj(f(\xi^{2j-1}))=f(conj(\xi^{2j-1}))=f(\xi^{M-2j+1})です。だからσ(f)=(f(\xi^{2j-1}))_{j=1,\dots,N}N次元ベクトルですが、後半N/2個の要素は前半のN/2個の要素を逆順にして複素共役をとったものです。つまり情報としては前半のN/2個で十分です。

実係数多項式fについてのσ(f)
実係係数多項式の像

逆に、一般の複素数係数多項式f \in ℂ[X]/(X^N+1)
条件(real-cond) : conj(f(\xi^{2j-1}))=f(\xi^{M-2j+1}) for j=1,\dots,N/2
を満たすとf \in ℝ[X]/(X^N+1)です。
なぜなら任意のf(X) \in ℂ[X]/(X^N+1)は、ある実数係数多項式g, h \in ℝ[X]/(X^N+1)を使ってf(X)=g(X)+ih(X)と書けます。t:=2j-1とすると、

conj(f(\xi^t))=conj(g(\xi^t)+ih(\xi^t))=g(\xi^{M-t})-ih(\xi^{M-t}).

ここで条件(real-cond)より

conj(f(\xi^t))=f(\xi^{M-t})=g(\xi^{M-t})+ih(\xi^{M-t}).

両者が等しいのでh(\xi^{M-t})=0. 複素共役をとればh(\xi^t)=0. これがt=1,3,\dots,N-1で成り立つのでh(X)=0. これはf \in ℝ[X]/(X^N+1)を意味します。

そこで、ℂ^Nの前半だけを取り出す写像を定義します。

π: ℂ^N \ni (z_1, \dots, z_N) \mapsto (z_1, \dots, z_{N/2}) \in ℂ^{N/2}.

この逆写像は一意には決まりませんが、前半分から後ろ半分を逆順の複素共役で復元する写像を

π^{-1}: ℂ^{N/2} \ni (z_1,...,z_{N/2}) \mapsto (z_1,...,z_{N/2}, conj(z_{N/2}), .., conj(z_1)) \in ℂ^N

と定義します。すると先程の議論によりσ(ℝ[X]/(X^N+1))の要素は条件(real-cond)を満たし、逆に条件(real-cond)を満たすf \in ℂ[X]/(X^N+1)f \in ℝ[X]/(X^N+1)なのでH:=π^{-1}(ℂ^{N/2}) \subseteq ℂ^Nとするとσ(ℝ[X])=Hです。
関係がややこしくなったので図示すると

ℂ[X]ℝ[X]の関係
CとRの関係

CKKSの平文空間とエンコード・デコード

ようやくCKKSの平文空間を定義する準備が出来ました。R:=ℤ[X]/(X^N+1)とします。Rは整数係数多項式をX^N+1で割った余りの集合です。RがCKKSの平文空間です。
実はCKKSは厳密な準同型暗号ではなく、近似準同型暗号というもので、暗号化して復号すると元の値から少しずれます。加算や乗算でも誤差がでます。
暗号化する準備で発生する誤差を制御するための値をスケール因子Δといいます。小数xを整数に丸めたものを[x]と書き、より一般に多項式fの各係数を整数に丸めたものも[f]と書くことにします。
暗号化したい複素N/2次元ベクトルz \in ℂ^{N/2}をとり、f:=σ^{-1}(\pi^{-1}(z))とします。前節の図で右端の要素を左端の空間に持ってきます。
fは実数係数多項式で、それをスケール因子Δ倍して係数を整数に丸めたもの[Δf] \in Rを得る操作をエンコードといいます。

Ecd : ℂ^{N/2} \ni z \mapsto [Δσ^{-1}(\pi^{-1}(z))] \in R=ℤ[X]/(X^N+1).

逆に平文空間Rの多項式fに対して\pi(σ(Δ^{-1}f)) \in ℂ^{N/2}を得る操作をデコードといいます。

Dcd : R=ℤ[X]/(X^N+1) \ni f \mapsto \pi(σ(Δ^{-1}f)) \in ℂ^{N/2}.

エンコードとデコードは扱いたいN/2次元ベクトルをCKKSの平文空間Rに移したり、元に戻したりする操作であって、暗号化・復号ではないことに注意してください。
また、エンコードの際に丸め処理が入っているのでエンコードしてデコードしても完全に元に戻るとは限らないことにも注意してください。スケール因子Δを大きくとれば、その誤差を小さくできます。

まとめ

CKKSの平文空間R=ℤ[X]/(X^N+1)を定義しました。ℂ^{N/2}と実数係数多項式の集合R=ℤ[X]/(X^N+1)との関係を調べ、それらの間を行ったり、来たりするエンコードとデコードを定義しました。

GitHubで編集を提案

Discussion