Exemple #1
0
    def apply(self, ciphertext):
        """
        Re-encrypts the given ciphertext with this re-encryption information.

        Arguments:
            ciphertext::Ciphertext -- The ciphertext to be re-encrypted.

        Returns:
            reencrypted_ciphertext::Ciphertext  -- A re-encryption of
                ciphertext performed with this re-encryption information.

        Throws:
            IncompatibleCiphertextError --
                If the ciphertext and this re-encryption information are not
                compatible. Either because their length in blocks differs, or
                because they don't have the same public key.
        """
        # Check length compatibility
        if(ciphertext.get_length() != self.get_length()):
            raise IncompatibleCiphertextError("The given ciphertext is " \
                "incompatible with this re-encryption information object: " \
                "The two objects have different length. There are %d blocks "\
                "of ciphertext and %d blocks of re-encryption information." \
                % (ciphertext.get_length(), self.get_length()))

        # Check key compatibility
        if(ciphertext.pk_fingerprint != self.public_key.get_fingerprint()):
            raise IncompatibleCiphertextError("The given ciphertext is " \
                "incompatible with this re-encryption information object: " \
                "The public key used to encrypt the ciphertext is different " \
                "from the one used to generate this re-encryption " \
                "information object.")

        # Get nbits and p
        nbits = self.public_key.cryptosystem.get_nbits()
        prime = self.public_key.cryptosystem.get_prime()

        # For each block of the ciphertext, apply the corresponding block of
        # re-encryption.
        reencrypted_ciphertext = Ciphertext(nbits, ciphertext.pk_fingerprint)
        for i in range(0, self.get_length()):
            gamma, delta = ciphertext[i]
            gr, yr = self[i]
            new_gamma = (gr * gamma) % prime
            new_delta = (yr * delta) % prime
            reencrypted_ciphertext.append(new_gamma, new_delta)

        return reencrypted_ciphertext
Exemple #2
0
 def encrypt(s, m, raw=False):
     """
 RSA Encryption
 Args:
   m   : Plaintext Message (must be integer object)
   raw : Is result wrapped by Ciphertext object?
 Return: RSA Ciphertext or Encrypted integer (m^e mod n)
 """
     c = pow(m, s.e, s.n)
     if raw:
         return c
     return Ciphertext(s, c)
Exemple #3
0
 def encrypt(s, m, raw=False):
     """
 RC4 Encryption
 Args:
   m   : Plaintext Message (must be string object)
   raw : Is result wrapped by Ciphertext object?
 Return: RC4 Ciphertext object or Encrypted String (c_i = m_i XOR PRGA())
 """
     c = "".join([chr(ord(x) ^ ord(y)) for x, y in zip(m, s.prga(len(m)))])
     if raw:
         return c
     return Ciphertext(s, c)
 def encrypt_bitstream(self, bitstream, pad_to=None, task_monitor=None):
     """
     Encrypts the given bitstream into a ciphertext object.
     
     Arguments:
         bitstream::BitStream-- A stream of bits to encrypt 
                                (see BitStream utility class).
         pad_to::int            -- Minimum size (in bytes) of the resulting 
                                ciphertext. Data will be padded before 
                                encryption to match this size.
         task_monitor::TaskMonitor    -- A task monitor for this task.
     
     Returns:
         ciphertext:Ciphertext    -- A ciphertext object encapsulating the 
                                    encrypted data.        
     """
     random = StrongRandom()
     
     ## PART 1
     # First, format the bitstream as per Ciphertext.py Note 001,
     # previous to encryption.
     #     [size (64 bits) | message (size bits) | padding (X bits) ]
     ##
     formated_bitstream = BitStream()
     
     # The first 64 encode the size of the actual data in bits
     SIZE_BLOCK_LENGTH = 64
     size_in_bits = bitstream.get_length()
     
     if(size_in_bits >= 2**SIZE_BLOCK_LENGTH):
         raise ValueError("The size of the bitstream to encrypt is larger " \
                          "than 16 Exabits. The current format for  " \
                          "PloneVote ciphertext only allows encrypting a  " \
                          "maximum of 16 Exabits of information.")
     
     formated_bitstream.put_num(size_in_bits, SIZE_BLOCK_LENGTH)
     
     # We then copy the contents of the original bitstream
     bitstream.seek(0)
     formated_bitstream.put_bitstream_copy(bitstream)
     
     # Finally, we append random data until we reach the desired pad_to 
     # length
     unpadded_length = formated_bitstream.get_length()
     if(pad_to != None and (pad_to * 8) > unpadded_length):
         full_length = pad_to * 8
     else:
         full_length = unpadded_length
     
     padding_left = full_length - unpadded_length
     
     while(padding_left > 1024):
         padding_bits = random.randint(1, 2**1024)
         formated_bitstream.put_num(padding_bits,1024)
         padding_left -= 1024
     
     if(padding_left > 0):
         padding_bits = random.randint(1, 2**padding_left)
         formated_bitstream.put_num(padding_bits, padding_left)
         padding_left = 0
     
     ## PART 2
     # We encrypt the formated bitsteam using ElGamal into a Ciphertext 
     # object.
     # See "Handbook of Applied Cryptography" Algorithm 8.18
     ##
     
     # block_size is the size of each block of bits to encrypt
     # since we can only encrypt messages in [0, p - 1]
     # we should use (nbits - 1) as the block size, where 
     # 2**(nbits - 1) < p < 2**nbits
     
     block_size = self.cryptosystem.get_nbits() - 1
     prime = self.cryptosystem.get_prime()
     generator = self.cryptosystem.get_generator()
     
     # We pull data from the bitstream one block at a time and encrypt it
     formated_bitstream.seek(0)
     ciphertext = \
         Ciphertext(self.cryptosystem.get_nbits(), self.get_fingerprint()) 
     
     plaintext_bits_left = formated_bitstream.get_length()
     
     # Check if we have a task monitor and register with it
     if(task_monitor != None):
         # We will do two tick()s per block to encrypt: one for generating 
         # the gamma component of the ciphertext block and another for the 
         # delta component (those are the two time intensive steps, 
         # because of exponentiation). 
         ticks = math.ceil((1.0 * plaintext_bits_left) / block_size) * 2
         encrypt_task_mon = \
             task_monitor.new_subtask("Encrypt data", expected_ticks = ticks)
     
     while(plaintext_bits_left > 0):
     
         # get next block (message, m, etc) to encrypt
         if(plaintext_bits_left >= block_size):
             block = formated_bitstream.get_num(block_size)
             plaintext_bits_left -= block_size
         else:
             block = formated_bitstream.get_num(plaintext_bits_left)
             # Encrypt as if the stream was filled with random data past its 
             # end, this avoids introducing a 0's gap during decryption to 
             # bitstream
             displacement = block_size - plaintext_bits_left
             block = block << displacement
             padding = random.randint(0, 2**displacement - 1)
             assert (padding / 2**displacement == 0), \
                         "padding should be at most displacement bits long"
             block = block | padding
             plaintext_bits_left = 0
         
         # Select a random integer k, 1 <= k <= p − 2
         k = random.randint(1, prime - 2)
         
         # Compute gamma and delta
         gamma = pow(generator, k, prime)
         if(task_monitor != None): encrypt_task_mon.tick()
         
         delta = (block * pow(self._key, k, prime)) % prime
         if(task_monitor != None): encrypt_task_mon.tick()
         
         # Add this encrypted data portion to the ciphertext object
         ciphertext.append(gamma, delta)
     
     # return the ciphertext object
     return ciphertext
Exemple #5
0
    def encrypt_bitstream(self, bitstream, pad_to=None, task_monitor=None):
        """
        Encrypts the given bitstream into a ciphertext object.
        
        Arguments:
            bitstream::BitStream-- A stream of bits to encrypt 
                                   (see BitStream utility class).
            pad_to::int            -- Minimum size (in bytes) of the resulting 
                                   ciphertext. Data will be padded before 
                                   encryption to match this size.
            task_monitor::TaskMonitor    -- A task monitor for this task.
        
        Returns:
            ciphertext:Ciphertext    -- A ciphertext object encapsulating the 
                                       encrypted data.        
        """
        random = StrongRandom()

        ## PART 1
        # First, format the bitstream as per Ciphertext.py Note 001,
        # previous to encryption.
        #     [size (64 bits) | message (size bits) | padding (X bits) ]
        ##
        formated_bitstream = BitStream()

        # The first 64 encode the size of the actual data in bits
        SIZE_BLOCK_LENGTH = 64
        size_in_bits = bitstream.get_length()

        if (size_in_bits >= 2**SIZE_BLOCK_LENGTH):
            raise ValueError("The size of the bitstream to encrypt is larger " \
                             "than 16 Exabits. The current format for  " \
                             "PloneVote ciphertext only allows encrypting a  " \
                             "maximum of 16 Exabits of information.")

        formated_bitstream.put_num(size_in_bits, SIZE_BLOCK_LENGTH)

        # We then copy the contents of the original bitstream
        bitstream.seek(0)
        formated_bitstream.put_bitstream_copy(bitstream)

        # Finally, we append random data until we reach the desired pad_to
        # length
        unpadded_length = formated_bitstream.get_length()
        if (pad_to != None and (pad_to * 8) > unpadded_length):
            full_length = pad_to * 8
        else:
            full_length = unpadded_length

        padding_left = full_length - unpadded_length

        while (padding_left > 1024):
            padding_bits = random.randint(1, 2**1024)
            formated_bitstream.put_num(padding_bits, 1024)
            padding_left -= 1024

        if (padding_left > 0):
            padding_bits = random.randint(1, 2**padding_left)
            formated_bitstream.put_num(padding_bits, padding_left)
            padding_left = 0

        ## PART 2
        # We encrypt the formated bitsteam using ElGamal into a Ciphertext
        # object.
        # See "Handbook of Applied Cryptography" Algorithm 8.18
        ##

        # block_size is the size of each block of bits to encrypt
        # since we can only encrypt messages in [0, p - 1]
        # we should use (nbits - 1) as the block size, where
        # 2**(nbits - 1) < p < 2**nbits

        block_size = self.cryptosystem.get_nbits() - 1
        prime = self.cryptosystem.get_prime()
        generator = self.cryptosystem.get_generator()

        # We pull data from the bitstream one block at a time and encrypt it
        formated_bitstream.seek(0)
        ciphertext = \
            Ciphertext(self.cryptosystem.get_nbits(), self.get_fingerprint())

        plaintext_bits_left = formated_bitstream.get_length()

        # Check if we have a task monitor and register with it
        if (task_monitor != None):
            # We will do two tick()s per block to encrypt: one for generating
            # the gamma component of the ciphertext block and another for the
            # delta component (those are the two time intensive steps,
            # because of exponentiation).
            ticks = math.ceil((1.0 * plaintext_bits_left) / block_size) * 2
            encrypt_task_mon = \
                task_monitor.new_subtask("Encrypt data", expected_ticks = ticks)

        while (plaintext_bits_left > 0):

            # get next block (message, m, etc) to encrypt
            if (plaintext_bits_left >= block_size):
                block = formated_bitstream.get_num(block_size)
                plaintext_bits_left -= block_size
            else:
                block = formated_bitstream.get_num(plaintext_bits_left)
                # Encrypt as if the stream was filled with random data past its
                # end, this avoids introducing a 0's gap during decryption to
                # bitstream
                displacement = block_size - plaintext_bits_left
                block = block << displacement
                padding = random.randint(0, 2**displacement - 1)
                assert (padding / 2**displacement == 0), \
                            "padding should be at most displacement bits long"
                block = block | padding
                plaintext_bits_left = 0

            # Select a random integer k, 1 <= k <= p − 2
            k = random.randint(1, prime - 2)

            # Compute gamma and delta
            gamma = pow(generator, k, prime)
            if (task_monitor != None): encrypt_task_mon.tick()

            delta = (block * pow(self._key, k, prime)) % prime
            if (task_monitor != None): encrypt_task_mon.tick()

            # Add this encrypted data portion to the ciphertext object
            ciphertext.append(gamma, delta)

        # return the ciphertext object
        return ciphertext