python: неверная строка в кодировке base64: количество символов данных (5) не может быть на 1 больше, чем кратное 4 - PullRequest
1 голос
/ 11 марта 2019

выдает следующую ошибку:

Значение исключения:
Неверная строка в кодировке base64: количество символов данных (5) не может быть на 1 больше, чем кратное 4
Расположение исключения: D: \ Program Files \ Python \ lib \ base64.py в b64decode, строка 87 «

Я ввожу питон так:

key = hashlib.md5("exit_care".encode("ascii")).hexdigest().encode("ascii")
key_64 = base64.urlsafe_b64decode(key)
cipher_suite = Fernet(key_64)  

1 Ответ

1 голос
/ 11 марта 2019

Если вы используете класс Fernet, предоставляемый пакетом cryptography python, вам необходимо кодировать ваш ключ как base64, а не декодировать его перед передачей. Кодировка преобразуется в указанную форму,декодирование преобразуется из указанной формы. В настоящее время вы конвертируете exit_care в ascii (не обязательно), вычисляете хеш md5, получаете шестнадцатеричное представление и снова конвертируете его в ascii.Затем ваша программа пытается интерпретировать этот шестнадцатеричный-> ascii md5 хэш как строку в кодировке base64 при использовании base64.urlsafe_b64decode(key).Это точка отказа на данный момент.Скорее всего, вы хотите использовать base64.urlsafe_b64encode(key) вместо того, чтобы конвертировать его в base64, необходимый для использования Fernet.

Возможно вам может потребоваться заполнить его до 32 байтов , как предполагает документация Fernet https://cryptography.io/en/latest/fernet/#cryptography.fernet.Fernet

Параметры: ключ (байты) - URL-безопасный base64-кодированный 32-байтовый ключ.Это должно быть в секрете.Любой, у кого есть этот ключ, может создавать и читать сообщения.

Это связано с тем, что MD5 создаст 128-битное значение, которое закодировано как 22-символьная строка base64 (фактически 24, потому что python автоматически добавляет ккратный 4).См. https://stackoverflow.com/a/13296298/6269138 о том, почему это так.Рассматривая реализацию Fernet, они проверяют длину строки в 64-битной кодировке, чтобы увидеть, равна ли она длине 32, и выдают ошибку, если это не так. Вы можете набрать правую клавишу с помощью =, если хотите, или использовать алгоритм генерации / растягивания ключа, описанный ниже.

Я рекомендую использовать настройку, аналогичную настройкев документации Fernet пакета python для криптографии, найденного здесь https://cryptography.io/en/latest/fernet/#using-passwords-with-fernet для растягивания ключа.Код со страницы вставлен ниже, заменяя PBKDF2HMAC на HKDF, поскольку первый требует соли и, вероятно, излишним в этой ситуации, если вы не храните пароли в производственной базе данных.

>>> import base64
>>> import os
>>> from cryptography.fernet import Fernet
>>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
>>> password = b"password"
>>> hkdf = HKDF(
...     algorithm=hashes.SHA256(),  # You can swap this out for hashes.MD5()
...     length=32,
...     salt=None,    # You may be able to remove this line but I'm unable to test
...     info=None,    # You may also be able to remove this line
...     backend=default_backend()
... )
>>> key = base64.urlsafe_b64encode(hkdf.derive(password))
>>> f = Fernet(key)
>>> token = f.encrypt(b"Secret message!")
>>> token
b'...'
>>> f.decrypt(token)  # Process the key in the exact same manner to decode an encoded message
b'Secret message!'
...