Ejemplo n.º 1
0
    def raw_encrypt(self, plaintext, r_value=None):
        """Paillier encryption of a positive integer plaintext < :attr:`n`.

        You probably should be using :meth:`encrypt` instead, because it
        handles positive and negative ints and floats.

        Args:
          plaintext (int): a positive integer < :attr:`n` to be Paillier
            encrypted. Typically this is an encoding of the actual
            number you want to encrypt.
          r_value (int): obfuscator for the ciphertext; by default (i.e.
            r_value is None), a random value is used.

        Returns:
          int: Paillier encryption of plaintext.

        Raises:
          TypeError: if plaintext is not an int.
        """
        if not isinstance(plaintext, int):
            raise TypeError('Expected int type plaintext but got: %s' %
                            type(plaintext))

        if self.n - self.max_int <= plaintext < self.n:
            # Very large plaintext, take a sneaky shortcut using inverses
            neg_plaintext = self.n - plaintext  # = abs(plaintext - nsquare)
            neg_ciphertext = powmod(self.g, neg_plaintext, self.nsquare)
            nude_ciphertext = invert(neg_ciphertext, self.nsquare)
        else:
            nude_ciphertext = powmod(self.g, plaintext, self.nsquare)

        r = r_value or self.get_random_lt_n()
        obfuscator = powmod(r, self.n, self.nsquare)

        return (nude_ciphertext * obfuscator) % self.nsquare
Ejemplo n.º 2
0
    def raw_encrypt(self, plaintext, r_value=None):
        """DGK encryption of a positive integer plaintext .
		You probably should be using :meth:`encrypt` instead, because it handles positive and negative ints and floats.

		Args:
			plaintext (int): a positive integer < :attr:`n` to be DGK
			encrypted. Typically this is an encoding of the actual 
			number you want to encrypt.
			r_value (int): obfuscator for the ciphertext; by default (i.e.
			r_value is None), a random value of 2t bits is used.
		Returns:
			int: DGK encryption of plaintext.

		Raises:
			TypeError: if plaintext is not an int or mpz.
		"""
        if not isinstance(plaintext, int) and not isinstance(
                plaintext, type(mpz(1))):
            raise TypeError('Expected int type plaintext but got: %s' %
                            type(plaintext))

        nude_ciphertext = powmod(self.g, plaintext, self.n)
        r = r_value or powmod(self.h, self.get_random_lt_2t(),
                              self.n)  # Pass the precomputed obfuscator
        obfuscator = r

        return (nude_ciphertext * obfuscator) % self.n
Ejemplo n.º 3
0
    def raw_decrypt(self, ciphertext):
        """Decrypt raw ciphertext and return raw plaintext.

        Args:
          ciphertext (int): (usually from :meth:`EncryptedNumber.ciphertext()`)
            that is to be Paillier decrypted.

        Returns:
          int: Paillier decryption of ciphertext. This is a positive
          integer < :attr:`public_key.n`.

        Raises:
          TypeError: if ciphertext is not an int.
        """
        if not isinstance(ciphertext, dict):
            raise TypeError('Expected ciphertext to be a dict, not: %s' %
                type(ciphertext))

        #decrypt_to_p = self.l_function(powmod(ciphertext, self.p-1, self.psquare), self.p) * self.hp % self.p
        #decrypt_to_q = self.l_function(powmod(ciphertext, self.q-1, self.qsquare), self.q) * self.hq % self.q
        #return self.crt(decrypt_to_p, decrypt_to_q)

        t1=invert(ciphertext['A'],self.nsquare)
        t2=powmod(t1,self.sk,self.nsquare)
        t3=ciphertext['B']
        t4=t3*t2
        one=powmod(1,1,self.nsquare)
        t5=t4 - one
        t6=t5%self.nsquare
        m = t6 // self.n
        return m
    def raw_decrypt(self, ciphertext):
        """Decrypt raw ciphertext and return raw plaintext.

        Args:
          ciphertext (int): (usually from :meth:`EncryptedNumber.ciphertext()`)
            that is to be Paillier decrypted.

        Returns:
          int: Paillier decryption of ciphertext. This is a positive
          integer < :attr:`public_key.n`.

        Raises:
          TypeError: if ciphertext is not an int.
        """
        if not isinstance(ciphertext, int):
            raise TypeError('Expected ciphertext to be an int, not: %s' %
                            type(ciphertext))

        decrypt_to_p = self.l_function(
            powmod(ciphertext, self.p - 1, self.psquare),
            self.p) * self.hp % self.p
        decrypt_to_q = self.l_function(
            powmod(ciphertext, self.q - 1, self.qsquare),
            self.q) * self.hq % self.q
        return self.crt(decrypt_to_p, decrypt_to_q)
Ejemplo n.º 5
0
    def _raw_mul(self, plaintext):
        """Returns the integer E(a * plaintext), where E(a) = ciphertext

        Args:
          plaintext (int): number by which to multiply the
            `EncryptedNumber`. *plaintext* is typically an encoding.
            0 <= *plaintext* < :attr:`~PaillierPublicKey.n`

        Returns:
          int: Encryption of the product of `self` and the scalar
            encoded in *plaintext*.

        Raises:
          TypeError: if *plaintext* is not an int.
          ValueError: if *plaintext* is not between 0 and
            :attr:`PaillierPublicKey.n`.
        """
        if not isinstance(plaintext, int):
            raise TypeError('Expected ciphertext to be int, not %s' %
                type(plaintext))

        if plaintext < 0 or plaintext >= self.public_key.n:
            raise ValueError('Scalar out of bounds: %i' % plaintext)

        if self.public_key.n - self.public_key.max_int <= plaintext:
            # Very large plaintext, play a sneaky trick using inverses
            neg_c = invert(self.ciphertext(False), self.public_key.nsquare)
            neg_scalar = self.public_key.n - plaintext
            return powmod(neg_c, neg_scalar, self.public_key.nsquare)
        else:
            return powmod(self.ciphertext(False), plaintext, self.public_key.nsquare)
Ejemplo n.º 6
0
    def raw_encrypt(self, plaintext, r_value=None):
        """Paillier encryption of a positive integer plaintext < :attr:`n`.

        You probably should be using :meth:`encrypt` instead, because it
        handles positive and negative ints and floats.

        Args:
          plaintext (int): a positive integer < :attr:`n` to be Paillier
            encrypted. Typically this is an encoding of the actual
            number you want to encrypt.
          r_value (int): obfuscator for the ciphertext; by default (i.e.
            r_value is None), a random value is used.

        Returns:
          int: Paillier encryption of plaintext.

        Raises:
          TypeError: if plaintext is not an int.
        """
        if not isinstance(plaintext, int):
            raise TypeError('Expected int type plaintext but got: %s' %
                            type(plaintext))

        if self.n - self.max_int <= plaintext < self.n:
            # Very large plaintext, take a sneaky shortcut using inverses
            neg_plaintext = self.n - plaintext  # = abs(plaintext - nsquare)
            neg_ciphertext = powmod(self.g, neg_plaintext, self.nsquare)
            nude_ciphertext = invert(neg_ciphertext, self.nsquare)
        else:
            nude_ciphertext = powmod(self.g, plaintext, self.nsquare)

        r = r_value or self.get_random_lt_n()
        obfuscator = powmod(r, self.n, self.nsquare)

        return (nude_ciphertext * obfuscator) % self.nsquare
def is_biprime_parametrized(N, pShares, qShares, testValue):
    """
    Test whether N is the product of two primes.
    If so, this test will succeed with probability 1.
    If N is not the product of two primes, the test will fail with at least 
    probability 1/2.
    """

    values = [
        int(powmod(testValue, x // 4, N)) for x in [
            sum(y) for y in zip(
                list(pShares.values())[1:],
                list(qShares.values())[1:])
        ]
    ]
    values = [
        int(powmod(testValue, (N - pShares[1] - qShares[1] + 1) // 4, N))
    ] + values
    product = mult_list(values[1:])
    if values[0] % N == product % N or values[0] % N == -product % N:
        # Test succeeds, so N is "probably" the product of two primes.
        return True

    # Test fails, so N is definitely not the product of two primes.
    return False
    def _raw_mul(self, plaintext):
        """Returns the integer E(a * plaintext), where E(a) = ciphertext

        Args:
          plaintext (int): number by which to multiply the
            `EncryptedNumber`. *plaintext* is typically an encoding.
            0 <= *plaintext* < :attr:`~PaillierPublicKey.n`

        Returns:
          int: Encryption of the product of `self` and the scalar
            encoded in *plaintext*.

        Raises:
          TypeError: if *plaintext* is not an int.
          ValueError: if *plaintext* is not between 0 and
            :attr:`PaillierPublicKey.n`.
        """
        if not isinstance(plaintext, int):
            raise TypeError('Expected ciphertext to be int, not %s' %
                            type(plaintext))

        if plaintext < 0 or plaintext >= self.public_key.n:
            raise ValueError('Scalar out of bounds: %i' % plaintext)

        if self.public_key.n - self.public_key.max_int <= plaintext:
            # Very large plaintext, play a sneaky trick using inverses
            neg_c = invert(self.ciphertext(False), self.public_key.nsquare)
            neg_scalar = self.public_key.n - plaintext
            return powmod(neg_c, neg_scalar, self.public_key.nsquare)
        else:
            return powmod(self.ciphertext(False), plaintext,
                          self.public_key.nsquare)
    def raw_decrypt(self, ciphertext):
        if not isinstance(ciphertext, int):
            raise TypeError('Expected ciphertext to be an int, not: %s' %
                            type(ciphertext))

        decrypt_to_p = self.l_function(
            powmod(ciphertext, self.p - 1, self.psquare),
            self.p) * self.hp % self.p
        decrypt_to_q = self.l_function(
            powmod(ciphertext, self.q - 1, self.qsquare),
            self.q) * self.hq % self.q
        return self.crt(decrypt_to_p, decrypt_to_q)
    def _raw_mul(self, plaintext):
        if not isinstance(plaintext, int):
            raise TypeError('Expected ciphertext to be int, not %s' %
                            type(plaintext))

        if plaintext < 0 or plaintext >= self.public_key.n:
            raise ValueError('Scalar out of bounds: %i' % plaintext)

        if self.public_key.n - self.public_key.max_int <= plaintext:
            # Very large plaintext, play a sneaky trick using inverses
            neg_c = invert(self.ciphertext(False), self.public_key.nsquare)
            neg_scalar = self.public_key.n - plaintext
            return powmod(neg_c, neg_scalar, self.public_key.nsquare)
        else:
            return powmod(self.ciphertext(False), plaintext,
                          self.public_key.nsquare)
Ejemplo n.º 11
0
 def __init__(self, n,p,q, random_alpha):
     self.n = n
     #self.g = n + 1
     self.nsquare = n * n
     self.random_alpha = random_alpha % self.nsquare
     self.p = p
     self.q = q
     self.pp = self.p - 1 // 2
     self.qq = self.q -1 // 2
     self.g = random.randrange(1048576)
     self.max_int = n // 3 - 1
     one = powmod (1,1,self.nsquare)
     ppqq=self.pp*self.qq
     k = powmod(self.g,ppqq,self.n)
     self.k = k - 1 // self.n
     self.MK ={"pp":self.pp,"qq":self.qq}
     self.h = powmod(self.g, self.random_alpha,self.nsquare)
Ejemplo n.º 12
0
    def raw_encrypt(self, plaintext, r_value=None):
        """Paillier encryption of a positive integer plaintext < :attr:`n`.

        You probably should be using :meth:`encrypt` instead, because it
        handles positive and negative ints and floats.

        Args:
          plaintext (int): a positive integer < :attr:`n` to be Paillier
            encrypted. Typically this is an encoding of the actual
            number you want to encrypt.
          r_value (int): obfuscator for the ciphertext; by default (i.e.
            r_value is None), a random value is used.

        Returns:
          int: Paillier encryption of plaintext.

        Raises:
          TypeError: if plaintext is not an int.
        """
        if not isinstance(plaintext, int):
            raise TypeError('Expected int type plaintext but got: %s' %
                            type(plaintext))

        #if self.n - self.max_int <= plaintext < self.n:
            # Very large plaintext, take a sneaky shortcut using inverses
            #neg_plaintext = self.n - plaintext  # = abs(plaintext - nsquare)
            #neg_ciphertext = (self.n * neg_plaintext + 1) % self.nsquare
            #nude_ciphertext = invert(neg_ciphertext, self.nsquare)
        #else:
            # we chose g = n + 1, so that we can exploit the fact that
            # (n+1)^plaintext = n*plaintext + 1 mod n^2
        
        nude_ciphertext = (self.n * plaintext + 1) % self.nsquare

        r = random.randrange(256) % self.nsquare
        obfuscator_hr = powmod(self.h, r, self.nsquare)

        obfuscator_gr = powmod(self.g, r, self.nsquare)
        A = obfuscator_gr

        B = (nude_ciphertext * obfuscator_hr) % self.nsquare
        ciphertext = {"A":A,"B":B}
        return ciphertext
Ejemplo n.º 13
0
    def raw_decrypt(self, ciphertext):
        """Decrypt raw ciphertext and return raw plaintext.

        Args:
          ciphertext (int): (usually from :meth:`EncryptedNumber.ciphertext()`)
            that is to be Paillier decrypted.

        Returns:
          int: Paillier decryption of ciphertext. This is a positive
          integer < :attr:`public_key.n`.

        Raises:
          TypeError: if ciphertext is not an int.
        """
        if not isinstance(ciphertext, int):
            raise TypeError('Expected ciphertext to be an int, not: %s' %
                type(ciphertext))

        decrypt_to_p = self.l_function(powmod(ciphertext, self.p-1, self.psquare), self.p) * self.hp % self.p
        decrypt_to_q = self.l_function(powmod(ciphertext, self.q-1, self.qsquare), self.q) * self.hq % self.q
        return self.crt(decrypt_to_p, decrypt_to_q)
    def raw_decrypt(self, ciphertext):

        if not isinstance(ciphertext, int):
            raise TypeError('Expected ciphertext to be an int, not: %s' %
                            type(ciphertext))

        n = self.n
        t = self.t
        SecretKeyShares = self.SecretKeyShares
        theta = self.theta

        nFac = math.factorial(n)

        #c = Ciphertext.ciphertext()
        c = ciphertext
        N = self.public_key.n
        NSquare = N**2
        shares = SecretKeyShares.shares
        degree = SecretKeyShares.degree

        # NB: Here the reconstruction set is implicity defined, but any
        # large enough subset of shares will do.
        reconstruction_shares = {
            key: shares[key]
            for key in list(shares.keys())[:degree + 1]
        }

        lagrange_interpol_enum = {
            i: mult_list([j for j in reconstruction_shares.keys() if i != j])
            for i in reconstruction_shares.keys()
        }
        lagrange_interpol_denom = {
            i: mult_list([(j - i) for j in reconstruction_shares.keys()
                          if i != j])
            for i in reconstruction_shares.keys()
        }
        exponents = [
            (nFac * lagrange_interpol_enum[i] * reconstruction_shares[i]) //
            lagrange_interpol_denom[i] for i in reconstruction_shares.keys()
        ]

        # Notice that the partial decryption is already raised to the power given
        # by the Lagrange interpolation coefficient
        partialDecryptions = [powmod(c, exp, NSquare) for exp in exponents]
        combinedDecryption = mult_list(partialDecryptions) % NSquare

        if (combinedDecryption - 1) % N != 0:
            print("Error, combined decryption minus one not divisible by N")

        message = ((combinedDecryption - 1) // N * invert(theta, N)) % N

        return message
Ejemplo n.º 15
0
 def raw_transform(self,encrypted_number):
     ciphertext = encrypted_number.ciphertext
     if not isinstance(ciphertext, dict):
         raise TypeError('Expected ciphertext to be a dict, not: %s' % type(ciphertext))
     A = ciphertext['A']
     A1 = invert(ciphertext['A'],self.public_key.nsquare)
     t2 = powmod(A1,self.sk,self.public_key.nsquare)
     t3 = ciphertext['B']
     t4=t3*t2
     B=t4%self.public_key.nsquare
     transformed_cipher = {"A":A,"B":B}
     print('transformerssssss',transformed_cipher)
     encrypted_number.ciphertext = transformed_cipher
     return encrypted_number
Ejemplo n.º 16
0
    def raw_decrypt0(self, ciphertext):
        """Decrypt raw ciphertext and return raw plaintext.

		Args:
			ciphertext (int): (usually from :meth:`EncryptedNumber.ciphertext()`)
				that is to be DGK decrypted.

		Returns:
			int: DGK decryption of ciphertext. 0 if the plaintext is 0 by 
			checking cyphertext^v mod p == 1, 1 otherwise
		"""

        c = powmod(ciphertext, self.v, self.p)
        if c == 1:
            return 0
        else:
            return 1
    def raw_encrypt(self, plaintext, r_value=None):

        if not isinstance(plaintext, int):
            raise TypeError('Expected int type plaintext but got: %s' %
                            type(plaintext))

        if self.n - self.max_int <= plaintext < self.n:
            # Very large plaintext, take a sneaky shortcut using inverses
            neg_plaintext = self.n - plaintext  # = abs(plaintext - nsquare)
            neg_ciphertext = (self.n * neg_plaintext + 1) % self.nsquare
            nude_ciphertext = invert(neg_ciphertext, self.nsquare)
        else:
            # we chose g = n + 1, so that we can exploit the fact that
            # (n+1)^plaintext = n*plaintext + 1 mod n^2
            nude_ciphertext = (self.n * plaintext + 1) % self.nsquare

        r = r_value or self.get_random_lt_n()
        obfuscator = powmod(r, self.n, self.nsquare)

        return (nude_ciphertext * obfuscator) % self.nsquare
Ejemplo n.º 18
0
    def raw_encrypt(self, plaintext, r_value=None):
        """Paillier encryption of a positive integer plaintext < :attr:`n`.
            一个正整数的加密
        You probably should be using :meth:`encrypt` instead, because it
        handles positive and negative ints and floats.
        应该使用方法encrypt加密,因为他处理正负的整数和浮点数
        Args:
          plaintext (int): a positive integer < :attr:`n` to be Paillier
            encrypted. Typically this is an encoding of the actual
            number you want to encrypt.
            plaintext(int)为一个小于n的要加密的实际数字编码
          r_value (int): obfuscator for the ciphertext; by default (i.e.
            r_value is None), a random value is used.
        密文模糊处理;默认情况下时(即r_value为None)使用随机值。
        Returns:
          int: Paillier encryption of plaintext.
          plaintext的Paillier加密

        Raises:
          TypeError: if plaintext is not an int.
          异常:plaintext不是整数
        """
        #异常判断
        if not isinstance(plaintext, int):
            raise TypeError('Expected int type plaintext but got: %s' %
                            type(plaintext))
        #加密plaintext
        if self.n - self.max_int <= plaintext < self.n:
            # Very large plaintext, take a sneaky shortcut using inverses
            neg_plaintext = self.n - plaintext  # = abs(plaintext - nsquare)
            neg_ciphertext = (self.n * neg_plaintext + 1) % self.nsquare
            nude_ciphertext = invert(neg_ciphertext, self.nsquare)
        else:
            # we chose g = n + 1, so that we can exploit the fact that
            # (n+1)^plaintext = n*plaintext + 1 mod n^2
            nude_ciphertext = (self.n * plaintext + 1) % self.nsquare

        r = r_value or self.get_random_lt_n()
        obfuscator = powmod(r, self.n, self.nsquare)#使用gmp

        return (nude_ciphertext * obfuscator) % self.nsquare
Ejemplo n.º 19
0
    def raw_decrypt(self, ciphertext):
        """Decrypt raw ciphertext and return raw plaintext.

        Args:
          ciphertext (int): (usually from :meth:`EncryptedNumber.ciphertext()`)
            that is to be Paillier decrypted.

        Returns:
          int: Paillier decryption of ciphertext. This is a positive
          integer < :attr:`public_key.n`.

        Raises:
          TypeError: if ciphertext is not an int.
        """
        if not isinstance(ciphertext, int):
            raise TypeError('Expected ciphertext to be an int, not: %s' %
                            type(ciphertext))

        u = powmod(ciphertext, self.Lambda, self.public_key.nsquare)
        l_of_u = (u - 1) // self.public_key.n
        return (l_of_u * self.mu) % self.public_key.n
Ejemplo n.º 20
0
    def raw_decrypt(self, ciphertext):
        """Decrypt raw ciphertext and return raw plaintext.

        Args:
          ciphertext (int): (usually from :meth:`EncryptedNumber.ciphertext()`)
            that is to be Paillier decrypted.

        Returns:
          int: Paillier decryption of ciphertext. This is a positive
          integer < :attr:`public_key.n`.

        Raises:
          TypeError: if ciphertext is not an int.
        """
        if not isinstance(ciphertext, int):
            raise TypeError('Expected ciphertext to be an int, not: %s' %
                type(ciphertext))

        u = powmod(ciphertext, self.Lambda, self.public_key.nsquare)
        l_of_u = (u - 1) // self.public_key.n
        return (l_of_u * self.mu) % self.public_key.n
Ejemplo n.º 21
0
    def obfuscate(self):
        """Disguise ciphertext by multiplying by r ** n with random r.

        This operation must be performed for every `EncryptedNumber`
        that is sent to an untrusted party, otherwise eavesdroppers
        might deduce relationships between this and an antecedent
        `EncryptedNumber`.

        For example::

            enc = public_key.encrypt(1337)
            send_to_nsa(enc)       # NSA can't decrypt (we hope!)
            product = enc * 3.14
            send_to_nsa(product)   # NSA can deduce 3.14 by bruteforce attack
            product2 = enc * 2.718
            product2.obfuscate()
            send_to_nsa(product)   # NSA can't deduce 2.718 by bruteforce attack
        """
        r = self.public_key.get_random_lt_n()
        r_pow_n = powmod(r, self.public_key.n, self.public_key.nsquare)
        self.__ciphertext = self.__ciphertext * r_pow_n % self.public_key.nsquare
        self.__is_obfuscated = True
Ejemplo n.º 22
0
    def obfuscate(self):
        """Disguise ciphertext by multiplying by r ** n with random r.

        This operation must be performed for every `EncryptedNumber`
        that is sent to an untrusted party, otherwise eavesdroppers
        might deduce relationships between this and an antecedent
        `EncryptedNumber`.

        For example::

            enc = public_key.encrypt(1337)
            send_to_nsa(enc)       # NSA can't decrypt (we hope!)
            product = enc * 3.14
            send_to_nsa(product)   # NSA can deduce 3.14 by bruteforce attack
            product2 = enc * 2.718
            product2.obfuscate()
            send_to_nsa(product)   # NSA can't deduce 2.718 by bruteforce attack
        """
        r = self.public_key.get_random_lt_n()
        r_pow_n = powmod(r, self.public_key.n, self.public_key.nsquare)
        self.__ciphertext['A'] = self.__ciphertext['A'] * r_pow_n % self.public_key.nsquare
        self.__is_obfuscated = True
 def obfuscate(self):
     r = self.public_key.get_random_lt_n()
     r_pow_n = powmod(r, self.public_key.n, self.public_key.nsquare)
     self.__ciphertext = self.__ciphertext * r_pow_n % self.public_key.nsquare
     self.__is_obfuscated = True
Ejemplo n.º 24
0
 def testPowMod(self):
     self.assertEqual(util.powmod(5, 3, 3), 2)
     self.assertEqual(util.powmod(2, 10, 1000), 24)
Ejemplo n.º 25
0
 def testPowMod(self):
     self.assertEqual(util.powmod(5, 3, 3), 2)
     self.assertEqual(util.powmod(2, 10, 1000), 24)
Ejemplo n.º 26
0
 def h_function(self, x, xsquare):
     """Computes the h-function as defined in Paillier's paper page 12,
     'Decryption using Chinese-remaindering'.
     """
     return invert(self.l_function(powmod(self.public_key.g, x - 1, xsquare),x), x)
Ejemplo n.º 27
0
 def h_function(self, x, xsquare):
     """Computes the h-function as defined in Paillier's paper page 12,
     'Decryption using Chinese-remaindering'.
     """
     return invert(self.l_function(powmod(self.public_key.g, x - 1, xsquare),x), x)
Ejemplo n.º 28
0
 def exponentiate(self,m):
     ciphertext=self.ciphertext
     text ={}   
     text['A'] = powmod(ciphertext['A'],m, self.public_key.nsquare)
     text['B'] = powmod(ciphertext['B'],m,self.public_key.nsquare)
     return text  
Ejemplo n.º 29
0
def handle_client(conn):
    #Sending message to connected client
    #conn.send('Welcome to the server. Type something and hit enter\n'.encode('ASCII')) #send only takes string
    #infinite loop so that function do not terminate and thread do not end.
    while True:

        #Receiving blinded message from client
        data = conn.recv(1024)
        print(sys.getsizeof(data), data)
        if not data:
            break

        #determine if ZKP was sent or blind signature
        print("Data: ", data)

        try:
            print("Data decoded: ", data.decode('ascii'))
            if data.decode('ascii') == "ZKP START":
                print("here...")
                #start ZKP
                for i in range(1, 5):
                    successful = False  #used to control if the multiplicative inverse of x^e does not exist, then repeat the round
                    while not successful:
                        #wait for u
                        c = conn.recv(2049)
                        print("C data: ", c)
                        c = int(c.decode('ascii'))
                        print("Received c: ", c)
                        u = conn.recv(2048)
                        u = int(u.decode('ascii'))
                        print("Received u: ", u)
                        A = random.randint(3, 20)
                        e = random.randint(0, A)
                        print("e: ", e)
                        conn.send(bytes(str(e), 'ascii'))
                        wn = conn.recv(2048)
                        wn = wn.decode('ascii')
                        if wn != "restart":
                            wn = int(wn)
                            print("wn: ", wn)
                            v = conn.recv(2048)
                            v = int(v.decode('ascii'))
                            print("v: ", v)
                            gv = powmod(public_key.g, v, public_key.nsquare)
                            ce = powmod(c, e, public_key.nsquare)
                            check = (gv * ce * wn) % public_key.nsquare
                            print("N2: ", public_key.nsquare)
                            print("Check: ", check)
                            print("u: ", u)
                            if check == u:
                                conn.send(bytes("PASS ROUND", 'ascii'))
                                successful = True
                            elif check == "Invalid":
                                conn.send(bytes("REPEAT ROUND", 'ascii'))
                            else:
                                conn.send(bytes("FAILED ROUND", 'ascii'))
                                successful = True
                        else:
                            print(
                                "Retrying with new s and e... no inverse to w."
                            )
        except UnicodeDecodeError:
            print("there...")
            #print(type(data),data.decode('ascii'),data)
            #calculate signature
            msg_blinded_signature = RSA_private_key.sign(data, 0)
            print(msg_blinded_signature[0])
            print(type(msg_blinded_signature[0]))
            #send the signature, second element is always None
            conn.send(bytes(str(msg_blinded_signature[0]), 'ascii'))
        except ValueError:
            pass