コード例 #1
0
ファイル: homenc.py プロジェクト: phapdn/HE_LogReg
 def __neg__(self):
     result = EncNum(Ciphertext(self.encrypted))
     evaluator.negate(result.encrypted)
     return result
コード例 #2
0
evaluator = Evaluator(context)

decryptor = Decryptor(context, secret_key)

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

value2 = 15
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")
コード例 #3
0
ファイル: datatypes.py プロジェクト: wgxli/simple-fhe
def load_encrypted_value(filepath: str) -> EncryptedValue:
    """Loads a saved encrypted value from the given file."""
    ciphertext = Ciphertext()
    ciphertext.load(simplefhe._context, filepath)
    return EncryptedValue(ciphertext)
コード例 #4
0
def plainMultiplication(element, d):
    delta = encoderF.encode(d)
    temp = Ciphertext()
    evaluator.multiply_plain(element, delta, temp)
    evaluator.relinearize(temp, ev_keys)
    return (temp)
コード例 #5
0
ファイル: seal_matrix.py プロジェクト: uriariel/ppsvm
 def __init__(self, rows: int, cols: int):
     self.rows = rows
     self.cols = cols
     self.data = tuple(Ciphertext() for i in range(rows))
コード例 #6
0
def example_ckks_encoder():
    print("Example: Encoders / CKKS Encoder")

    #[CKKSEncoder] (For CKKS scheme only)
    #
    #In this example we demonstrate the Cheon-Kim-Kim-Song (CKKS) scheme for
    #computing on encrypted real or complex numbers. We start by creating
    #encryption parameters for the CKKS scheme. There are two important
    #differences compared to the BFV scheme:
    #
    #    (1) CKKS does not use the plain_modulus encryption parameter;
    #    (2) Selecting the coeff_modulus in a specific way can be very important
    #        when using the CKKS scheme. We will explain this further in the file
    #        `ckks_basics.cpp'. In this example we use CoeffModulus::Create to
    #        generate 5 40-bit prime numbers.

    parms = EncryptionParameters(scheme_type.CKKS)

    poly_modulus_degree = 8192
    parms.set_poly_modulus_degree(poly_modulus_degree)
    parms.set_coeff_modulus(
        CoeffModulus.Create(poly_modulus_degree,
                            IntVector([40, 40, 40, 40, 40])))

    #We create the SEALContext as usual and print the parameters.
    context = SEALContext.Create(parms)
    print_parameters(context)

    #Keys are created the same way as for the BFV scheme.
    keygen = KeyGenerator(context)
    public_key = keygen.public_key()
    secret_key = keygen.secret_key()
    relin_keys = keygen.relin_keys()

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

    #To create CKKS plaintexts we need a special encoder: there is no other way
    #to create them. The IntegerEncoder and BatchEncoder cannot be used with the
    #CKKS scheme. The CKKSEncoder encodes vectors of real or complex numbers into
    #Plaintext objects, which can subsequently be encrypted. At a high level this
    #looks a lot like what BatchEncoder does for the BFV scheme, but the theory
    #behind it is completely different.

    encoder = CKKSEncoder(context)

    #In CKKS the number of slots is poly_modulus_degree / 2 and each slot encodes
    #one real or complex number. This should be contrasted with BatchEncoder in
    #the BFV scheme, where the number of slots is equal to poly_modulus_degree
    #and they are arranged into a matrix with two rows.

    slot_count = encoder.slot_count()
    print("Number of slots: {}".format(slot_count))

    #We create a small vector to encode; the CKKSEncoder will implicitly pad it
    #with zeros to full size (poly_modulus_degree / 2) when encoding.

    input = DoubleVector([0.0, 1.1, 2.2, 3.3])
    print("Input vector: ")
    print_vector(input)

    #Now we encode it with CKKSEncoder. The floating-point coefficients of `input'
    #will be scaled up by the parameter `scale'. This is necessary since even in
    #the CKKS scheme the plaintext elements are fundamentally polynomials with
    #integer coefficients. It is instructive to think of the scale as determining
    #the bit-precision of the encoding; naturally it will affect the precision of
    #the result.
    #
    #In CKKS the message is stored modulo coeff_modulus (in BFV it is stored modulo
    #plain_modulus), so the scaled message must not get too close to the total size
    #of coeff_modulus. In this case our coeff_modulus is quite large (200 bits) so
    #we have little to worry about in this regard. For this simple example a 30-bit
    #scale is more than enough.

    plain = Plaintext()
    scale = 2.0**30
    print("Encode input vector.")
    encoder.encode(input, scale, plain)

    #We can instantly decode to check the correctness of encoding.
    output = DoubleVector()
    print("    + Decode input vector ...... Correct.")
    encoder.decode(plain, output)
    print_vector(output)

    #The vector is encrypted the same was as in BFV.
    encrypted = Ciphertext()
    print("Encrypt input vector, square, and relinearize.")
    encryptor.encrypt(plain, encrypted)

    #Basic operations on the ciphertexts are still easy to do. Here we square the
    #ciphertext, decrypt, decode, and print the result. We note also that decoding
    #returns a vector of full size (poly_modulus_degree / 2); this is because of
    #the implicit zero-padding mentioned above.

    evaluator.square_inplace(encrypted)
    evaluator.relinearize_inplace(encrypted, relin_keys)

    #We notice that the scale in the result has increased. In fact, it is now the
    #square of the original scale: 2^60.

    print("    + Scale in squared input: {} ( {} bits)".format(
        encrypted.scale(), log2(encrypted.scale())))

    print("Decrypt and decode.")
    decryptor.decrypt(encrypted, plain)
    encoder.decode(plain, output)
    print("    + Result vector ...... Correct.")
    print_vector(output)
コード例 #7
0
def example_batching():
    print_example_banner("Example: Batching with PolyCRTBuilder")

    parms = EncryptionParameters()
    parms.set_poly_modulus("1x^4096 + 1")
    parms.set_coeff_modulus(seal.coeff_modulus_128(4096))

    parms.set_plain_modulus(40961)

    context = SEALContext(parms)
    print_parameters(context)

    qualifiers = context.qualifiers()

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

    gal_keys = GaloisKeys()
    keygen.generate_galois_keys(30, gal_keys)

    #ev_keys = EvaluationKeys()
    #keygen.generate_evaluation_keys(30, ev_keys)

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

    crtbuilder = PolyCRTBuilder(context)

    slot_count = (int)(crtbuilder.slot_count())
    row_size = (int)(slot_count / 2)
    print("Plaintext matrix row size: " + (str)(row_size))

    def print_matrix(matrix):
        print("")
        print_size = 5

        current_line = "    ["
        for i in range(print_size):
            current_line += ((str)(matrix[i]) + ", ")
        current_line += ("..., ")
        for i in range(row_size - print_size, row_size):
            current_line += ((str)(matrix[i]))
            if i != row_size - 1: current_line += ", "
            else: current_line += "]"
        print(current_line)

        current_line = "    ["
        for i in range(row_size, row_size + print_size):
            current_line += ((str)(matrix[i]) + ", ")
        current_line += ("..., ")
        for i in range(2 * row_size - print_size, 2 * row_size):
            current_line += ((str)(matrix[i]))
            if i != 2 * row_size - 1: current_line += ", "
            else: current_line += "]"
        print(current_line)
        print("")

    #     [ 0,  1,  2,  3,  0,  0, ...,  0 ]
    #     [ 4,  5,  6,  7,  0,  0, ...,  0 ]
    pod_matrix = [0] * slot_count
    pod_matrix[0] = 0
    pod_matrix[1] = 1
    pod_matrix[2] = 2
    pod_matrix[3] = 3
    pod_matrix[row_size] = 4
    pod_matrix[row_size + 1] = 5
    pod_matrix[row_size + 2] = 6
    pod_matrix[row_size + 3] = 7

    print("Input plaintext matrix:")
    print_matrix(pod_matrix)

    plain_matrix = Plaintext()
    crtbuilder.compose(pod_matrix, plain_matrix)

    encrypted_matrix = Ciphertext()
    print("Encrypting: ")
    encryptor.encrypt(plain_matrix, encrypted_matrix)
    print("Done")
    print("Noise budget in fresh encryption: " +
          (str)(decryptor.invariant_noise_budget(encrypted_matrix)) + " bits")

    pod_matrix2 = []
    for i in range(slot_count):
        pod_matrix2.append((i % 2) + 1)
    plain_matrix2 = Plaintext()
    crtbuilder.compose(pod_matrix2, plain_matrix2)
    print("Second input plaintext matrix:")
    print_matrix(pod_matrix2)

    print("Adding and squaring: ")
    evaluator.add_plain(encrypted_matrix, plain_matrix2)
    evaluator.square(encrypted_matrix)
    evaluator.relinearize(encrypted_matrix, ev_keys)
    print("Done")

    print("Noise budget in result: " +
          (str)(decryptor.invariant_noise_budget(encrypted_matrix)) + " bits")

    plain_result = Plaintext()
    print("Decrypting result: ")
    decryptor.decrypt(encrypted_matrix, plain_result)
    print("Done")

    crtbuilder.decompose(plain_result)
    pod_result = [
        plain_result.coeff_at(i) for i in range(plain_result.coeff_count())
    ]

    print("Result plaintext matrix:")
    print_matrix(pod_result)

    encryptor.encrypt(plain_matrix, encrypted_matrix)
    print("Unrotated matrix: ")
    print_matrix(pod_matrix)
    print("Noise budget in fresh encryption: " +
          (str)(decryptor.invariant_noise_budget(encrypted_matrix)) + " bits")

    # Now rotate the rows to the left 3 steps, decrypt, decompose, and print.
    evaluator.rotate_rows(encrypted_matrix, 3, gal_keys)
    print("Rotated rows 3 steps left: ")
    decryptor.decrypt(encrypted_matrix, plain_result)
    crtbuilder.decompose(plain_result)
    pod_result = [
        plain_result.coeff_at(i) for i in range(plain_result.coeff_count())
    ]
    print_matrix(pod_result)
    print("Noise budget after rotation" +
          (str)(decryptor.invariant_noise_budget(encrypted_matrix)) + " bits")

    # Rotate columns (swap rows), decrypt, decompose, and print.
    evaluator.rotate_columns(encrypted_matrix, gal_keys)
    print("Rotated columns: ")
    decryptor.decrypt(encrypted_matrix, plain_result)
    crtbuilder.decompose(plain_result)
    pod_result = [
        plain_result.coeff_at(i) for i in range(plain_result.coeff_count())
    ]
    print_matrix(pod_result)
    print("Noise budget after rotation: " +
          (str)(decryptor.invariant_noise_budget(encrypted_matrix)) + " bits")

    # Rotate rows to the right 4 steps, decrypt, decompose, and print.
    evaluator.rotate_rows(encrypted_matrix, -4, gal_keys)
    print("Rotated rows 4 steps right: ")
    decryptor.decrypt(encrypted_matrix, plain_result)
    crtbuilder.decompose(plain_result)
    pod_result = [
        plain_result.coeff_at(i) for i in range(plain_result.coeff_count())
    ]
    print_matrix(pod_result)
    print("Noise budget after rotation: " +
          (str)(decryptor.invariant_noise_budget(encrypted_matrix)) + " bits")
コード例 #8
0
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: "))

for i in range(n):
    plain_a = []
    a=[]
    for j in range(n):
        encrypted_data1= Ciphertext()
        ran=random.randint(0,10)
        plain_a.append(ran)
        encryptor.encrypt(encoderF.encode(ran), encrypted_data1)
        a.append(encrypted_data1)
    A.append(a)
    plain_A.append(plain_a)
    print(plain_a)

delta, C = matrixOperations.inverseMatrix(A)

print(delta)
コード例 #9
0
ファイル: LHEtest.py プロジェクト: tanu17/PySEAL
def parallel_encryption(element):
	temp=Ciphertext()
	encryptor.encrypt(encoderF.encode(element), temp)
	return(temp)
コード例 #10
0
ファイル: examples.py プロジェクト: karllab41/PySEAL
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)))
コード例 #11
0
ファイル: examples.py プロジェクト: karllab41/PySEAL
def example_basics_ii():
    print_example_banner("Example: Basics II")

    # In this example we explain what relinearization is, how to use it, and how
    # it affects noise budget consumption.

    # First we set the parameters, create a SEALContext, and generate the public
    # and secret keys. We use slightly larger parameters than be fore to be able
    # to do more homomorphic multiplications.
    parms = EncryptionParameters()
    parms.set_poly_modulus("1x^8192 + 1")

    # The default coefficient modulus consists of the following primes:

    #     0x7fffffffba0001,
    #     0x7fffffffaa0001,
    #     0x7fffffff7e0001,
    #     0x3fffffffd60001.

    # The total size is 219 bits.
    parms.set_coeff_modulus(seal.coeff_modulus_128(8192))
    parms.set_plain_modulus(1 << 10)

    context = SEALContext(parms)
    print_parameters(context)

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

    # We also set up an Encryptor, Evaluator, and Decryptor here. We will
    # encrypt polynomials directly in this example, so there is no need for
    # an encoder.
    encryptor = Encryptor(context, public_key)
    evaluator = Evaluator(context)
    decryptor = Decryptor(context, secret_key)

    # There are actually two more types of keys in SEAL: `evaluation keys' and
    # `Galois keys'. Here we will discuss evaluation keys, and Galois keys will
    # be discussed later in example_batching().

    # In SEAL, a valid ciphertext consists of two or more polynomials with
    # coefficients integers modulo the product of the primes in coeff_modulus.
    # The current size of a ciphertext can be found using Ciphertext::size().
    # A freshly encrypted ciphertext always has size 2.
    #plain1 = Plaintext("1x^2 + 2x^1 + 3")
    plain1 = Plaintext("1x^2 + 2x^1 + 3")
    encrypted = Ciphertext()

    print("")
    print("Encrypting " + plain1.to_string() + ": ")
    encryptor.encrypt(plain1, encrypted)
    print("Done")
    print("Size of a fresh encryption: " + (str)(encrypted.size()))
    print("Noise budget in fresh encryption: " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")

    # Homomorphic multiplication results in the output ciphertext growing in size.
    # More precisely, if the input ciphertexts have size M and N, then the output
    # ciphertext after homomorphic multiplication will have size M+N-1. In this
    # case we square encrypted twice to observe this growth (also observe noise
    # budget consumption).
    evaluator.square(encrypted)
    print("Size after squaring: " + (str)(encrypted.size()))
    print("Noise budget after squaring: " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")
    plain2 = Plaintext()
    decryptor.decrypt(encrypted, plain2)
    print("Second power: " + plain2.to_string())

    evaluator.square(encrypted)
    print("Size after squaring: " + (str)(encrypted.size()))
    print("Noise budget after squaring: " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")

    # It does not matter that the size has grown -- decryption works as usual.
    # Observe from the print-out that the coefficients in the plaintext have
    # grown quite large. One more squaring would cause some of them to wrap
    # around plain_modulus (0x400), and as a result we would no longer obtain
    # the expected result as an integer-coefficient polynomial. We can fix this
    # problem to some extent by increasing plain_modulus. This would make sense,
    # since we still have plenty of noise budget left.
    plain2 = Plaintext()
    decryptor.decrypt(encrypted, plain2)
    print("Fourth power: " + plain2.to_string())

    # The problem here is that homomorphic operations on large ciphertexts are
    # computationally much more costly than on small ciphertexts. Specifically,
    # homomorphic multiplication on input ciphertexts of size M and N will require
    # O(M*N) polynomial multiplications to be performed, and an addition will
    # require O(M+N) additions. Relinearization reduces the size of the ciphertexts
    # after multiplication back to the initial size (2). Thus, relinearizing one
    # or both inputs before the next multiplication, or e.g. before serializing the
    # ciphertexts, can have a huge positive impact on performance.

    # Another problem is that the noise budget consumption in multiplication is
    # bigger when the input ciphertexts sizes are bigger. In a complicated
    # computation the contribution of the sizes to the noise budget consumption
    # can actually become the dominant term. We will point this out again below
    # once we get to our example.

    # Relinearization itself has both a computational cost and a noise budget cost.
    # These both depend on a parameter called `decomposition bit count', which can
    # be any integer at least 1 [dbc_min()] and at most 60 [dbc_max()]. A large
    # decomposition bit count makes relinearization fast, but consumes more noise
    # budget. A small decomposition bit count can make relinearization slower, but
    # might not change the noise budget by any observable amount.

    # Relinearization requires a special type of key called `evaluation keys'.
    # These can be created by the KeyGenerator for any decomposition bit count.
    # To relinearize a ciphertext of size M >= 2 back to size 2, we actually need
    # M-2 evaluation keys. Attempting to relinearize a too large ciphertext with
    # too few evaluation keys will result in an exception being thrown.

    # We repeat our computation, but this time relinearize after both squarings.
    # Since our ciphertext never grows past size 3 (we relinearize after every
    # multiplication), it suffices to generate only one evaluation key.

    # First, we need to create evaluation keys. We use a decomposition bit count
    # of 16 here, which can be thought of as quite small.
    ev_keys16 = EvaluationKeys()

    # This function generates one single evaluation key. Another overload takes
    # the number of keys to be generated as an argument, but one is all we need
    # in this example (see above).
    keygen.generate_evaluation_keys(16, ev_keys16)

    print("")
    print("Encrypting " + plain1.to_string() + ": ")
    encryptor.encrypt(plain1, encrypted)
    print("Done")
    print("Size of a fresh encryption: " + (str)(encrypted.size()))
    print("Noise budget in fresh encryption: " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")

    evaluator.square(encrypted)
    print("Size after squaring: " + (str)(encrypted.size()))
    print("Noise budget after squaring: " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")

    evaluator.relinearize(encrypted, ev_keys16)
    print("Size after relinearization: " + (str)(encrypted.size()))
    print("Noise budget after relinearizing (dbs = " +
          (str)(ev_keys16.decomposition_bit_count()) + "): " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")

    evaluator.square(encrypted)
    print("Size after second squaring: " + (str)(encrypted.size()) + " bits")
    print("Noise budget after second squaring: " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")

    evaluator.relinearize(encrypted, ev_keys16)
    print("Size after relinearization: " + (str)(encrypted.size()))
    print("Noise budget after relinearizing (dbs = " +
          (str)(ev_keys16.decomposition_bit_count()) + "): " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")

    decryptor.decrypt(encrypted, plain2)
    print("Fourth power: " + plain2.to_string())

    # Of course the result is still the same, but this time we actually
    # used less of our noise budget. This is not surprising for two reasons:

    #     - We used a very small decomposition bit count, which is why
    #       relinearization itself did not consume the noise budget by any
    #       observable amount;
    #     - Since our ciphertext sizes remain small throughout the two
    #       squarings, the noise budget consumption rate in multiplication
    #       remains as small as possible. Recall from above that operations
    #       on larger ciphertexts actually cause more noise growth.

    # To make matters even more clear, we repeat the computation a third time,
    # now using the largest possible decomposition bit count (60). We are not
    # measuring the time here, but relinearization with these evaluation keys
    # is significantly faster than with ev_keys16.
    ev_keys60 = EvaluationKeys()
    keygen.generate_evaluation_keys(seal.dbc_max(), ev_keys60)

    print("")
    print("Encrypting " + plain1.to_string() + ": ")
    encryptor.encrypt(plain1, encrypted)
    print("Done")
    print("Size of a fresh encryption: " + (str)(encrypted.size()))
    print("Noise budget in fresh encryption: " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")

    evaluator.square(encrypted)
    print("Size after squaring: " + (str)(encrypted.size()))
    print("Noise budget after squaring: " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")
    evaluator.relinearize(encrypted, ev_keys60)
    print("Size after relinearization: " + (str)(encrypted.size()))
    print("Noise budget after relinearizing (dbc = " +
          (str)(ev_keys60.decomposition_bit_count()) + "): " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")

    evaluator.square(encrypted)
    print("Size after second squaring: " + (str)(encrypted.size()))
    print("Noise budget after second squaring: " +
          (str)(decryptor.invariant_noise_budget) + " bits")
    evaluator.relinearize(encrypted, ev_keys60)
    print("Size after relinearization: " + (str)(encrypted.size()))
    print("Noise budget after relinearizing (dbc = " +
          (str)(ev_keys60.decomposition_bit_count()) + "): " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")

    decryptor.decrypt(encrypted, plain2)
    print("Fourth power: " + plain2.to_string())

    # Observe from the print-out that we have now used significantly more of our
    # noise budget than in the two previous runs. This is again not surprising,
    # since the first relinearization chops off a huge part of the noise budget.

    # However, note that the second relinearization does not change the noise
    # budget by any observable amount. This is very important to understand when
    # optimal performance is desired: relinearization always drops the noise
    # budget from the maximum (freshly encrypted ciphertext) down to a fixed
    # amount depending on the encryption parameters and the decomposition bit
    # count. On the other hand, homomorphic multiplication always consumes the
    # noise budget from its current level. This is why the second relinearization
    # does not change the noise budget anymore: it is already consumed past the
    # fixed amount determinted by the decomposition bit count and the encryption
    # parameters.

    # We now perform a third squaring and observe an even further compounded
    # decrease in the noise budget. Again, relinearization does not consume the
    # noise budget at this point by any observable amount, even with the largest
    # possible decomposition bit count.
    evaluator.square(encrypted)
    print("Size after third squaring " + (str)(encrypted.size()))
    print("Noise budget after third squaring: " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")
    evaluator.relinearize(encrypted, ev_keys60)
    print("Size after relinearization: " + (str)(encrypted.size()))
    print("Noise budget after relinearizing (dbc = " +
          (str)(ev_keys60.decomposition_bit_count()) + "): " +
          (str)(decryptor.invariant_noise_budget(encrypted)) + " bits")

    decryptor.decrypt(encrypted, plain2)
    print("Eighth power: " + plain2.to_string())
コード例 #12
0
    def get_matched_scale_vectors(self, a: Ciphertext,
                                  b: Ciphertext) -> (Ciphertext, Ciphertext):
        a_tag = Ciphertext(a)
        b_tag = Ciphertext(b)

        a_index = self.context.get_context_data(a.parms_id()).chain_index()
        b_index = self.context.get_context_data(b.parms_id()).chain_index()

        # Changing the mod if required, else just setting the scale
        if a_index < b_index:
            self.evaluator.mod_switch_to_inplace(b_tag, a.parms_id())

        elif a_index > b_index:
            self.evaluator.mod_switch_to_inplace(a_tag, b.parms_id())

        a_tag.set_scale(self.scale)
        b_tag.set_scale(self.scale)

        return a_tag, b_tag
コード例 #13
0
 def trace(M):
     t = Ciphertext(M[0][0])
     for i in range(1, len(M)):
         evaluator.add(t, M[i][i])
     return (t)
コード例 #14
0
def trace(M):
	e=Ciphertext()
	encryptor.encrypt("0", encrypted_data2)
	for i in range(0,n):
		evaluator.add(M[i][i],e)
	return (e)
コード例 #15
0
ファイル: homenc.py プロジェクト: phapdn/HE_LogReg
def encrypt(n):
    plain = encoder.encode(n)
    encrypted = Ciphertext()
    encryptor.encrypt(plain, encrypted)
    return EncNum(encrypted)
コード例 #16
0
def scal_encrypt(scal, encryption, encoding):
	plain = encoding.encode(scal)
	encrypted = Ciphertext()
	encryption.encrypt(plain, encrypted)
	return encrypted
コード例 #17
0
def example_batch_encoder():
    print("Example: Encoders / Batch Encoder")

    #[BatchEncoder] (For BFV scheme only)
    #
    #Let N denote the poly_modulus_degree and T denote the plain_modulus. Batching
    #allows the BFV plaintext polynomials to be viewed as 2-by-(N/2) matrices, with
    #each element an integer modulo T. In the matrix view, encrypted operations act
    #element-wise on encrypted matrices, allowing the user to obtain speeds-ups of
    #several orders of magnitude in fully vectorizable computations. Thus, in all
    #but the simplest computations, batching should be the preferred method to use
    #with BFV, and when used properly will result in implementations outperforming
    #anything done with the IntegerEncoder.

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

    #To enable batching, we need to set the plain_modulus to be a prime number
    #congruent to 1 modulo 2*poly_modulus_degree. Microsoft SEAL provides a helper
    #method for finding such a prime. In this example we create a 20-bit prime
    #that supports batching.
    parms.set_plain_modulus(PlainModulus.Batching(poly_modulus_degree, 20))
    context = SEALContext.Create(parms)
    print_parameters(context)

    #We can verify that batching is indeed enabled by looking at the encryption
    #parameter qualifiers created by SEALContext.
    ##HERE
    qualifiers = context.qualifiers()
    print("Batching enabled: {}".format(qualifiers.using_batching))

    keygen = KeyGenerator(context)
    public_key = keygen.public_key()
    secret_key = keygen.secret_key()
    relin_keys = keygen.relin_keys()
    encryptor = Encryptor(context, public_key)
    evaluator = Evaluator(context)
    decryptor = Decryptor(context, secret_key)

    #Batching is done through an instance of the BatchEncoder class.
    batch_encoder = BatchEncoder(context)

    #The total number of batching `slots' equals the poly_modulus_degree, N, and
    #these slots are organized into 2-by-(N/2) matrices that can be encrypted and
    #computed on. Each slot contains an integer modulo plain_modulus.
    slot_count = batch_encoder.slot_count()
    row_size = int(slot_count / 2)
    print("Plaintext matrix row size: {}".format(row_size))

    #The matrix plaintext is simply given to BatchEncoder as a flattened vector
    #of numbers. The first `row_size' many numbers form the first row, and the
    #rest form the second row. Here we create the following matrix:
    #
    #    [ 0,  1,  2,  3,  0,  0, ...,  0 ]
    #    [ 4,  5,  6,  7,  0,  0, ...,  0 ]

    pod_matrix = Int64Vector([0] * slot_count)
    pod_matrix[0] = 0
    pod_matrix[1] = 1
    pod_matrix[2] = 2
    pod_matrix[3] = 3
    pod_matrix[row_size] = 4
    pod_matrix[row_size + 1] = 5
    pod_matrix[row_size + 2] = 6
    pod_matrix[row_size + 3] = 7

    print("Input plaintext matrix:")
    print_matrix(pod_matrix, row_size)

    #First we use BatchEncoder to encode the matrix into a plaintext polynomial.
    plain_matrix = Plaintext()
    print("Encode plaintext matrix:")
    batch_encoder.encode(pod_matrix, plain_matrix)

    #We can instantly decode to verify correctness of the encoding. Note that no
    #encryption or decryption has yet taken place.
    print("    + Decode plaintext matrix ...... Correct.")
    pod_result = Int64Vector([0] * slot_count)
    batch_encoder.decode(plain_matrix, pod_result)
    print_matrix(pod_result, row_size)

    #Next we encrypt the encoded plaintext.
    encrypted_matrix = Ciphertext()
    print("Encrypt plain_matrix to encrypted_matrix.")
    encryptor.encrypt(plain_matrix, encrypted_matrix)
    print("    + Noise budget in encrypted_matrix: {} bits".format(
        decryptor.invariant_noise_budget(encrypted_matrix)))

    #Operating on the ciphertext results in homomorphic operations being performed
    #simultaneously in all 8192 slots (matrix elements). To illustrate this, we
    #form another plaintext matrix
    #
    #    [ 1,  2,  1,  2,  1,  2, ..., 2 ]
    #    [ 1,  2,  1,  2,  1,  2, ..., 2 ]
    #
    #and encode it into a plaintext.

    pod_matrix2 = UInt64Vector([1, 2] * row_size)
    plain_matrix2 = Plaintext()
    batch_encoder.encode(pod_matrix2, plain_matrix2)
    print("Second input plaintext matrix:")
    print_matrix(pod_matrix2, row_size)

    #We now add the second (plaintext) matrix to the encrypted matrix, and square
    #the sum.
    print("Sum, square, and relinearize.")
    evaluator.add_plain_inplace(encrypted_matrix, plain_matrix2)
    evaluator.square_inplace(encrypted_matrix)
    evaluator.relinearize_inplace(encrypted_matrix, relin_keys)

    #How much noise budget do we have left?
    print("    + Noise budget in result: {} bits".format(
        decryptor.invariant_noise_budget(encrypted_matrix)))

    #We decrypt and decompose the plaintext to recover the result as a matrix.
    plain_result = Plaintext()
    print("Decrypt and decode result.")
    decryptor.decrypt(encrypted_matrix, plain_result)
    batch_encoder.decode(plain_result, pod_result)
    print("    + Result plaintext matrix ...... Correct.")
    print_matrix(pod_result, row_size)
コード例 #18
0
        def _new_ciphertext(self, arg=None):

            if arg is None:
                return Ciphertext()
            else:
                return Ciphertext(arg)
コード例 #19
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)))
コード例 #20
0
encrypt_fullMatrix(S_encoded)
print("asdk;vknasifnbsdf")

normalize(rawX0)
# have to find a way to make normalize an encrytped function

for i in range(len(rawX0)):
    rawX0[i] = rawX0[i][1:]
tX = [[1] * 245] + rawX0

# encrypting matrix tX
tX_encrypted = []
for i in range(n):
    tx_enc = []
    for j in range(m):
        temp = Ciphertext()
        encryptor.encrypt(encoderF.encode(S_encoded[i][j]), temp)
        tx_enc.append(temp)
    tX_encrypted.append(tx_enc)

X = [list(tup) for tup in zip(*tX)]

for i in range(len(y)):
    temp = Ciphertext()
    encryptor.encrypt(encoderF.encode(int(y[i])), temp)
    y[i] = temp

k = len(X[0])  # k =3

print("here1")
U1 = matMultiply(tX_encrypted, y)
コード例 #21
0
def trace(M):
    t = Ciphertext()
    diag = np.diag(M)
    evaluator.add_many(diag, t)
    return (t)
コード例 #22
0
def trace(M):
    # calculates trace of a matrix
    t = Ciphertext(M[0][0])
    for i in range(1, n):
        evaluator.add(t, M[i][i])
    return (t)
コード例 #23
0
def inverseMatrix(M):
    n = len(M)
    Power_vector_Half = Power_vector_HalfCalculation(M)
    trace_vector = TraceCalculation(Power_vector_Half)
    coefficientPoly = coefficientPolyCreate(trace_vector, n)

    M_inverse = []
    determinant = coefficientPoly.pop()
    print("determinant by HE: ", decryption_num(determinant))

    # x = [0]*n-i-1 + [1] + [0]*i
    for i in range(n - 1, -1, -1):
        powerMatrix_X = []
        for j in range(len(Power_vector_Half)):
            #a= Power_vector_Half[j][i]
            powerMatrix_X.append(Power_vector_Half[j][i])
            #decrypt_matrix(a)
        # multiplies x with powers I, A, A^2 ... A^( [n/2  + 0.5] )

        for j in range(len(Power_vector_Half), n):
            # to avoid budget of only one matrix to go down, we randomly choose vector.
            # differece will be noticable when matrix is large, here n is 4, so wont matter much here
            partition_1 = random.randint(n // 4 + 1, n // 2)
            if (j - partition_1 >= len(Power_vector_Half)):
                partition_1 = len(Power_vector_Half) - 1
            partition_2 = j - partition_1
            multiplier1 = Power_vector_Half[partition_1][:i + 1]
            multiplier2 = Power_vector_Half[partition_2][i]
            Z = matrixMultiply(multiplier1, multiplier2)
            powerMatrix_X.append(list(Z.flatten()))
        # powerMatrix_X is powerMatrix multiplied by x vector

        for j in range(len(powerMatrix_X)):
            powerMatrix_X[j] = powerMatrix_X[j][:i + 1]
            for l in range(len(powerMatrix_X[j])):
                evaluator.multiply(powerMatrix_X[j][l],
                                   coefficientPoly[n - 1 - j])
                evaluator.relinearize(powerMatrix_X[j][l], ev_keys)

        tInverseRow = [list(tup) for tup in zip(*powerMatrix_X)]
        InverseRow = []
        for z in range(len(tInverseRow)):
            temp = Ciphertext()
            evaluator.add_many(tInverseRow[z], temp)
            InverseRow.append(temp)

        M_inverse.append(InverseRow)

    M_inverse = multiplyDeterminant(M_inverse, determinant)
    assert (n * (n + 1) / 2 == len(M_inverse))
    # recontruct the lower triangle
    X = []
    sInd = 0
    for i in range(n):
        X.append(M_inverse[sInd:sInd + n - i])
        sInd += n - i
    X.reverse()
    # complete the symmetric matrix
    for rowIndex in range(n):
        assert (len(X[rowIndex]) <= n)
        X[rowIndex] += [None] * (n - len(X[rowIndex]))
    for rowIndex in range(n):
        for colIndex in range(rowIndex + 1, n):
            assert (X[rowIndex][colIndex] == None)
            X[rowIndex][colIndex] = X[colIndex][rowIndex]

    X_array = np.asarray(X)
    return (X_array)
コード例 #24
0
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])

for j in range(10):
    evaluator.multiply(A[0], A[1])
    evaluator.multiply(A[0], A[2])
    evaluator.add(A[1], A[2])
    for i in range(len(A)):
        print("Noise budget of [" + str(i) + "] :" +
              str((decryptor.invariant_noise_budget(A[i]))) + " bits")
        print("A[%d]: " % (i), )
        print_value(A[i])