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
Missing Providername When Debugging Azurefunction as Well as Deploying Azure Function
Canadian Postal Code Validation
Caching the Result from a [N Async] Factory Method Iff It Doesn't Throw
Xmlserialize a Custom Collection with an Attribute
How to Prevent Datagridview from Flickering When Scrolling Horizontally
Enable-Migrations Exception Calling "Setdata" with "2" Argument(S)
Adding Multiple Icons (Win32-Resource) to .Net-Application
What's the Best Way to Compare Double and Int
How to Use the 7Z Sdk to Compress and Decompress a File
What Is the Easiest Way to Do Inter Process Communication in C#
How to Connect to a Ms Access File (Mdb) Using C#
How to Change the Culture of a Winforms Application at Runtime