Moved ASP.NET site to new server, CryptographicException: Key not valid for use...

Posted on 2009-04-18
Medium Priority
Last Modified: 2012-05-06
I moved our web applications from one server to another and now I get the following message when I visit the site:

CryptographicException: Key not valid for use in specified state.

Our developer is no longer with the company and I am not that great with ASP.NET, so I don't know where to look.  I believe the problem is related to a key pair issue - do I need to export a key pair of some sort from the old server and import it to the new server?  We are using identical software, Server 2008 x64 + IIS7.
Stack Trace
[CryptographicException: Key not valid for use in specified state.
   System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope) +669
   Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.ProtectedKey.Unprotect() +22
   Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.SymmetricCryptographer.Encrypt(Byte[] plaintext) +54
   Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.SymmetricAlgorithmProvider.Encrypt(Byte[] plaintext) +610
   Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Cryptographer.EncryptSymmetric(ISymmetricCryptoProvider provider, String plaintext) +75
   MyCompany_Services.InOutBoard.rgInOutBoard_ItemDataBound(Object sender, GridItemEventArgs e) in C:\pathtocode\InOutBoard.aspx.cs:158
   Telerik.Web.UI.GridItem.SetupItem(Boolean dataBind, Object dataItem, GridColumn[] columns, ControlCollection rows) +925
   Telerik.Web.UI.GridItemBuilder.InitializeItem(Int32 dataSourceIndex, String& nextItemHierarchicalIndex, Boolean& itemIsInEditMode) +192
   Telerik.Web.UI.GridItemBuilder.CreateItems(GridGroupingContext group) +438
   Telerik.Web.UI.GridItemBuilder.CreateGroupSubItems(GridGroupingContext group, GridEnumerableBase enumerable) +727
   Telerik.Web.UI.GridItemBuilder.HandleGrouping(GridGroupingContext group, GridEnumerableBase enumerable, Boolean& isGroup, Boolean& isGroupFooter) +84
   Telerik.Web.UI.GridItemBuilder.CreateItems(GridGroupingContext group) +254
   Telerik.Web.UI.GridTableView.CreateControlHierarchy(Boolean useDataSource) +830
   Telerik.Web.UI.GridTableView.CreateChildControls(IEnumerable dataSource, Boolean useDataSource) +562
   System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data) +72
   System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data) +147
   System.Web.UI.WebControls.DataBoundControl.PerformSelect() +261
   Telerik.Web.UI.GridTableView.PerformSelect() +9
   Telerik.Web.UI.GridTableView.DataBind() +363
   Telerik.Web.UI.RadGrid.DataBind() +73
   System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound() +82
   System.Web.UI.WebControls.CompositeDataBoundControl.CreateChildControls() +95
   System.Web.UI.Control.EnsureChildControls() +146
   Telerik.Web.UI.GridBaseDataList.get_Controls() +20
   Telerik.Web.UI.RadAjaxControl.PopulatePlainPanels(Control parent, List`1 list, Control root) +109
   Telerik.Web.UI.RadAjaxControl.OnPagePreRender(Object sender, EventArgs e) +1531
   System.EventHandler.Invoke(Object sender, EventArgs e) +0
   System.Web.UI.Control.OnPreRender(EventArgs e) +11022094
   System.Web.UI.Control.PreRenderRecursiveInternal() +108
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3394
Here's line 158 of InOutBoard.aspx.cs:
encryptedUserID = Cryptographer.EncryptSymmetric("AesCryptoServiceProvider", unencryptedUserID);

Open in new window

Question by:solidisquad
LVL 14

Accepted Solution

GiftsonDJohn earned 2000 total points
ID: 24178177
Try this.


I've been struggling with the whole problem of deploying Cryptography Application Block encryption keys. In my scenario, I'm publishing a Windows application to a server where users will install it using ClickOnce deployment. Also, since the data is encrypted before it is stored in a database and decrypted when recovered, all users must be using exactly the same encryption key. Otherwise, errors are generated when pulling data out of the database that was not encrypted on the user's current workstation.

I think I have a solution that works for all the users and all workstations in a large enterprise, so it may work for developers deploying to a web server as well.

1. Create a key in LocalMachine scope. My App.config section looks like this when I'm finished:

<add algorithmType="System.Security.Cryptography.RijndaelManaged, mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089"
protectedKeyProtectionScope="LocalMachine" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.SymmetricAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=, Culture=neutral, PublicKeyToken=null"
name="RijndaelManaged" />

2. Export the key to a text file using the Enterprise Library Configuration Tool. (Right click on the provider node, and choose Export key from the context menu)

3. When publishing to the deployment server, do not include the key file. In this case, XFileSecurity.key is not published to the deployment server, so that it is not copied to the user's workstation when they run the ClickOnce install.

4. Do publish the text file that the Enterprise Library Configuration Tool created when you exported the key. In my scenario, every user who installs the app gets a copy of the exported text file, secured with a password specified when it was exported.

5. When the user runs the application for the first time, it is basically a matter of recovering the key from the exported text file, creating a key file in the location you wish, and then updating the App.config (or Web.config) file.
It seems like a lot of work, and it is. The function I use to do all this when the application starts up is included below. This particular development is VB, but it also works fine in C#. In my scenario, the app should not run without encryption, and will fail with nasty errors without it, so I run this function before I load my main form and exit with a message if it returns false.

The key method here is: KeyManager.RestoreKey. This allows one to migrate the key from one machine to another programmatically.

Imports System.IO
Imports System.Configuration
Imports System.Security.Cryptography
Imports Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Configuration
Imports Microsoft.Practices.EnterpriseLibrary.Security.Cryptography

-- Private class members
Private Const SECURITYKEYFILE As String = "XFileSecurity.key"
Private Const KEYIMPORTFILE As String = "ColorIndex.txt"
Private Const KEYIMPORTFILE_PW As String = "color2007"

Private Function ApplicationSecured() As Boolean
Dim secure As Boolean = False
Dim sCurrentPath As String = Application.ExecutablePath
Do Until sCurrentPath.EndsWith("\")
sCurrentPath = sCurrentPath.Remove(sCurrentPath.Length - 1)
Dim importFile As String = sCurrentPath & KEYIMPORTFILE
Dim keyFile As String = sCurrentPath & SECURITYKEYFILE
If Not My.Computer.FileSystem.FileExists(keyFile) Then
Dim key As ProtectedKey = KeyManager.RestoreKey(File.Open(importFile, FileMode.Open, FileAccess.Read), KEYIMPORTFILE_PW, DataProtectionScope.LocalMachine)
KeyManager.Write(File.Open(keyFile, FileMode.Create), key)
End If
Dim cfg As Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
If cfg.HasFile Then
Dim cryptoSection As ConfigurationSection = cfg.Sections("securityCryptographyConfiguration")
If Not cryptoSection Is Nothing Then
Dim cryptoSettings As CryptographySettings = cryptoSection
Dim data As SymmetricProviderData = cryptoSettings.SymmetricCryptoProviders.Get(0)
Dim sSetPath As String = data.ElementInformation.Properties("protectedKeyFilename").Value.ToString()
If sSetPath <> keyFile Then
data.ElementInformation.Properties("protectedKeyFilename").Value = keyFile
End If
secure = True
End If
End If
Return secure
End Function


Author Closing Comment

ID: 31571897
GiftsonDJohn, thanks for the extensive reply!  Unfortunately, I am not able to test this in my environment because I removed the encryption from my application - it was being used to encrypt a publically-known number that was even displayed on the page.  Following your logic and code, I believe this method would have solved my problem and I think it makes a good addition to the EE knowledgebase.

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Just a quick little trick I learned recently.  Now that I'm using jQuery with abandon in my asp.net applications, I have grown tired of the following syntax:      (CODE) I suppose it just offends my sense of decency to put inline VBScript on a…
Problem Hi all,    While many today have fast Internet connection, there are many still who do not, or are connecting through devices with a slower connect, so light web pages and fast load times are still popular.    If your ASP.NET page …
This video shows how to quickly and easily deploy an email signature for all users in Office 365 and prevent it from being added to replies and forwards. (the resulting signature is applied on the server level in Exchange Online) The email signat…
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Suggested Courses

850 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