Ejemplo n.º 1
0
    def __init__(self, keys_path):
        """
        :param keys_path: Path to the directory containg public keys.
        :type keys_path: ``str``
        """
        if not os.path.exists(keys_path):
            raise ValueError('Directory with public keys doesnt exist')

        self._keys_path = keys_path

        self._keyczar = Encrypter.Read(self._keys_path)
        self._aes = AESCrypto()
    def test_aes_decrypt(self):
        aes = AESCrypto()

        # Test data is not padded so we assume pad is a no-op
        aes._unpad_data
        aes._unpad_data = lambda data: data

        for item in AES_CBC_TEST_VECTORS:
            key = item['key'].decode('hex')
            iv = item['iv'].decode('hex')
            expected_plain_text = item['plaintext'].decode('hex')
            cipher_text = item['ciphertext'].decode('hex')

            # Decrypt assumes data contains IV and is padded, but test data is
            # not padded
            data = iv + cipher_text
            decrypted = aes.decrypt(key=key, data=data)
            self.assertEqual(decrypted, expected_plain_text)
Ejemplo n.º 3
0
    def test_aes_decrypt(self):
        aes = AESCrypto()

        # Test data is not padded so we assume pad is a no-op
        aes._unpad_data
        aes._unpad_data = lambda data: data

        for item in AES_CBC_TEST_VECTORS:
            key = item['key'].decode('hex')
            iv = item['iv'].decode('hex')
            expected_plain_text = item['plaintext'].decode('hex')
            cipher_text = item['ciphertext'].decode('hex')

            # Decrypt assumes data contains IV and is padded, but test data is
            # not padded
            data = iv + cipher_text
            decrypted = aes.decrypt(key=key, data=data)
            self.assertEqual(decrypted, expected_plain_text)
Ejemplo n.º 4
0
    def __init__(self, keys_path):
        """
        :param keys_path: Path to the directory containg public keys.
        :type keys_path: ``str``
        """
        if not os.path.exists(keys_path):
            raise ValueError('Directory with public keys doesnt exist')

        self._keys_path = keys_path

        self._keyczar = Encrypter.Read(self._keys_path)
        self._aes = AESCrypto()
    def test_aes_encrypt(self, mock_func):
        aes = AESCrypto()

        for item in AES_CBC_TEST_VECTORS:
            key = item['key'].decode('hex')
            iv = item['iv'].decode('hex')
            plain_text = item['plaintext'].decode('hex')
            expected_cipher_text = item['ciphertext'].decode('hex')

            mock_func.return_value = iv

            encrypted_with_iv_and_pad = aes.encrypt(key=key, data=plain_text)

            # Remove IV
            encrypted = encrypted_with_iv_and_pad[len(iv):]

            # Unpad
            encrypted = encrypted[:-len(plain_text)]

            self.assertEqual(encrypted, expected_cipher_text)

            # Also test round-trip
            decrypted = aes.decrypt(key=key, data=encrypted_with_iv_and_pad)
            self.assertEqual(decrypted, plain_text)
Ejemplo n.º 6
0
    def test_aes_encrypt(self, mock_func):
        aes = AESCrypto()

        for item in AES_CBC_TEST_VECTORS:
            key = item['key'].decode('hex')
            iv = item['iv'].decode('hex')
            plain_text = item['plaintext'].decode('hex')
            expected_cipher_text = item['ciphertext'].decode('hex')

            mock_func.return_value = iv

            encrypted_with_iv_and_pad = aes.encrypt(key=key, data=plain_text)

            # Remove IV
            encrypted = encrypted_with_iv_and_pad[len(iv):]

            # Unpad
            encrypted = encrypted[:-len(plain_text)]

            self.assertEqual(encrypted, expected_cipher_text)

            # Also test round-trip
            decrypted = aes.decrypt(key=key, data=encrypted_with_iv_and_pad)
            self.assertEqual(decrypted, plain_text)
Ejemplo n.º 7
0
class HybridCryptoEncrypter(HybridCryptoMixin):
    """
    Class which provides functionality for encrypting data using hybrid
    cryptosystem.
    """
    def __init__(self, keys_path):
        """
        :param keys_path: Path to the directory containg public keys.
        :type keys_path: ``str``
        """
        if not os.path.exists(keys_path):
            raise ValueError('Directory with public keys doesnt exist')

        self._keys_path = keys_path

        self._keyczar = Encrypter.Read(self._keys_path)
        self._aes = AESCrypto()

    def encrypt(self, data):
        """
        Encrypt provided data.
        """
        if len(data) > self.long_message_threshold:
            cipher_text = self._encrypt_long_message(data=data)
        else:
            cipher_text = self._encrypt_short_message(data=data)

        return cipher_text

    def _encrypt_short_message(self, data):
        """
        Encrypt a short message using public-key cryptography.

        :param data: Data to encrypt.
        :type data: ``str``
        """
        header = 'hpkc'
        data = str(data)

        if len(data) > self.long_message_threshold:
            raise ValueError('Data is too long and cant be encrypted using '
                             'PKC')

        cipher_text = header + self._keyczar.Encrypt(data)
        return cipher_text

    def _encrypt_long_message(self, data):
        """
        Encrypt a long message using hybrid cryptography.

        Data is encrypted using the following approach:

        1. Generate fresh symmetric AES key for the data encapsulation scheme
        2. Encrypt provided data using data encapsulation scheme
        3. Encrypt generates AES key using key encapsulation scheme (PKC)
        4. Assemble a final message - header + pkc_encrypted_aes_key +
        delimiter + aes_encrypted_data

        :param data: Data to encrypt.
        :type data: ``str``
        """
        header = 'haes'

        # Generate a fresh symmetric key for the data encapsulation scheme
        aes_key = RandBytes(n=self.aes_key_size)
        aes_key = str(aes_key)

        # Encrypt message using data encapsulation scheme (AES)
        aes_cipher_text = self._aes.encrypt(key=aes_key, data=data)
        aes_cipher_text = Base64WSEncode(aes_cipher_text)

        # Encrypt AES key using key encapsulation scheme
        key_cipher_text = self._keyczar.Encrypt(aes_key)

        # Assemble a final message
        parts = [header, key_cipher_text, self.delimiter, aes_cipher_text]
        msg_cipher_text = ''.join(parts)

        return msg_cipher_text

    def _aes_encrypt(self, key, data):
        header = 'paes'
        cipher_text = self._aes.encrypt(key=key, data=data)

        msg_cipher_text = header + cipher_text
        return msg_cipher_text
Ejemplo n.º 8
0
class HybridCryptoDecrypter(HybridCryptoMixin):
    def __init__(self, keys_path):
        """
        :param keys_path: Path to the directory containg private keys.
        :type keys_path: ``str``
        """
        if not os.path.exists(keys_path):
            raise ValueError('Directory with private keys doesnt exist')

        self._keys_path = keys_path

        self._keyczar = Crypter.Read(self._keys_path)
        self._aes = AESCrypto()

    def decrypt(self, data):
        """
        Decypt provided data.
        """
        header = self._get_header(data=data)

        if header not in ['hpkc', 'haes']:
            msg = 'Invalid cipher text (missing or corrupted header)'
            raise ValueError(msg)

        if header == 'haes':
            plain_text = self._decrypt_long_message(data=data)
        elif header == 'hpkc':
            plain_text = self._decrypt_short_message(data=data)

        return plain_text

    def _decrypt_short_message(self, data):
        """
        Decrypt a short message.
        """
        data = self._remove_header(data=data)
        plain_text = self._keyczar.Decrypt(data)
        return plain_text

    def _decrypt_long_message(self, data):
        """
        Decrypt a long message.
        """
        data = self._remove_header(data=data)
        delimiter_index = data.rindex(self.delimiter)

        aes_key_cipher_text = data[:delimiter_index]
        aes_key = self._keyczar.Decrypt(aes_key_cipher_text)

        data_cipher_text = data[delimiter_index + 1:]
        data_cipher_text = Base64WSDecode(data_cipher_text)

        plain_text = self._aes.decrypt(key=aes_key, data=data_cipher_text)
        return plain_text

    def _aes_decrypt(self, key, data):
        header = self._get_header(data=data)

        if header != 'paes':
            raise ValueError('Invalid or missing header')

        data = self._remove_header(data=data)
        plain_text = self._aes.decrypt(key=key, data=data)
        return plain_text
Ejemplo n.º 9
0
class HybridCryptoEncrypter(HybridCryptoMixin):
    """
    Class which provides functionality for encrypting data using hybrid
    cryptosystem.
    """

    def __init__(self, keys_path):
        """
        :param keys_path: Path to the directory containg public keys.
        :type keys_path: ``str``
        """
        if not os.path.exists(keys_path):
            raise ValueError('Directory with public keys doesnt exist')

        self._keys_path = keys_path

        self._keyczar = Encrypter.Read(self._keys_path)
        self._aes = AESCrypto()

    def encrypt(self, data):
        """
        Encrypt provided data.
        """
        if len(data) > self.long_message_threshold:
            cipher_text = self._encrypt_long_message(data=data)
        else:
            cipher_text = self._encrypt_short_message(data=data)

        return cipher_text

    def _encrypt_short_message(self, data):
        """
        Encrypt a short message using public-key cryptography.

        :param data: Data to encrypt.
        :type data: ``str``
        """
        header = 'hpkc'
        data = str(data)

        if len(data) > self.long_message_threshold:
            raise ValueError('Data is too long and cant be encrypted using '
                             'PKC')

        cipher_text = header + self._keyczar.Encrypt(data)
        return cipher_text

    def _encrypt_long_message(self, data):
        """
        Encrypt a long message using hybrid cryptography.

        Data is encrypted using the following approach:

        1. Generate fresh symmetric AES key for the data encapsulation scheme
        2. Encrypt provided data using data encapsulation scheme
        3. Encrypt generates AES key using key encapsulation scheme (PKC)
        4. Assemble a final message - header + pkc_encrypted_aes_key +
        delimiter + aes_encrypted_data

        :param data: Data to encrypt.
        :type data: ``str``
        """
        header = 'haes'

        # Generate a fresh symmetric key for the data encapsulation scheme
        aes_key = RandBytes(n=self.aes_key_size)
        aes_key = str(aes_key)

        # Encrypt message using data encapsulation scheme (AES)
        aes_cipher_text = self._aes.encrypt(key=aes_key, data=data)
        aes_cipher_text = Base64WSEncode(aes_cipher_text)

        # Encrypt AES key using key encapsulation scheme
        key_cipher_text = self._keyczar.Encrypt(aes_key)

        # Assemble a final message
        parts = [header, key_cipher_text, self.delimiter, aes_cipher_text]
        msg_cipher_text = ''.join(parts)

        return msg_cipher_text

    def _aes_encrypt(self, key, data):
        header = 'paes'
        cipher_text = self._aes.encrypt(key=key, data=data)

        msg_cipher_text = header + cipher_text
        return msg_cipher_text
Ejemplo n.º 10
0
class HybridCryptoDecrypter(HybridCryptoMixin):
    def __init__(self, keys_path):
        """
        :param keys_path: Path to the directory containg private keys.
        :type keys_path: ``str``
        """
        if not os.path.exists(keys_path):
            raise ValueError('Directory with private keys doesnt exist')

        self._keys_path = keys_path

        self._keyczar = Crypter.Read(self._keys_path)
        self._aes = AESCrypto()

    def decrypt(self, data):
        """
        Decypt provided data.
        """
        header = self._get_header(data=data)

        if header not in ['hpkc', 'haes']:
            msg = 'Invalid cipher text (missing or corrupted header)'
            raise ValueError(msg)

        if header == 'haes':
            plain_text = self._decrypt_long_message(data=data)
        elif header == 'hpkc':
            plain_text = self._decrypt_short_message(data=data)

        return plain_text

    def _decrypt_short_message(self, data):
        """
        Decrypt a short message.
        """
        data = self._remove_header(data=data)
        plain_text = self._keyczar.Decrypt(data)
        return plain_text

    def _decrypt_long_message(self, data):
        """
        Decrypt a long message.
        """
        data = self._remove_header(data=data)
        delimiter_index = data.rindex(self.delimiter)

        aes_key_cipher_text = data[:delimiter_index]
        aes_key = self._keyczar.Decrypt(aes_key_cipher_text)

        data_cipher_text = data[delimiter_index + 1:]
        data_cipher_text = Base64WSDecode(data_cipher_text)

        plain_text = self._aes.decrypt(key=aes_key, data=data_cipher_text)
        return plain_text

    def _aes_decrypt(self, key, data):
        header = self._get_header(data=data)

        if header != 'paes':
            raise ValueError('Invalid or missing header')

        data = self._remove_header(data=data)
        plain_text = self._aes.decrypt(key=key, data=data)
        return plain_text