.Net CryptographicException"对象已存在"在Azure上

时间:2017-01-12 14:15:42

标签: .net azure cryptography azure-web-sites cryptographicexception

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

网站在特定时间使用以下代码创建一个容纳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部分中实现)不起作用..

有任何想法或建议吗?

由于

Riana

1 个答案:

答案 0 :(得分:2)

我认为问题在于您基本上是在尝试创建两次具有相同名称的Machine wide容器。我假设pre-prodprod环境位于同一台计算机上,可能是您的App Service中的部署插槽?我至少可以使用此设置复制您的问题。还有一些其他的设置可能会产生相同的情况,我猜,但这是最有可能的。

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

  • 授予访问权限的身份
  • 货柜店
  • 容器名称

对于身份,我们可以使用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.

的两个广告位都出现故障

因此,总而言之,更改容器名称以包含对环境唯一的内容将解决问题。它不一定是身份(但是你将在机器上运行的每个App Service获得一个身份,因此它是相当安全的),如果你将它设置为{{1},它可能是环境的名称在您的App Service中,确保它分别设置为ENVIRONMENT VARIABLEpre-prod

Here is the playaround code to test it