Search code examples
c#encryptionencodingaes

Why isn't the encoded key equal to the original key?


Language: C#, Framework: .NET Core 3.1

I am using encryption based on AES.

Research:
Key Format AES

Gilles: An AES key is just a bunch of bits with no structure.

The Key and IV need to be stored since they are randomly generated each time and they are required for Encryption and Decryption.

I need to store it as a string for particular reasons, so I want to be able to convert a byte array to a string and backwards if needed using encoding.

The conversion happens using UTF-8 encoding.

My problem:
I've put a breakpoint in my code and the contents of the byte array are clearly different from the original array. I've tried switching to other encoding formats but this also failed. In a nutshell, the data changed and this would result in being unable to decrypt a message because the AES key and IV would be incorrect.

Update:
The UTF-8 conversion doesn't work when keyBytes doesn't contain valid utf8 data and the encoder will generate fallback data which causes the problem.

Example:

using (Aes myAes = Aes.Create())
{
    bool valid = false;
    byte[] keyBytes = myAes.Key;
    Encoding utf8WithoutBom = new UTF8Encoding(true);

    string key = utf8WithoutBom.GetString(keyBytes);
    byte[] outputBytes = utf8WithoutBom.GetBytes(key);

    if (myAes.Key.Length == outputBytes.Length) {
        for (int i = 0; i < myAes.Key.Length; i++) {
            if (outputBytes[i] == keyBytes[i]) {
                valid = true;
            }

            else {
                valid = false;
                break;
            }
        }
    }

    if (valid == true) {
        Console.WriteLine("Succes");
    }

    else {
        Console.WriteLine("Error");
        throw new Exception("The keys do not match.");
    }
}

Result:
- Output: byte[] with a size between 50~54 Error
- Desired Output: byte[32] with the same data as the original array Succes

Question:
Why are the contents of the output byte array different from the original byte array?


Solution

  • The conversion from byte[] -> string -> byte[] will only work when the initial byte array contains a valid utf8 content. Not every 32 byte array does that.

    If the original array contains invalid data, the byte[] -> string conversion will already return some fallback data and a second conversion will convert those fallback values to their corresponding bytes.

    If you want to encode an arbitrary byte array into a string, use Base64 or some other general data encoding, but not utf8.