Перейти к содержанию

Шифрование

Ormar предоставляет способ шифрования только полей в базе данных. Доступные бэкэнд шифрования позволяют как одностороннее шифрование (HASH), так и двунаправленное шифрование/дешифрование (FERNET).

!!!Обратите внимание, что для работы шифрования необходимо установить дополнительный пакет шифрования.

1
Вы можете сделать это manually `pip install cryptography` or with ormar by `pip install ormar[crypto]`

!!! Внимание: добавление encrypt_backend приводит к изменению типа столбца базы данных на ТЕКСТ, что необходимо отразить в db путем переноса или изменения вручную.

Определение шифрования полей

Для шифрования поля необходимо передать как минимум параметры encrypt_secret и encrypt_backend.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
«Органа»((
    metadata=metadata
    database= база данных
)

Класс Filter(ormar.Model):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    name: str = ormar.String(max_length =100,
                             encrypt_secret ="secret123",
                             Encrypt_backend =ormar. EncryptBackends.FERNET)

!!!предупреждает, что вы можете зашифровать все типы полей, кроме столбца primary_key и серии выключений (ForeignKey и ManyToMany). Проверьте данные бэкэнда для получения дополнительной информации.

Доступные серверные

Хаш

HASH-это односторонний хеш (например, пароль), который никогда не расшифруется при получении.

Чтобы настроить его, передайте соответствующие значения на задней стороне.

1
2
3
4
# rest of model definition
password: str = ormar.String(max_length =128)
                         encrypt_secret ="secret123",
                         Encrypt_backend =ormar. EncryptBackends.HASH)

Обратите внимание, что, поскольку этот бэкэнд никогда не расшифрует сохраненное значение, он работает только для строковых полей. Используемый хеш является sha512, поэтому длина поля должна быть>=128.

Обратите внимание, что в бэнде HASH можно фильтровать по полному значению, но фильтры, такие как contains, не будут работать, поскольку сравниваются значения шифрования

!!!note Обратите внимание, что предоставленный encrypt_secret сначала хеширует себя и используется в качестве соли, поэтому вам нужно заново создать этот шаг для сравнения с сохраненной строкой. order_by не будет работать, так как сравнение зашифрованных строк, поэтому вы не можете надежно сортировать их.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Hash(ormar.Model):
    ormar_config = base_ormar_config.copy (tablename="hashes")

    id: int = ormar.Integer(primary_key =True)
    name: str = ormar.String(max_length =128,
                             encrypt_secret ="udxc32",
                             Encrypt_backend =ormar. EncryptBackends.HASH)


await Hash(name ='test1').save()

Note the steps to recreate the stored value
Вы можете использовать также криптографические пакеты instead of hashlib
secret = hashlib.sha256("udxc32".encode()).digest(
secret = base64.urlsafe_b64encode(secret)
hashed_test1 = hashlib.sha512(secret + 'test1'. encode()).hexdigest(

# full value Comparison works
hash1 = await Hash. objects.get (name ='test1')
assert hash1.name == hashed_test1

But Partial Comparison does not (hashed strings are compared)
С Pytest raises(NoMatch):
    await Filter.jects.get (name__icontains ='test')

Финетт

FERNET-это двойной интерфейс шифрования/дешифрования

Чтобы настроить его, передайте соответствующие значения на задней стороне.

1
2
3
# rest of model definition
year: int = ormar.Integer(encrypt_secret ="secret123",
                          Encrypt_backend =ormar. EncryptBackends.FERNET)

Значения шифруются по пути к терминалу базы данных и дешифруются при выходе. Доступны для всех типов, так как возвращаемое значение интерпретируется как соответствующий тип Python.

!!! Обратите внимание, что в бэкэнде FERNET вы полностью теряете возможность фильтрации, так как часть зашифрованного значения является временной меткой. То же самое относится и к order_by, так как сравниваются зашифрованные строки, поэтому вы не можете надежно сортировать их.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Класс Filter(ormar.Model):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    name: str = ormar.String(max_length =100,
                             encrypt_secret ="asd123",
                             Encrypt_backend =ormar. EncryptBackends.FERNET)

wait Filter(name ='test1').save()
wait Filter(name ='test1').save()

# values are properly encrypted and later decrypted
filters = await Filter.objects.all()
assert filters[0].name == filters[1].name == 'test1'

«But You can not filter at all since part of the fernet hash is a timestamp
What Means That Eeven if You Encrypt the same string 2 times it will be different
С Pytest raises(NoMatch):
    await Filter. objects.get (name ='test1')

Пользовательский бэкэнд

Если вы хотите поддерживать другие типы шифрования (AES), вы можете предоставить свой собственный EncryptionBackend.

Чтобы настроить бэкэнд, вам нужно подкласс класса ormar.fields.EncryptBackend и предоставить ему необходимый бэкэнд.

Пример виртуального бэнда (без выполнения каких-либо действий) может выглядеть следующим образом:

1
2
3
4
5
6
7
8
9
class DummyBackend(ormar.fields.EncryptBackend):
    def_initialize_backend (self, secret_key: bytes) -> None:
        Pass

    def encrypt(self, value: Any) -> str:
        Возврат стоимости

    def decrypt(self, value: Any) -> str:
        Возврат ценности

Для использования этого бэкэнда установите для encrypt_backend значение CUSTOM и укажите его в качестве параметра с помощью encrypt_custom_backend.

1
2
3
4
5
6
7
8
9
Класс Filter(ormar.Model):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    name: str = ormar.String(max_length =100,
                             encrypt_secret ="secret123",
                             encrypt_backend =ormar. EncryptBackends.CUSTOM,
                             encrypt_custom_backend = DumyBackend
                             )