콘텐츠로 이동

CKKS 부트스트랩 (Bootstrapping)

암호문은 생성시 잔여 곱셈 횟수가 설정이 되어있고 이후 곱셈을 할 때마다 결과물의 잔여 곱셈 횟수(level)가 줄어드는 방식입니다. 잔여 곱셈 횟수가 0인 암호문은 더이상 곱셈을 할 수 없고 부트스트래핑 연산을 해야합니다.

일반 부트스트랩

부트스트랩 연산에는 부트스트랩 키가 필요합니다. 부트스트랩 연산에 필요한 모든 고정 회전 키로 이루어져 있어서 크기가 12.3GB 정도입니다.

from desilofhe import Engine

engine = Engine(use_bootstrap=True)
secret_key = engine.create_secret_key()
public_key = engine.create_public_key(secret_key)
relinearization_key = engine.create_relinearization_key(secret_key)
conjugation_key = engine.create_conjugation_key(secret_key)
bootstrap_key = engine.create_bootstrap_key(secret_key, stage_count=3)

message = [-1, 0, 1]
ciphertext = engine.encrypt(message, public_key, level=0)
bootstrapped = engine.bootstrap(
    ciphertext, relinearization_key, conjugation_key, bootstrap_key
)

간이 부트스트랩 키

부트스트랩 키를 대신해 회전 키와 간이 부트스트랩 키를 사용해서도 부트스트랩을 수행할 수 있습니다. 회전 키를 사용하여 메모리 사용이 3.8GB 정도로 적지만 느립니다.

from desilofhe import Engine

engine = Engine(use_bootstrap=True)
secret_key = engine.create_secret_key()
public_key = engine.create_public_key(secret_key)
relinearization_key = engine.create_relinearization_key(secret_key)
conjugation_key = engine.create_conjugation_key(secret_key)
rotation_key = engine.create_rotation_key(secret_key)
small_bootstrap_key = engine.create_small_bootstrap_key(secret_key)

message = [-1, 0, 1]
ciphertext = engine.encrypt(message, public_key, level=0)
bootstrapped = engine.bootstrap(
    ciphertext,
    relinearization_key,
    conjugation_key,
    rotation_key,
    small_bootstrap_key,
)

bootstrapped_stage_count_5 = engine.bootstrap(
    ciphertext,
    relinearization_key,
    conjugation_key,
    rotation_key,
    small_bootstrap_key,
    stage_count=5,
)

벤치마크

다음은 부트스트랩의 성능 벤치마크입니다. 실험환경은 CPU의 경우 Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz 을 사용하였고 GPU의 경우 NVIDIA GeForce RTX 5090를 사용하였습니다. 10번 측정한 값의 평균치입니다.

Key
Size
Stage
Count
Runtime (s)
1 Thread

4 Threads

16 Threads

GPU
Small 3 112.855 49.511 34.892 3.244
Small 4 72.206 30.261 21.456 2.087
Small 5 69.744 28.182 19.953 1.860
Medium 3 29.953 12.602 9.679 0.798
Medium 4 24.568 10.166 7.721 0.666
Medium 5 23.184 9.292 7.024 0.610
Large 3 27.919 11.707 9.410 0.775
Large 4 23.825 10.085 8.002 0.682
Large 5 21.833 8.843 6.805 0.605

희소 부트스트랩

희소 부트스트랩은 암호문의 슬롯 갯수를 줄여서 부트스트랩 속도를 빠르게 하는 기법입니다. 간이 부트스트랩 키를 사용하거나 부트스트랩 키를 생성해서 수행할 수 있습니다.

부트스트랩 키

from desilofhe import Engine

engine = Engine(slot_count=1024, use_bootstrap=True)
secret_key = engine.create_secret_key()
public_key = engine.create_public_key(secret_key)
relinearization_key = engine.create_relinearization_key(secret_key)
conjugation_key = engine.create_conjugation_key(secret_key)
bootstrap_key = engine.create_bootstrap_key(secret_key, stage_count=3)

message = [-1, 0, 1, 0] * 256
ciphertext = engine.encrypt(message, public_key, level=0)
bootstrapped = engine.bootstrap(
    ciphertext, relinearization_key, conjugation_key, bootstrap_key
)

간이 부트스트랩 키

from desilofhe import Engine

engine = Engine(slot_count=1024, use_bootstrap=True)
secret_key = engine.create_secret_key()
public_key = engine.create_public_key(secret_key)
relinearization_key = engine.create_relinearization_key(secret_key)
conjugation_key = engine.create_conjugation_key(secret_key)
rotation_key = engine.create_rotation_key(secret_key)
small_bootstrap_key = engine.create_small_bootstrap_key(secret_key)

message = [-1, 0, 1, 0] * 256
ciphertext = engine.encrypt(message, public_key, level=0)
bootstrapped = engine.bootstrap(
    ciphertext,
    relinearization_key,
    conjugation_key,
    rotation_key,
    small_bootstrap_key,
    stage_count=1,
)

벤치마크

다음은 희소 부트스트랩의 성능 벤치마크입니다. 실험환경은 CPU의 경우 Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz 을 사용하였고 GPU의 경우 NVIDIA GeForce RTX 5090를 사용하였습니다. 10번 측정한 값의 평균치입니다.

Slot
Count
Key
Size
Stage
Count
Runtime (s)
1 Thread

4 Threads

16 Threads

GPU
32 Small 1 43.691 16.939 11.995 0.958
32 Small 2 32.765 12.445 8.973 0.715
32 Medium 1 26.860 10.705 7.842 0.601
32 Medium 2 25.064 10.038 7.174 0.563
32 Large 1 26.677 10.675 7.947 0.608
1024 Small 2 71.156 27.944 19.692 1.621
1024 Small 3 49.461 18.887 13.523 1.115
1024 Small 4 45.306 17.388 12.363 1.030
1024 Medium 2 29.124 11.797 8.873 0.713
1024 Medium 3 25.419 10.089 7.478 0.609
1024 Medium 4 23.737 9.517 6.942 0.586
1024 Large 2 27.490 11.422 8.808 0.698
1024 Large 3 24.107 9.995 7.500 0.615

손실 부트스트랩

손실 부트스트랩은 부트스트랩 내부 연산 순서를 변경하여서 노이즈가 증가하는 대신 빠른 속도를 얻는 기법입니다. 결과물의 소수점 유효자리가 대강 절반 정도 줄어듭니다. 일반적으로는 일반 부트스트랩의 사용이 권장됩니다만 필요한 정확도에 따라서 의미가 있을 수도 있습니다. 간이 부트스트랩 키를 사용하거나 손실 부트스트랩 키를 생성해서 수행할 수 있습니다.

손실 부트스트랩 키

from desilofhe import Engine

engine = Engine(use_bootstrap=True)
secret_key = engine.create_secret_key()
public_key = engine.create_public_key(secret_key)
relinearization_key = engine.create_relinearization_key(secret_key)
conjugation_key = engine.create_conjugation_key(secret_key)
lossy_bootstrap_key = engine.create_lossy_bootstrap_key(
    secret_key, stage_count=3
)

message = [-1, 0, 1]
ciphertext = engine.encrypt(message, public_key, level=3)
bootstrapped = engine.lossy_bootstrap(
    ciphertext, relinearization_key, conjugation_key, lossy_bootstrap_key
)

간이 부트스트랩 키

from desilofhe import Engine

engine = Engine(use_bootstrap=True)
secret_key = engine.create_secret_key()
public_key = engine.create_public_key(secret_key)
relinearization_key = engine.create_relinearization_key(secret_key)
conjugation_key = engine.create_conjugation_key(secret_key)
rotation_key = engine.create_rotation_key(secret_key)
small_bootstrap_key = engine.create_small_bootstrap_key(secret_key)

message = [-1, 0, 1]
ciphertext_level_3 = engine.encrypt(message, public_key, level=3)
bootstrapped = engine.lossy_bootstrap(
    ciphertext_level_3,
    relinearization_key,
    conjugation_key,
    rotation_key,
    small_bootstrap_key,
)

ciphertext_level_5 = engine.encrypt(message, public_key, level=5)
bootstrapped_stage_count_5 = engine.lossy_bootstrap(
    ciphertext_level_5,
    relinearization_key,
    conjugation_key,
    rotation_key,
    small_bootstrap_key,
    stage_count=5,
)

벤치마크

다음은 손실 부트스트랩의 성능 벤치마크입니다. 실험환경은 CPU의 경우 Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz 을 사용하였고 GPU의 경우 NVIDIA GeForce RTX 5090를 사용하였습니다. 10번 측정한 값의 평균치입니다.

Key
Size
Stage
Count
Runtime (s)
1 Thread

4 Threads

16 Threads

GPU
Small 3 88.473 39.457 28.426 2.994
Small 4 60.810 25.715 18.462 1.946
Small 5 60.956 25.286 17.898 1.763
Medium 3 27.058 11.120 8.460 0.743
Medium 4 23.013 9.275 7.074 0.632
Medium 5 21.614 8.803 6.587 0.583
Large 3 24.660 10.575 8.288 0.736
Large 4 22.537 9.248 7.324 0.643
Large 5 20.418 8.476 6.422 0.586

손실 부트스트랩의 경우 실수값만 있는 암호문에 대해서 좀 더 빨리 수행됩니다.

Key
Size
Stage
Count
Runtime (s)
1 Thread

4 Threads

16 Threads

GPU
Small 3 81.182 36.468 26.231 2.816
Small 4 54.158 22.795 16.481 1.764
Small 5 54.706 22.387 15.977 1.573
Medium 3 19.560 8.181 6.291 0.546
Medium 4 15.120 6.534 5.056 0.436
Medium 5 15.980 6.428 4.778 0.419
Large 3 17.569 7.589 6.120 0.539
Large 4 15.494 6.545 5.313 0.455
Large 5 14.183 5.803 4.563 0.398

부호 부트스트랩

부호 부트스트랩은 손실 부트스트랩의 응용으로서 부호 메세지(-1 또는 1)를 높은 정밀도로 부트스트랩 할 수 있는 기법입니다. 부호 메세지밖에 부트스트랩 할 수 없는 대신, 결과물의 유효자리가 대강 3배 이상 늘어납니다. 부호 메세지에 대해서 효율적인 노이즈 제거가 가능하며, 이로 인해 min 과 max 같은 비교 연산을 빠르고 정밀하게 수행할 수 있게 도와줍니다. 간이 부트스트랩 키를 사용하거나 손실 부트스트랩 키를 생성해서 수행할 수 있습니다.

손실 부트스트랩 키를 이용한 부호 부트스트랩

from desilofhe import Engine

engine = Engine(use_bootstrap=True)
secret_key = engine.create_secret_key()
public_key = engine.create_public_key(secret_key)
relinearization_key = engine.create_relinearization_key(secret_key)
conjugation_key = engine.create_conjugation_key(secret_key)
lossy_bootstrap_key = engine.create_lossy_bootstrap_key(
    secret_key, stage_count=3
)

message = [-1, 1]
ciphertext = engine.encrypt(message, public_key, level=3)
bootstrapped = engine.sign_bootstrap(
    ciphertext, relinearization_key, conjugation_key, lossy_bootstrap_key
)

간이 부트스트랩 키

from desilofhe import Engine

engine = Engine(use_bootstrap=True)
secret_key = engine.create_secret_key()
public_key = engine.create_public_key(secret_key)
relinearization_key = engine.create_relinearization_key(secret_key)
conjugation_key = engine.create_conjugation_key(secret_key)
rotation_key = engine.create_rotation_key(secret_key)
small_bootstrap_key = engine.create_small_bootstrap_key(secret_key)

message = [-1, 1]
ciphertext_level_3 = engine.encrypt(message, public_key, level=3)
bootstrapped = engine.sign_bootstrap(
    ciphertext_level_3,
    relinearization_key,
    conjugation_key,
    rotation_key,
    small_bootstrap_key,
)

ciphertext_level_5 = engine.encrypt(message, public_key, level=5)
bootstrapped_stage_count_5 = engine.sign_bootstrap(
    ciphertext_level_5,
    relinearization_key,
    conjugation_key,
    rotation_key,
    small_bootstrap_key,
    stage_count=5,
)

부호 메세지 부트스트랩 오차

다음은 일반, 손실, 부호 부트스트랩을 각각 이용하여, 부호 메세지(-1 또는 1)를 부트스트랩할 때 발생하는 평균 오차입니다. 부호 메시지에 대해서는 일반 부트스트랩과 손실 부트스트랩의 정밀도가 유사하게 측정되지만, 메시지 구간이 전체 [-1, 1]일 경우에는 일반 부트스트랩이 더 높은 정밀도를 보입니다.

Regular
Bootstrap
Lossy
Bootstrap
Sign
Bootstrap
Average error 1.60562e-3 1.60562e-3 3.10572e-10

벤치마크

다음은 부호 부트스트랩의 성능 벤치마크입니다. 실험환경은 CPU의 경우 Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz 을 사용하였고 GPU의 경우 NVIDIA GeForce RTX 5090를 사용하였습니다. 10번 측정한 값의 평균치입니다.

Key
Size
Stage
Count
Runtime (s)
1 Thread

4 Threads

16 Threads

GPU
Small 3 90.156 40.110 28.902 3.010
Small 4 62.716 26.354 18.871 1.954
Small 5 62.520 25.710 18.166 1.749
Medium 3 28.490 11.804 8.920 0.751
Medium 4 24.785 9.980 7.494 0.643
Medium 5 23.152 9.552 6.992 0.594
Large 3 26.978 11.193 8.767 0.746
Large 4 24.212 10.027 7.755 0.654
Large 5 21.975 9.037 6.800 0.591

부호 부트스트랩의 경우 실수값만 있는 암호문에 대해서 좀 더 빨리 수행됩니다.

Key
Size
Stage
Count
Runtime (s)
1 Thread

4 Threads

16 Threads

GPU
Small 3 83.431 36.998 26.711 2.805
Small 4 54.858 23.234 16.717 1.756
Small 5 55.208 22.943 16.296 1.579
Medium 3 20.354 8.515 6.547 0.559
Medium 4 17.047 6.906 5.291 0.449
Medium 5 16.954 6.703 5.015 0.425
Large 3 18.636 7.825 6.389 0.542
Large 4 16.413 6.971 5.543 0.464
Large 5 15.217 6.160 4.752 0.408