2011-01-21 4 views
8

Я скопировал исходный код из одного приложения в другое, оба работают на одном компьютере. Я также использую одну и ту же строку для containerName ниже в обоих приложениях.Объект уже существует в RSACryptoServiceProvider

Что мешает моему новому приложению читать ключ, сохраненный в другом приложении? Все остальные вещи равны, зарегистрированные в учетной записи пользователя и т.д.

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

    // Get error "object already exists" below. 
    RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams); 

ответ

7

Пробовали ли вы предоставить права для всех, например, для файлов в «Документах и ​​Settings \ All Users \ Application Data \ Microsoft \ Crypto \ RSA \ Machine Keys», как это описано здесь:

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

+0

Может не применять, так как я запуск того же кода в двух разных проектах, но под одной и той же учетной записью пользователя. – LamonteCristo

+0

Является ли это местом Windows XP? «C: \ ProgramData \ Microsoft \ Crypto \ RSA \ MachineKeys» - это место Vista (и выше), которое я думаю. – granadaCoder

2

Я столкнулся с этой проблемой, потому что моя служба WCF не имеет разрешения на доступ к хранилищу ключей. У меня в прошлом проблемы, следуя инструкциям, чтобы предоставить пользователю ASPNET доступ на чтение, что я нашел здесь: http://msdn.microsoft.com/en-us/library/2w117ede.aspx#Y898

5

Другим решением является создание доступа к каждому по коду:

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); 
+0

Просто столкнулся с этой проблемой. Использование командной строки 'aspnet_regiis -pa" SampleKeys "" NT AUTHORITY \ NETWORK SERVICE "не работало, но ваше решение выполнило эту работу. Большое спасибо! –

+1

Вместо «всех» мне пришлось передать «новый SecurityIdentifier (WellKnownSidType.WorldSid, null)». Я предполагаю, что это не сработало, потому что пользователь «каждый» локализован на моем языке на моей машине. – Tom

+2

Точно так же, как FYI для тех, кто находит это, использовать 'CryptoKeyAccessRule', вам нужно выполнить' using System.Security.AccessControl', а для 'new SecurityIdentifier' и' WellKnownSidType', это 'using System.Security.Principal'. VS 2015 хорош в том, чтобы предлагать исправления для пространств имен, но любой, кто использует версию до этого, кто может не знать пространства имен так хорошо, может с трудом узнать, что импортировать. Сообщите нам свои сборки, когда вы импортируете вещи, которые находятся за пределами установленного по умолчанию !!! – vapcguy

0

Я недавно столкнулся с этим вопросом с несколькими развернутыми сайтами IIS на одном сервере (Windows 2008 R2). В нашей среде каждый сайт работает в разных пулах приложений, но в некоторых случаях этим пулам может быть присвоен одинаковый идентификатор.

Наше приложение создает ключ, если он не существует, и помещает его в контейнер с именем, основанным на текущем идентификаторе. Первый развернутый сайт всегда работал, но если бы мы развернули другой сайт в другой пул приложений с одинаковым идентификатором, второй не удался.

Оказывается, что при сохранении ключа Windows дает полный доступ к пользователю «IIS APPPOOL \ AppPoolName», а не к идентификатору, который мы присвоили пулу.

Таким образом, наше решение было дать контейнеру явные разрешения для текущей идентичности (это похоже на @ WebMixer Ответим, единственное отличие заключается в 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); 
+0

Я получил 'Не могу конвертировать из 'System.Security.Principal.WindowsIdentity' в 'System.Security.Principal.IdentityReference'', когда я попытался вставить это, как написано. Возможно, нужен новый SecurityIdentifier (System.Security.Principal.WindowsIdentity.GetCurrent(). ToString()) '? – vapcguy

+0

Не уверен. Кажется, что-то могло измениться за последние пару лет. Некоторое время назад мы удалили код выше. –

+0

Пробовал, компилирует, но получил ошибку 'System.ArgumentException: значение было недопустимым', поэтому ему это не понравилось. Я не думаю, что это синтаксис, хотя я получил то же самое, используя предложение Тома на ответе Webmixer ('new SecurityIdentifier (WellKnownSidType.WorldSid, null)'). Если я использовал ответ Webmixer напрямую, чтобы использовать '' every "', я получил 'CryptographicException: Object уже существует'. – vapcguy