# CKKS Part1：普通编码和解码

## 介绍

CKKS使用多项式，因为与向量计算相比，它们在安全性和效率之间提供了良好的折衷。【也就是使用RLWE和LWE之间区别，RLWE更加安全和高效

## CKKS编码

CKKS利用整型多项式环的丰富结构实现其明文和密文空间。尽管如此，数据更多地以向量的形式出现，而不是以多项式的形式出现。

## 普通编码

### 实现

1、现在我们使用Python实现普通的编码和解码：

import numpy as np

# First we set the parameters
M = 8
N = M //2

# We set xi, which will be used in our computations（计算M次单位根）
xi = np.exp(2 * np.pi * 1j / M)
xi


from numpy.polynomial import Polynomial

class CKKSEncoder:
"""Basic CKKS encoder to encode complex vectors into polynomials."""

def __init__(self, M: int):
"""Initialization of the encoder for M a power of 2.

xi, which is an M-th root of unity will, be used as a basis for our computations（计算M次单位根）.
"""
self.xi = np.exp(2 * np.pi * 1j / M)
self.M = M

@staticmethod
def vandermonde(xi: np.complex128, M: int) -> np.array:
"""Computes the Vandermonde matrix from a m-th root of unity.（根据M次单位根计算范德蒙矩阵）"""

N = M //2
matrix = []
# We will generate each row of the matrix
for i in range(N):
# For each row we select a different root
root = xi ** (2 * i + 1)
row = []

# Then we store its powers
for j in range(N):
row.append(root ** j)
matrix.append(row)
return matrix

def sigma_inverse(self, b: np.array) -> Polynomial:
"""Encodes the vector b in a polynomial using an M-th root of unity（将向量编码为多项式）."""

# First we create the Vandermonde matrix
A = CKKSEncoder.vandermonde(self.xi, M)

# Then we solve the system
coeffs = np.linalg.solve(A, b)//得到系数

# Finally we output the polynomial
p = Polynomial(coeffs)//转为多项式形式
return p

def sigma(self, p: Polynomial) -> np.array:
"""Decodes a polynomial by applying it to the M-th roots of unity.（将多项式解码为向量）"""

outputs = []
N = self.M //2

# We simply apply the polynomial on the roots（只需将M次单位根的次幂代入多项式即可）
for i in range(N):
root = self.xi ** (2 * i + 1)
output = p(root)
outputs.append(output)
return np.array(outputs)


2、让我们先对一个实数向量进行编码：

# First we initialize our encoder（新建一个对象）
encoder = CKKSEncoder(M)

b = np.array([1, 2, 3, 4])
b


array([1, 2, 3, 4])

p = encoder.sigma_inverse(b)
p


3、现在让我们看看如何从多项式中提取我们最初得到的向量（解码）：

b_reconstructed = encoder.sigma(p)
b_reconstructed


np.linalg.norm(b_reconstructed - b)//误差范数


$$σ$$的同态性质是由于：$$X^{N}+1=0\; and\; \zeta ^{N}+1=0$$
4、我们现在可以开始对几个向量进行编码，看看如何对它们执行同态运算并对其进行解码。

m1 = np.array([1, 2, 3, 4])
m2 = np.array([1, -2, 3, -4])

p1 = encoder.sigma_inverse(m1)
p2 = encoder.sigma_inverse(m2)


$$p2=(-0.4999999999999997-3.3306690738754696e^{-16}j)+((-0.7071067811865472-9.43689570931383e^{-16}j))x+((2.4563684419831585e^{-15}-2.5j))x^2+((0.7071067811865475+1.8318679906315083e^{-15}j))x^3$$

p_add = p1 + p2


encoder.sigma(p_add)


5、因为在进行乘法运算时，我们可能会得到阶数大于N的项，我们需要使用$$X^N+1$$进行模运算。

poly_modulo = Polynomial([1,0,0,0,1])
poly_modulo


p_mult = p1 * p2 % poly_modulo
p


6、最后，如果我们解码它，我们可以看到我们得到了预期的结果。

encoder.sigma(p_mult)


posted @ 2022-01-31 12:40  PamShao  阅读(7180)  评论(16编辑  收藏  举报