Object already exists in RSACryptoServiceProvider
Asked Answered
O

4

10

I copied the source code from one application to another, both running on the same machine. I am also using the same string for containerName below in both applications.

What is preventing my new application from reading the key that was saved in the other application? All other things are equal, logged in user account etc.

     CspParameters cspParams = new CspParameters();
     cspParams.KeyContainerName = containerName;
     cspParams.Flags = CspProviderFlags.UseMachineKeyStore;

     // Get error "object already exists" below.
     RSACryptoServiceProvider  rsaKey = new RSACryptoServiceProvider(cspParams);
Orison answered 21/1, 2011 at 20:45 Comment(0)
S
7

Did you try to grant permissions to Everyone, for example, for files in "Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\Machine Keys", as it described there:

http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/f7b9f928-a794-47f2-a5bd-9f64ca375040

Schach answered 21/1, 2011 at 22:7 Comment(2)
May not apply since I'm running the same code in two different projects, but under the same user account.Orison
Is that the Windows XP location? "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys" is the Vista (and up) location I think.Horologium
L
6

Another solution is to set access to everyone by code :

CspParameters cspParams;
cspParams = new CspParameters(PROVIDER_RSA_FULL);
cspParams.KeyContainerName = CONTAINER_NAME;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";

CryptoKeyAccessRule rule = new CryptoKeyAccessRule("everyone", CryptoKeyRights.FullControl, AccessControlType.Allow);

cspParams.CryptoKeySecurity = new CryptoKeySecurity();
cspParams.CryptoKeySecurity.SetAccessRule(rule);
Lyophilic answered 2/9, 2011 at 12:38 Comment(3)
Just ran into this problem. Using the commandline aspnet_regiis -pa "SampleKeys" "NT AUTHORITY\NETWORK SERVICE" didn't work, but your solution did the job. Thanks a lot!Risarise
Instead of "everyone" I had to pass new SecurityIdentifier(WellKnownSidType.WorldSid, null). I assume it didn't work because "everyone" user is localized to my language on my machine.Unwieldy
Just as FYI to anyone finding this, to use CryptoKeyAccessRule, you have to do using System.Security.AccessControl, and for new SecurityIdentifier and WellKnownSidType, it's using System.Security.Principal. VS 2015 is good about suggesting fixes for namespaces, but anyone using a version before that, who might not know the namespaces so well, might have a hard time finding out what to import. Tell us your assemblies when you import things that are outside the default!!!Fallfish
K
2

I ran into this problem because my WCF service did not have permission to access the keystore. I got past the problem by following the instructions to grant the user ASPNET read access that I found here: http://msdn.microsoft.com/en-us/library/2w117ede.aspx#Y898

Krystinakrystle answered 1/3, 2011 at 14:21 Comment(0)
C
1

I recently ran into this issue with multiple deployed IIS sites on a single server (Windows 2008 R2). Our environment has each site running on different application pools, but in some cases, those pools can be assigned the same identity.

Our application creates a key if one does not exist, and places it in a container with a name based on the current identity. The first deployed site always worked, but if we deployed another site into another app pool with the same identity, the second would fail.

Turns out that when the key is stored, Windows gives full access to the user "IIS APPPOOL\AppPoolName", and not the identity that we have assigned to the pool.

So, our solution was to give the container explicit permissions to the current identity (this is similar to @Webmixer's answer, the only difference is in the CryptoKeyAccessRule):

CspParameters cspParams;
cspParams = new CspParameters(PROVIDER_RSA_FULL);
cspParams.KeyContainerName = CONTAINER_NAME;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";

CryptoKeyAccessRule rule = new CryptoKeyAccessRule(System.Security.Principal.WindowsIdentity.GetCurrent(), CryptoKeyRights.FullControl, AccessControlType.Allow);

cspParams.CryptoKeySecurity = new CryptoKeySecurity();
cspParams.CryptoKeySecurity.SetAccessRule(rule);
Cryptogam answered 9/9, 2014 at 16:58 Comment(3)
I got Cannot convert from 'System.Security.Principal.WindowsIdentity' to 'System.Security.Principal.IdentityReference' when I tried inserting this, as written. Maybe needs new SecurityIdentifier(System.Security.Principal.WindowsIdentity.GetCurrent().ToString())?Fallfish
Not sure. I guess something might have changed in the last couple of years. We retired the code above some time ago.Cryptogam
Tried it, it compiles, but got error System.ArgumentException: Value was invalid, so it didn't like it. I don't think it's the syntax, though - I got the same thing using Tom's suggestion on Webmixer's answer (new SecurityIdentifier(WellKnownSidType.WorldSid, null)). If I used Webmixer's answer directly, to use "everyone", I got CryptographicException: Object already exists.Fallfish

© 2022 - 2024 — McMap. All rights reserved.