[TenSEAL] Tutorial 2 : Working with Approximate Numbers
CKKS에 대한 자세한 소개는 다음을 참고한다.
https://blog.openmined.org/ckks-explained-part-1-simple-encoding-and-decoding/
1. Theory : CKKS
Cheon-Kim-Kim-Song (CKKS)는 leveled 동형 암호 스킴으로 real numbers에 대해 approximate arithmetics을 지원한다. 간단한 구조는 다음과 같다.
CKKS parameter는 크게 3가지가 있다.
- Scaling factor
- Polynomial modulus degree
- Coefficient modulus size
Scaling factor
Vector of real number를 plaintext polynomial로 encoding하는 과정이 필요하다.
$$ 1.01011 = 101011 * 2^{-5} $$
Polynomial modulus degree
그림에서 $N$을 의미하며 다음의 관계가 있다.
- number of coefficients in plaintext polynomial
- size of ciphertext elements
- computational performance of the scheme (bigger is worse)
- security level (bigger is better)
TenSEAL에서 $N$은 2의 거듭제곱 형태로만 가능하다. (1024, 2048, 4096 , ...)
Coefficient modulus size
List of binary size로 이 list를 이용해 SEAL이 list of primes를 생성한다. 그림에서는 $q$를 의미한다. 다음의 관계를 가진다.
- size of ciphertext elements
- length of the list = level of the scheme = number of encrypted multiplication supported
- security level (bigger is worse)
TenSEAL에서 계수 모듈러스의 각 소수는 최대 60비트여야 하며 1 mod 2*poly_modulus_degree와 일치해야 한다. 다시 말하면 prime을 2*$N$으로 mod 연산을 수행했을 때, 나머지가 1이어야 한다는 의미이다.
CKKS key는 크게 4가지 종류가 있다.
- Secret key
- Decryption에 사용됨 / No share
- Public encryption key
- Encryption에 사용
- Relinearization key
- 새로운 ciphertext의 크기는 2임
- $K$와 $L$ 크기의 ciphertext를 곱하면, $K+L-1$이 됨
- size가 커지면 연산 속도가 느려짐
- Relinearization을 통해 크기를 2로 다시 줄임
- 이를 수행하기 위해서는 secret key에 의해 생성된 pulbic key, relinearization key가 필요함
- Galois key (optional)
- vector의 회전 및 복제를 위한
CKKS 내부 operation은 크게 2가지가 있다.
- Relinearization
- TenSEAL에서는 encrypted multiplication 이후에 자동으로 수행
- 암호문의 크기를 2로 줄이는 과정
- $K+1$의 encrypted ciphertext를 relinearization하기 위해서는 $K-1$의 relinearization key가 필요함
- Rescaling
- TenSEAL에서는 encrypted나 plain multiplication 이후에 자동으로 수행
- Approximation error는 지수적으로 커짐. 이를 해결하기 위해 대부분의 HE 스킴은 modulus-switching을 사용함. CKKS의 경우에는 rescaling을 수행함. Rescaling 알고리즘을 통해 error는 선형적으로 커짐
- $q_1, ..., q_k$로 modulo된 encrypted ciphertext가 주어지면, $q_1, ..., q_{k-1}$로 modulo down하고 message를 scale down함
- 이 operation은 coefficient modulus로부터 하나의 prime을 소모하기 때문에, 다 쓰면 더 이상 곱셈을 수행할 수 없음.
2. TenSEAL CKKS
우선적으로 수행할 것은 CKKS TenSEAL context를 만드는 것이다.
def context():
context = ts.context(
ts.SCHEME_TYPE.CKKS, # scheme
8192, # poly modulus degree
coeff_mod_bit_sizes=[60, 40, 40, 60])
# coefficient modulus size
# 4 primes of 60, 40, 40, 60 bits
# 2 multiplication supported
context.global_scale = pow(2, 40) # scaling factor
context.generate_galois_keys()
return context
context = context()
모델 학습을 위해서 tensor를 만들어야 한다. TenSEAL에서 지원하는 구조는 다음과 같다.
우선 plain tensor를 만드는 방법은 다음과 같다.
plain1 = ts.plain_tensor([1,2,3,4], [2,2])
print(" First tensor: Shape = {} Data = {}".format(plain1.shape, plain1.tolist()))
plain2 = ts.plain_tensor(np.array([5,6,7,8]).reshape(2,2))
print(" Second tensor: Shape = {} Data = {}".format(plain2.shape, plain2.tolist()))
Encrypt하기 전에 ckks에서 암호화와 복호화를 어떻게 진행하는지 알아보자.
2.1. CKKS encoding + decoding
Complex나 real number를 plaintext polynomial로 encoding하는 과정이 필요하다.
만약 polynomial modulus degree가 $N$이면, $N/2$개의 complex number가 plaintext elements로 변환될 수 있다. 또한 slot-wise 연산을 지원하지 때문에, SIMD가 가능하다. 그림으로 나타내면 다음과 같다.
2.2. CKKS encryption + decryption
Plaintext로 변환했으면, 이제 ckks로 암호화할 수 있다.
TenSEAL에서 만들 수 있는 element는 3개 정도이다.
- BFVvector : 1D integer array
- CKKSvector : 1D float array
- CKKStensor : N-dimensional float array
코드는 다음과 같다.
encrypted_tensor1 = ts.ckks_tensor(context, plain1)
encrypted_tensor2 = ts.ckks_tensor(context, plain2)
print(" Shape = {}".format(encrypted_tensor1.shape))
print(" Encrypted Data = {}.".format(encrypted_tensor1))
encrypted_tensor_from_np = ts.ckks_tensor(context, np.array([5,6,7,8]).reshape([2,2]))
print(" Shape = {}".format(encrypted_tensor_from_np.shape))
였는데 TenSEAL은 마지막 commit이 2년전으로 MS에서 버린 것 같으니 다른거 공부한다
'잡기술 > Homomorphic Encryption' 카테고리의 다른 글
[TenSEAL] Tutorial 1 : Training and Evaluation of Logistic Regression on Encrypted Data (0) | 2024.07.02 |
---|