AES密钥(字节数组)转换为字符串在Python中

huangapple go评论91阅读模式
英文:

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(&#39;&#39;)
_int_again = int(_str)
print(_int_again)
print(type(_int_again))
print(&#39;&#39;)
_bytes_again = _int.to_bytes(_len, &quot;big&quot;, signed=True)
print(_bytes_again)
print(type(_bytes_again))

output:


-6597165323605166304435026916416471029
&lt;class &#39;str&#39;&gt;
-6597165323605166304435026916416471029
&lt;class &#39;int&#39;&gt;
b&#39;\xfb\tn\xa3\x0e\n\xaf|J~Z\x92s\xc3@\x0b&#39;
&lt;class &#39;bytes&#39;&gt;

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&quot;secret&quot;
key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CFB)
ct_bytes = cipher.encrypt(data)
iv = b64encode(cipher.iv).decode(&#39;utf-8&#39;)
ct = b64encode(ct_bytes).decode(&#39;utf-8&#39;)
b64key = b64encode(key).decode(&#39;utf-8&#39;)
result = json.dumps({&#39;key&#39;: b64key, &#39;iv&#39;:iv, &#39;ciphertext&#39;:ct})
try:
b64 = json.loads(result)
iv = b64decode(b64[&#39;iv&#39;])
key = b64decode(b64[&#39;key&#39;])
ct = b64decode(b64[&#39;ciphertext&#39;])
cipher = AES.new(key, AES.MODE_CFB, iv=iv)
pt = cipher.decrypt(ct)
print(&quot;The message was: &quot;, pt)
except (ValueError, KeyError):
print(&quot;Incorrect decryption&quot;)

I don't try it, so I don't know if works, but such is the official documentation, is very possible that works.

huangapple
  • 本文由 发表于 2023年3月31日 03:18:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75892168.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定