Генерация секрета AES 256 GCM с использованием заданного ключа в python

Я пытаюсь внедрить шифрование AES в python.
Я ссылаюсь на образец кода Java, чтобы выполнить это.
В Java 256-битный секрет (с использованием данного ключа) генерируется с использованием

Key secretKey = new SecretKeySpec(Base64.decodeBase64(GIVEN_KEY), "AES");

Я пытаюсь сделать то же самое в python, используя следующий фрагмент

secret = hashlib.sha256(GIVEN_KEY.encode()).digest()

Но строка, закодированная с помощью реализации Python, не может быть расшифрована. Являются ли приведенные выше фрагменты похожими, или я что-то упускаю?


person Hrishi    schedule 06.08.2020    source источник


Ответы (1)


В Java в качестве ключа используется декодированное в Base64 значение GIVEN_KEY, в Python — хэш SHA256 GIVEN_KEY. Оба не одинаковы.

Аналог в Python будет выглядеть примерно так:

import base64
...
secret = base64.b64decode(GIVEN_KEY.encode()) # by default UTF8 encoded

РЕДАКТИРОВАНИЕ: в связанном коде (стр. 31) ключ Base64url закодирован без заполнения:

QOahfcdo98NLjYJuhP4-VKigx51NkUETsKlIu9uXZFY

который можно узнать по символу - и длине, не кратной 4.

Это соответствует Base64url, декодированному в последовательность байтов

40e6a17dc768f7c34b8d826e84fe3e54a8a0c79d4d914113b0a948bbdb976456

который представляет собой 32-байтовый ключ (AES-256) и может быть протестирован, например. здесь.

В Python вы можете декодировать Base64url с помощью urlsafe_b64decode. Однако ожидается добавленное закодированное значение Base64url, поэтому сначала необходимо добавить заполнение, например. с помощью метода repad из здесь.

import base64

# from https://stackoverflow.com/a/9024884/9014097
def repad(data):
    return data + "=" * (-len(data)%4)

GIVEN_KEY = 'QOahfcdo98NLjYJuhP4-VKigx51NkUETsKlIu9uXZFY'

secret = base64.urlsafe_b64decode(repad(GIVEN_KEY).encode()) 
print(secret.hex()) # 40e6a17dc768f7c34b8d826e84fe3e54a8a0c79d4d914113b0a948bbdb976456
person user 9014097    schedule 06.08.2020
comment
Если это не решит проблему, было бы лучше опубликовать оба кода. - person user 9014097; 06.08.2020
comment
Декодирование Base64 не решит эту проблему, длина символа GIVEN_KEY не обязательно кратна 4. SecretKeySpec выполняет какой-то вывод ключа. - person Hrishi; 06.08.2020
comment
SecretKeySpec создает SecretKey на основе переданного byte[], базовые данные не изменяются, здесь. Если его длина не соответствует действительному ключу AES (16, 24, 32 байта), позже (т. е. во время шифрования/дешифрования) выдается исключение. Вероятно, ваша проблема где-то в другом. Я могу только порекомендовать вам опубликовать оба кода. - person user 9014097; 06.08.2020
comment
... длина символа GIVEN_KEY не обязательно кратна 4... С дополнением длина должна быть кратна 4. Возможно, во время кодирования ключа применяется вариант Base64, который не набивается. Base64.decodeBase64 декодирует строки в кодировке Base64 и Base64url. В то время как Base64.encodeBase64String прокладки, Base64.encodeBase64URLSafeString нет. Возможно, вам следует проверить, какой вариант Base64 использовался для кодирования ключа. - person user 9014097; 06.08.2020
comment
См. раздел «Пример кода Java для шифрования AES» в этого документа (номер страницы 31). ), я пытаюсь воссоздать это в python. - person Hrishi; 06.08.2020
comment
Код Java действительно использует закодированный ключ Base64url без заполнения, который должен быть соответствующим образом декодирован в коде Python, см. раздел EDIT в моем ответе. - person user 9014097; 06.08.2020
comment
Это некоторый прогресс. Я попробовал этот метод. Теперь у меня больше не возникает проблема с длиной ключа. Но удаленная служба по-прежнему не может расшифровать строку, которую я шифрую. Позвольте мне также поделиться кодом Python для справки. - person Hrishi; 06.08.2020
comment
@Hrishi - здесь есть ответ на этот вопрос. Пожалуйста, задайте новый вопрос и опубликуйте оба кода в вопросе (а не только в виде ссылок в комментариях). Спасибо. - person user 9014097; 06.08.2020