【问题标题】:Keyset does not exist when accessing certificate from azure web site从 azure 网站访问证书时密钥集不存在
【发布时间】:2020-03-13 04:38:07
【问题描述】:

当我使用以下代码从本地或天蓝色网站上的文件系统访问证书时,我没有问题:

X509Certificate2 certificate = new X509Certificate2(keyFilePath, "mysecret", X509KeyStorageFlags.MachineKeySet |
                   X509KeyStorageFlags.PersistKeySet |
                   X509KeyStorageFlags.Exportable);

但是,当我按照 https://azure.microsoft.com/en-us/blog/using-certificates-in-azure-websites-applications/ 的说明使用 azure 证书存储时,前 3 到 9 个请求一切正常,所有后续调用都在以下行失败

var rsa = certificate.PrivateKey as RSACryptoServiceProvider;

在站点重新启动之前出现错误“System.Security.Cryptography.CryptographicException: Keyset 不存在”,然后至少可以处理另外 3 个请求。

我很困惑为什么它适用于至少 3 个和最多 9 个请求,然后总是因错误而失败。如有任何建议,我将不胜感激。

【问题讨论】:

    标签: c# azure azure-web-app-service x509certificate


    【解决方案1】:

    从 PFX 加载时,您指定了 PersistKeySet,通常仅在您计划将证书保存到证书存储时才应设置。尽管代码的某些方面可能会尝试变得聪明并自行清理私钥,方法是将 RSACryptoServiceProvider 对象的 PersistKeyInCsp 标记为 false

    我指出这一点的原因是“密钥集不存在”错误几乎总是意味着“证书存储被告知存在私钥,但有人在没有通知证书存储的情况下删除了它”。最有可能的罪魁祸首是某处将PersistKeyInCsp 设置为false(这意味着“在 Dispose/Finalize 上删除密钥文件”)。

    如果您将 PersistKeyInCsp 设置为 false 但不手动处理对象,则由于终结器,您将获得延迟清理,这可以解释为什么它是 3-9 成功而不是确定性数字。

    (我也不得不指出你应该使用cert.GetRSAPrivateKey() 而不是cert.PrivateKey,因为a)它是类型安全的,b)它是调用者拥有的生命周期(你应该处理它)而不是共享/模糊的生命周期。它使事情变得更加可预测,尽管它几乎从不返回 RSACryptoServiceProvider,所以你不应该尝试强制转换它)

    【讨论】:

    • 谢谢。我能够通过不将 PersistKeyInCsp 设置为 false 来“解决”该问题。不幸的是,x509Certificates 和 Cryptography 都在我的驾驶室之外。我正在使用的代码是我们在网上找到的一个库,用于为 Google firebase 生成令牌。虽然我现在已经畅通无阻,但显然我应该对它的内部运作进行一些研究,而不是将那个库视为一个黑盒子。
    • 我将new X509Certificate2(certificateBytes, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable) 更改为new X509Certificate2(certificateBytes, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable)(即:我删除了PersistKeySet)但它不起作用。它随机抛出“Keyset不存在”......
    【解决方案2】:

    看起来像显式处理(带有using关键字)解决了这个问题:

    using (X509Certificate2 certificate = new X509Certificate2(keyFilePath, "mysecret", X509KeyStorageFlags.MachineKeySet |
                       X509KeyStorageFlags.PersistKeySet |
                       X509KeyStorageFlags.Exportable))
    {
    // ... use cert
    }
    

    【讨论】:

    • 我用完了 BouncyCastle。这个(使用 X509...)解决方案在本地和 Azure Web App 中有效,但在 Functions 中无效,只有 BouncyCastle 提供了帮助。
    • 可以确认 BouncyCastly 似乎是唯一可靠的解决方案。过去没有它时会出现问题,主要是在重负载下。
    【解决方案3】:

    单身人士为我工作:

      class static CertificateSingleton
      {
           private static X509Certificate2 certificate;
    
           public Get()
           {
                if (certificate == null) 
                {
                     byte[] certificateBytes = .....;
                     string password = .....;
    
                     certificate = new X509Certificate2(certificateBytes, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
                }
    
                return certificate;
           }
      }
    

    所以每次我想使用它时,我都会使用CertificatesSingleton.Get(),这样可以保证我每次都使用相同的实例。

    【讨论】:

      猜你喜欢
      • 2015-11-23
      • 2011-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多