英文:
AES Key (Byte array) to string on Python
问题
I have translated the relevant code from the provided text:
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 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
Please note that I've removed the HTML encoding of characters, and the translation should now be more suitable for Python usage. If you have any more specific questions or need further assistance, feel free to ask.
英文:
Ok, I'm a programmer on C#, I used to have a program that transform a byte array from the AES key and IV to a base64 string and write this on a file. But I'm with a big problem, I need to made te same thing on Python, and the Python works very bad with byte arrays. I'm with this problem, I tried to generate a key with 'Crypto.Random.get_random_bytes(16)' and convert he to a string, on the C#, its simple, I convert to base64, and the base64 is almost the same that strings, we can concatanate with normal strings, write in files and all the other things. But in the Python when I convert a byte array to a string, give me this error:
key = get_random_bytes(16).decode(encoding="utf-8")
> 'utf-8' codec can't decode byte 0xaf in position 2: invalid start byte
This doesn't is the same problem all the time, the position and byte change occasionally. And the problems is on the str() too. So, I tried to convert to a base64 string, I haved this problem with the linebreak maker:
breaked = '\n'.join(key[i:i+every] for i in range(0, len(key), every))
>TypeError: sequence item 0: expected str instance, bytes found
So, like a distressed person I remove the linebraker, and try put all on one line.
text = "------ Crypton Key Begin ------\n"+key+"\n------ Crypton Key End ------"
> TypeError: can only concatenate str (not "bytes") to str
So oook, its very problematic, so I tried write on the file only the base64.
fob.write(key)
> TypeError: write() argument must be str, not bytes
I don't know more what can I do, because in the C# a simple code works fine. If help, this is the C# Code:
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;
My Python class:
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
答案1
得分: -2
在代码中,你分享了如何将字节(bytes)转换为整数(int)和整数转换为字符串(str),以及如何反转这些转换。你还提到了一种使用JSON的方法来加密和解密数据。这是一种很有用的示例,让你展示了不同数据类型之间的转换和处理。
如果你有任何关于代码或加密的问题,请随时提问。
英文:
Well, before I write the solution I want to say one thing. I search for answer on a lot of places, everybody say that don't have a good solution, I don't judge, because such @Jonn Hanley say, nobody will write the code for you. The reason to I write this is, never give up, because in the majority of the times the solution don't will be easy, but will exist.
And my thank you to @Maurice Meyer on this question, because in this question he show me a important detail, the bytes can be converted on int, and int can be converted to str, and the reverse is true.
Thinking this, I write this simple code:
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))
My output:
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'>
Obvius, have ways that this string can be more coded, in my .py I will made this string more differente that the simple int, because that's too obvious, but the important is:
Yes, have a simple way to transform a bytes on a str.
---> EDITED <------> 01/04/2023 9h44 <---
Some peoples are with doubt about my code, so I will complement my answer.
I know that its works, because I tried on a loop and I don't receive problems, and the exit every is the same. But if someone have doubt, no problems, paste this code on a python File and try for yourself:
_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))
output:
-6597165323605166304435026916416471029
<class 'str'>
-6597165323605166304435026916416471029
<class 'int'>
b'\xfb\tn\xa3\x0e\n\xaf|J~Z\x92s\xc3@\x0b'
<class 'bytes'>
If you have the same output, it works, you can see that is the same bytes of my first output. I'll explaine some important things to you code don't brick. First, See the byte lenght, if this are different then you will receive problems, the same thing about "big" and "little" the calling 'byte order'. Give the signed too, because this say to the code if can be negative integer, I accept the negative, so I put True. If you put False, every that you receive a negative number the code will throw a exeption on you. Give the same arguments to the conversion and to revert the conversion and it will works.
If you alread have some doubt about my code, I don't judge you, I think that you can use json, like the official documentation say:
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")
I don't try it, so I don't know if works, but such is the official documentation, is very possible that works.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论