def test_validate_encryption(self):
        # Arrange
        queue_name = self._create_queue()
        kek = KeyWrapper('key1')
        self.qs.key_encryption_key = kek
        self.qs.put_message(queue_name, u'message')

        # Act
        self.qs.key_encryption_key = None  # Message will not be decrypted
        li = self.qs.peek_messages(queue_name)
        message = li[0].content
        message = loads(message)

        encryption_data = message['EncryptionData']

        wrapped_content_key = encryption_data['WrappedContentKey']
        wrapped_content_key = _WrappedContentKey(
            wrapped_content_key['Algorithm'],
            b64decode(
                wrapped_content_key['EncryptedKey'].encode(encoding='utf-8')),
            wrapped_content_key['KeyId'])

        encryption_agent = encryption_data['EncryptionAgent']
        encryption_agent = _EncryptionAgent(
            encryption_agent['EncryptionAlgorithm'],
            encryption_agent['Protocol'])

        encryption_data = _EncryptionData(
            b64decode(encryption_data['ContentEncryptionIV'].encode(
                encoding='utf-8')), encryption_agent, wrapped_content_key,
            {'EncryptionLibrary': __version__})
        message = message['EncryptedMessageContents']
        content_encryption_key = kek.unwrap_key(
            encryption_data.wrapped_content_key.encrypted_key,
            encryption_data.wrapped_content_key.algorithm)

        #Create decryption cipher
        backend = backends.default_backend()
        algorithm = AES(content_encryption_key)
        mode = CBC(encryption_data.content_encryption_IV)
        cipher = Cipher(algorithm, mode, backend)

        #decode and decrypt data
        decrypted_data = _decode_base64_to_bytes(message)
        decryptor = cipher.decryptor()
        decrypted_data = (decryptor.update(decrypted_data) +
                          decryptor.finalize())

        #unpad data
        unpadder = PKCS7(128).unpadder()
        decrypted_data = (unpadder.update(decrypted_data) +
                          unpadder.finalize())

        decrypted_data = decrypted_data.decode(encoding='utf-8')

        # Assert
        self.assertEqual(decrypted_data, u'message')
Ejemplo n.º 2
0
    def test_validate_encryption(self):
        # Arrange
        entity = self._create_default_entity_for_encryption()
        key_encryption_key = KeyWrapper('key1')
        self.ts.key_encryption_key = key_encryption_key
        self.ts.insert_entity(self.table_name, entity)

        # Act
        self.ts.key_encryption_key = None
        entity = self.ts.get_entity(self.table_name, entity['PartitionKey'],
                                    entity['RowKey'])

        # Note the minor discrepancy from the normal decryption process: because the entity was retrieved
        # without being decrypted, the encrypted_properties list is now stored in an EntityProperty object
        # and is already raw bytes.
        encrypted_properties_list = entity['_ClientEncryptionMetadata2'].value
        encryption_data = entity['_ClientEncryptionMetadata1']
        encryption_data = _dict_to_encryption_data(loads(encryption_data))

        content_encryption_key = key_encryption_key.unwrap_key(
            encryption_data.wrapped_content_key.encrypted_key,
            encryption_data.wrapped_content_key.algorithm)

        digest = Hash(SHA256(), default_backend())
        digest.update(encryption_data.content_encryption_IV +
                      (entity['RowKey'] + entity['PartitionKey'] +
                       '_ClientEncryptionMetadata2').encode('utf-8'))
        metadataIV = digest.finalize()
        metadataIV = metadataIV[:16]

        cipher = _generate_AES_CBC_cipher(content_encryption_key, metadataIV)

        # Decrypt the data.
        decryptor = cipher.decryptor()
        encrypted_properties_list = decryptor.update(
            encrypted_properties_list) + decryptor.finalize()

        # Unpad the data.
        unpadder = PKCS7(128).unpadder()
        encrypted_properties_list = unpadder.update(
            encrypted_properties_list) + unpadder.finalize()

        encrypted_properties_list = encrypted_properties_list.decode('utf-8')

        # Strip the square braces from the ends and split string into list.
        encrypted_properties_list = loads(encrypted_properties_list)

        entity_iv, encrypted_properties, content_encryption_key = \
            (encryption_data.content_encryption_IV, encrypted_properties_list, content_encryption_key)

        decrypted_entity = deepcopy(entity)

        for property in encrypted_properties_list:
            value = entity[property]

            digest = Hash(SHA256(), default_backend())
            digest.update(entity_iv +
                          (entity['RowKey'] + entity['PartitionKey'] +
                           property).encode('utf-8'))
            propertyIV = digest.finalize()
            propertyIV = propertyIV[:16]

            cipher = _generate_AES_CBC_cipher(content_encryption_key,
                                              propertyIV)

            # Decrypt the property.
            decryptor = cipher.decryptor()
            decrypted_data = (decryptor.update(value.value) +
                              decryptor.finalize())

            # Unpad the data.
            unpadder = PKCS7(128).unpadder()
            decrypted_data = (unpadder.update(decrypted_data) +
                              unpadder.finalize())

            decrypted_data = decrypted_data.decode('utf-8')

            decrypted_entity[property] = decrypted_data

        decrypted_entity.pop('_ClientEncryptionMetadata1')
        decrypted_entity.pop('_ClientEncryptionMetadata2')

        # Assert
        self.assertEqual(decrypted_entity['sex'], 'male')