Example #1
0
    def set_parms(self, parms: EncryptionParameters, print_parms=False):
        self._parms = parms
        self._context = SEALContext.Create(self._parms)
        self._encoder = IntegerEncoder(self._context)
        self._evaluator = Evaluator(self._context)

        if print_parms:
            self.print_parameters(self._context)
Example #2
0
    def __init__(self):

        # set parameters for encryption
        parms = EncryptionParameters()
        parms.set_poly_modulus("1x^2048 + 1")
        parms.set_coeff_modulus(seal.coeff_modulus_128(2048))
        parms.set_plain_modulus(1 << 8)
       
        self.context = SEALContext(parms)
        keygen = KeyGenerator(self.context)
        self.encoder = IntegerEncoder(self.context.plain_modulus())
      
        public_key = keygen.public_key()
        self.encryptor = Encryptor(self.context, public_key)
      
        secret_key = keygen.secret_key()
        self.decryptor = Decryptor(self.context, secret_key)
def encryption(value):
    # IntegerEncoder with base 2
    encoder = IntegerEncoder(context.plain_modulus())

    # generate public/private keys
    keygen = KeyGenerator(context)
    public_key = keygen.public_key()
    secret_key = keygen.secret_key()

    # encrypts public key
    encryptor = Encryptor(context, public_key)

    # perform computations on ciphertexts
    evaluator = Evaluator(context)

    # decrypts secret key
    decryptor = Decryptor(context, secret_key)

    # perform encryptions
    plaintext = encoder.encode(value)

    # convert into encrypted ciphertext
    encrypt = Ciphertext()
    encryptor.encrypt(plaintext, encrypt)
    print("Encryption successful!")
    print("Encrypted ciphertext: " + (str)(value) + " as " +
          plaintext.to_string())

    # noise budget of fresh encryptions
    print("Noise budget: " + (str)(decryptor.invariant_noise_budget(encrypt)) +
          " bits")

    # decrypts result
    result = Plaintext()
    decryptor.decrypt(encrypt, result)
    print("Decryption successful!")

    print("Plaintext: " + result.to_string())

    # decode for original integer
    print("Original node: " + (str)(encoder.decode_int32(result)) + "\n")
Example #4
0
def test2():
    img_path = '00001.jpg'
    img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
    print("Original image dimensions {}".format(img.shape))
    sift = cv2.xfeatures2d.SIFT_create()
    (kps, desc) = sift.detectAndCompute(img, None)

    desc = preprocessing.normalize(np.array(
        desc.flatten()[:DESC_SIZE]).reshape(1, DESC_SIZE),
                                   norm='l2')
    descriptor_vec1 = desc
    descriptor_vec2 = descriptor_vec1
    context = config()
    public_key, secret_key = keygen(context)

    encoder = IntegerEncoder(context.plain_modulus())
    encryptor = Encryptor(context, public_key)
    crtbuilder = PolyCRTBuilder(context)
    evaluator = Evaluator(context)
    decryptor = Decryptor(context, secret_key)

    slot_count = (int)(crtbuilder.slot_count())
    print("slot count {}".format(slot_count))
    print("Plaintext shape", descriptor_vec1.shape)
    plain_matrix = decompose_plain(slot_count, descriptor_vec1, crtbuilder)

    for i in range(10000):
        encrypted_matrix = Ciphertext()
        print("Encrypting: ")
        time_start = time.time()
        encryptor.encrypt(plain_matrix, encrypted_matrix)
        time_end = time.time()
        print("Done in time {}".format((str)(1000 * (time_end - time_start))))

        print("Square:")
        time_start = time.time()
        evaluator.square(encrypted_matrix)
        time_end = time.time()
        print("Square is done in {} miliseconds".format(
            (str)(1000 * (time_end - time_start))))

        plain_result = Plaintext()
        print("Decryption plain: ")
        time_start = time.time()
        decryptor.decrypt(encrypted_matrix, plain_result)
        time_end = time.time()
        print("Decryption is done in {} miliseconds".format(
            (str)(1000 * (time_end - time_start))))
        # print("Plaintext polynomial: {}".format(plain_result.to_string()))
        # print("Decoded integer: {}".format(encoder.decode_int32(plain_result)))
        print("Noise budget {} bits".format(
            decryptor.invariant_noise_budget(encrypted_matrix)))
Example #5
0
def initialize_encryption():
	print_example_banner("Example: Basics I");
	parms = EncryptionParameters()
	parms.set_poly_modulus("1x^2048 + 1")
	# factor: 0xfffffffff00001.
	parms.set_coeff_modulus(seal.coeff_modulus_128(2048))
	parms.set_plain_modulus(1 << 8)
	context = SEALContext(parms)
	print_parameters(context);
	# Here we choose to create an IntegerEncoder with base b=2.
	encoder = IntegerEncoder(context.plain_modulus())
	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)
	return encryptor, evaluator, decryptor, encoder, context
Example #6
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,
         )
# to determine the security of their parameter choices.

# Our recommended values for the coefficient modulus can be easily accessed
# through the functions

#     coeff_modulus_128bit(int)
#     coeff_modulus_192bit(int)
parms.set_coeff_modulus(seal.coeff_modulus_128(2048))
# The plaintext modulus can be any positive integer, even though here we take
# it to be a power of two.
parms.set_plain_modulus(1 << 8)
# 1 << 8 is bitwise operation which means 1 shifted eight times ie 2^8=256
context = SEALContext(parms)


encoder = IntegerEncoder(context.plain_modulus())
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)

value=7
plain1 = encoder.encode(value1)
print("Encoded " + (str)(value) + " as polynomial " + plain1.to_string() + " (plain1)")

encrypted _data= Ciphertext()
encryptor.encrypt(plain, encrypted_data)
print("Noise budget in encrypted1: " + (str)(decryptor.invariant_noise_budget(encrypted_data)) + " bits")
Example #8
0
def pickle_ciphertext():
    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 the parameters that we have chosen
    print_parameters(context);

    encoder = IntegerEncoder(context.plain_modulus())


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

    # To be able to encrypt, we need to construct an instance of Encryptor. Note that
    # the Encryptor only requires the public 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)

    # We start by encoding two integers as plaintext polynomials.
    value1 = 5;
    plain1 = encoder.encode(value1);
    print("Encoded " + (str)(value1) + " as polynomial " + plain1.to_string() + " (plain1)")

    value2 = -7;
    plain2 = encoder.encode(value2);
    print("Encoded " + (str)(value2) + " as polynomial " + plain2.to_string() + " (plain2)")

    # Encrypting the values is easy.
    encrypted1 = Ciphertext()
    encrypted2 = Ciphertext()
    print("Encrypting plain1: ", encrypted1)
    encryptor.encrypt(plain1, encrypted1)
    print("Done (encrypted1)", encrypted1)

    print("Encrypting plain2: ")
    encryptor.encrypt(plain2, encrypted2)
    print("Done (encrypted2)")






    # output = open('ciphertest.pkl', 'wb')
    # dill.dumps(encrypted_save, output)
    # output.close()
    # encrypted1 = dill.load(open('ciphertest.pkl', 'rb'))


    output = open('session.pkl', 'wb')
    dill.dump_session('session.pkl')

    del encrypted1
    sill.load_session('session.pkl')







    # To illustrate the concept of noise budget, we print the budgets in the fresh
    # encryptions.
    print("Noise budget in encrypted1: " + (str)(decryptor.invariant_noise_budget(encrypted1)) + " bits")
    print("Noise budget in encrypted2: " + (str)(decryptor.invariant_noise_budget(encrypted2)) + " bits")

    # As a simple example, we compute (-encrypted1 + encrypted2) * encrypted2.

    # Negation is a unary operation.
    evaluator.negate(encrypted1)

    # Negation does not consume any noise budget.
    print("Noise budget in -encrypted1: " + (str)(decryptor.invariant_noise_budget(encrypted1)) + " bits")

    # Addition can be done in-place (overwriting the first argument with the result,
    # or alternatively a three-argument overload with a separate destination variable
    # can be used. The in-place variants are always more efficient. Here we overwrite
    # encrypted1 with the sum.
    evaluator.add(encrypted1, encrypted2)

    # It is instructive to think that addition sets the noise budget to the minimum
    # of the input noise budgets. In this case both inputs had roughly the same
    # budget going on, and the output (in encrypted1) has just slightly lower budget.
    # Depending on probabilistic effects, the noise growth consumption may or may
    # not be visible when measured in whole bits.
    print("Noise budget in -encrypted1 + encrypted2: " + (str)(decryptor.invariant_noise_budget(encrypted1)) + " bits")

    # Finally multiply with encrypted2. Again, we use the in-place version of the
    # function, overwriting encrypted1 with the product.
    evaluator.multiply(encrypted1, encrypted2)

    # Multiplication consumes a lot of noise budget. This is clearly seen in the
    # print-out. The user can change the plain_modulus to see its effect on the
    # rate of noise budget consumption.
    print("Noise budget in (-encrypted1 + encrypted2) * encrypted2: " + (str)(
        decryptor.invariant_noise_budget(encrypted1)) + " bits")

    # Now we decrypt and decode our result.
    plain_result = Plaintext()
    print("Decrypting result: ")
    decryptor.decrypt(encrypted1, plain_result)
    print("Done")

    # Print the result plaintext polynomial.
    print("Plaintext polynomial: " + plain_result.to_string())

    # Decode to obtain an integer result.
    print("Decoded integer: " + (str)(encoder.decode_int32(plain_result)))
Example #9
0
print("Importing dataset...")
data = pd.read_csv('/app/Social_Network_Ads.csv')
dataset = data.iloc[:, [2, 3, 4]].values
#dataset1 = data.iloc [:, [2, 3]].values
print("Done\n\n\n")

print("Setting encryption parameters...")
parms = EncryptionParameters()
parms.set_poly_modulus("1x^16384 + 1")
parms.set_coeff_modulus(seal.coeff_modulus_128(16384))
parms.set_plain_modulus(1 << 12)
print("Done\n\n\n")

context = SEALContext(parms)
#print_parameters(context);
encoder = IntegerEncoder(context.plain_modulus())
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)
encoder = FractionalEncoder(context.plain_modulus(), context.poly_modulus(),
                            2048, 32, 3)

X, Y = splitDataset(dataset, 0.8)
size = len(X)
size_y = len(Y)

X1 = [[0 for x in range(2)] for y in range(size)]
Y1 = [[0 for x in range(2)] for y in range(size)]
                 Plaintext,            \
                 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())
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)

A = []
n = int(input("Enter dimension: "))

for i in range(n):
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)
Example #12
0
def example_integer_encoder():
    print("Example: Encoders / Integer Encoder")
    #[IntegerEncoder] (For BFV scheme only)
    #
    #The IntegerEncoder encodes integers to BFV plaintext polynomials as follows.
    #First, a binary expansion of the integer is computed. Next, a polynomial is
    #created with the bits as coefficients. For example, the integer
    #
    #    26 = 2^4 + 2^3 + 2^1
    #
    #is encoded as the polynomial 1x^4 + 1x^3 + 1x^1. Conversely, plaintext
    #polynomials are decoded by evaluating them at x=2. For negative numbers the
    #IntegerEncoder simply stores all coefficients as either 0 or -1, where -1 is
    #represented by the unsigned integer plain_modulus - 1 in memory.
    #
    #Since encrypted computations operate on the polynomials rather than on the
    #encoded integers themselves, the polynomial coefficients will grow in the
    #course of such computations. For example, computing the sum of the encrypted
    #encoded integer 26 with itself will result in an encrypted polynomial with
    #larger coefficients: 2x^4 + 2x^3 + 2x^1. Squaring the encrypted encoded
    #integer 26 results also in increased coefficients due to cross-terms, namely,
    #
    #    (2x^4 + 2x^3 + 2x^1)^2 = 1x^8 + 2x^7 + 1x^6 + 2x^5 + 2x^4 + 1x^2;
    #
    #further computations will quickly increase the coefficients much more.
    #Decoding will still work correctly in this case (evaluating the polynomial
    #at x=2), but since the coefficients of plaintext polynomials are really
    #integers modulo plain_modulus, implicit reduction modulo plain_modulus may
    #yield unexpected results. For example, adding 1x^4 + 1x^3 + 1x^1 to itself
    #plain_modulus many times will result in the constant polynomial 0, which is
    #clearly not equal to 26 * plain_modulus. It can be difficult to predict when
    #such overflow will take place especially when computing several sequential
    #multiplications.
    #
    #The IntegerEncoder is easy to understand and use for simple computations,
    #and can be a good tool to experiment with for users new to Microsoft SEAL.
    #However, advanced users will probably prefer more efficient approaches,
    #such as the BatchEncoder or the CKKSEncoder.

    parms = EncryptionParameters(scheme_type.BFV)
    poly_modulus_degree = 4096
    parms.set_poly_modulus_degree(poly_modulus_degree)
    parms.set_coeff_modulus(CoeffModulus.BFVDefault(poly_modulus_degree))

    #There is no hidden logic behind our choice of the plain_modulus. The only
    #thing that matters is that the plaintext polynomial coefficients will not
    #exceed this value at any point during our computation; otherwise the result
    #will be incorrect.

    parms.set_plain_modulus(512)
    context = SEALContext.Create(parms)
    print_parameters(context)

    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)

    #We create an IntegerEncoder.
    encoder = IntegerEncoder(context)

    #First, we encode two integers as plaintext polynomials. Note that encoding
    #is not encryption: at this point nothing is encrypted.
    value1 = 5
    plain1 = encoder.encode(value1)
    print("Encode {} as polynomial {} (plain1), ".format(
        value1, plain1.to_string()))

    value2 = -7
    plain2 = encoder.encode(value2)
    print("    encode {} as polynomial {} (plain2)".format(
        value2, plain2.to_string()))

    #Now we can encrypt the plaintext polynomials.
    encrypted1 = Ciphertext()
    encrypted2 = Ciphertext()
    print("Encrypt plain1 to encrypted1 and plain2 to encrypted2.")
    encryptor.encrypt(plain1, encrypted1)
    encryptor.encrypt(plain2, encrypted2)
    print("    + Noise budget in encrypted1: {} bits".format(
        decryptor.invariant_noise_budget(encrypted1)))
    print("    + Noise budget in encrypted2: {} bits".format(
        decryptor.invariant_noise_budget(encrypted2)))

    #As a simple example, we compute (-encrypted1 + encrypted2) * encrypted2.
    encryptor.encrypt(plain2, encrypted2)
    encrypted_result = Ciphertext()
    print(
        "Compute encrypted_result = (-encrypted1 + encrypted2) * encrypted2.")
    evaluator.negate(encrypted1, encrypted_result)
    evaluator.add_inplace(encrypted_result, encrypted2)
    evaluator.multiply_inplace(encrypted_result, encrypted2)
    print("    + Noise budget in encrypted_result: {} bits".format(
        decryptor.invariant_noise_budget(encrypted_result)))
    plain_result = Plaintext()
    print("Decrypt encrypted_result to plain_result.")
    decryptor.decrypt(encrypted_result, plain_result)

    #Print the result plaintext polynomial. The coefficients are not even close
    #to exceeding our plain_modulus, 512.
    print("    + Plaintext polynomial: {}".format(plain_result.to_string()))

    #Decode to obtain an integer result.
    print("Decode plain_result.")
    print("    + Decoded integer: {} ...... Correct.".format(
        encoder.decode_int32(plain_result)))
Example #13
0
class Encryption:
    '''
    Provides encryption / encoding methods to realize the homomorphic operations
    '''

    
    def __init__(self):

        # set parameters for encryption
        parms = EncryptionParameters()
        parms.set_poly_modulus("1x^2048 + 1")
        parms.set_coeff_modulus(seal.coeff_modulus_128(2048))
        parms.set_plain_modulus(1 << 8)
       
        self.context = SEALContext(parms)
        keygen = KeyGenerator(self.context)
        self.encoder = IntegerEncoder(self.context.plain_modulus())
      
        public_key = keygen.public_key()
        self.encryptor = Encryptor(self.context, public_key)
      
        secret_key = keygen.secret_key()
        self.decryptor = Decryptor(self.context, secret_key)
      
        
      
    def encrypt_live_neighbours_grid(self, live_neighbours_grid, dim):
        '''
        Encodes the live neighbor matrix by applying following rules. If the cell [i][j] has 2 neighbors with 0,
        3 neighbors with 2, and otherwise with -2. Afterwards encrypt it using PySEAL and store in a list

        :param live_neighbours_grid: live neighbor matrix as np array
        :param dim: dimension of the board
        :return: List of encoded and encrypted neighbors
        '''

        encrypted_live_neighbours_grid = []

        # Loop through every element of the board and encrypt it
        for i in range(dim):
           for j in range(dim):
               # transformation / encoding rules
               if(live_neighbours_grid[i][j] == 2):
                   value = 0
               elif(live_neighbours_grid[i][j] == 3):
                    value = 2
               elif(live_neighbours_grid[i][j] > 3 or live_neighbours_grid[i][j] < 2):
                    value = -2
                
               # element-wise homomorphic encryption
               encrypted = Ciphertext()
               plain = self.encoder.encode(value)
               self.encryptor.encrypt(plain, encrypted)
               encrypted_live_neighbours_grid.append(encrypted)
                
        return encrypted_live_neighbours_grid
    
    def encrypt_old_grid(self, old_grid, dim):
        '''
        Encrypts each element in the old board state using PySEAL and adds it to a list

        :param old_grid:
        :param dim:
        :return:
        '''
        
        encrypted_old_grid = []

        # Loop through every element of the board and encrypt it
        for i in range(dim):
            for j in range(dim):
                # element-wise homomorphic encryption
                encrypted = Ciphertext()
                value = old_grid[i][j]
                plain = self.encoder.encode(value)
                self.encryptor.encrypt(plain, encrypted)
                encrypted_old_grid.append(encrypted)
               
        return encrypted_old_grid
    
    def decrypt_new_grid(self, encrypted_new_grid, dim):
        '''
        Decrypts a homomorphic-encrypted grid by looping through every element,
        decrypt it and then applying the decoding rules to get the new board state

        :param encrypted_new_grid:
        :param dim:
        :return:
        '''

        new_grid = numpy.zeros(dim*dim, dtype='i').reshape(dim,dim)
        
        for i in range(dim):
          for j in range(dim):
              plain = Plaintext()
              
              encrypted = encrypted_new_grid[dim*i + j]
                  
              self.decryptor.decrypt(encrypted, plain)
              value = self.encoder.decode_int32(plain)
              
              # transformation / decoding rules
              if(value <= 0):
                  new_grid[i][j] = 0
              elif(value > 0):
                  new_grid[i][j] = 1
              
        return new_grid
Example #14
0
def example_basics_i():
    print_example_banner("Example: Basics I")

    # In this example we demonstrate setting up encryption parameters and other
    # relevant objects for performing simple computations on encrypted integers.

    # SEAL uses the Fan-Vercauteren (FV) homomorphic encryption scheme. We refer to
    # https://eprint.iacr.org/2012/144 for full details on how the FV scheme works.
    # For better performance, SEAL implements the "FullRNS" optimization of FV, as
    # described in https://eprint.iacr.org/2016/510.

    # The first task is to set up an instance of the EncryptionParameters class.
    # It is critical to understand how these different parameters behave, how they
    # affect the encryption scheme, performance, and the security level. There are
    # three encryption parameters that are necessary to set:

    #     - poly_modulus (polynomial modulus);
    #     - coeff_modulus ([ciphertext] coefficient modulus);
    #     - plain_modulus (plaintext modulus).

    # A fourth parameter -- noise_standard_deviation -- has a default value of 3.19
    # and should not be necessary to modify unless the user has a specific reason
    # to and knows what they are doing.

    # The encryption scheme implemented in SEAL cannot perform arbitrary computations
    # on encrypted data. Instead, each ciphertext has a specific quantity called the
    # `invariant noise budget' -- or `noise budget' for short -- measured in bits.
    # The noise budget of a freshly encrypted ciphertext (initial noise budget) is
    # determined by the encryption parameters. Homomorphic operations consume the
    # noise budget at a rate also determined by the encryption parameters. In SEAL
    # the two basic homomorphic operations are additions and multiplications, of
    # which additions can generally be thought of as being nearly free in terms of
    # noise budget consumption compared to multiplications. Since noise budget
    # consumption is compounding in sequential multiplications, the most significant
    # factor in choosing appropriate encryption parameters is the multiplicative
    # depth of the arithmetic circuit that needs to be evaluated. Once the noise
    # budget in a ciphertext reaches zero, it becomes too corrupted to be decrypted.
    # Thus, it is essential to choose the parameters to be large enough to support
    # the desired computation; otherwise the result is impossible to make sense of
    # even with the secret key.
    parms = EncryptionParameters()

    # We first set the polynomial modulus. This must be a power-of-2 cyclotomic
    # polynomial, i.e. a polynomial of the form "1x^(power-of-2) + 1". The polynomial
    # modulus should be thought of mainly affecting the security level of the scheme;
    # larger polynomial modulus makes the scheme more secure. At the same time, it
    # makes ciphertext sizes larger, and consequently all operations slower.
    # Recommended degrees for poly_modulus are 1024, 2048, 4096, 8192, 16384, 32768,
    # but it is also possible to go beyond this. Since we perform only a very small
    # computation in this example, it suffices to use a very small polynomial modulus
    parms.set_poly_modulus("1x^2048 + 1")

    # Next we choose the [ciphertext] coefficient modulus (coeff_modulus). The size
    # of the coefficient modulus should be thought of as the most significant factor
    # in determining the noise budget in a freshly encrypted ciphertext: bigger means
    # more noise budget. Unfortunately, a larger coefficient modulus also lowers the
    # security level of the scheme. Thus, if a large noise budget is required for
    # complicated computations, a large coefficient modulus needs to be used, and the
    # reduction in the security level must be countered by simultaneously increasing
    # the polynomial modulus.

    # To make parameter selection easier for the user, we have constructed sets of
    # largest allowed coefficient moduli for 128-bit and 192-bit security levels
    # for different choices of the polynomial modulus. These recommended parameters
    # follow the Security white paper at http://HomomorphicEncryption.org. However,
    # due to the complexity of this topic, we highly recommend the user to directly
    # consult an expert in homomorphic encryption and RLWE-based encryption schemes
    # to determine the security of their parameter choices.

    # Our recommended values for the coefficient modulus can be easily accessed
    # through the functions

    #     coeff_modulus_128bit(int)
    #     coeff_modulus_192bit(int)

    # for 128-bit and 192-bit security levels. The integer parameter is the degree
    # of the polynomial modulus.

    # In SEAL the coefficient modulus is a positive composite number -- a product
    # of distinct primes of size up to 60 bits. When we talk about the size of the
    # coefficient modulus we mean the bit length of the product of the small primes.
    # The small primes are represented by instances of the SmallModulus class; for
    # example coeff_modulus_128bit(int) returns a vector of SmallModulus instances.

    # It is possible for the user to select their own small primes. Since SEAL uses
    # the Number Theoretic Transform (NTT) for polynomial multiplications modulo the
    # factors of the coefficient modulus, the factors need to be prime numbers
    # congruent to 1 modulo 2*degree(poly_modulus). We have generated a list of such
    # prime numbers of various sizes, that the user can easily access through the
    # functions

    #     small_mods_60bit(int)
    #     small_mods_50bit(int)
    #     small_mods_40bit(int)
    #     small_mods_30bit(int)

    # each of which gives access to an array of primes of the denoted size. These
    # primes are located in the source file util/globals.cpp.

    # Performance is mainly affected by the size of the polynomial modulus, and the
    # number of prime factors in the coefficient modulus. Thus, it is important to
    # use as few factors in the coefficient modulus as possible.

    # In this example we use the default coefficient modulus for a 128-bit security
    # level. Concretely, this coefficient modulus consists of only one 56-bit prime
    # factor: 0xfffffffff00001.
    parms.set_coeff_modulus(seal.coeff_modulus_128(2048))

    # The plaintext modulus can be any positive integer, even though here we take
    # it to be a power of two. In fact, in many cases one might instead want it to
    # be a prime number; we will see this in example_batching(). The plaintext
    # modulus determines the size of the plaintext data type, but it also affects
    # the noise budget in a freshly encrypted ciphertext, and the consumption of
    # the noise budget in homomorphic multiplication. Thus, it is essential to try
    # to keep the plaintext data type as small as possible for good performance.
    # The noise budget in a freshly encrypted ciphertext is

    #     ~ log2(coeff_modulus/plain_modulus) (bits)

    # and the noise budget consumption in a homomorphic multiplication is of the
    # form log2(plain_modulus) + (other terms).
    parms.set_plain_modulus(1 << 8)

    # Now that all parameters are set, we are ready to construct a SEALContext
    # object. This is a heavy class that checks the validity and properties of
    # the parameters we just set, and performs and stores several important
    # pre-computations.
    context = SEALContext(parms)

    # Print the parameters that we have chosen
    print_parameters(context)

    # Plaintexts in the FV scheme are polynomials with coefficients integers modulo
    # plain_modulus. To encrypt for example integers instead, one can use an
    # `encoding scheme' to represent the integers as such polynomials. SEAL comes
    # with a few basic encoders:

    # [IntegerEncoder]
    # Given an integer base b, encodes integers as plaintext polynomials as follows.
    # First, a base-b expansion of the integer is computed. This expansion uses
    # a `balanced' set of representatives of integers modulo b as the coefficients.
    # Namely, when b is odd the coefficients are integers between -(b-1)/2 and
    # (b-1)/2. When b is even, the integers are between -b/2 and (b-1)/2, except
    # when b is two and the usual binary expansion is used (coefficients 0 and 1).
    # Decoding amounts to evaluating the polynomial at x=b. For example, if b=2,
    # the integer

    #     26 = 2^4 + 2^3 + 2^1

    # is encoded as the polynomial 1x^4 + 1x^3 + 1x^1. When b=3,

    #     26 = 3^3 - 3^0

    # is encoded as the polynomial 1x^3 - 1. In memory polynomial coefficients are
    # always stored as unsigned integers by storing their smallest non-negative
    # representatives modulo plain_modulus. To create a base-b integer encoder,
    # use the constructor IntegerEncoder(plain_modulus, b). If no b is given, b=2
    # is used.

    # [FractionalEncoder]
    # The FractionalEncoder encodes fixed-precision rational numbers as follows.
    # It expands the number in a given base b, possibly truncating an infinite
    # fractional part to finite precision, e.g.

    #     26.75 = 2^4 + 2^3 + 2^1 + 2^(-1) + 2^(-2)

    # when b=2. For the sake of the example, suppose poly_modulus is 1x^1024 + 1.
    # It then represents the integer part of the number in the same way as in
    # IntegerEncoder (with b=2 here), and moves the fractional part instead to the
    # highest degree part of the polynomial, but with signs of the coefficients
    # changed. In this example we would represent 26.75 as the polynomial

    #     -1x^1023 - 1x^1022 + 1x^4 + 1x^3 + 1x^1.

    # In memory the negative coefficients of the polynomial will be represented as
    # their negatives modulo plain_modulus.

    # [PolyCRTBuilder]
    # If plain_modulus is a prime congruent to 1 modulo 2*degree(poly_modulus), the
    # plaintext elements can be viewed as 2-by-(degree(poly_modulus) / 2) matrices
    # with elements integers modulo plain_modulus. When a desired computation can be
    # vectorized, using PolyCRTBuilder can result in massive performance improvements
    # over naively encrypting and operating on each input number separately. Thus,
    # in more complicated computations this is likely to be by far the most important
    # and useful encoder. In example_batching() we show how to use and operate on
    # encrypted matrix plaintexts.

    # For performance reasons, in homomorphic encryption one typically wants to keep
    # the plaintext data types as small as possible, which can make it challenging to
    # prevent data type overflow in more complicated computations, especially when
    # operating on rational numbers that have been scaled to integers. When using
    # PolyCRTBuilder estimating whether an overflow occurs is a fairly standard task,
    # as the matrix slots are integers modulo plain_modulus, and each slot is operated
    # on independently of the others. When using IntegerEncoder or FractionalEncoder
    # it is substantially more difficult to estimate when an overflow occurs in the
    # plaintext, and choosing the plaintext modulus very carefully to be large enough
    # is critical to avoid unexpected results. Specifically, one needs to estimate how
    # large the largest coefficient in  the polynomial view of all of the plaintext
    # elements becomes, and choose the plaintext modulus to be larger than this value.
    # SEAL comes with an automatic parameter selection tool that can help with this
    # task, as is demonstrated in example_parameter_selection().

    # Here we choose to create an IntegerEncoder with base b=2.
    encoder = IntegerEncoder(context.plain_modulus())

    # We are now ready to generate the secret and public keys. For this purpose we need
    # an instance of the KeyGenerator class. Constructing a KeyGenerator automatically
    # generates the public and secret key, which can then be read to local variables.
    # 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()

    # To be able to encrypt, we need to construct an instance of Encryptor. Note that
    # the Encryptor only requires the public 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)

    # We start by encoding two integers as plaintext polynomials.
    value1 = 5
    plain1 = encoder.encode(value1)
    print("Encoded " + (str)(value1) + " as polynomial " + plain1.to_string() +
          " (plain1)")

    value2 = -7
    plain2 = encoder.encode(value2)
    print("Encoded " + (str)(value2) + " as polynomial " + plain2.to_string() +
          " (plain2)")

    # Encrypting the values is easy.
    encrypted1 = Ciphertext()
    encrypted2 = Ciphertext()
    print("Encrypting plain1: ")
    encryptor.encrypt(plain1, encrypted1)
    print("Done (encrypted1)")

    print("Encrypting plain2: ")
    encryptor.encrypt(plain2, encrypted2)
    print("Done (encrypted2)")

    # To illustrate the concept of noise budget, we print the budgets in the fresh
    # encryptions.
    print("Noise budget in encrypted1: " +
          (str)(decryptor.invariant_noise_budget(encrypted1)) + " bits")
    print("Noise budget in encrypted2: " +
          (str)(decryptor.invariant_noise_budget(encrypted2)) + " bits")

    # As a simple example, we compute (-encrypted1 + encrypted2) * encrypted2.

    # Negation is a unary operation.
    evaluator.negate(encrypted1)

    # Negation does not consume any noise budget.
    print("Noise budget in -encrypted1: " +
          (str)(decryptor.invariant_noise_budget(encrypted1)) + " bits")

    # Addition can be done in-place (overwriting the first argument with the result,
    # or alternatively a three-argument overload with a separate destination variable
    # can be used. The in-place variants are always more efficient. Here we overwrite
    # encrypted1 with the sum.
    evaluator.add(encrypted1, encrypted2)

    # It is instructive to think that addition sets the noise budget to the minimum
    # of the input noise budgets. In this case both inputs had roughly the same
    # budget going on, and the output (in encrypted1) has just slightly lower budget.
    # Depending on probabilistic effects, the noise growth consumption may or may
    # not be visible when measured in whole bits.
    print("Noise budget in -encrypted1 + encrypted2: " +
          (str)(decryptor.invariant_noise_budget(encrypted1)) + " bits")

    # Finally multiply with encrypted2. Again, we use the in-place version of the
    # function, overwriting encrypted1 with the product.
    evaluator.multiply(encrypted1, encrypted2)

    # Multiplication consumes a lot of noise budget. This is clearly seen in the
    # print-out. The user can change the plain_modulus to see its effect on the
    # rate of noise budget consumption.
    print("Noise budget in (-encrypted1 + encrypted2) * encrypted2: " +
          (str)(decryptor.invariant_noise_budget(encrypted1)) + " bits")

    # Now we decrypt and decode our result.
    plain_result = Plaintext()
    print("Decrypting result: ")
    decryptor.decrypt(encrypted1, plain_result)
    print("Done")

    # Print the result plaintext polynomial.
    print("Plaintext polynomial: " + plain_result.to_string())

    # Decode to obtain an integer result.
    print("Decoded integer: " + (str)(encoder.decode_int32(plain_result)))
Example #15
0
                 Plaintext,            \
                 SEALContext,          \
                 EvaluationKeys,       \
                 GaloisKeys,           \
                 PolyCRTBuilder,       \
                 ChooserEncoder,       \
                 ChooserEvaluator,     \
                 ChooserPoly

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

encoder = IntegerEncoder(context.plain_modulus())
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)

A=[]
X=[]
n=int(input("Enter dimension: "))

for i in range(n):
	a=[]
	x=[]
	for j in range(n):