def __init__(self, context):
     """
     Class providing decryption operation
     :param context: Context initialising HE parameters
     """
     self.context = context.context
     self.secret_key = context.secret_key
     self.decryptor = Decryptor(self.context, self.secret_key)
     self.encoder = FractionalEncoder(self.context.plain_modulus(),
                                      self.context.poly_modulus(), 64, 32,
                                      3)
     self.evaluator = context.evaluator
 def __init__(self, context: FracContext):
     """
     Class providing encoding and encryption operations, operations over
     encrypted data
     :param context: Context initialising HE parameters
     """
     self.context = context.context
     self.public_key = context.public_key
     self.encryptor = Encryptor(self.context, self.public_key)
     self.encoder = FractionalEncoder(self.context.plain_modulus(),
                                      self.context.poly_modulus(), 64, 32,
                                      3)
     self.evaluator = context.evaluator
     self.ev_keys = EvaluationKeys()
     context.keygen.generate_evaluation_keys(seal.dbc_max(), self.ev_keys)
Beispiel #3
0
def seal_obj():
    # params obj
    params = EncryptionParameters()
    # set params
    params.set_poly_modulus("1x^4096 + 1")
    params.set_coeff_modulus(seal.coeff_modulus_128(4096))
    params.set_plain_modulus(1 << 16)
    # get context
    context = SEALContext(params)
    # get evaluator
    evaluator = Evaluator(context)
    # gen keys
    keygen = KeyGenerator(context)
    public_key = keygen.public_key()
    private_key = keygen.secret_key()
    # evaluator keys
    ev_keys = EvaluationKeys()
    keygen.generate_evaluation_keys(30, ev_keys)
    # get encryptor and decryptor
    encryptor = Encryptor(context, public_key)
    decryptor = Decryptor(context, private_key)
    # float number encoder
    encoder = FractionalEncoder(context.plain_modulus(),
                                context.poly_modulus(), 64, 32, 3)
    return evaluator, encoder.encode, encoder.decode, encryptor.encrypt, decryptor.decrypt, ev_keys
Beispiel #4
0
    def decrypt(self, raw_data):
        if not self.initialized:
            self.log("Not initialized")
            return False

        # Setup the encoder
        encoder = FractionalEncoder(self.context.plain_modulus(), self.context.poly_modulus(), 64, 32, 3)
        
        # Unpickle, base64 decode, and decrypt each ciphertext result
        decrypted_data = []
        for d in raw_data:
            encrypted_data = pickle.loads( base64.b64decode(d) )
            plain_data = Plaintext()
            self.decryptor.decrypt(encrypted_data, plain_data)
            decrypted_data.append( str(encoder.decode(plain_data)) )

        return decrypted_data
    def __init__(self, matrix=None):
        """

        :param matrix: numpy.ndarray to be encrypted.
        """

        self.parms = EncryptionParameters()
        self.parms.set_poly_modulus("1x^2048 + 1")
        self.parms.set_coeff_modulus(seal.coeff_modulus_128(2048))
        self.parms.set_plain_modulus(1 << 8)

        self.context = SEALContext(self.parms)

        # self.encoder = IntegerEncoder(self.context.plain_modulus())
        self.encoder = FractionalEncoder(self.context.plain_modulus(),
                                         self.context.poly_modulus(), 64, 32,
                                         3)

        self.keygen = KeyGenerator(self.context)
        self.public_key = self.keygen.public_key()
        self.secret_key = self.keygen.secret_key()

        self.encryptor = Encryptor(self.context, self.public_key)
        self.decryptor = Decryptor(self.context, self.secret_key)

        self.evaluator = Evaluator(self.context)

        self._saved = False
        self._encrypted = False
        self._id = '{0:04d}'.format(np.random.randint(1000))

        if matrix is not None:
            assert len(
                matrix.shape) == 2, "Only 2D numpy matrices accepted currently"
            self.matrix = np.copy(matrix)
            self.encrypted_matrix = np.empty(self.matrix.shape, dtype=object)
            for i in range(self.matrix.shape[0]):
                for j in range(self.matrix.shape[1]):
                    self.encrypted_matrix[i, j] = Ciphertext()

        else:
            self.matrix = None
            self.encrypted_matrix = None

        print(self._id, "Created")
Beispiel #6
0
def initialize_fractional(
        poly_modulus_degree=4096,
        security_level_bits=128,
        plain_modulus_power_of_two=10,
        plain_modulus=None,
        encoder_integral_coefficients=1024,
        encoder_fractional_coefficients=3072,
        encoder_base=2
):
    parameters = EncryptionParameters()

    poly_modulus = "1x^" + str(poly_modulus_degree) + " + 1"
    parameters.set_poly_modulus(poly_modulus)

    if security_level_bits == 128:
        parameters.set_coeff_modulus(seal.coeff_modulus_128(poly_modulus_degree))
    elif security_level_bits == 192:
        parameters.set_coeff_modulus(seal.coeff_modulus_192(poly_modulus_degree))
    else:
        parameters.set_coeff_modulus(seal.coeff_modulus_128(poly_modulus_degree))
        print("Info: security_level_bits unknown - using default security_level_bits = 128")

    if plain_modulus is None:
        plain_modulus = 1 << plain_modulus_power_of_two

    parameters.set_plain_modulus(plain_modulus)

    context = SEALContext(parameters)

    print_parameters(context)

    global encoder
    encoder = FractionalEncoder(
        context.plain_modulus(),
        context.poly_modulus(),
        encoder_integral_coefficients,
        encoder_fractional_coefficients,
        encoder_base
    )

    keygen = KeyGenerator(context)
    public_key = keygen.public_key()
    secret_key = keygen.secret_key()

    global encryptor
    encryptor = Encryptor(context, public_key)

    global evaluator
    evaluator = Evaluator(context)

    global decryptor
    decryptor = Decryptor(context, secret_key)

    global evaluation_keys
    evaluation_keys = EvaluationKeys()

    keygen.generate_evaluation_keys(16, evaluation_keys)
Beispiel #7
0
def do_per_amount(amount, subtract_from=15):
    """
	Called on every message in the stream
	"""
    print("Transaction amount ", amount)
    parms = EncryptionParameters()
    parms.set_poly_modulus("1x^2048 + 1")
    parms.set_coeff_modulus(seal.coeff_modulus_128(2048))
    parms.set_plain_modulus(1 << 8)
    context = SEALContext(parms)

    # Encode
    encoder = FractionalEncoder(context.plain_modulus(),
                                context.poly_modulus(), 64, 32, 3)

    # To create a fresh pair of keys one can call KeyGenerator::generate() at any time.
    keygen = KeyGenerator(context)
    public_key = keygen.public_key()
    secret_key = keygen.secret_key()

    encryptor = Encryptor(context, public_key)

    plain1 = encoder.encode(amount)
    encoded2 = encoder.encode(subtract_from)

    # Encrypt
    encrypted1 = Ciphertext(parms)
    encryptor.encrypt(plain1, encrypted1)

    # Evaluate
    evaluator = Evaluator(context)
    evaluated = evaluate_subtraction_from_plain(evaluator, encrypted1,
                                                encoded2)

    # Decrypt and decode
    decryptor = Decryptor(context, secret_key)
    plain_result = Plaintext()
    decryptor.decrypt(evaluated, plain_result)
    result = encoder.decode(plain_result)

    str_result = "Amount left = " + str(result)
    print(str_result)
    return str_result
Beispiel #8
0
    def encrypt(self, data):
        if not self.initialized:
            self.log("Not initialized")
            return False

        # Setup the encoder
        encoder = FractionalEncoder(self.context.plain_modulus(), self.context.poly_modulus(), 64, 32, 3)

        # Create the array of encrypted data objects
        encrypted_data = []
        for raw_data in data:
            encrypted_data.append(Ciphertext(self.encrypt_params))
            self.encryptor.encrypt( encoder.encode(raw_data), encrypted_data[-1] )

        # Pickle each Ciphertext, base64 encode it, and store it in the array
        for i in range(0, len(encrypted_data)):
            encrypted_data[i].save("fhe_enc.bin")
            encrypted_data[i] = base64.b64encode( pickle.dumps(encrypted_data[i]) )

        return encrypted_data
Beispiel #9
0
    def evaluate(self, encrypted_data, lower_idx=0, higher_idx=-1):
        result = Ciphertext()

        # Setup the encoder
        encoder = FractionalEncoder(self.context.plain_modulus(), self.context.poly_modulus(), 64, 32, 3)

        # Unpack the data first
        unpacked_data = []
        for d in encrypted_data[lower_idx:higher_idx]:
            unpacked_data.append(pickle.loads(base64.b64decode(d)))

        # Perform operations
        self.evaluator.add_many(unpacked_data, result)
        div = encoder.encode(1/len(unpacked_data))
        self.evaluator.multiply_plain(result, div)

        # Pack the result
        result = base64.b64encode( pickle.dumps(result) )

        return result
Beispiel #10
0
    def _setup_members(self, context, config):

        self._encoder = FractionalEncoder(context.plain_modulus(),
                                          context.poly_modulus(),
                                          config['int_coeff'],
                                          config['fract_coeff'],
                                          config['base'])
        self._evaluator = Evaluator(context)

        pk, sk, self._ev_key = self._create_keys(context)
        self._encryptor = Encryptor(context, pk)
        self._decryptor = Decryptor(context, sk)
class FractionalDecryptorUtils:
    def __init__(self, context):
        """
        Class providing decryption operation
        :param context: Context initialising HE parameters
        """
        self.context = context.context
        self.secret_key = context.secret_key
        self.decryptor = Decryptor(self.context, self.secret_key)
        self.encoder = FractionalEncoder(self.context.plain_modulus(),
                                         self.context.poly_modulus(), 64, 32,
                                         3)
        self.evaluator = context.evaluator

    def decrypt(self, encrypted_res):
        plain_result = Plaintext()
        self.decryptor.decrypt(encrypted_res, plain_result)
        result = self.encoder.decode(plain_result)
        return result
Beispiel #12
0
 def set_encoder(
     self,
     fractional_encoder=True,
     whole_sign_digits=32,
     decimal_sign_digits=32,
     base=3,
 ):
     if fractional_encoder:
         self.__enco = FractionalEncoder(
             self._cont.plain_modulus(),
             self._cont.poly_modulus(),
             whole_sign_digits,
             decimal_sign_digits,
             base,
         )
     else:
         self.__enco = IntegerEncoder(
             self._cont.plain_modulus(),
             base,
         )
Beispiel #13
0
 def configure_params(self):
     with yaspin(
             text=
             'Initializing Encryptor, Eavaluator, Decryptor with generated parameters.....',
             spinner='dots') as sp2:
         self.frac_encoder = FractionalEncoder(self.context.plain_modulus(),
                                               self.context.poly_modulus(),
                                               64, 32, 3)
         self.encryptor = Encryptor(self.context, self.public_key)
         self.evaluator = Evaluator(self.context)
         self.decryptor = Decryptor(self.context, self.secret_key)
         if self.batching:
             self.crtbuilder = PolyCRTBuilder(self.context)
         sp2.hide()
         print(HTML(
             u'<b>></b> <msg> The system is ready to start encryption.</msg>'
         ),
               style=style)
         sp2.show()
         sp2.ok("✔")
Beispiel #14
0
	def __init__(self, poly_modulus = 2048 ,bit_strength = 128 ,plain_modulus = 1<<8, integral_coeffs = 64, fractional_coeffs = 32, fractional_base = 3):
		parms = EncryptionParameters()
		parms.set_poly_modulus("1x^{} + 1".format(poly_modulus))

		if (bit_strength == 128):
			parms.set_coeff_modulus(seal.coeff_modulus_128(poly_modulus))
		else:
			parms.set_coeff_modulus(seal.coeff_modulus_192(poly_modulus))
		parms.set_plain_modulus(plain_modulus)

		self.parms = parms
		context = SEALContext(parms)

		keygen = KeyGenerator(context)
		public_key = keygen.public_key()
		secret_key = keygen.secret_key()

		self.encryptor = Encryptor(context, public_key)
		self.evaluator = Evaluator(context)
		self.decryptor = Decryptor(context, secret_key)
		self.encoder = FractionalEncoder(context.plain_modulus(), context.poly_modulus(), integral_coeffs, fractional_coeffs, fractional_base)
class FractionalEncoderUtils:
    def __init__(self, context: FracContext):
        """
        Class providing encoding and encryption operations, operations over
        encrypted data
        :param context: Context initialising HE parameters
        """
        self.context = context.context
        self.public_key = context.public_key
        self.encryptor = Encryptor(self.context, self.public_key)
        self.encoder = FractionalEncoder(self.context.plain_modulus(),
                                         self.context.poly_modulus(), 64, 32,
                                         3)
        self.evaluator = context.evaluator
        self.ev_keys = EvaluationKeys()
        context.keygen.generate_evaluation_keys(seal.dbc_max(), self.ev_keys)

    def encode_rationals(self, numbers) -> List[Plaintext]:
        # encoding without encryption
        encoded_coefficients = []
        for i in range(len(numbers)):
            encoded_coefficients.append(self.encoder.encode(numbers[i]))
        return encoded_coefficients

    def encode_num(self, num) -> Plaintext:
        if type(num) == Plaintext or num is None:
            return num
        else:  # encoding without encryption
            return self.encoder.encode(num)

    def sum_enc_array(self, array: List[Ciphertext]) -> Ciphertext:
        # can applied for 1D array only
        encrypted_result = Ciphertext()
        self.evaluator.add_many(array, encrypted_result)
        return encrypted_result

    def encrypt_rationals(self, rational_numbers: List) -> List[Ciphertext]:
        """
        :param rational_numbers: array of rational numbers
        :return: encrypted result
        """
        encrypted_rationals = []
        for i in range(len(rational_numbers)):
            encrypted_rationals.append(Ciphertext(self.context.params))
            self.encryptor.encrypt(self.encoder.encode(rational_numbers[i]),
                                   encrypted_rationals[i])
        return encrypted_rationals

    def weighted_average(self, encrypted_rationals, encoded_coefficients,
                         encoded_divide_by) -> Ciphertext:
        """
        Weighted average, where weights encoded, not encrypted numbers
        :param encoded_divide_by: fixed point fractional, e.g 0.1 to perform division by 10
        :return: encrypted result
        """
        for i in range(len(encrypted_rationals)):
            self.evaluator.multiply_plain(encrypted_rationals[i],
                                          encoded_coefficients[i])

        encrypted_result = Ciphertext()
        self.evaluator.add_many(encrypted_rationals, encrypted_result)
        self.evaluator.multiply_plain(encrypted_result, encoded_divide_by)

        return encrypted_result

    def subtract(self, a: Ciphertext, b: Ciphertext) -> Ciphertext:
        """
        Substruction operation of 2 fractional numbers
        :param a: encrypted fractional value
        :param b: encrypted fractional value
        :return: substracted result
        """
        a = deepcopy(a)
        minus_sign = self.encoder.encode(-1)
        self.evaluator.multiply_plain(b, minus_sign)
        self.evaluator.add(a, b)
        return a

    def encrypt_num(self, value) -> Ciphertext:
        if type(value) == Ciphertext or value is None:
            return value
        else:
            encrypted = Ciphertext()
            if type(value) == Plaintext:
                self.encryptor.encrypt(value, encrypted)
            else:
                plain = self.encoder.encode(value)
                self.encryptor.encrypt(plain, encrypted)
            return encrypted

    def add(self, a: Ciphertext, b: Ciphertext) -> Ciphertext:
        """
        :param a: encrypted fractional value
        :param b: encrypted fractional value
        :return: encrypted sum of a and b
        """
        a = deepcopy(a)
        self.evaluator.add(a, b)
        return a

    def add_plain(self, a: Ciphertext, b: Plaintext) -> Ciphertext:
        """
        :param a: encrypted fractional value
        :param b: encoded fractional value
        :return: encrypted sum of a and b
        """
        a = deepcopy(a)
        self.evaluator.add_plain(a, b)
        return a

    def multiply(self, a: Ciphertext, b: Ciphertext) -> Ciphertext:
        """
        :param a: encrypted fractional value
        :param b: encrypted fractional value
        :return: encrypted product of a and b
        """
        a = deepcopy(a)
        self.evaluator.multiply(a, b)
        return a

    def multiply_plain(self, a: Ciphertext, b: Plaintext) -> Ciphertext:
        """
        :param a: encrypted fractional value
        :param b: encrypted fractional value
        :return: encrypted product of a and b
        """
        a = deepcopy(a)
        self.evaluator.multiply_plain(a, b)
        return a

    def relinearize(self, a: Ciphertext) -> Ciphertext:
        """
        :param a: encrypted fractional value, supposedly result of multiplication
        :return: relinearized a
        """
        a = deepcopy(a)
        self.evaluator.relinearize(a, self.ev_keys)
        return a
            p = Plaintext()
            decryptor.decrypt(y, p)
            m.append(encoderF.decode(p))
        M.append(m)
    return (M)


########################## paramaters required #################################

parms = EncryptionParameters()
parms.set_poly_modulus("1x^8192 + 1")
parms.set_coeff_modulus(seal.coeff_modulus_128(8192))
parms.set_plain_modulus(1 << 21)
context = SEALContext(parms)

encoderF = FractionalEncoder(context.plain_modulus(), context.poly_modulus(),
                             30, 34, 3)
keygen = KeyGenerator(context)
public_key = keygen.public_key()
secret_key = keygen.secret_key()

encryptor = Encryptor(context, public_key)
evaluator = Evaluator(context)
decryptor = Decryptor(context, secret_key)

########################## encoding main matrix ################################

A = [Ciphertext(), Ciphertext(), Ciphertext(), Ciphertext()]

for i in range(len(A)):
    encryptor.encrypt(encoderF.encode(i), A[i])
class CipherMatrix:
    """

    """
    def __init__(self, matrix=None):
        """

        :param matrix: numpy.ndarray to be encrypted.
        """

        self.parms = EncryptionParameters()
        self.parms.set_poly_modulus("1x^2048 + 1")
        self.parms.set_coeff_modulus(seal.coeff_modulus_128(2048))
        self.parms.set_plain_modulus(1 << 8)

        self.context = SEALContext(self.parms)

        # self.encoder = IntegerEncoder(self.context.plain_modulus())
        self.encoder = FractionalEncoder(self.context.plain_modulus(),
                                         self.context.poly_modulus(), 64, 32,
                                         3)

        self.keygen = KeyGenerator(self.context)
        self.public_key = self.keygen.public_key()
        self.secret_key = self.keygen.secret_key()

        self.encryptor = Encryptor(self.context, self.public_key)
        self.decryptor = Decryptor(self.context, self.secret_key)

        self.evaluator = Evaluator(self.context)

        self._saved = False
        self._encrypted = False
        self._id = '{0:04d}'.format(np.random.randint(1000))

        if matrix is not None:
            assert len(
                matrix.shape) == 2, "Only 2D numpy matrices accepted currently"
            self.matrix = np.copy(matrix)
            self.encrypted_matrix = np.empty(self.matrix.shape, dtype=object)
            for i in range(self.matrix.shape[0]):
                for j in range(self.matrix.shape[1]):
                    self.encrypted_matrix[i, j] = Ciphertext()

        else:
            self.matrix = None
            self.encrypted_matrix = None

        print(self._id, "Created")

    def __repr__(self):
        """

        :return:
        """
        print("Encrypted:", self._encrypted)
        if not self._encrypted:
            print(self.matrix)
            return ""

        else:
            return '[]'

    def __str__(self):
        """

        :return:
        """
        print("| Encryption parameters:")
        print("| poly_modulus: " + self.context.poly_modulus().to_string())

        # Print the size of the true (product) coefficient modulus
        print("| coeff_modulus_size: " + (
            str)(self.context.total_coeff_modulus().significant_bit_count()) +
              " bits")

        print("| plain_modulus: " +
              (str)(self.context.plain_modulus().value()))
        print("| noise_standard_deviation: " +
              (str)(self.context.noise_standard_deviation()))

        if self.matrix is not None:
            print(self.matrix.shape)

        return str(type(self))

    def __add__(self, other):
        """

        :param other:
        :return:
        """
        assert isinstance(
            other, CipherMatrix), "Can only be added with a CipherMatrix"

        A_enc = self._encrypted
        B_enc = other._encrypted

        if A_enc:
            A = self.encrypted_matrix
        else:
            A = self.matrix

        if B_enc:
            B = other.encrypted_matrix
        else:
            B = other.matrix

        assert A.shape == B.shape, "Dimension mismatch, Matrices must be of same shape. Got {} and {}".format(
            A.shape, B.shape)

        shape = A.shape

        result = CipherMatrix(np.zeros(shape, dtype=np.int32))
        result._update_cryptors(self.get_keygen())

        if A_enc:
            if B_enc:

                res_mat = result.encrypted_matrix
                for i in range(shape[0]):
                    for j in range(shape[1]):
                        self.evaluator.add(A[i, j], B[i, j], res_mat[i, j])

                result._encrypted = True

            else:
                res_mat = result.encrypted_matrix
                for i in range(shape[0]):
                    for j in range(shape[1]):
                        self.evaluator.add_plain(A[i, j],
                                                 self.encoder.encode(B[i, j]),
                                                 res_mat[i, j])

                result._encrypted = True

        else:
            if B_enc:

                res_mat = result.encrypted_matrix
                for i in range(shape[0]):
                    for j in range(shape[1]):
                        self.evaluator.add_plain(B[i, j],
                                                 self.encoder.encode(A[i, j]),
                                                 res_mat[i, j])

                result._encrypted = True

            else:

                result.matrix = A + B
                result._encrypted = False

        return result

    def __sub__(self, other):
        """

        :param other:
        :return:
        """
        assert isinstance(other, CipherMatrix)
        if other._encrypted:
            shape = other.encrypted_matrix.shape

            for i in range(shape[0]):
                for j in range(shape[1]):
                    self.evaluator.negate(other.encrypted_matrix[i, j])

        else:
            other.matrix = -1 * other.matrix

        return self + other

    def __mul__(self, other):
        """

        :param other:
        :return:
        """

        assert isinstance(
            other, CipherMatrix), "Can only be multiplied with a CipherMatrix"

        # print("LHS", self._id, "RHS", other._id)
        A_enc = self._encrypted
        B_enc = other._encrypted

        if A_enc:
            A = self.encrypted_matrix
        else:
            A = self.matrix

        if B_enc:
            B = other.encrypted_matrix
        else:
            B = other.matrix

        Ashape = A.shape
        Bshape = B.shape

        assert Ashape[1] == Bshape[0], "Dimensionality mismatch"
        result_shape = [Ashape[0], Bshape[1]]

        result = CipherMatrix(np.zeros(shape=result_shape))

        if A_enc:
            if B_enc:

                for i in range(Ashape[0]):
                    for j in range(Bshape[1]):

                        result_array = []
                        for k in range(Ashape[1]):

                            res = Ciphertext()
                            self.evaluator.multiply(A[i, k], B[k, j], res)

                            result_array.append(res)

                        self.evaluator.add_many(result_array,
                                                result.encrypted_matrix[i, j])

                result._encrypted = True

            else:

                for i in range(Ashape[0]):
                    for j in range(Bshape[1]):

                        result_array = []
                        for k in range(Ashape[1]):
                            res = Ciphertext()
                            self.evaluator.multiply_plain(
                                A[i, k], self.encoder.encode(B[k, j]), res)

                            result_array.append(res)

                        self.evaluator.add_many(result_array,
                                                result.encrypted_matrix[i, j])

                result._encrypted = True

        else:
            if B_enc:

                for i in range(Ashape[0]):
                    for j in range(Bshape[1]):

                        result_array = []
                        for k in range(Ashape[1]):
                            res = Ciphertext()
                            self.evaluator.multiply_plain(
                                B[i, k], self.encoder.encode(A[k, j]), res)

                            result_array.append(res)

                        self.evaluator.add_many(result_array,
                                                result.encrypted_matrix[i, j])

                result._encrypted = True

            else:

                result.matrix = np.matmul(A, B)
                result._encrypted = False

        return result

    def save(self, path):
        """

        :param path:
        :return:
        """

        save_dir = os.path.join(path, self._id)

        if self._saved:
            print("CipherMatrix already saved")

        else:
            assert not os.path.isdir(save_dir), "Directory already exists"
            os.mkdir(save_dir)

        if not self._encrypted:
            self.encrypt()

        shape = self.encrypted_matrix.shape

        for i in range(shape[0]):
            for j in range(shape[1]):

                element_name = str(i) + '-' + str(j) + '.ahem'
                self.encrypted_matrix[i, j].save(
                    os.path.join(save_dir, element_name))

        self.secret_key.save("/keys/" + "." + self._id + '.wheskey')

        self._saved = True
        return save_dir

    def load(self, path, load_secret_key=False):
        """

        :param path:
        :param load_secret_key:
        :return:
        """

        self._id = path.split('/')[-1]
        print("Loading Matrix:", self._id)

        file_list = os.listdir(path)
        index_list = [[file.split('.')[0].split('-'), file]
                      for file in file_list]

        M = int(max([int(ind[0][0]) for ind in index_list])) + 1
        N = int(max([int(ind[0][1]) for ind in index_list])) + 1
        del self.encrypted_matrix
        self.encrypted_matrix = np.empty([M, N], dtype=object)

        for index in index_list:
            i = int(index[0][0])
            j = int(index[0][1])

            self.encrypted_matrix[i, j] = Ciphertext()
            self.encrypted_matrix[i, j].load(os.path.join(path, index[1]))

        if load_secret_key:
            self.secret_key.load("/keys/" + "." + self._id + '.wheskey')

        self.matrix = np.empty(self.encrypted_matrix.shape)
        self._encrypted = True

    def encrypt(self, matrix=None, keygen=None):
        """

        :param matrix:
        :return:
        """

        assert not self._encrypted, "Matrix already encrypted"

        if matrix is not None:
            assert self.matrix is None, "matrix already exists"
            self.matrix = np.copy(matrix)

        shape = self.matrix.shape

        self.encrypted_matrix = np.empty(shape, dtype=object)

        if keygen is not None:
            self._update_cryptors(keygen)

        for i in range(shape[0]):
            for j in range(shape[1]):
                val = self.encoder.encode(self.matrix[i, j])
                self.encrypted_matrix[i, j] = Ciphertext()
                self.encryptor.encrypt(val, self.encrypted_matrix[i, j])

        self._encrypted = True

    def decrypt(self, encrypted_matrix=None, keygen=None):
        """

        :return:
        """

        if encrypted_matrix is not None:
            self.encrypted_matrix = encrypted_matrix

        assert self._encrypted, "No encrypted matrix"

        del self.matrix
        shape = self.encrypted_matrix.shape

        self.matrix = np.empty(shape)

        if keygen is not None:
            self._update_cryptors(keygen)

        for i in range(shape[0]):
            for j in range(shape[1]):
                plain_text = Plaintext()
                self.decryptor.decrypt(self.encrypted_matrix[i, j], plain_text)
                self.matrix[i, j] = self.encoder.decode(plain_text)

        self._encrypted = False
        return np.copy(self.matrix)

    def get_keygen(self):
        """

        :return:
        """
        return self.keygen

    def _update_cryptors(self, keygen):
        """

        :param keygen:
        :return:
        """

        self.keygen = keygen
        self.public_key = keygen.public_key()
        self.secret_key = keygen.secret_key()

        self.encryptor = Encryptor(self.context, self.public_key)
        self.decryptor = Decryptor(self.context, self.secret_key)

        return
Beispiel #18
0
def test1():

    #TODO make the function taking dir name, iterating through all the descriptors, encrypting
    #TODO add progress bar - the videos are decrypted
    #TODO make a function taking a query and passing it to the sklearn function KNN with custom similarity funtion
    #TODO add progress bar - the search is performed (calculate distance between encrypted vectors)
    #TODO return results
    #TODO Vlad Display. The results are true. The same as we would compute similarity between ncrypted vectors.
    # In the same time we did not have to decrypt vectors stored in 3rd parity service to perform a search.
    #TODO get the metrics
    #TODO how to opimize

    a = np.ones((1, DESC_SIZE))
    b = np.ones((1, DESC_SIZE))
    for i in range(a.shape[1]):
        a[0, i] = random.uniform(0.0, 1.0)
        b[0, i] = random.uniform(0.0, 1.0)

    print("Descriptors for images a and b are: ")
    print("a ", a)
    print("b ", b)

    context, params = config()
    public_key, secret_key = keygen(context)

    frac_encoder = FractionalEncoder(context.plain_modulus(),
                                     context.poly_modulus(), 64, 32, 3)
    encryptor = Encryptor(context, public_key)
    evaluator = Evaluator(context)
    decryptor = Decryptor(context, secret_key)

    e1 = encrypt_vec(params, encryptor, frac_encoder, a)
    e3 = encrypt_vec(params, encryptor, frac_encoder, b)

    print("Calculate distance between plain a and b:")
    sim = euclidean_dist(a, b)
    print("Similarity between a and b: {}".format(sim))

    print("Calculating distance between encrypted a and b:")
    time_start = time.time()
    enc_res = euclidean_dist_enc(evaluator, e1, e3)
    time_end = time.time()
    print("Done. Time: {} miliseconds".format(
        (str)(1000 * (time_end - time_start))))

    plain_result = Plaintext()
    print("Decrypting result: ")
    time_start = time.time()
    decryptor.decrypt(enc_res, plain_result)
    res = frac_encoder.encode(plain_result)
    time_end = time.time()
    print("Done. Time: {} miliseconds".format(
        (str)(1000 * (time_end - time_start))))
    print(
        "........................................................................"
    )
    print("Noise budget {} bits".format(
        decryptor.invariant_noise_budget(enc_res)))
    print("Decrypted result {}, original result {}".format(res, sim))

    print("Calculate distance between plain a and a:")
    sim = euclidean_dist(a, a.copy())
    print("Similarity between a and b: {}".format(sim))

    print("Calculating distance between encrypted a and a:")
    time_start = time.time()
    enc_res = euclidean_dist_enc(evaluator, e1, e1)
    time_end = time.time()
    print("Done. Time: {} miliseconds".format(
        (str)(1000 * (time_end - time_start))))

    plain_result = Plaintext()
    print("Decrypting result: ")
    time_start = time.time()
    decryptor.decrypt(enc_res, plain_result)
    res = frac_encoder.encode(plain_result)
    time_end = time.time()
    print("Done. Time: {} miliseconds".format(
        (str)(1000 * (time_end - time_start))))
    print(
        "........................................................................."
    )
    print("Noise budget {} bits".format(
        decryptor.invariant_noise_budget(enc_res)))
    print("Decrypted result {}, original result {}".format(res, sim))
Beispiel #19
0
    encryptor.encrypt(plain_matrix, cm)
    # cm = [[0] * len(m[0]) for i in range(len(m))]
    # for i in range(len(m)):
    #     for j in range(len(m[0])):
    #         cm[i][j] = Ciphertext(parms)
    #         encryptor.encrypt(encoder.encode(m[i][j]), cm[i][j])
    print(cm)
    np.reshape(cm, (r, c))
    return cm


# v1 = [3.1, 4.159, 2.65, 3.5897, 9.3, 2.3, 8.46, 2.64, 3.383, 2.795]
# v2 = [0.1, 0.05, 0.05, 0.2, 0.05, 0.3, 0.1, 0.025, 0.075, 0.05]

encryptor = Encryptor(context, public_key)
encoder = FractionalEncoder(context.plain_modulus(), context.poly_modulus(),
                            64, 32, 3)


def decryptMatrix(cm):
    r, c = len(cm), len(cm[0])
    m = [[0] * c for i in range(r)]
    decryptor = Decryptor(context, secret_key)
    plain_result = Plaintext()
    for i in range(r):
        for j in range(c):
            decryptor.decrypt(cm[i][j], plain_result)
            m[i][j] = encoder.decode(plain_result)
    return m


# m1 = [[1,3,2],[4,3,1]]
    tM = [list(tup) for tup in zip(*M)]
    del (M)
    ncol = len(tM)
    for i in range(ncol):
        encrypt_matrix_row(tM[i], i)
    print("outside the loop")
    return (tM)


parms = EncryptionParameters()
parms.set_poly_modulus("1x^8192 + 1")
parms.set_coeff_modulus(seal.coeff_modulus_128(8192))
parms.set_plain_modulus(1 << 21)
context = SEALContext(parms)

encoderF = FractionalEncoder(context.plain_modulus(), context.poly_modulus(),
                             30, 34, 3)
keygen = KeyGenerator(context)
public_key = keygen.public_key()
secret_key = keygen.secret_key()

encryptor = Encryptor(context, public_key)
evaluator = Evaluator(context)
decryptor = Decryptor(context, secret_key)

dir_path = os.path.dirname(os.path.realpath(__file__))

snp = open(dir_path + "/snpMat.txt", "r+")
S = []
for row in snp.readlines():
    S.append(row.strip().split())
S = S[1:]
            p=Plaintext()
            decryptor.decrypt(y, p)
            m.append(encoderF.decode(p))
        M.append(m)
    return(M)



parms = EncryptionParameters()
parms.set_poly_modulus("1x^8192 + 1")
parms.set_coeff_modulus(seal.coeff_modulus_128(8192))
parms.set_plain_modulus(1 << 21)
context = SEALContext(parms)

#encoder = IntegerEncoder(context.plain_modulus())
encoderF = FractionalEncoder(context.plain_modulus(), context.poly_modulus(), 30, 34, 3) 
keygen = KeyGenerator(context)
public_key = keygen.public_key()
secret_key = keygen.secret_key()
#ev_keys40 = EvaluationKeys
#ev_keys20 = EvaluationKeys()
#keygen.generate_evaluation_keys(40,5,ev_keys40)
#keygen.generate_evaluation_keys(20,3,ev_keys20)
encryptor = Encryptor(context, public_key)
evaluator = Evaluator(context)
decryptor = Decryptor(context, secret_key)


plain_A = []
A=[]
n=int(input("Enter dimension: "))
Beispiel #22
0


if __name__ == '__main__':

	multiprocessing.freeze_support()

	########################## paramaters required #################################

	parms = EncryptionParameters()
	parms.set_poly_modulus("1x^16384 + 1")
	parms.set_coeff_modulus(seal.coeff_modulus_128(8192))
	parms.set_plain_modulus(1 << 25)
	context = SEALContext(parms)

	encoderF = FractionalEncoder(context.plain_modulus(), context.poly_modulus(), 34, 30, 3) 
	keygen = KeyGenerator(context)
	public_key = keygen.public_key()
	secret_key = keygen.secret_key()

	encryptor = Encryptor(context, public_key)
	evaluator = Evaluator(context)
	decryptor = Decryptor(context, secret_key)

	num_cores = multiprocessing.cpu_count() -1

	N=4
	b = numpy.random.random_integers(1,10,size=(N,N))
	X = (b + b.T)/2
	print("\nX:")
	print(X)
for i in range(16):
	A.append(random.randint(0,64))
A+=[0]*(100-16)
print(A)
for i in range(16,32,5):
	A[i]=1

parms = EncryptionParameters()
parms.set_poly_modulus("1x^2048 + 1")
parms.set_coeff_modulus(seal.coeff_modulus_128(2048))
parms.set_plain_modulus(1 << 8)

context = SEALContext(parms)
print_parameters(context)
encoder = IntegerEncoder(context.plain_modulus())
encoderF =FractionalEncoder(context.plain_modulus(), context.poly_modulus(), 64, 32, 3)
keygen = KeyGenerator(context)
public_key = keygen.public_key()
secret_key = keygen.secret_key()
encryptor = Encryptor(context, public_key)
evaluator = Evaluator(context)
decryptor = Decryptor(context, secret_key)

for i in range(len(A)):
	A_plain.append(encoder.encode(A[i]))
	A_cipherObject.append(Ciphertext())
	encryptor.encrypt(A_plain[i],A_cipherObject[i])
	print("Noise budget of "+ str(i)+" "+str((decryptor.invariant_noise_budget(A_cipherObject[i]))) + " bits")

A_cipherObject=chunk(A_cipherObject)
C=A_cipherObject
Beispiel #24
0
def dot_product():
    print("Example: Weighted Average")

    # In this example we demonstrate the FractionalEncoder, and use it to compute
    # a weighted average of 10 encrypted rational numbers. In this computation we
    # perform homomorphic multiplications of ciphertexts by plaintexts, which is
    # much faster than regular multiplications of ciphertexts by ciphertexts.
    # Moreover, such `plain multiplications' never increase the ciphertext size,
    # which is why we have no need for evaluation keys in this example.

    # We start by creating encryption parameters, setting up the SEALContext, keys,
    # and other relevant objects. Since our computation has multiplicative depth of
    # only two, it suffices to use a small poly_modulus.
    parms = EncryptionParameters()
    parms.set_poly_modulus("1x^2048 + 1")
    parms.set_coeff_modulus(seal.coeff_modulus_128(2048))
    parms.set_plain_modulus(1 << 8)

    context = SEALContext(parms)
    print_parameters(context)

    keygen = KeyGenerator(context)
    keygen2 = KeyGenerator(context)
    public_key = keygen.public_key()
    secret_key = keygen.secret_key()

    secret_key2 = keygen.secret_key()

    # We also set up an Encryptor, Evaluator, and Decryptor here.
    encryptor = Encryptor(context, public_key)
    evaluator = Evaluator(context)
    decryptor = Decryptor(context, secret_key2)

    # Create a vector of 10 rational numbers (as doubles).
    # rational_numbers = [3.1, 4.159, 2.65, 3.5897, 9.3, 2.3, 8.46, 2.64, 3.383, 2.795]
    rational_numbers = np.random.rand(10)

    # Create a vector of weights.
    # coefficients = [0.1, 0.05, 0.05, 0.2, 0.05, 0.3, 0.1, 0.025, 0.075, 0.05]
    coefficients = np.random.rand(10)

    my_result = np.dot(rational_numbers, coefficients)

    # We need a FractionalEncoder to encode the rational numbers into plaintext
    # polynomials. In this case we decide to reserve 64 coefficients of the
    # polynomial for the integral part (low-degree terms) and expand the fractional
    # part to 32 digits of precision (in base 3) (high-degree terms). These numbers
    # can be changed according to the precision that is needed; note that these
    # choices leave a lot of unused space in the 2048-coefficient polynomials.
    encoder = FractionalEncoder(context.plain_modulus(), context.poly_modulus(), 64, 32, 3)

    # We create a vector of ciphertexts for encrypting the rational numbers.
    encrypted_rationals = []
    rational_numbers_string = "Encoding and encrypting: "
    for i in range(10):
        # We create our Ciphertext objects into the vector by passing the
        # encryption parameters as an argument to the constructor. This ensures
        # that enough memory is allocated for a size 2 ciphertext. In this example
        # our ciphertexts never grow in size (plain multiplication does not cause
        # ciphertext growth), so we can expect the ciphertexts to remain in the same
        # location in memory throughout the computation. In more complicated examples
        # one might want to call a constructor that reserves enough memory for the
        # ciphertext to grow to a specified size to avoid costly memory moves when
        # multiplications and relinearizations are performed.
        encrypted_rationals.append(Ciphertext(parms))
        encryptor.encrypt(encoder.encode(rational_numbers[i]), encrypted_rationals[i])
        rational_numbers_string += (str)(rational_numbers[i])[:6]
        if i < 9: rational_numbers_string += ", "
    print(rational_numbers_string)

    # Next we encode the coefficients. There is no reason to encrypt these since they
    # are not private data.
    encoded_coefficients = []
    encoded_coefficients_string = "Encoding plaintext coefficients: "


    encrypted_coefficients =[]

    for i in range(10):
        encoded_coefficients.append(encoder.encode(coefficients[i]))
        encrypted_coefficients.append(Ciphertext(parms))
        encryptor.encrypt(encoded_coefficients[i], encrypted_coefficients[i])
        encoded_coefficients_string += (str)(coefficients[i])[:6]
        if i < 9: encoded_coefficients_string += ", "
    print(encoded_coefficients_string)

    # We also need to encode 0.1. Multiplication by this plaintext will have the
    # effect of dividing by 10. Note that in SEAL it is impossible to divide
    # ciphertext by another ciphertext, but in this way division by a plaintext is
    # possible.
    div_by_ten = encoder.encode(0.1)

    # Now compute each multiplication.

    prod_result = [Ciphertext() for i in range(10)]
    prod_result2 = [Ciphertext() for i in range(10)]

    print("Computing products: ")
    for i in range(10):
        # Note how we use plain multiplication instead of usual multiplication. The
        # result overwrites the first argument in the function call.
        evaluator.multiply_plain(encrypted_rationals[i], encoded_coefficients[i], prod_result[i])
        evaluator.multiply(encrypted_rationals[i], encrypted_coefficients[i], prod_result2[i])
    print("Done")

    # To obtain the linear sum we need to still compute the sum of the ciphertexts
    # in encrypted_rationals. There is an easy way to add together a vector of
    # Ciphertexts.

    encrypted_result = Ciphertext()
    encrypted_result2 = Ciphertext()

    print("Adding up all 10 ciphertexts: ")
    evaluator.add_many(prod_result, encrypted_result)
    evaluator.add_many(prod_result2, encrypted_result2)

    print("Done")

    # Perform division by 10 by plain multiplication with div_by_ten.
    # print("Dividing by 10: ")
    # evaluator.multiply_plain(encrypted_result, div_by_ten)
    # print("Done")

    # How much noise budget do we have left?
    print("Noise budget in result: " + (str)(decryptor.invariant_noise_budget(encrypted_result)) + " bits")

    # Decrypt, decode, and print result.
    plain_result = Plaintext()
    plain_result2 = Plaintext()
    print("Decrypting result: ")
    decryptor.decrypt(encrypted_result, plain_result)
    decryptor.decrypt(encrypted_result2, plain_result2)
    print("Done")

    result = encoder.decode(plain_result)
    print("Weighted average: " + (str)(result)[:8])

    result2 = encoder.decode(plain_result2)
    print("Weighted average: " + (str)(result2)[:8])

    print('\n\n', my_result)
                 SEALContext,          \
                 EvaluationKeys,       \
                 GaloisKeys,           \
                 PolyCRTBuilder,       \
                 ChooserEncoder,       \
                 ChooserEvaluator,     \
                 ChooserPoly

parms = EncryptionParameters()
parms.set_poly_modulus("1x^8192 + 1")
parms.set_coeff_modulus(seal.coeff_modulus_128(8192))
parms.set_plain_modulus(1 << 21)
context = SEALContext(parms)

#encoder = IntegerEncoder(context.plain_modulus())
encoderF = FractionalEncoder(context.plain_modulus(), context.poly_modulus(),
                             30, 34, 3)
keygen = KeyGenerator(context)
public_key = keygen.public_key()
secret_key = keygen.secret_key()
#ev_keys40 = EvaluationKeys
#ev_keys20 = EvaluationKeys()
#keygen.generate_evaluation_keys(40,5,ev_keys40)
#keygen.generate_evaluation_keys(20,3,ev_keys20)
encryptor = Encryptor(context, public_key)
evaluator = Evaluator(context)
decryptor = Decryptor(context, secret_key)


def print_plain(D):
    # function to print out all elements in a matrix
    for row in D:
Beispiel #26
0
def encrypt(input_file):
    X = np.load(input_file)

    print("Starting the system....\n")
    y, people_descriptors = search_for_centroids(X)
    X, y = unison_shuffled_copies(X, y)
    np.save(input_file, X)
    np.save('./class_lables.npy', np.array(y))
    np.save('./centroids.npy', np.array(people_descriptors))
    print(
        "All necessary dependencies are installed. Everything is up-to-date!")

    print("The encryption mode is entered!")

    time_start = time.time()
    print('Configuring the encryption parameters')
    context, params = config()
    time_end = time.time()
    #TODO time for the report. Put to the slides
    #TODO Remove from logs
    print("Parameters are configured. Time: {}\n".format(
        (str)(1000 * (time_end - time_start))))
    #print("Key generation .....")
    time_start = time.time()
    with yaspin(text='Generating public/private key pair',
                spinner='dots') as sp1:
        public_key, secret_key = keygen(context)
        time.sleep(1)
        sp1.hide()
        print(HTML(
            u'<b>></b> <msg>public/private key pair </msg> <sub-msg>is generated</sub-msg>'
        ),
              style=style)
        sp1.show()
        sp1.ok("✔")

    time_end = time.time()
    print("Keys are generated!  Time: {}".format(
        (str)(1000 * (time_end - time_start))))

    with yaspin(
            text=
            'Initializing Encryptor, Eavaluator, Decryptor with generated parameters.....',
            spinner='dots') as sp2:
        frac_encoder = FractionalEncoder(context.plain_modulus(),
                                         context.poly_modulus(), 64, 32, 3)
        encryptor = Encryptor(context, public_key)
        evaluator = Evaluator(context)
        decryptor = Decryptor(context, secret_key)

        p = []
        p.append(params)
        p.append(context)
        p.append(frac_encoder)
        p.append(encryptor)
        p.append(evaluator)
        p.append(decryptor)
        ENC_CONF = p
        sp2.hide()
        print(HTML(
            u'<b>></b> <msg> The system is ready to start encryption.</msg>'),
              style=style)
        sp2.show()
        sp2.ok("✔")

    #enc_X = np.empty(X.shape, dtype=object)
    with yaspin(text='Subscribing to the online-video stream.',
                spinner='clock') as sp3:
        time.sleep(5)
        sp3.hide()
        print(HTML(u'<b>></b> <msg> Success</msg>'), style=style)
        sp3.show()
        sp3.ok("✔")

    print("Detecting people")
    time_start = time.time()
    with yaspin(
            text='Encrypting the descriptor').white.bold.shark.on_blue as sp4:
        for i, x in enumerate(X):
            sp4.write("Got descriptor of 1x{} dimension for a person".format(
                x.shape[0]))
            time.sleep(1)
            #enc_X[i, :] = encrypt_vec(params, encryptor, frac_encoder, x)
            encrypt_vec(params, encryptor, frac_encoder, x)

            dists = []
            for j in range(people_descriptors.shape[0]):
                dist1 = euclidean_dist(people_descriptors[j], x)
                dists.append(dist1)
            sp4.write(
                "Distance between 'Current' person and Person #{}: {:.2f} - Person #{}: {:.2f} - Person #{}: {:.2f} - Person #{}: {:.2f}"
                .format(0, dists[0], 1, dists[1], 2, dists[2], 3, dists[3]))
            time.sleep(1)
            dists = np.array(dists)
            if (dists[dists < 0.6] is not None):
                d = np.sort(dists)[0]
                sp4.write(
                    "🔦FOUND descriptor similar to Person #{}".format(d))
                time.sleep(1)
            sp4.hide()
            print(HTML(
                u'<b>�</b> <msg>descriptor {}</msg> <sub-msg>encryption complete</sub-msg>'
                .format(i)),
                  style=style)
            sp4.show()
        #sp.ok("All stream is encrypted")
        sp4.ok("✔")

    time_end = time.time()
    print("Encryption is complete.")
    print(
        "ALL {} descriptors are successfully encrypted and sent to the CLOUD.".
        format(X.shape[0]))
    print("Time: {}".format((str)(1000 * (time_end - time_start))))
Beispiel #27
0
def unit_test():
    parms = EncryptionParameters()
    parms.set_poly_modulus("1x^8192 + 1")
    parms.set_coeff_modulus(seal.coeff_modulus_128(8192))
    parms.set_plain_modulus(1 << 10)
    context = SEALContext(parms)

    # Print the parameters that we have chosen
    print_parameters(context)
    encoder = FractionalEncoder(context.plain_modulus(),
                                context.poly_modulus(), 64, 32, 3)
    keygen = KeyGenerator(context)
    public_key = keygen.public_key()
    secret_key = keygen.secret_key()
    encryptor = Encryptor(context, public_key)

    # Computations on the ciphertexts are performed with the Evaluator class.
    evaluator = Evaluator(context)

    # We will of course want to decrypt our results to verify that everything worked,
    # so we need to also construct an instance of Decryptor. Note that the Decryptor
    # requires the secret key.

    decryptor = Decryptor(context, secret_key)
    learningRate = 0.1
    learningRate_data = encoder.encode(learningRate)
    learningRate_e = Ciphertext()
    encryptor.encrypt(learningRate_data, learningRate_e)

    updatedVals = []
    updatedVals.append(50)
    updatedVals.append(50)
    updatedVals_unenc = []

    updatedVals_unenc.append(updatedVals[0])
    updatedVals_unenc.append(updatedVals[1])

    for i in range(15):
        x = 1
        y = 1
        updatedVals = learn(x, y, evaluator, updatedVals[0], updatedVals[1],
                            encoder, encryptor, learningRate_e, decryptor)
        ypred = updatedVals_unenc[0] * x + updatedVals_unenc[1]
        error = ypred - y
        updatedVals_unenc[0] = updatedVals_unenc[0] - x * error * learningRate
        updatedVals_unenc[1] = updatedVals_unenc[1] - error * learningRate
        print((str)(updatedVals[1]) + ":" + (str)(updatedVals[0]) + ":" +
              (str)(updatedVals_unenc[1]) + ":" + (str)(updatedVals_unenc[0]))

        x = 2
        y = 3
        updatedVals = learn(x, y, evaluator, updatedVals[0], updatedVals[1],
                            encoder, encryptor, learningRate_e, decryptor)
        ypred = updatedVals_unenc[0] * x + updatedVals_unenc[1]
        error = ypred - y
        updatedVals_unenc[0] = updatedVals_unenc[0] - x * error * learningRate
        updatedVals_unenc[1] = updatedVals_unenc[1] - error * learningRate
        print((str)(updatedVals[1]) + ":" + (str)(updatedVals[0]) + ":" +
              (str)(updatedVals_unenc[1]) + ":" + (str)(updatedVals_unenc[0]))

        x = 4
        y = 3
        updatedVals = learn(x, y, evaluator, updatedVals[0], updatedVals[1],
                            encoder, encryptor, learningRate_e, decryptor)
        ypred = updatedVals_unenc[0] * x + updatedVals_unenc[1]
        error = ypred - y
        updatedVals_unenc[0] = updatedVals_unenc[0] - x * error * learningRate
        updatedVals_unenc[1] = updatedVals_unenc[1] - error * learningRate
        print((str)(updatedVals[1]) + ":" + (str)(updatedVals[0]) + ":" +
              (str)(updatedVals_unenc[1]) + ":" + (str)(updatedVals_unenc[0]))

        x = 3
        y = 2
        updatedVals = learn(x, y, evaluator, updatedVals[0], updatedVals[1],
                            encoder, encryptor, learningRate_e, decryptor)
        ypred = updatedVals_unenc[0] * x + updatedVals_unenc[1]
        error = ypred - y
        updatedVals_unenc[0] = updatedVals_unenc[0] - x * error * learningRate
        updatedVals_unenc[1] = updatedVals_unenc[1] - error * learningRate
        print((str)(updatedVals[1]) + ":" + (str)(updatedVals[0]) + ":" +
              (str)(updatedVals_unenc[1]) + ":" + (str)(updatedVals_unenc[0]))

        x = 5
        y = 5
        updatedVals = learn(x, y, evaluator, updatedVals[0], updatedVals[1],
                            encoder, encryptor, learningRate_e, decryptor)
        ypred = updatedVals_unenc[0] * x + updatedVals_unenc[1]
        error = ypred - y
        updatedVals_unenc[0] = updatedVals_unenc[0] - x * error * learningRate
        updatedVals_unenc[1] = updatedVals_unenc[1] - error * learningRate
        print((str)(updatedVals[1]) + ":" + (str)(updatedVals[0]) + ":" +
              (str)(updatedVals_unenc[1]) + ":" + (str)(updatedVals_unenc[0]))