Specified Key Is Not a Valid Size for This Algorithm

Specified key is not a valid size for this algorithm

The string "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678912" when base64-decoded yields 48 bytes (384 bits). RijndaelManaged supports 128, 192 and 256 bit keys.

A valid 128-bit key is new byte[]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } or if you need to get it from base64 : Convert.FromBase64String("AAECAwQFBgcICQoLDA0ODw==").

The default blocksize is 128 bits, so the same byte-array will work as the IV.

Specified key is not a valid size for this algorithm. Nothing else worked

I believe your Key needs to be 16 bytes long. new byte[] {} will create a Key that is 0 bytes long

Error: Specified key is not a valid size for this algorithm

DES algorithm expects 64-bit (8 bytes) key. Your sEncryptionKey has length of 6 chars, that's why you get "Specified key is not a valid size" error.

DES works with 64-bit keys and these keys should not be human-friendly passprases like 'SomePass'. They should be binary keys that cover all possible variety for 64-bit keys (2^64 different combinations). Otherwise your encryption will be much more weaker than DES standard implies.

That's why when using symmetric encryption algorithms from System.Security.Cryptography, you should treat your secret not as final key that will be used for encryption but as a passphrase from which you generate encryption key. You perform this generation by constructing instance of System.Security.Cryptography.Rfc2898DeriveBytes with your passprase and some salt (which could be randomly generated but should also be used during decryption).

Another problem with your code is that you're using initialization vector (IV) with 6 bytes length. It should also be 8-bytes length and you should use random initialization vector for each encryption. You could generate IV by calling DESCryptoServiceProvider.GenerateIV() method and accessing DESCryptoServiceProvider.IV property.

And final note. Since you convert returnstring to Base64 there is no need in replacing all those special characters, like '&' and '$'. Base64 charset consists from digits, numbers and '+', '/', '=' symbols. You could replace only these 3 chars.

So here is edit of your code based on above comments:

public static class EncryptDecrypt
{
private static string sEncryptionPassphrase = "B@|@j!";

public static string Encrypt(string stringToEncrypt)
{
try
{
string returnstring;
var salt = GenerateSalt();
using (var keyBytes = new Rfc2898DeriveBytes(sEncryptionPassphrase, salt))
{
var key = keyBytes.GetBytes(8);

DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.GenerateIV();
byte[] inputByteArray = Encoding.UTF8.GetBytes(stringToEncrypt);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(key, des.IV), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
returnstring = Convert.ToBase64String(ms.ToArray());
}

//URL Encryption Avoid Reserved Characters
returnstring = returnstring.Replace("/", "-2F-");
returnstring = returnstring.Replace("+", "-2B-");
returnstring = returnstring.Replace("=", "-3D-");

return returnstring;
}
catch (Exception e)
{
return e.Message;
}
}

private static byte[] GenerateSalt()
{
var randomBytes = new byte[8];
using (var rngCsp = new RNGCryptoServiceProvider())
{
rngCsp.GetBytes(randomBytes);
}
return randomBytes;
}
}

Aes encryption in .net Core 3.0 'Specified key is not a valid size for this algorithm.'

You did wrong here- var key = Encoding.UTF8.GetBytes("mysmallkey");
Refer Documentation here Aes Class
and AES Documentation

I suggest you by using LegalKeySizes property in AES class you can check the valid size of your key. The valid key sizes are specified by the particular symmetric algorithm implementation and are listed in the LegalKeySizes property.

 public virtual KeySizes[] LegalKeySizes { get; }

You will get the below output

var key = Encoding.UTF8.GetBytes("mysmallkey");
//myAes.Key = Key; //ERROR
KeySizes[] ks = myAes.LegalKeySizes;
foreach (KeySizes item in ks)
{
Console.WriteLine("Legal min key size = " + item.MinSize);
Console.WriteLine("Legal max key size = " + item.MaxSize);
//Output
// Legal min key size = 128
// Legal max key size = 256
}

if you are using 128 bit then Length of secret key should be 16 for 128 bits key size
Try this one

 var key = Encoding.UTF8.GetBytes("mysmallkey123456");

For 192 bit - Length of the secret key should be 24 for 192 bits key
size sample key will be like this

mysmallkey12345512987651 

For 256 bit - Length of the secret key should be 32 for 256 bits key
size sample key

mysmallkey1234551298765134567890

System.Security.Cryptography.CryptographicException: Specified key is not a valid size for this algorithm

The solution was to not first convert my string into a bytearray and then do a hexstring conversion.

The string in the keyvault was already a "hexstring"

So getting rid of this.

byte[] tempBytes = utf8.GetBytes(keyStringValue);
var hexString = BitConverter.ToString(tempBytes);
hexString = hexString.Replace("-", "").ToLower();

And from

var keyStringValue = _configuration.GetValue<string>("the-key-i-want")

pass that to the hexstring conversion

  private static byte[] FromHex(string keyStringValue)
{
int NumberChars = keyStringValue.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(keyStringValue.Substring(i, 2), 16);

return bytes;
}

And Bob is your uncle.

TripleDESCryptoServiceProvider Specified key is not a valid size for this algorithm at 128 bytes?

Key sizes are in bits not in bytes. 3DES key size is 168, 112 or 56 bits, depending on keying option. The C# implementation supports key sizes of 128 and 192 bits, from which it will only use 112 and 168 bits, respectively.

The key specified is not a valid key for this encryption: Key size is not valid. Got key length of: 15

BTW, I assume this code is just for testing purpose, since passing the encryption key alongside the encrypted text utterly and completely defeats the purpose of encryption ;-)

Is there a way to find out what is causing an error

With troubleshooting, location() tends to get in the way, so best to temporarily replace it with a hyperlink. Then you'll be able to output the original key generated and compare it to what's actually received on the home page.

Test Case (Single Page)

<cfscript>
// It make take a few executions to hit a failing key like `n+Py4flPF6uOwNXwpq2J4g==`.
pg_info = { "plain" : "text" };
key = "generateSecretKey(("AES"),128);
data = encrypt(serializeJSON(pg_info), key, "AES", "HEX");

writeOutput( "[key] "& key &"<br>[encoded] "& encodeForURL(key) &"<br><br>");
writeOutput( '<a href="#CGI.SCRIPT_NAME#?str=#encodeForURL(key)#&dt=#data#">Test</a>' );


if ( url.keyExists("str")) {

writeDump( var=[url.str], label="url.str (Original)" );
writeDump( var=[DecodeFromURL(url.str)], label="url.str (Decoded)" );

key = DecodeFromURL(url.str);
strData = deserializeJSON(decrypt(url.dt, key, "AES", "HEX"));
writeDump( var=strData, label="strData" );
}

</cfscript>

how to fix this issue?

CF already decodes url parameters automatically. So decoding url.str a second time alters the original key value, causing decrypt() to fail because the key is no longer valid. Notice with a failing key like n+Py4flPF6uOwNXwpq2J4g== the original url.str value differs from the decoded key?

  • url.str (Original) n+Py4flPF6uOwNXwpq2J4g== (has "+" char)

  • key (Decoded) n Py4flPF6uOwNXwpq2J4g== ("+" changes to space char)

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

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 Topics



Leave a reply



Submit