def test_generate_privatekey(self):
     """
     Creates a new ThresholdEncryptionSetUp and generate commitments for 
     all trustees add them to the  ThresholdEncryptionSetUp
     and generate a private key
     """
     cryptosystem = get_cryptosystem()
     commitments = []
     
     # Generate a new instance of ThresholdEncryptionSetUp
     tSetUp = ThresholdEncryptionSetUp(cryptosystem, 
                                       self.num_trustees, self.threshold)                         
     # Adding the keys from trustees
     for i in range(self.num_trustees):
         tSetUp.add_trustee_public_key(i, self.trustees[i].public_key)
     
     # Generate commitmes for trustees
     for i in range(self.num_trustees):
         commitments.append(tSetUp.generate_commitment()) 
         
     # generate_private_key must raise ThresholdEncryptionSetUpStateError
     # if called without added commitments
     self.assertRaises(ThresholdEncryptionSetUpStateError, 
                       tSetUp.generate_private_key,
                       0,self.trustees[0].private_key)
                       
     # Adding the first  self.num_trustees - 1 commitments from trustees
     for i in range(self.num_trustees - 1):
        tSetUp.add_trustee_commitment(i, commitments[i])
        
     # generate_private_key must raise ThresholdEncryptionSetUpStateError
     # if called without all added commitments
     self.assertRaises(ThresholdEncryptionSetUpStateError, 
                       tSetUp.generate_private_key,
                       0,self.trustees[0].private_key)
                      
     # Add the last commitments from trustees 
     tSetUp.add_trustee_commitment(self.num_trustees - 1, 
                             commitments[self.num_trustees - 1])
                             
     # Must fail if the trustee doenst have his corresponding private_key
     self.assertRaises(InvalidCommitmentError,tSetUp.generate_private_key,
                       0,self.trustees[1].private_key)
                  
     privatekey = tSetUp.generate_private_key(0,self.trustees[0].private_key)
     
     # The privatekey atributes must be the expected from  tSetUp
     self.assertTrue(privatekey.cryptosystem, cryptosystem)
     self.assertEqual(privatekey.num_trustees, self.num_trustees)
     self.assertEqual(privatekey.threshold, self.threshold)
     self.assertEqual(privatekey.public_key, 
                      tSetUp.generate_public_key()) 
    def test_generate_privatekey(self):
        """
        Creates a new ThresholdEncryptionSetUp and generate commitments for 
        all trustees add them to the  ThresholdEncryptionSetUp
        and generate a private key
        """
        cryptosystem = get_cryptosystem()
        commitments = []

        # Generate a new instance of ThresholdEncryptionSetUp
        tSetUp = ThresholdEncryptionSetUp(cryptosystem, self.num_trustees,
                                          self.threshold)
        # Adding the keys from trustees
        for i in range(self.num_trustees):
            tSetUp.add_trustee_public_key(i, self.trustees[i].public_key)

        # Generate commitmes for trustees
        for i in range(self.num_trustees):
            commitments.append(tSetUp.generate_commitment())

        # generate_private_key must raise ThresholdEncryptionSetUpStateError
        # if called without added commitments
        self.assertRaises(ThresholdEncryptionSetUpStateError,
                          tSetUp.generate_private_key, 0,
                          self.trustees[0].private_key)

        # Adding the first  self.num_trustees - 1 commitments from trustees
        for i in range(self.num_trustees - 1):
            tSetUp.add_trustee_commitment(i, commitments[i])

        # generate_private_key must raise ThresholdEncryptionSetUpStateError
        # if called without all added commitments
        self.assertRaises(ThresholdEncryptionSetUpStateError,
                          tSetUp.generate_private_key, 0,
                          self.trustees[0].private_key)

        # Add the last commitments from trustees
        tSetUp.add_trustee_commitment(self.num_trustees - 1,
                                      commitments[self.num_trustees - 1])

        # Must fail if the trustee doenst have his corresponding private_key
        self.assertRaises(InvalidCommitmentError, tSetUp.generate_private_key,
                          0, self.trustees[1].private_key)

        privatekey = tSetUp.generate_private_key(0,
                                                 self.trustees[0].private_key)

        # The privatekey atributes must be the expected from  tSetUp
        self.assertTrue(privatekey.cryptosystem, cryptosystem)
        self.assertEqual(privatekey.num_trustees, self.num_trustees)
        self.assertEqual(privatekey.threshold, self.threshold)
        self.assertEqual(privatekey.public_key, tSetUp.generate_public_key())
class TestThresholdPrivateKey(unittest.TestCase):
    """
    Test the class: plonevotecryptolib.Threshold.ThresholdPublicKey.
    ThresholdPublicKey
    """
    def setUp(self):
        """
        Unit test setup method.
        """
        self.num_trustees = 5
        self.threshold = 3
        self.trustees = []
        self.commitments = []
        for i in range(self.num_trustees):
            self.trustees.append(Trustee())

        # Generate a new instance of ThresholdEncryptionSetUp to be used
        # for generate publickeys
        cryptosystem = get_cryptosystem()
        self.tSetUp = ThresholdEncryptionSetUp(cryptosystem, self.num_trustees,
                                               self.threshold)
        # Adding the keys from trustees
        for i in range(self.num_trustees):
            self.tSetUp.add_trustee_public_key(i, self.trustees[i].public_key)
        # Generate commitmes for trustees
        for i in range(self.num_trustees):
            self.commitments.append(self.tSetUp.generate_commitment())
        # Adding the  trustees  commitments
        for i in range(self.num_trustees):
            self.tSetUp.add_trustee_commitment(i, self.commitments[i])

        self.tpkey = self.tSetUp.generate_public_key()

    def test_privatekey_generation(self):
        """
        Create a new ThresholdPrivateKey, verify that is created correctly
        """

        privatekey = ThresholdPrivateKey(self.tSetUp.cryptosystem,
                                         self.num_trustees, self.threshold,
                                         self.tpkey,
                                         self.trustees[0].private_key)

        # The values of the parameters must be the same we expect
        self.assertEquals(privatekey.cryptosystem, self.tSetUp.cryptosystem)
        self.assertEquals(privatekey.num_trustees, self.num_trustees)
        self.assertEquals(privatekey.threshold, self.threshold)
        self.assertEquals(privatekey.public_key, self.tpkey)
        self.assertEquals(privatekey._key, self.trustees[0].private_key)

    def test_partial_decryption(self):
        """
        Create a ciphertext with the threshold public key and decrypt it and 
        create others ciphertext to prove IncompatibleCiphertextError
        """

        tprk = self.tSetUp.generate_private_key(0,
                                                self.trustees[0].private_key)
        text_to_encrypt_dir = os.path.join(
            os.path.dirname(__file__), "TestThresholdPrivateKey.resources")
        text_to_encrypt = os.path.join(text_to_encrypt_dir, "text_to_encrypt")
        text_encrypted = self.tpkey.encrypt_text(text_to_encrypt)

        # Decrypt the file created with our public key must be fine
        tprk.generate_partial_decryption(text_encrypted)

        # Create another ThresholdEcryptuonSetUp with other 1024 bits
        # cryptosys to create a cypthertext that cant be decrypted
        second_cryptosys_file = os.path.join(
            os.path.dirname(__file__),
            "TestThresholdEncryptionSetUp.resources",
            "test1024bits_second.pvcryptosys")
        # Load the cryptosystem from file
        second_cryptosys = EGCryptoSystem.from_file(second_cryptosys_file)
        secondtSetUp = ThresholdEncryptionSetUp(second_cryptosys,
                                                self.num_trustees,
                                                self.threshold)
        # Adding the keys from trustees for 2ndsetUp
        for i in range(self.num_trustees):
            secondtSetUp.add_trustee_public_key(i, self.trustees[i].public_key)
        secondcommitments = []
        # Generate commitmes for trustees for 2ndsetUp
        for i in range(self.num_trustees):
            secondcommitments.append(secondtSetUp.generate_commitment())
        # Adding the secont trustees  commitments
        for i in range(self.num_trustees):
            secondtSetUp.add_trustee_commitment(i, secondcommitments[i])
        # Generate secon cryptosis publickey
        secondtpkey = secondtSetUp.generate_public_key()
        # Encrypt the file with the secon cryptosis publickey
        secondtext_encrypted = secondtpkey.encrypt_text(text_to_encrypt)

        # Try to decryp something created with other ThresholdEcryptuonSetUp
        # must raise IncompatibleCiphertextError

        self.assertRaises(IncompatibleCiphertextError,
                          tprk.generate_partial_decryption,
                          secondtext_encrypted)

        # Create another ThresholdEcryptuonSetUp with other 512 bits
        # cryptosys to create a cypthertext that cant be decrypted
        third_cryptosys_file = os.path.join(
            os.path.dirname(__file__),
            "TestThresholdEncryptionSetUp.resources",
            "test512bits.pvcryptosys")
        # Load the cryptosystem from file
        third_cryptosys = EGCryptoSystem.from_file(third_cryptosys_file)
        thirdtSetUp = ThresholdEncryptionSetUp(third_cryptosys,
                                               self.num_trustees,
                                               self.threshold)
        # Adding the keys from trustees for 2ndsetUp
        for i in range(self.num_trustees):
            thirdtSetUp.add_trustee_public_key(i, self.trustees[i].public_key)
        thirdcommitments = []
        # Generate commitmes for trustees for 2ndsetUp
        for i in range(self.num_trustees):
            thirdcommitments.append(thirdtSetUp.generate_commitment())
        # Adding the secont trustees  commitments
        for i in range(self.num_trustees):
            thirdtSetUp.add_trustee_commitment(i, thirdcommitments[i])
        # Generate secon cryptosis publickey
        thirdtpkey = thirdtSetUp.generate_public_key()
        # Encrypt the file with the secon cryptosis publickey
        thirdtext_encrypted = thirdtpkey.encrypt_text(text_to_encrypt)

        # Try to decryp something created with other ThresholdEcryptuonSetUp
        # must raise IncompatibleCiphertextError

        self.assertRaises(IncompatibleCiphertextError,
                          tprk.generate_partial_decryption,
                          thirdtext_encrypted)

    def test_partial_decryption_w_task_monitor(self):
        """
        Test that partial decryption can be monitored using a TaskMonitor 
        object.
        """
        # Get a new task monitor and a counter
        task_monitor = TaskMonitor()
        partialDecryptionCounter = Counter()

        # Register a task monitor callback to increment the counter once
        # for each 5% progress of partial decryption
        def partial_decryption_callback(tm):
            partialDecryptionCounter.increment()

        task_monitor.add_on_progress_percent_callback(
            partial_decryption_callback, percent_span=5.0)

        # Generate a partial decryption passing the task_monitor object

        tprk = self.tSetUp.generate_private_key(0,
                                                self.trustees[0].private_key)
        text_to_encrypt_dir = os.path.join(
            os.path.dirname(__file__), "TestThresholdPrivateKey.resources")
        text_to_encrypt = os.path.join(text_to_encrypt_dir, "text_to_encrypt")
        text_encrypted = self.tpkey.encrypt_text(text_to_encrypt)
        tprk.generate_partial_decryption(text_encrypted, task_monitor)

        # Check that the counter has been incremented 100/5 = 20 times
        self.assertEqual(partialDecryptionCounter.value, 20)

    def test_save_load_file(self):
        """
        Test that we can correctly save a ThresholdPrivateKey to a file and 
        load it back. 
        """
        # Get a new threshold private key object
        pkey = self.tSetUp.generate_private_key(0,
                                                self.trustees[0].private_key)

        # Get a temporary file object using tempfile
        (file_object, file_path) = tempfile.mkstemp()

        # We close the file descriptor since we will not be using it, instead
        # PublicKey's methods take the filename and open/close the file as
        # needed.
        # Note that using mkstemp() instead tempfile.TemporaryFile means the
        # file remains in the filesystem even after it is closed.
        os.close(file_object)

        # Save the key using to_file(...)
        pkey.to_file(file_path)
        # Load it back using ThresholdPrivateKey.from_file(...)
        recovered_key = ThresholdPrivateKey.from_file(file_path)
        # Check that parameters and keys match (and thus they're the same key)
        self.assertEqual(pkey.cryptosystem, recovered_key.cryptosystem)
        self.assertEqual(pkey.num_trustees, recovered_key.num_trustees)
        self.assertEqual(pkey.threshold, recovered_key.threshold)
        self.assertEqual(pkey.public_key.get_fingerprint(),
                         recovered_key.public_key.get_fingerprint())
        self.assertEqual(pkey._key, recovered_key._key)

        # Delete the temporary file
        os.remove(file_path)

    def test_load_invalid_file(self):
        """
        Test that loading a threshold private key from a file in an invalid 
        format raises an appropriate exception.
        """
        # Construct the path to the directory where our invalid test files are
        # located:
        invalid_files_dir = os.path.join(os.path.dirname(__file__),
                                         "TestThresholdPrivateKey.resources",
                                         "invalid_tprivatekey_xml_files")

        # Add invalid private key files as needed
        for file_name in [
                "err_missing_pub_key_elem.pvpubkey",
                "err_not_valid_number_elem.pvpubkey",
                "err_prv_key_too_large.pvpubkey",
                "err_pub_key_too_large.pvpubkey",
                "err_par_pub_key_too_large.pvpubkey"
        ]:
            inv_file = os.path.join(invalid_files_dir, file_name)
            self.assertRaises(InvalidPloneVoteCryptoFileError,
                              ThresholdPrivateKey.from_file, inv_file)
class TestThresholdPrivateKey(unittest.TestCase):
    """
    Test the class: plonevotecryptolib.Threshold.ThresholdPublicKey.
    ThresholdPublicKey
    """
    
    def setUp(self):
        """
        Unit test setup method.
        """
        self.num_trustees = 5
        self.threshold = 3
        self.trustees = []
        self.commitments = []
        for i in range(self.num_trustees):
            self.trustees.append(Trustee())
            
        # Generate a new instance of ThresholdEncryptionSetUp to be used
        # for generate publickeys
        cryptosystem = get_cryptosystem()
        self.tSetUp = ThresholdEncryptionSetUp(cryptosystem, 
                                          self.num_trustees, self.threshold)                         
        # Adding the keys from trustees
        for i in range(self.num_trustees):
            self.tSetUp.add_trustee_public_key(i, self.trustees[i].public_key)
        # Generate commitmes for trustees
        for i in range(self.num_trustees):
            self.commitments.append(self.tSetUp.generate_commitment())               
        # Adding the  trustees  commitments 
        for i in range(self.num_trustees):
           self.tSetUp.add_trustee_commitment(i, self.commitments[i])
         
        self.tpkey = self.tSetUp.generate_public_key()
            
    def test_privatekey_generation(self):
        """
        Create a new ThresholdPrivateKey, verify that is created correctly
        """
        
        privatekey = ThresholdPrivateKey(self.tSetUp.cryptosystem, 
                                         self.num_trustees,
                                         self.threshold, self.tpkey,
                                         self.trustees[0].private_key)
                                         
        # The values of the parameters must be the same we expect
        self.assertEquals(privatekey.cryptosystem, self.tSetUp.cryptosystem)
        self.assertEquals(privatekey.num_trustees, self.num_trustees)
        self.assertEquals(privatekey.threshold, self.threshold)
        self.assertEquals(privatekey.public_key, self.tpkey)
        self.assertEquals(privatekey._key, self.trustees[0].private_key)
                
    def test_partial_decryption(self):
        """
        Create a ciphertext with the threshold public key and decrypt it and 
        create others ciphertext to prove IncompatibleCiphertextError
        """

        tprk = self.tSetUp.generate_private_key(0, self.trustees[0].private_key)
        text_to_encrypt_dir = os.path.join(os.path.dirname(__file__), 
                                           "TestThresholdPrivateKey.resources")
        text_to_encrypt = os.path.join(text_to_encrypt_dir, "text_to_encrypt")
        text_encrypted = self.tpkey.encrypt_text(text_to_encrypt)
        
        # Decrypt the file created with our public key must be fine
        tprk.generate_partial_decryption(text_encrypted)
        
        # Create another ThresholdEcryptuonSetUp with other 1024 bits
        # cryptosys to create a cypthertext that cant be decrypted
        second_cryptosys_file = os.path.join(os.path.dirname(__file__), 
                                      "TestThresholdEncryptionSetUp.resources",
                                      "test1024bits_second.pvcryptosys")
        # Load the cryptosystem from file
        second_cryptosys = EGCryptoSystem.from_file(second_cryptosys_file)      
        secondtSetUp = ThresholdEncryptionSetUp(second_cryptosys, 
                                          self.num_trustees, self.threshold)
         # Adding the keys from trustees for 2ndsetUp
        for i in range(self.num_trustees):
            secondtSetUp.add_trustee_public_key(i, self.trustees[i].public_key)
        secondcommitments = []
        # Generate commitmes for trustees for 2ndsetUp
        for i in range(self.num_trustees):
            secondcommitments.append(secondtSetUp.generate_commitment()) 
        # Adding the secont trustees  commitments 
        for i in range(self.num_trustees):
            secondtSetUp.add_trustee_commitment(i, secondcommitments[i])
        # Generate secon cryptosis publickey
        secondtpkey = secondtSetUp.generate_public_key()
        # Encrypt the file with the secon cryptosis publickey
        secondtext_encrypted = secondtpkey.encrypt_text(text_to_encrypt)
        
        
        # Try to decryp something created with other ThresholdEcryptuonSetUp 
        # must raise IncompatibleCiphertextError
        
        self.assertRaises(IncompatibleCiphertextError, 
                         tprk.generate_partial_decryption, secondtext_encrypted)


        # Create another ThresholdEcryptuonSetUp with other 512 bits
        # cryptosys to create a cypthertext that cant be decrypted
        third_cryptosys_file = os.path.join(os.path.dirname(__file__), 
                                      "TestThresholdEncryptionSetUp.resources",
                                      "test512bits.pvcryptosys")
        # Load the cryptosystem from file
        third_cryptosys = EGCryptoSystem.from_file(third_cryptosys_file)      
        thirdtSetUp = ThresholdEncryptionSetUp(third_cryptosys, 
                                          self.num_trustees, self.threshold)
         # Adding the keys from trustees for 2ndsetUp
        for i in range(self.num_trustees):
            thirdtSetUp.add_trustee_public_key(i, self.trustees[i].public_key)
        thirdcommitments = []
        # Generate commitmes for trustees for 2ndsetUp
        for i in range(self.num_trustees):
            thirdcommitments.append(thirdtSetUp.generate_commitment()) 
        # Adding the secont trustees  commitments 
        for i in range(self.num_trustees):
            thirdtSetUp.add_trustee_commitment(i, thirdcommitments[i])
        # Generate secon cryptosis publickey
        thirdtpkey = thirdtSetUp.generate_public_key()
        # Encrypt the file with the secon cryptosis publickey
        thirdtext_encrypted = thirdtpkey.encrypt_text(text_to_encrypt)
        
        
        # Try to decryp something created with other ThresholdEcryptuonSetUp 
        # must raise IncompatibleCiphertextError
        
        self.assertRaises(IncompatibleCiphertextError, 
                         tprk.generate_partial_decryption, thirdtext_encrypted)

    def test_partial_decryption_w_task_monitor(self):
        """
        Test that partial decryption can be monitored using a TaskMonitor 
        object.
        """
        # Get a new task monitor and a counter
        task_monitor = TaskMonitor()
        partialDecryptionCounter = Counter()
        
        # Register a task monitor callback to increment the counter once 
        # for each 5% progress of partial decryption
        def partial_decryption_callback(tm):
            partialDecryptionCounter.increment()
        
        task_monitor.add_on_progress_percent_callback(
                            partial_decryption_callback, percent_span = 5.0)
        
        # Generate a partial decryption passing the task_monitor object
        
        tprk = self.tSetUp.generate_private_key(0, self.trustees[0].private_key)
        text_to_encrypt_dir = os.path.join(os.path.dirname(__file__), 
                                           "TestThresholdPrivateKey.resources")
        text_to_encrypt = os.path.join(text_to_encrypt_dir, "text_to_encrypt")
        text_encrypted = self.tpkey.encrypt_text(text_to_encrypt)        
        tprk.generate_partial_decryption(text_encrypted, task_monitor)
        
        
        # Check that the counter has been incremented 100/5 = 20 times
        self.assertEqual(partialDecryptionCounter.value, 20)

    def test_save_load_file(self):
        """
        Test that we can correctly save a ThresholdPrivateKey to a file and 
        load it back. 
        """
        # Get a new threshold private key object
        pkey = self.tSetUp.generate_private_key(0, self.trustees[0].private_key)
        
        # Get a temporary file object using tempfile
        (file_object, file_path) = tempfile.mkstemp()
        
        # We close the file descriptor since we will not be using it, instead 
        # PublicKey's methods take the filename and open/close the file as 
        # needed.
        # Note that using mkstemp() instead tempfile.TemporaryFile means the 
        # file remains in the filesystem even after it is closed.
        os.close(file_object)
        
        # Save the key using to_file(...)
        pkey.to_file(file_path)        
        # Load it back using ThresholdPrivateKey.from_file(...)
        recovered_key = ThresholdPrivateKey.from_file(file_path)
        # Check that parameters and keys match (and thus they're the same key)
        self.assertEqual(pkey.cryptosystem, recovered_key.cryptosystem)
        self.assertEqual(pkey.num_trustees, recovered_key.num_trustees)
        self.assertEqual(pkey.threshold, recovered_key.threshold)
        self.assertEqual(pkey.public_key.get_fingerprint(),
                         recovered_key.public_key.get_fingerprint())
        self.assertEqual(pkey._key, recovered_key._key)
        
        # Delete the temporary file
        os.remove(file_path)        
        
    def test_load_invalid_file(self):
        """
        Test that loading a threshold private key from a file in an invalid 
        format raises an appropriate exception.
        """
        # Construct the path to the directory where our invalid test files are 
        # located:
        invalid_files_dir = os.path.join(os.path.dirname(__file__), 
                                         "TestThresholdPrivateKey.resources",
                                         "invalid_tprivatekey_xml_files")
        
        # Add invalid private key files as needed                               
        for file_name in ["err_missing_pub_key_elem.pvpubkey",
                          "err_not_valid_number_elem.pvpubkey",
                          "err_prv_key_too_large.pvpubkey",
                          "err_pub_key_too_large.pvpubkey",
                          "err_par_pub_key_too_large.pvpubkey"]:
            inv_file = os.path.join(invalid_files_dir, file_name)
            self.assertRaises(InvalidPloneVoteCryptoFileError, 
                              ThresholdPrivateKey.from_file, inv_file)