Ключ AES (массив байтов) для строки на Python

Хорошо, я программист на C#, у меня была программа, которая преобразовывала массив байтов из ключа AES и IV в строку base64 и записывала это в файл. Но у меня большая проблема, мне нужно сделать то же самое на Python, а Python очень плохо работает с байтовыми массивами. Я с этой проблемой, я попытался сгенерировать ключ с помощью «Crypto.Random.get_random_bytes (16)» и преобразовать его в строку, на C# это просто, я конвертирую в base64, а base64 почти такой же эти строки, мы можем конкатенировать с обычными строками, записывать в файлы и делать все остальное. Но в Python, когда я конвертирую массив байтов в строку, я получаю эту ошибку:

key = get_random_bytes(16).decode(encoding = "utf-8")

Кодек utf-8 не может декодировать байт 0xaf в позиции 2: недопустимый начальный байт

Это не всегда одна и та же проблема, время от времени меняются позиция и байт. И проблемы на str() тоже. Итак, я попытался преобразовать строку в base64, у меня была эта проблема с создателем разрыва строки:

breaked = '\n'.join(key[i:i+every] for i in range(0, len(key), every))

TypeError: элемент последовательности 0: ожидаемый экземпляр str, байты найдены

Так что, как огорченный человек, я убираю линейный прерыватель и пытаюсь поставить все на одну линию.

text = "------ Crypton Key Begin ------\n"+key+"\n------ Crypton Key End ------"

TypeError: может объединять только строку str (не «байты») с строкой

Итак, это очень проблематично, поэтому я попытался записать в файл только base64.

fob.write(key)

TypeError: аргумент write() должен быть строкой, а не байтами

Я больше не знаю, что я могу сделать, потому что в C# простой код работает нормально. Если поможете, это код С#:


Aes aesAlgorithm = Aes.Create();
aesAlgorithm.KeySize = 256;
aesAlgorithm.GenerateKey();
aesAlgorithm.GenerateIV();
_key = aesAlgorithm.Key;
_vector = aesAlgorithm.IV;

FileText = string.Format("----- Start Key File -----\n<0>{0}</0>\n<1>{1}</1>\n----- End Key File -----",
     Convert.ToBase64String(_key),
     Convert.ToBase64String(_vector)
)
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "SEA file (*.sea) | *.sea";
if (saveFileDialog.ShowDialog() == true)
     File.WriteAllText(saveFileDialog.FileName, FileText);
else return;

Мой класс Python:


from tkinter.filedialog import asksaveasfilename, askopenfilename
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from base64 import b64encode

class Crypton:
    @staticmethod
    def GetKey():
        return get_random_bytes(16).decode(encoding = "utf-8")

    @staticmethod
    def Encrypt(data, key):
        if type(key) != type(str):
            if type(key) == type(get_random_bytes(16)):
                key = key.decode(encoding='utf-8')
            else:
                raise Exception("The type of the key is not supported.")
        cipher = AES.new(key, AES.MODE_EAX)
        ciphertext, tag = cipher.encrypt_and_digest(data)
        nonce = cipher.nonce
        str_decoded = Crypton.ToString([key, ciphertext, tag, nonce])
        return str_decoded

    @staticmethod
    def Decrypt(str_decoded):
        binary_decoded = Crypton.ToBinary(str_decoded)
        cipher = AES.new(binary_decoded[0], AES.MODE_EAX, binary_decoded[3])
        data = cipher.decrypt_and_verify(binary_decoded[1], binary_decoded[2])
        return data

    @staticmethod
    def Decrypt(key, ciphertext, tag, nonce):
        return Crypton.Decrypt([key, ciphertext, tag, nonce])

    @staticmethod
    def ToBinary(str_decoded):
        utf = 'utf-8'
        key = str_decoded[0].encode(encoding=utf)
        ciphertext = str_decoded[1].encode(encoding=utf)
        tag = str_decoded[2].encode(encoding=utf)
        nonce = str_decoded[3].encode(encoding=utf)
        return [key, ciphertext, tag, nonce]

    @staticmethod
    def ToString(binary_decoded):
        utf = 'utf-8'
        key = binary_decoded[0].decode(encoding=utf)
        ciphertext = binary_decoded[1].decode(encoding=utf)
        tag = binary_decoded[2].decode(encoding=utf)
        nonce = binary_decoded[3].decode(encoding=utf)
        return [key, ciphertext, tag, nonce]

    @staticmethod
    def CreateCryptonKeyFile(key):
        bricked_key = Crypton.BreakKey(key)
        text = "------ Crypton Key Begin ------\n"+bricked_key+"\n------  Crypton Key End  ------"
        file = asksaveasfilename(
            filetypes=[("Crypton Key File", ".cey")],
            defaultextension = ".cey")
        with open(file, 'w') as fob:
            fob.write(text)

    @staticmethod
    def BreakKey(key):
        every = 31
        breaked = '\n'.join(key[i:i+every] for i in range(0, len(key), every))
        return breaked

    @staticmethod
    def ReadCryptonKeyFile():
        file = askopenfilename(
            filetypes=[("Crypton Key File", ".cey")],
            defaultextension = ".cey")
        with open(file, 'r').read() as infile:
            return Crypton.ReadCryptonKeyString(infile)

    @staticmethod
    def ReadCryptonKeyString(string):
        key = ''.join(
            string.replace("------ Crypton Key Begin ------\n", "")\
            .replace("\n------  Crypton Key End  ------", "")\
            .split('\n')
        )
        return key

Какого черта. Возможно, вам следует сначала понять, что вы делаете, прежде чем приступать к реализации. В классе C# нет даже никакого шифрования, и вы по-прежнему используете декодирование UTF-8 случайных байтов, хотя знаете, что это неправильно. Что вы сделали, взяли случайные блоки кода из Интернета?

Maarten Bodewes 02.04.2023 19:31

Подождите, я использую официальную библиотеку для всего, что связано с шифрованием. Я много ищу в сезон, я не знаю всех мест, где я был. Об этом я сказал @John Hanley, мой вопрос о преобразовании строки в байты закрыт. Если у вас есть критика по поводу моей окончательной программы и моей криптографии, сообщите мне чат, форум или другое место, где вы можете помочь мне с моей разработкой, но это не то место.

DazzRick 03.04.2023 20:50
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
138
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ну, прежде чем я напишу решение, я хочу сказать одну вещь. Я ищу ответ во многих местах, все говорят, что у них нет хорошего решения, я не сужу, потому что, как говорит @Jonn Hanley, никто не будет писать код для вас. Причина, по которой я пишу это, заключается в том, чтобы никогда не сдаваться, потому что в большинстве случаев решение не будет простым, но будет существовать.

И моя благодарность @Maurice Meyer за этот вопрос, потому что в этом вопросе он показал мне важную деталь, байты могут быть преобразованы в int, а int могут быть преобразованы в str, и наоборот.

Думая об этом, я пишу этот простой код:

from Crypto.Random import get_random_bytes
_bytes = get_random_bytes(16)
print(_bytes)
print(type(_bytes))
print('')
_len = len(_bytes) #Same to the 16 on get_random_bytes
print(_len)
_int = int.from_bytes(_bytes, "big", signed=True)
print(_int)
print(type(_int))
print('')
_str = str(_int)
print(_str)
print(type(_str))
print('')
_int_again = int(_str)
print(_int_again)
print(type(_int_again))
print('')
_bytes_again = _int.to_bytes(_len, "big", signed=True)
print(_bytes_again)
print(type(_bytes_again))

Мой вывод:

b'\xfb\tn\xa3\x0e\n\xaf|J~Z\x92s\xc3@\x0b'
<class 'bytes'>

16
-6597165323605166304435026916416471029
<class 'int'>

-6597165323605166304435026916416471029
<class 'str'>

-6597165323605166304435026916416471029
<class 'int'>

b'\xfb\tn\xa3\x0e\n\xaf|J~Z\x92s\xc3@\x0b'
<class 'bytes'>

Очевидно, есть способы, которыми эта строка может быть более закодирована, в моем .py я сделаю эту строку более отличной от простого int, потому что это слишком очевидно, но важно следующее:

Да, есть простой способ преобразовать байты на ул.

---> РЕДАКТИРОВАНО <------> 04.01.2023 9:44 <---

Некоторые люди сомневаются в моем коде, поэтому я дополню свой ответ.

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


_len = 16
_int = -6597165323605166304435026916416471029
_str = str(_int)
print(_str)
print(type(_str))
print('')
_int_again = int(_str)
print(_int_again)
print(type(_int_again))
print('')
_bytes_again = _int.to_bytes(_len, "big", signed=True)
print(_bytes_again)
print(type(_bytes_again))

выход:


-6597165323605166304435026916416471029
<class 'str'>

-6597165323605166304435026916416471029
<class 'int'>

b'\xfb\tn\xa3\x0e\n\xaf|J~Z\x92s\xc3@\x0b'
<class 'bytes'>

Если у вас такой же вывод, он работает, вы можете видеть, что это те же байты моего первого вывода. Я объясню некоторые важные вещи, чтобы код не блокировался. Во-первых, посмотрите длину байта, если она отличается, у вас возникнут проблемы, то же самое с «большим» и «маленьким» вызывающим «порядком байтов». Дайте и подписанный, потому что это говорит коду, что если может быть отрицательное целое число, я принимаю отрицательное значение, поэтому я ставлю True. Если вы укажете False, каждый раз, когда вы получаете отрицательное число, код будет вызывать исключение. Дайте те же аргументы для преобразования и для отмены преобразования, и оно будет работать.

Если у вас уже есть какие-то сомнения относительно моего кода, я не осуждаю вас, я думаю, что вы можете использовать json, например, официальную документацию скажите:


import json
from base64 import b64encode
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes

data = b"secret"
key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CFB)
ct_bytes = cipher.encrypt(data)
iv = b64encode(cipher.iv).decode('utf-8')
ct = b64encode(ct_bytes).decode('utf-8')
b64key = b64encode(key).decode('utf-8')
result = json.dumps({'key': b64key, 'iv':iv, 'ciphertext':ct})

try:
    b64 = json.loads(result)
    iv = b64decode(b64['iv'])
    key = b64decode(b64['key'])
    ct = b64decode(b64['ciphertext'])
    cipher = AES.new(key, AES.MODE_CFB, iv=iv)
    pt = cipher.decrypt(ct)
    print("The message was: ", pt)
except (ValueError, KeyError):
    print("Incorrect decryption")

Я не пробовал, поэтому не знаю, работает ли, но такова официальная документация, вполне возможно, что работает.

У вас есть два эксперта по криптографии, предлагающие вам критику, и вы настаиваете на том, чтобы выстрелить себе в ногу. Многие люди задаются вопросом, как компании так легко взламываются. Это пример отношения, которое провоцирует нарушения безопасности.

John Hanley 03.04.2023 03:21

Ну, я постараюсь быть краток. Ваша проблема связана не с моим ответом о байтах в строку, а с моей окончательной программой. Нет проблем, если вы считаете, что у меня есть лучший способ сделать это, сообщите мне в чате, на форуме или где-нибудь еще, где я могу поговорить с вами или с другими экспертами по криптографии, я объясню весь мой проект, и я буду с умом, открытым для критики. Мне действительно нужна помощь и советы по моей финальной программе, например, вы сказали, что я новичок, но я не хочу вас беспокоить, например, вы сказали, что вас здесь нет, чтобы кодировать для меня.

DazzRick 03.04.2023 20:43

Другие вопросы по теме