RSACryptoServiceProvider CryptographicException System Cannot Find the File Specified under ASP.NET
Asked Answered
G

5

18

I have an application which is making use of the RSACryptoServiceProvider to decrypt some data using a known private key (stored in a variable).

When the IIS Application Pool is configured to use Network Service, everything runs fine.

However, when we configure the IIS Application Pool to run the code under a different Identity, we get the following:

System.Security.Cryptography.CryptographicException: The system cannot find the file specified.

   at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
   at System.Security.Cryptography.RSACryptoServiceProvider.ImportParameters(RSAParameters parameters)
   at System.Security.Cryptography.RSA.FromXmlString(String xmlString)

The code is something like this:

byte[] input; 
byte[] output; 
string private_key_xml; 

var provider = new System.Cryptography.RSACryptoServiceProvider(this.m_key.Key_Size);
provider.FromXmlString(private_key_xml); // Fails Here when Application Pool Identity != Network Service

ouput = provider.Decrypt(input, false); // False = Use PKCS#1 v1.5 Padding

There are resources which attempt to answer it by stating that you should give the user read access to the machine key store - however there is no definitive answer to solve this issue.

Environment: IIS 6.0, Windows Server 2003 R2, .NET 3.5 SP1

Glissando answered 9/7, 2009 at 9:48 Comment(0)
V
14

Indeed you need to work a code like this

CspParameters _cpsParameter;
RSACryptoServiceProvider RSAProvider;

_cpsParameter = new CspParameters();
_cpsParameter.Flags = CspProviderFlags.UseMachineKeyStore;

RSAProvider = new RSACryptoServiceProvider(1024, _cpsParameter); 

The following users need access to the folder: C:\Documents and Settings\All Users\Application data\Microsoft\Crypto\RSA\MachineKeys

  1. IIS user account (anonymmous)
  2. The user account you use to impersonate your application in the web.config settings.

So now it is working fine for me.

Volitant answered 24/8, 2009 at 19:41 Comment(2)
Thanks for the answer - I havn't had a chance to actually test this yet. Do you know if new accounts by default (clean windows install) have access to this already? We're trying to avoid having to modify too much - and this seems like a particularly bizzare issue for something that should run under low/medium trust.Glissando
Will, I'm not sure! This particular problem happened to my machine only. I've tried into another developer machine and things work as supposed to. In the server, our systems runs under a different user context, so I had no problem too.Volitant
D
40

I fixed this by setting "Load User Profile" to True (was False) in the Application Pool's Advanced Settings / Process Model section.

The application had been working perfectly on Server 2003 R2 / IIS 6 and the problem appeared as I was configuring it on our new 2008 R2 server.

Got the idea to try it at:

http://social.msdn.microsoft.com/forums/en-US/clr/thread/7ea48fd0-8d6b-43ed-b272-1a0249ae490f/

YMMV

Diver answered 29/4, 2010 at 23:14 Comment(5)
This is because the keys are stored in DPAPI security.stackexchange.com/q/1771/396Punctilio
Thanks, worked for me on the server, but not locally, I wander why. I read this function tries to access the key store and fails because of permissions, even though the code doesn't use need the key store.Enwind
Ok, I found out why it didn't work in my machine.It's because I used an application pool which is used was already used for other applications too. I am not quite sure why it caused a problem, but when I set a dedicated application pool, it worked!Enwind
Thanks! Was having this problem in production only, and this fixed it.Dripping
Does anyone know why it works? It worked on 2008 but it stopped at 2012. @Tim says it should stop working on 2008 already.Fisherman
V
14

Indeed you need to work a code like this

CspParameters _cpsParameter;
RSACryptoServiceProvider RSAProvider;

_cpsParameter = new CspParameters();
_cpsParameter.Flags = CspProviderFlags.UseMachineKeyStore;

RSAProvider = new RSACryptoServiceProvider(1024, _cpsParameter); 

The following users need access to the folder: C:\Documents and Settings\All Users\Application data\Microsoft\Crypto\RSA\MachineKeys

  1. IIS user account (anonymmous)
  2. The user account you use to impersonate your application in the web.config settings.

So now it is working fine for me.

Volitant answered 24/8, 2009 at 19:41 Comment(2)
Thanks for the answer - I havn't had a chance to actually test this yet. Do you know if new accounts by default (clean windows install) have access to this already? We're trying to avoid having to modify too much - and this seems like a particularly bizzare issue for something that should run under low/medium trust.Glissando
Will, I'm not sure! This particular problem happened to my machine only. I've tried into another developer machine and things work as supposed to. In the server, our systems runs under a different user context, so I had no problem too.Volitant
L
8

Try setting

System.Security.Cryptography.RSACryptoServiceProvider.UseMachineKeyStore = true;

EDIT: Then try using

var provider = new System.Security.Cryptography.RSACryptoServiceProvider();

instead of the constructor with the integer-parameter. That constructor tries to generate a key with the specified key-length, and you might not be able to do that with your permissions.

Leitao answered 9/7, 2009 at 10:3 Comment(3)
This worked for me on IIS7 with the default apppool identity.Dentistry
It seems that you can also call "new RSACryptoServiceProvider(new CspParameters { Flags = CspProviderFlags.UseMachineKeyStore })" if you don't want to enable the flag globally.Jambalaya
This also fixed my error Access is Denied while instantiating a RSACryptoServiceProvider.Stalker
E
2

I just wanted to comment that Rasmus Faber's solution worked for me (with one minor edit):

System.Cryptography.RSACryptoServiceProvider.UseMachineKeyStore = true;
RSACryptoServiceProvider provider = new System.Cryptography.RSACryptoServiceProvider();

I was trying to get MailBee.net to sign an outgoing message using DKIM and got the same message that the OP received. Of course everything was fine on my dev machine, but when uploading to my clients webhost, I ran into this problem. Like I said, the solution above worked for me while others that I found online (including the msdn forum link above) didn't.

(I'd upvote and comment, but I don't have enough rep to do so. :P )

Thanks Rasmus Faber!

Eigenfunction answered 25/8, 2010 at 3:27 Comment(0)
B
0

Only when i add

Flags = CspProviderFlags.UseMachineKeyStore

Problem solved for me.

{
    string keyName = "Secret***";
    CspParameters parameters = new CspParameters()
    {
        KeyContainerName = keyName,
        Flags = CspProviderFlags.UseMachineKeyStore
    };
}
Bula answered 19/1, 2021 at 15:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.