【问题标题】:Object already exists in RSACryptoServiceProvider对象已存在于 RSACryptoServiceProvider 中
【发布时间】:2011-06-13 09:55:11
【问题描述】:

我将源代码从一个应用程序复制到另一个应用程序,两者都在同一台机器上运行。我还在两个应用程序中为下面的 containerName 使用相同的字符串。

是什么阻止了我的新应用程序读取保存在其他应用程序中的密钥?其他一切都是平等的,登录用户帐户等。

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

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

【问题讨论】:

    标签: c# encryption cryptography rsacryptoserviceprovider


    【解决方案1】:

    您是否尝试向所有人授予权限,例如,对于“文档和设置\所有用户\应用程序数据\Microsoft\Crypto\RSA\Machine Keys”中的文件,如其所述:

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

    【讨论】:

    • 可能不适用,因为我在两个不同的项目中运行相同的代码,但在同一个用户帐户下。
    • 那是 Windows XP 的位置吗? “C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys”是我认为的 Vista(及更高版本)位置。
    【解决方案2】:

    另一种解决方案是通过代码设置每个人的访问权限:

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

    【讨论】:

    • 刚刚遇到这个问题。使用命令行aspnet_regiis -pa "SampleKeys" "NT AUTHORITY\NETWORK SERVICE" 不起作用,但您的解决方案完成了工作。非常感谢!
    • 我必须通过new SecurityIdentifier(WellKnownSidType.WorldSid, null) 而不是“每个人”。我认为它不起作用,因为“每个人”用户在我的机器上都本地化为我的语言。
    • 对于任何发现此问题的人仅供参考,要使用CryptoKeyAccessRule,您必须使用using System.Security.AccessControl,对于new SecurityIdentifierWellKnownSidType,它是using System.Security.Principal。 VS 2015 在建议修复命名空间方面做得很好,但是任何使用之前版本的人,可能不太了解命名空间,可能很难找出要导入的内容。当您导入默认值之外的内容时,请告诉我们您的程序集!!!
    【解决方案3】:

    我遇到了这个问题,因为我的 WCF 服务没有访问密钥库的权限。我按照我在此处找到的授予用户 ASPNET 读取访问权限的说明解决了这个问题:http://msdn.microsoft.com/en-us/library/2w117ede.aspx#Y898

    【讨论】:

      【解决方案4】:

      我最近在单个服务器 (Windows 2008 R2) 上部署了多个 IIS 站点时遇到了这个问题。我们的环境中的每个站点都在不同的应用程序池上运行,但在某些情况下,可以为这些池分配相同的标识。

      如果密钥不存在,我们的应用程序会创建一个密钥,并将其放置在一个容器中,该容器的名称基于当前身份。第一个部署的站点始终可以运行,但如果我们将另一个站点部署到具有相同标识的另一个应用程序池中,第二个站点就会失败。

      事实证明,当存储密钥时,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);
      

      【讨论】:

      • 当我尝试插入这个时,我得到了Cannot convert from 'System.Security.Principal.WindowsIdentity' to 'System.Security.Principal.IdentityReference',如所写。也许需要new SecurityIdentifier(System.Security.Principal.WindowsIdentity.GetCurrent().ToString())
      • 不确定。我想在过去的几年里可能发生了一些变化。我们前段时间停用了上面的代码。
      • 试过了,可以编译,但是报错System.ArgumentException: Value was invalid,所以不喜欢。不过,我认为这不是语法 - 我使用 Tom 对 Webmixer 的回答 (new SecurityIdentifier(WellKnownSidType.WorldSid, null)) 的建议得到了同样的结果。如果我直接使用 Webmixer 的答案,使用"everyone",我得到了CryptographicException: Object already exists
      猜你喜欢
      • 1970-01-01
      • 2012-07-10
      • 1970-01-01
      • 2017-02-24
      • 2018-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多