Хорошо, я программист на 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
Подождите, я использую официальную библиотеку для всего, что связано с шифрованием. Я много ищу в сезон, я не знаю всех мест, где я был. Об этом я сказал @John Hanley, мой вопрос о преобразовании строки в байты закрыт. Если у вас есть критика по поводу моей окончательной программы и моей криптографии, сообщите мне чат, форум или другое место, где вы можете помочь мне с моей разработкой, но это не то место.
Ну, прежде чем я напишу решение, я хочу сказать одну вещь. Я ищу ответ во многих местах, все говорят, что у них нет хорошего решения, я не сужу, потому что, как говорит @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")
Я не пробовал, поэтому не знаю, работает ли, но такова официальная документация, вполне возможно, что работает.
У вас есть два эксперта по криптографии, предлагающие вам критику, и вы настаиваете на том, чтобы выстрелить себе в ногу. Многие люди задаются вопросом, как компании так легко взламываются. Это пример отношения, которое провоцирует нарушения безопасности.
Ну, я постараюсь быть краток. Ваша проблема связана не с моим ответом о байтах в строку, а с моей окончательной программой. Нет проблем, если вы считаете, что у меня есть лучший способ сделать это, сообщите мне в чате, на форуме или где-нибудь еще, где я могу поговорить с вами или с другими экспертами по криптографии, я объясню весь мой проект, и я буду с умом, открытым для критики. Мне действительно нужна помощь и советы по моей финальной программе, например, вы сказали, что я новичок, но я не хочу вас беспокоить, например, вы сказали, что вас здесь нет, чтобы кодировать для меня.
Какого черта. Возможно, вам следует сначала понять, что вы делаете, прежде чем приступать к реализации. В классе C# нет даже никакого шифрования, и вы по-прежнему используете декодирование UTF-8 случайных байтов, хотя знаете, что это неправильно. Что вы сделали, взяли случайные блоки кода из Интернета?