【问题标题】:.Net CryptographicException "Object already exists" on AzureAzure 上的 .Net CryptographicException“对象已存在”
【发布时间】:2017-01-12 14:15:42
【问题描述】:

我们在 Azure 上的两个 Web 应用程序上部署了一个网站:一个生产版本和一个预生产版本。

网站在特定时间创建一个容器来托管 RSA 密钥,使用以下代码:

// -----------------------------
// Part 1 : Initialize csp params
// -----------------------------
const int PROVIDER_RSA_FULL = 1;
const string CONTAINER_NAME = "OurKeyContainer";
CspParameters cspParams;
cspParams = new CspParameters(PROVIDER_RSA_FULL);
cspParams.KeyContainerName = CONTAINER_NAME;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";

// --------------------------------------------------
// Part 2 : A try to set folder access rights to "everyone"
// --------------------------------------------------
// http://whowish-programming.blogspot.fr/2010/10/systemsecuritycryptographycryptographic.html
// http://stackoverflow.com/questions/5013881/c-sharp-how-do-i-get-the-everybody-user
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
var rule = new CryptoKeyAccessRule(sid, CryptoKeyRights.FullControl, AccessControlType.Allow);
cspParams.CryptoKeySecurity = new CryptoKeySecurity();
cspParams.CryptoKeySecurity.SetAccessRule(rule);

return new RSACryptoServiceProvider(cspParams);

问题是此代码仅适用于其中一个网站,即实际首次启动的网站。第二个抛出 CryptographicException “对象已存在”。

谷歌搜索后,该问题似乎是由执行网站的用户无权访问密钥容器引起的,但不幸的是,推荐的修复(在我们上面代码的第 2 部分中实现)不起作用..

有什么想法或建议吗?

谢谢

丽安娜

【问题讨论】:

  • 您是否尝试过 Granting Read Access to an RSA Encryption Key 通过 KUDU 获取您失败的 Web 应用程序的身份?您可以找到 Aspnet_regiis.exe 文件的位置here
  • 嗨,布鲁斯,感谢您的回复。我阅读了您发送的网址,但 Azure 控制台和 Kudu 都无法识别 aspnet_regiis 命令。有什么建议吗?
  • 对于 .NET Framework 版本 4(32 位系统),您可以将您的目录更改为 D:\Windows\Microsoft.NET\Framework\v4.0.30319,对于 .NET Framework 版本 4(64 位系统),您可以更改您的目录通过 KUDU 到 D:\Windows\Microsoft.NET\Framework64\v4.0.30319
  • 我设法运行the recommended command¶它告诉我它已经成功,然后我重新启动了我的网站.. 但不幸的是,我仍然有同样的例外.. :-( .

标签: .net azure cryptography azure-web-app-service cryptographicexception


【解决方案1】:

我认为问题在于您基本上是在尝试两次创建具有相同名称的机器范围的容器。我假设pre-prodprod 环境在同一台机器上,可能作为应用服务中的部署槽?我至少可以用这个设置复制你的问题。我猜还有一些其他设置可能会产生相同的情况,但这是最有可能的。

您可以在此设置中更改三项会产生不同结果的内容:

  • 授予访问权限的身份
  • 集装箱商店
  • 容器名称

对于身份,我们可以使用Everyone(您已经尝试过)或Current,我们可以从 WindowsIdentity 获得

    private IdentityReference GetWindowsIdentity()
    {
        return System.Security.Principal.WindowsIdentity.GetCurrent().User;
    }

    private IdentityReference GetEveryoneIdentity()
    {
        return new SecurityIdentifier(WellKnownSidType.WorldSid, null);
    }

容器存储可以是machine wide 或仅用于当前用户

// machine wide store
var cspParams = new CspParameters(PROVIDER_RSA_FULL)
{
    ...
    Flags = CspProviderFlags.UseMachineKeyStore;
    ...
};

// default store
var cspParams = new CspParameters(PROVIDER_RSA_FULL)
{
    ...
    Flags = CspProviderFlags.UseDefaultKeyContainer;
    ...
};

对于商店名称,我们可以选择一些东西,在您的情况下,您可以选择相同的名称,但我们也可以为身份设置一些独特的东西

    KeyContainerName = "OurKeyContainer",

    KeyContainerName = $"OurKeyContainer-{identity}",

不同的组合会产生不同的结果:

每个人的身份,机器范围的商店,相同的容器名称System.Security.Cryptography.CryptographicException: Object already exists. 的插槽之一上失败

每个人的身份,机器范围的商店,每个身份的容器好的

每个人的身份、用户存储、相同的容器名称在两个插槽上都失败,System.Security.Cryptography.CryptographicException: The system cannot find the file specified.

每个人的身份、用户存储、每个身份的容器好的

当前身份,机器范围的存储,相同的容器名称System.Security.Cryptography.CryptographicException: Object already exists. 的插槽之一上失败

当前身份、机器范围的存储、每个身份的容器好的

当前身份、用户存储、相同的容器名称在两个插槽上都失败,System.Security.Cryptography.CryptographicException: The system cannot find the file specified.

当前身份、用户存储、每个身份的容器在两个插槽上都失败,System.Security.Cryptography.CryptographicException: The system cannot find the file specified.

因此,总而言之,更改容器的名称以包含环境独有的内容将解决问题。它不一定是身份(但您将在机器上运行的每个应用服务获得一个身份,因此它相当安全),如果您将其设置为 ENVIRONMENT VARIABLE ,它可能是环境的名称您的应用服务,并确保将其分别设置为 pre-prodprod

Here is the playaround code to test it

【讨论】:

  • 您好,非常感谢您花时间进行所有这些测试!我只是想知道使用许多不同的密钥容器来托管相同的密钥有什么可能的缺点?
  • 这取决于您是否想要/需要从其他来源使用它们?我认为一个好的分隔符可能是每个环境。不知道可能有什么缺点,我认为这在很大程度上取决于您如何使用容器以及您在其中存储的内容。但我(目前)看不到每个环境/机器密钥至少有一个容器有任何真正的缺点。
猜你喜欢
  • 1970-01-01
  • 2017-07-12
  • 1970-01-01
  • 2012-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
  • 1970-01-01
相关资源
最近更新 更多