开发者

Certificate stored in cert store disappearing from ASP.NET application over time

I've got a code signing certificate from Thawte that I'm using to dynamically generate and sign ClickOnce deployment manifests. The problem is that the ASP.NET application that generates and signs these manifests works fine when we restart IIS or re-import the signing certificate, but over time the following function fails to find the certificate:

private static X509Certificate2 GetSigningCertificate(string thumbprint)
{
    X509Store x509Store = new X509Store(StoreLocation.CurrentUser);
    try
    {
        x509Store.Open(OpenFlags.ReadOnly);
        X509Certificate2Collection x509Certificate2Collection = x509Store.Certificates.Find(
            X509开发者_运维百科FindType.FindByThumbprint, thumbprint, false);

        if (x509Certificate2Collection.Count == 0)
            throw new ApplicationException(
                "SigningThumbprint returned 0 results.  Does the code signing certificate exist in the personal store?",
                null);

        if (x509Certificate2Collection.Count > 1)
            throw new ApplicationException(
                "SigningThumbprint returned more than 1 result.  This isn't possible", null);

        var retval = x509Certificate2Collection[0];

        if(retval.PrivateKey.GetType() != typeof(RSACryptoServiceProvider))
            throw new ApplicationException("Only RSA certificates are allowed for code signing");

        return retval;
    }
    finally
    {
        x509Store.Close();
    }
}

Eventually the application starts throwing errors that it can't find the certificate. I'm stumped because I think the cert is installed correctly (or mostly correct) because it does find the cert when we start the ASP.NET application, but at some point we hit the Count==0 branch and it's just not true: the cert is in the application pool user's "Current User\Personal" cert store.

Question: Why might a cert all of a sudden "disappear" or not be able to be found?


Figured it out on our own (painfully).

The certificate needed to be installed in the LocalMachine store and the application pool account read permissions to the cert using WinHttpCertCfg or CACLS.exe if it's going to be used from an ASP.NET application. Using the CurrentUser store of the account running the application pool was causing the problem. I'm guessing there's some sort of race condition or something that's not entirely cool about accessing the CurrentUser store from a user that isn't running in a interactive logon session.

We were unable to do this at first because we were invoking the MAGE tool to do the ClickOnce deployment manifest creation/signing, and that requires the code signing cert to be in the CurrentUser\My store. However, we've eliminated the need for MAGE by a) creating the manifest from a template file and replacing the values we need to substitute out and b) by signing the manifest by calling the code MAGE calls via reflection that exists in the BuildTasks.v3.5 DLL. As a result we have more control over what cert we use to sign the manifest and can put it wherever we want. Otherwise we'd be stuck had we not gone a little "lower level".


We had the same issue, and it turns out the application pool needed to be set to load the the user profile of the (domain) account that we use to run the application.

If you notice that accessing the My certificate store works while you're signed in with the application pool's user, but not if you were not signed in while the apppool spun up, then this might be the cause for you, too.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜