11.1. Paillier Encryption#

import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np

from aijack.defense.paillier import (
    PaillierKeyGenerator,
    PaillierTensor,
)
/usr/local/lib/python3.10/dist-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm
/usr/local/lib/python3.10/dist-packages/torchvision/io/image.py:13: UserWarning: Failed to load image Python extension: '/usr/local/lib/python3.10/dist-packages/torchvision/image.so: undefined symbol: _ZN3c104cuda20CUDACachingAllocator9allocatorE'If you don't plan on using image functionality from `torchvision.io`, you can ignore this warning. Otherwise, there might be something wrong with your environment. Did you have `libjpeg` or `libpng` installed before building `torchvision` from source?
  warn(
keygenerator = PaillierKeyGenerator(512)
pk, sk = keygenerator.generate_keypair()

11.1.1. Basics#

ct_1 = pk.encrypt(13)
assert sk.decrypt2int(ct_1) == 13

ct_2 = ct_1 * 2
assert sk.decrypt2int(ct_2) == 26

ct_3 = ct_1 + 5.6
np.testing.assert_array_almost_equal(sk.decrypt2float(ct_3), 18.6, decimal=6)

ct_4 = ct_1 + ct_3
np.testing.assert_array_almost_equal(sk.decrypt2float(ct_4), 31.6, decimal=6)

11.1.2. PyTorch - Tensor#

ct_1 = pk.encrypt(13)
ct_2 = pk.encrypt(0.5)
ct_3 = ct_1 + ct_2

pt_1 = PaillierTensor([ct_1, ct_2, ct_3])
torch.testing.assert_close(
    pt_1.decrypt(sk), torch.Tensor([13, 0.5, 13.5]), atol=1e-5, rtol=1
)

pt_2 = pt_1 + torch.Tensor([0.4, 0.1, 0.2])
torch.testing.assert_close(
    pt_2.decrypt(sk), torch.Tensor([13.4, 0.6, 13.7]), atol=1e-5, rtol=1
)

pt_3 = pt_1 * torch.Tensor([1, 2.5, 0.5])
torch.testing.assert_close(
    pt_3.decrypt(sk), torch.Tensor([13, 1.25, 6.75]), atol=1e-5, rtol=1
)

pt_4 = pt_1 - torch.Tensor([0.7, 0.3, 0.6])
torch.testing.assert_close(
    pt_4.decrypt(sk), torch.Tensor([14.3, 0.2, 12.9]), atol=1e-5, rtol=1
)

pt_5 = pt_1 * 2
torch.testing.assert_close(
    pt_5.decrypt(sk), torch.Tensor([26, 1, 27]), atol=1e-5, rtol=1
)

11.1.3. PyTorch - NN#

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(10, 5)
        self.fc2 = nn.Linear(5, 2)

    def forward(self, x):
        x = self.fc1(x)
        x = self.fc2(x)
        return x
model = Net()
data = list(range(10))
tensor = torch.Tensor([data])

encrypted_data = [pk.encrypt(d) for d in data]
encrypted_tensor = PaillierTensor([encrypted_data])
model(tensor)
tensor([[ 1.8293, -2.0024]], grad_fn=<AddmmBackward0>)
model(encrypted_tensor).decrypt(sk)
tensor([[ 1.8293, -2.0024]])