ASP.NET Protected Configuration - How to encrypt with just public key? - asp.net

When using ASP.NET protected configuration, how can I encrypt the config with just the public key?
I can export a public key file. I would like to then use this public key to encrypt the configuration files on another server for later deployment. However, I can't figure out how to get aspnet_regiis to use the exported public key.
Basically, I tried importing just the public key into a container, and then encrypt it. However, when I do that, instead of using the existing key to encrypt, it creates an entirely new key pair, overwriting the existing public key. In the script below, if you rename each of the copied files back to connections.config, and try to decrypt them, the first one (connectionstring_server.encrypted) will fail, while the second (connectionstring_build.encrypted) will succeed), proving that a new keypair was created.
Here is a batch file that demonstrates the approach I have tried (edit: this is just an example to test the aspnet_regiis capabilities. My actual usage of it would, obviously, be slightly different) :
REM delete container in case it already exists
\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pz "MyKeys"
REM create container
\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pc "MyKeys"
REM export key
\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -px "MyKeys" "publicKey.xml"
REM encrypt file
\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pef "connectionStrings" . -prov "MyProvider"
REM copy encrypted file for later comparison
copy connections.config connectionstring_server.encrypted
pause
REM decrypt file
\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pdf "connectionStrings" .
REM delete continer
\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pz "MyKeys"
REM import public key
\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pi "MyKeys" publicKey.xml
REM encrypt file with just public key - THIS DOES NOT WORK CORRECTLY, it creates a new keypair
\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pef "connectionStrings" . -prov "MyProvider"
REM copy back encrypted file
copy connections.config connectionstring_build.encrypted
pause
REM decrypt file
\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pdf "connectionStrings" .
And here is a sample web.config
<?xml version="1.0"?>
<configuration>
<configProtectedData>
<providers>
<add name="MyProvider" keyContainerName="MyKeys" type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" useMachineContainer="true" />
</providers>
</configProtectedData>
<connectionStrings configSource="connections.config" />
</configuration>
And the corresponding connections.config:
<connectionStrings>
<add name="SomConnectionName" connectionString="Data Source=somedatasource; Initial Catalog=somedatabase; Integrated Security=SSPI; Persist Security Info=False;" providerName="System.Data.SqlClient" />
</connectionStrings>
Edit:
Answer suggested below that I could export the private key as well. That would indeed allow the encryption to work, but I shouldn't need the private key to encrypt. What I want to do is leave the private key just on the server that will use the config file, and store the public key in a more accessible place. Is the inability to do this simply a limitation of aspnet_regiis?

I think your problem is in the export command, when you export you need to specify the -pri argument to tell aspnet_regiis that you want to export the private key as well as the public key.
REM export key
\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -px "MyKeys" "publicKey.xml" -pri
Without the private key your import is still creating its own keypair. This may be a Microsoft bug, aspnet_regiis should at least warn you that it was not able to import your incomplete key and that it made a new one instead...
Exporting just the public key could be useful, you could then give your operations or development group the xml file and they would be able to encrypt the config file before it is deployed to the server without having to divulge the private key. Also, this way you wouldn't need to run the encryption process on each server in your farm.

I don't know if it's a bug or not, but I've definitely run into this problem as well. The public AND private keys need to imported into the Windows key store for any of the .net functions to work. However, the private key can be protected by not specifying the -exp switch when importing the key.

Related

Decrypt encrypted value using DPAPI

I have encrypted value and I tried to decrypt it using asp_regiis.exe.
<configuration>
<connectionStrings
configProtectionProvider="DataProtectionConfigurationProvider">
<EncryptedData>
<CipherData>
<CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl....fK39sbTH</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
</configuration>
When I run this command:
aspnet_regiis.exe -pdf "connectionStrings" "C:\Users\Test"
I have this error:
Decrypting configuration section...
Failed to decrypt using provider 'DataProtectionConfigurationProvider'. Error message from the provider:
Data at the root level is invalid. Line 1, position 1.
Failed!
What seems wrong with this? I need to find the decrypted value.
Please advise.

How to make relative path to database in app.config using SQLite/entity framework

I want to be able to use a relative path to use a SQLite DB on more than 1 pc.
the connectionstring in the app.config looks like this now:
<add name="DBPersonEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SQLite;provider connection string='data source="C:\Users\Dreeze\Documents\Test DB2\DBPerson.s3db"'" providerName="System.Data.EntityClient" />
The DB file is in the same folder as the app... i would like to make the path relative so it refers to the apps folder. Can anyone help me change this connectionstring?
Use this connectionString
<add name="DWContext" connectionString="Data Source=|DataDirectory|DBPerson.s3db" providerName="System.Data.SQLite" />
Then set DataDirectory path on your code before initializing Context objext.
string executable = System.Reflection.Assembly.GetExecutingAssembly().Location;
string path = (System.IO.Path.GetDirectoryName(executable));
AppDomain.CurrentDomain.SetData("DataDirectory", path);
You should be able to use the data directory substitution string:
provider connection string='data source="|DataDirectory|DBPerson.s3db"'

How do I select/enforce AES encryption with aspnet_regiis to encrypt web.config values?

I need to encrypt part of our web.config for our ASP.Net 4.0 project, but we are required to use AES and the default appears to be Triple DES. How can I tell it to use AES encryption instead?
In the command prompt I do the following commands:
aspnet_regiis -pc "NetFrameworkConfigurationKey" -exp
aspnet_regiis -pe "connectionStrings" -app "/<myapp>"
I figure I set the encryption method to AES by selecting the appropriate CSP (-csp) but I haven't been able to find or figure out the name of the right one.
And one of the lines in the encrypted web.config is:
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
The provider is selected using the -prov parameter to aspnet_regiis. The providers are registered in the web/machine.config using the configProtectedData section. In order to register AES you would use something like this:
<configProtectedData>
<providers>
<add name="AesProvider"
type="Microsoft.ApplicationHost.AesProtectedConfigurationProvider"
description="Uses an AES session key to encrypt and decrypt"
keyContainerName="iisConfigurationKey" cspProviderName=""
useOAEP="false" useMachineContainer="true"
sessionKey="aSessionKeyGoesHere" />
</providers>
</configProtectedData>
On my machine RSA and DPAPI are the preconfigured algorithms in machine.config.
Provided that the AES provider is registered you should be able to encrypt a config section using:
aspnet_regiis -pe "connectionStrings" -app "/<myapp>" -prov "AesProvider"

Encrypt config file for HttpHandler

I have "Class library projet" which works as HttpHandler later at a webserver. So I have locally 2 files app.config (for local dev, because it is a dll) and web.config (for remote web server).
So now I wanted to encrypt config file. Everything was encrypted and imported at remote web server. But the handler doesn't work. I receive an error: "Failed to decrypt using provider 'My_Provider'. Error message from the provider: The RSA key container could not be opened."
At my dev PC everything works fine. What is wrong?
So this my export steps
cd %windir%\Microsoft.NET\Framework\v4.0.30319
aspnet_regiis -pc "My_Keys" -exp
aspnet_regiis -pa "My_Keys" "IIS APPPOOL\CustomAppPool"
aspnet_regiis -pef "connectionStrings" "HandlerProjectPath" -prov
"My_Provider"
aspnet_regiis -px "MyKeys" "HandlerProjectPath\MyKeys.xml" -pri
pause
these are import step
%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -pi
"My_Keys" "MyKeys.xml"
pause
p.s. My handler works at IIS 7 inside my custom AppPool with name "CustomAppPool". I specially created an app pool name at my PC.
this is my configData
Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=MSIL"
keyContainerName="My_Keys"
useMachineContainer="true" />
</providers> </configProtectedData>
Thanks in advance!
I think you need to grant access to the container to the IIS Identity assigned to your AppPool, after you import the key pair.

Trying to use encrypted system.web/identity on web service errors with "Failed to decrypt using provider"

I'm receiving the following error when trying to access a web service that is using (for temporary reasons) an encrypted system.web/identity entry:
Failed to decrypt using provider 'DataProtectionConfigurationProvider'. Error message from the provider: The RSA key container could not be opened.
I've followed the steps found in comments at http://blogs.msdn.com/mosharaf/archive/2005/11/17/protectedConfiguration.aspx, and these are the steps I've done:
Added "xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"" to the configuration attribute in the web service's web.config
Create a container using aspnet_regiis -pc "DataProtectionConfigurationProviderKeys" -exp
Added the following to the web.config:
<configProtectedData>
<providers>
<clear />
<add name="DataProtectionConfigurationProvider"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,processorArchitecture=MSIL"
keyContainerName="DataProtectionConfigurationProviderKeys"
useMachineContainer="true" />
</providers>
</configProtectedData>
Granted access to the key container to the account IIS is running under: aspnet_regiis -pa "DataProtectionConfigurationProviderKeys" "eca\iusr_xxxxx". I also granted access to the impersonated account (e.g. the one in the identity attribute) using the same command.
I then encrypted the system.web/identity entry: aspnet_regiis -pef "system.web/identity" "C:\ddrive\EcaDevelopment\EcaApplicationsNet2\Projects\TASV2\Mainline\src\TASV2.WordToPdf.WebSvc" -prov "DataProtectionConfigurationProvider"
But, when I try to run my test harness against the web service, I get:
Failed to decrypt using provider 'DataProtectionConfigurationProvider'. Error message from the provider: The RSA key container could not be opened.
What have I missed out? Can I actually encrypt just the identity tag? I can encrypt and use the connectionStrings no problem...

Resources