Home > Mobile >  I am using GUID as key and it's throwing error Specified key is not a valid size for this algor
I am using GUID as key and it's throwing error Specified key is not a valid size for this algor

Time:08-25

I have below method for symmetric encryption a string content,

 public static class EncodeExtension
{
    public static string AesEncryptString(this string plainText, string key)
    {
        byte[] iv = new byte[16];
        byte[] array;

        using (Aes aes = Aes.Create())
        {
            aes.Key = Encoding.UTF8.GetBytes(key);
            aes.IV = iv;

            ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream))
                    {
                        streamWriter.Write(plainText);
                    }

                    array = memoryStream.ToArray();
                }
            }
        }

        return Convert.ToBase64String(array);
    }
}

Now I want to pass a random Guid as a key for each string content string,

var key1 = Guid.NewGuid().ToString();
var encryptedData = "test1".AesEncryptString(key1);


var key2 = Guid.NewGuid().ToString();
var encryptedData = "test2".AesEncryptString(key2);

Here I am getting Specified key is not a valid size for this algorithm? What key size it's expecting here? I do generate a random key size ?

CodePudding user response:

Even if you can, never use a GUID for encryption key because they're not guaranteed to produce a cryptographically secure random number. It might be significantly easier to crack a GUID-based key than a securely generated key. Never use GUID for cryptographically sensitive operations.

I don't recommend running a KDF over the GUID either since that doesn't change the low entropy underneath.

As of .NET 6, it's way easier to generate a cryptographically secure random key:

byte[] key = RandomNumberGenerator.GetBytes(32); // generate 256-bits

CodePudding user response:

byte[] iv = new byte[16];
byte[] array;
using var aes = Aes.Create();
aes.Key = Encoding.UTF8.GetBytes(key);
aes.IV = iv;

Everything about this is terribly broken.

16 bytes that represent a valid UTF8 string, is not very random. If I saw your code, I would be able to guess a significant fraction of the bits of your key.

.IV must always be unique. If you ever encrypt two different inputs with the same .Key & .IV, your encryption can be easily broken. It's common to generate a random IV and write it as plain text into the output. eg memoryStream.Write(aes.IV)

Using a salted hash to turn a password string into a key is better, but only if you can ensure that your salt is kept secret.

CodePudding user response:

This error comes from the fact that the size in bytes of the GUID UTF8 string isn't a valid key size for AES (128, 192 or 256 bits).

You could use a key derivation function such as PBKDF2 to derive the key from your GUID. PBKDF2 is implemented in .net by the class Rfc2898DeriveBytes

public static string AesEncryptString(this string plainText, string key) {
    byte[] array;
    byte[] keyBytes;

    using (Aes aes = Aes.Create())
    {
        using (Rfc2898DeriveBytes pbkdf = new Rfc2898DeriveBytes(key, Encoding.UTF8.GetBytes(key)))
        {
            // here 16 bytes for AES128
            keyBytes = pbkdf.GetBytes(16);
        }

        aes.Key = keyBytes;
        //for convenience here we use the key as iv too
        aes.IV = keyBytes;

        ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream))
                {
                    streamWriter.Write(plainText);
                }

                array = memoryStream.ToArray();
            }
        }
    }

    return Convert.ToBase64String(array); 
 }

Be careful as you will have to use the same behavior to generate the key on decryption too.

  • Related