Solved

Specified key is not a valid size for this algorithm

Posted on 2013-01-14
33
2,976 Views
Last Modified: 2013-02-15
I have the following Encryption algorithm and I am getting the Specified key is not a valid size for this algorithm error.

        public string Encrypt(string toEncrypt, bool useHashing, string key)
        {
            // If string is null or whitespace, return toEncrypt
            if (String.IsNullOrEmpty(toEncrypt) || String.IsNullOrWhiteSpace(toEncrypt) || toEncrypt.Equals(DBNull.Value))
                return toEncrypt;

            // Strip blanks from end of string
            toEncrypt = toEncrypt.Trim();
     
            byte[] keyArray;
            byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

            System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
            if (String.IsNullOrEmpty(key))
                // Get the key from config file
                key = (string)settingsReader.GetValue("SecurityKey", typeof(String));
            //System.Windows.Forms.MessageBox.Show(key);
            if (useHashing)
            {
                //MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
                SHA512CryptoServiceProvider hashmd5 = new SHA512CryptoServiceProvider();
                keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
                hashmd5.Clear();
            }
            else
                keyArray = UTF8Encoding.UTF8.GetBytes(key);

            TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
            tdes.Key = keyArray;
            tdes.Mode = CipherMode.ECB;
            tdes.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = tdes.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            tdes.Clear();
            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }

Open in new window

The above code is in a DLL that is registered on the server.

Here is the code that I am using to test the DLL.

<%@LANGUAGE="VBSCRIPT"%>
<%
Set Encrypt = Server.CreateObject("EnCryptDecrypt.CryptorEngine")

tmpStr = Encrypt.Encrypt("12345", true, "abcdefghijklmnop")
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>

<body>
<p>Encryption Test</p>
<% Response.Write tmpStr %>
</body>
</html>

Open in new window


I can't figure out why the error is occurring since the key being used is 16 characters which should be 128 bits.  The SHA512 supports 128 bit, 192 bit and 256 bit keys.

Any help would be great!
0
Comment
Question by:dyarosh
  • 17
  • 13
  • 3
33 Comments
 
LVL 11

Expert Comment

by:rharland2009
Comment Utility
SHA512 uses hexadecimal digits. Hexadecimal digits are 4 bits per. I think you need 32.
0
 

Author Comment

by:dyarosh
Comment Utility
Does my key have to be in HEX?  I tried the following key and got the same error message:

tmpStr = Encrypt.Encrypt("12345", true, "abcdefghijklmnopqrstuvwxyz123456")
0
 
LVL 11

Expert Comment

by:rharland2009
Comment Utility
No, it should not need to be in hex.
0
 

Author Comment

by:dyarosh
Comment Utility
I still get the error using this as the key: abcdefghijklmnopqrstuvwxyz123456

Any thoughts?
0
 
LVL 11

Expert Comment

by:rharland2009
Comment Utility
Each of those characters is a byte, not a bit.
I think you need to shorten it to match the keylength you're after.
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
Wy are you using UTF8 for encoding?can you as part of your test output what the key length is and the string that is being passed to the encrypt function.
0
 

Author Comment

by:dyarosh
Comment Utility
I modified my the Encryption Program to return the KeyHashSize and I modified my calling program to tell me how many bytes are in my key.  Here are the results:

String to encrypt: 12345
Key: abcdefghijklmnopqrstuvwxyz123456
Results: Encryption Key: 256     Key in Bytes: 32

I'm still getting the invalid key size error.  I should say that I modified my original post to use SHA256CryptoServiceProvider hashmd5 = new SHA256CryptoServiceProvider();

As to why I'm using UTF8 for encoding:  I copied this algorithm from a post that I found on the web.

Any other thoughts?
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
Which .net framework are you working with?
http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha512cryptoserviceprovider.aspx

You have several from triple des, des, and sha512 within the DLL.
0
 

Author Comment

by:dyarosh
Comment Utility
.Net Framework 4
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
The computeHASH method requires three parameters.
Or it takes a stream of data

Your key is effectively an integer representing the number of bytes in the string you passed.
http://msdn.microsoft.com/en-us/library/xsy6z64h%28v=vs.100%29.aspx

http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha512%28v=vs.100%29.aspx
0
 

Author Comment

by:dyarosh
Comment Utility
I don't see where it requires 3 parameters:

HashAlgorithm.ComputeHash Method (Byte[])

I am passing it a byte array by calling UTF8Encoding.UTF8.GetBytes(key).
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
GetBytes reports the bytes as int.

The link http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha512%28v=vs.100%29.aspx
ref ComputeHash there are three options.

The link dealing with the GetBytes method of the UTF-8 returns an INT and not a string array.
0
 

Author Comment

by:dyarosh
Comment Utility
I see your point about GetBytes but here is a test that I've done and the attached file shows the results.

namespace CVL
{
    public partial class test : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
        protected void EncryptBtn_Click(object sender, EventArgs e)
        {
            string key = KeyValue.Text;
            byte[] keyArray;
            keyArray = UTF8Encoding.UTF8.GetBytes(key);
            string tmpStr = keyArray.Count().ToString() + "<br />";
            
            foreach (byte k in keyArray)
            {
                tmpStr = tmpStr + k + "<br />";
            }
            StatusMsg.Text = tmpStr;
            //CryptorEngine encrypt = new CryptorEngine();
            //StatusMsg.Text = encrypt.Encrypt(EncryptValue.Text, true, key);
            //StatusMsg.Text = StatusMsg.Text + "   Key in Bytes: " + tmpStr;
        }
    }
}

Open in new window


So from what I can tell I am returning a byte array that has 32 elements which is the key size.
UTF8.GetBytes.bmp
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
I am not sure what the output is.
0
 

Author Comment

by:dyarosh
Comment Utility
32 is the number of bytes in the array.  The values after represent the bytes of the key.  I'm showing that my key is 32 bytes and this line

keyArray = UTF8Encoding.UTF8.GetBytes(key);

is returning a byte array.
0
 

Author Comment

by:dyarosh
Comment Utility
I have narrowed down the error to coming from the 3DES code but still don't know why.  This screen shot shows the key I'm using (16 characters), number of bytes in byte array and the values in the byte array.
3DESerror.bmp
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

Author Comment

by:dyarosh
Comment Utility
Found the problem.  The ComputeHash is returning a 32 byte array regardless of how few characters are in the key.  The 3DES needs a key that is 16 or 24 bytes.

Since I can't use 3DES, do you have any suggestions for finishing the encryption?  I need it to be FIPs compliant.
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
I think 3des has to use a hex key 0-9 and a-f
http://www.cryptosys.net/3des.html
0
 

Author Comment

by:dyarosh
Comment Utility
I installed the app on 3 other servers and don't have the problem on them so I've narrowed the problem down to something specific on the production server.  One of the things I discovered is the production server doesn't seem to be referencing the corrrect algorithm (see screen shot).  The error indicates that it is using the RijindaelManaged which is not FIPs compliant.  In my code I am using Rijindael as shown below.

        public string Encrypt(string PlainText, string key, string Salt="21stIn", 
            string HashAlgorithm = "SHA1", int PasswordIterations = 2,
            string InitialVector = "OFRna73m*aze01xY", int KeySize = 256)
        {
            // If string is null or whitespace, return toEncrypt
            if (String.IsNullOrEmpty(PlainText) || String.IsNullOrWhiteSpace(PlainText) || PlainText.Equals(DBNull.Value))
                return "";

            // Strip blanks from end of string
            PlainText = PlainText.Trim();

            System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
            if (String.IsNullOrEmpty(key))
                // Get the key from config file
                key = (string)settingsReader.GetValue("SecurityKey", typeof(String));
            
            byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
            byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
            byte[] PlainTextBytes = Encoding.UTF8.GetBytes(PlainText);
            PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(key, SaltValueBytes, HashAlgorithm, PasswordIterations);  
            byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
            [b]Rijndael SymmetricKey = Rijndael.Create();[/b]            SymmetricKey.Mode = CipherMode.CBC;
            byte[] CipherTextBytes = null;
            using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes))
            {
                using (MemoryStream MemStream = new MemoryStream())
                {
                    using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write))
                    {
                        CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
                        CryptoStream.FlushFinalBlock();
                        CipherTextBytes = MemStream.ToArray();
                        MemStream.Close();
                        CryptoStream.Close();
                    }
                }
            }
            SymmetricKey.Clear();
            return Convert.ToBase64String(CipherTextBytes);
        }

Open in new window


So my question is, how do I find out why the production server is using the Managed version while the other servers are not?  I've compared the IIS settings between the servers and I don't see a difference.
FIPs-Error.bmp
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
.net version for the site? Double check the steps you follow when setting this up from scratch, versus the setup on the production server. Is the DLL have to be part f authorized components on the production system?
0
 

Author Comment

by:dyarosh
Comment Utility
I haven't setup any of the servers.  I have access to the servers.  How do I check if DLL has to be part of authorized components?  How do I authorize it?  Production server is running Windows Server 2003.
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
In IIS 6 you need to check web service extensions to see if the one you need is added and approved.
0
 

Author Comment

by:dyarosh
Comment Utility
I checked Web Service Extensions and both machines have ASP.NET v4.0.30319.  I checked the aspnet_isapii.dll on both machines and they are the same size.  The only difference I see is that the machine that the DLL works on has Windows SharePoint Services v3 allowed under Web Extensions where the machine where the DLL is not working does not.  I am not using SharePoint Services that I am aware of.
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
Is the DLL that includes these functions registered on both systems?
i.e. when you setting up your software on a new system, what process do you go through?
Was the same process followed for the production system?
0
 

Author Comment

by:dyarosh
Comment Utility
That I can't answer because my group does not set up the systems.
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
You have a custom DLL that includes your encryption functions. Does that DLL get added to the production environment or is your encrypt.encrypt method in the code uses a system DLL function rather than your own.
0
 

Author Comment

by:dyarosh
Comment Utility
I use the following to register my custom DLL:

%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\regasm EncryptDecrypt.dll /codebase /tlb:EnCryptDecrypt.tlb

I run this from the folder where my DLL is.
0
 
LVL 76

Accepted Solution

by:
arnold earned 500 total points
Comment Utility
Based on your issue, the DLL does not seem to register or you have a misconfiguration where the code you think is being executed is not being run on the production server while running everywhere else.

The only thing that I can suggest is that you confirm that the code that exists on the production server is the code you are running on the development and other systems where it was setup.  One way is to add to your code an output line that is a comment in html
<!-- Version of your page code -->

This way view source on the production output will tell you whether the issue is with the server/code or it still has an incorrect version.

You can use the comment options as a means to debug as well. i.e. check if debug variable is set within your code, and output data points of interest within comments or write debug data into a database.


The code you posted does use FIPS as the test.
What is the process within your firm that gets your code onto the production system?


When you say you run the code to register the DLL, do you first unregister the old ones you had?
regasm /u EncryptDecrypt.dll?

This might be what the difference is.
Try it first on a test system where this code currently does not exist. Register an older version of your DLL.
See what happens. then try to update the setup with a newer version. Does the issue remain or does the setup start functioning?
0
 

Author Comment

by:dyarosh
Comment Utility
I did as you suggested and still have the same problem.  At this point I think the problem has to be on the Production server and not with my code.  I am able to run on a different production server ok so at this point I am going to have to install my application on that server.  I appreciate all your help.
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
You mean you added the comment identifier and it reflects the correct response but still getting the same error? Double check the calling page to make sure it is not the one with the wrong crypto selector.
0
 

Author Comment

by:dyarosh
Comment Utility
I would like to close this question without a result.  The problem still exists on the Production Server and we used a different server that didn't have the problem.
0
 
LVL 76

Expert Comment

by:arnold
Comment Utility
Did this exchange help you at all?  I.e. comments helped to lead you to move this application to a new server, pick and assign whatever point value you want and close the question, alternatively you can ask to delete this question.
0
 

Author Closing Comment

by:dyarosh
Comment Utility
My problem still exists but your help enabled me to narrow down the problem to a specific server.  Since we are putting a plan in place to migrate our applications from that server to another one where the DLL works I am not going to pursue this any longer.  Thank you for your time and help on this.
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Suggested Solutions

Suppose you are a shopaholic and you shop online frequently from a website. That means that is obvious that you would have been registered yourself on that website. Now, once in a while that website that you always buy from becomes a victim of phish…
Many companies are looking to get out of the datacenter business and to services like Microsoft Azure to provide Infrastructure as a Service (IaaS) solutions for legacy client server workloads, rather than continuing to make capital investments in h…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now