0

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

DazzRick
  • 85
  • 7
  • 1
    What the heck. Maybe you should first have a clue what you are doing before you start implementing. There isn't even any encryption in the C# class, and you still use UTF-8 decoding of random bytes, while you know it is wrong. What did you do, grab random code blocks from the internet? – Maarten Bodewes Apr 02 '23 at 17:31
  • Wait, I use the [official library](https://learn.microsoft.com/pt-br/dotnet/api/system.security.cryptography.aes?view=netframework-4.8.1) for all that involved encrypting. I search a lot in season, I don't know all the places that I went. Such I sayed to @John Hanley, my question about string to bytes is closed. If you have some criticism about my final program and about my cryptography, so tell me a chat, forum or other place that you can help me with my development, but it don't is the place. – DazzRick Apr 03 '23 at 18:50

1 Answers1

-2

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.

DazzRick
  • 85
  • 7
  • You have two cryptography experts offering you criticism and you insist on shooting yourself in the foot. Many people wonder how companies are so easily hacked. This is an example of the attitude that invites security breaches. – John Hanley Apr 03 '23 at 01:21
  • Well, I'll try to be short. You problem don't is with my answer about bytes to string, you problem is with my final program. No problems, if you think that I have a better way to do this, so tell me a chat, forum or somewhere that I can talk to you or to the others cryptography experts, I'll explain all my project and I'll be with the mind open to criticism. I really need help and tips about my final program, such you sayed I'm a begginer, but I don't want bother you, such you sayed that you don't was here to code for me. – DazzRick Apr 03 '23 at 18:43