如何使FiddlerCore编程式证书安装“粘”在程序中?

7
我正在使用FiddlerCore来捕获HTTP请求。只要手动安装了Fiddler证书,包括SSL捕获在内的所有操作都可以正常工作。我一直通过Fiddler选项菜单进行手动安装,这样可以正常工作。
然而,如果我使用FiddlerCore提供的CertMaker类静态方法添加Fiddler证书,我会发现我只能在当前会话中使用添加到证书根目录下的证书。一旦我关闭应用程序并重新启动,CertMaker.rootCertExists()返回false。
我使用以下代码为当前用户安装证书(此时是从显式菜单选项):
public static bool InstallCertificate()
{
    if (!CertMaker.rootCertExists())
    {
        if (!CertMaker.createRootCert())
            return false;

        if (!CertMaker.trustRootCert())
            return false;
    }

    return true;
}

证书已安装并出现在当前用户的根证书存储中。如果我在当前运行的应用程序中捕获SSL请求,它可以正常工作。
然而,如果我关闭正在运行的exe,重新启动并调用CertMaker.certRootExists(),它会返回false,如果我尝试捕获SSL请求,则浏览器中的SSL连接将失败。如果我重新创建证书,然后在应用程序保持运行状态的情况下再次运行请求,它就能正常工作了。此时,我在根存储中就有两个证书。
退出并重新启动后,certMaker.certRootExists()仍然返回false。唯一让它起作用的方法是在每个exe会话中注册证书。
我做错了什么导致安装无法在同一应用程序执行之间保留?
2个回答

12

通过移除FiddlerCore安装的默认CertMaker.dllBcMakeCert.dll程序集,并使用和分发makecert.exe可执行文件,我能够解决这个问题并创建可在EXE会话间使用的持久证书。

makecert.exe似乎以一种可用于应用程序多次运行的方式创建证书,而包含的程序集仅对当前应用程序的运行会话有效。

更新:

如果您想使用FiddlerCore默认安装的CertMaker.dllBcMakeCert.dll,则必须使用Fiddler的内部首选项对象有效地缓存和设置证书和私钥。有几个键保存了证书被创建后的值,您需要捕获这些值,并将它们写入某种配置存储中。

在下面的例子中,我有一个静态配置对象,保存证书和密钥(在应用程序关闭时持久化到配置文件):

public static bool InstallCertificate()
{
    if (!CertMaker.rootCertExists())           
    {
        if (!CertMaker.createRootCert())
            return false;

        if (!CertMaker.trustRootCert())
            return false;

        // persist Fiddlers certificate into app specific config
        App.Configuration.UrlCapture.Cert = 
           FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.cert", null);
        App.Configuration.UrlCapture.Key = 
           FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.key", null);
    }

    return true;
}

public static bool UninstallCertificate()
{
    if (CertMaker.rootCertExists())
    {
        if (!CertMaker.removeFiddlerGeneratedCerts(true))
            return false;
    }
    // persist Fiddlers certificate into app specific config
    App.Configuration.UrlCapture.Cert = null;
    App.Configuration.UrlCapture.Key = null;
    return true;
}

安装证书后,此代码会将证书和私钥捕获到配置对象中,并稍后保留该值。卸载时,这些值被清除。

在应用程序开始或捕获过程开始之前,在调用CertMaker.rootCertExists()之前,从配置值设置密钥。我在我的捕获表单的开头执行此操作:

public FiddlerCapture()
{
    InitializeComponent();

    // read previously saved Fiddler certificate from app specific config
    if (!string.IsNullOrEmpty(App.Configuration.UrlCapture.Cert))
    {
        FiddlerApplication.Prefs.SetStringPref("fiddler.certmaker.bc.key", 
                                               App.Configuration.UrlCapture.Key);
        FiddlerApplication.Prefs.SetStringPref("fiddler.certmaker.bc.cert", 
                                               App.Configuration.UrlCapture.Cert);
    }
}

当使用CertMaker.dll时,使用此机制保存和设置捕获设置可使证书在多个EXE会话中持久存在。

有关更详细的信息,请参阅FiddlerCore上的这篇详细博客文章


非常感谢您提供的解决方案。但是,是否有可能它不适用于Firefox?在这种情况下,我需要在Firefox中手动安装FiddlerRoot.cer。有没有办法避免这种情况发生? - Cher
有没有一种方法可以抑制弹出的对话框,以安装证书? - Frank Q.

0

如果还有人感兴趣,我找到了一个更简单的解决方案,基于Fiddler提供的演示。这个演示只是调用CertMaker.trustRootCert(),奇怪的是,它就生效了!第一次会询问是否安装证书,但之后,该函数只会返回true,不会再弹出窗口。

与你和我的原始程序不同,证书无需自己去让它生效,所以我分析了一下与演示的区别。我注意到其中一个区别是演示没有引用CertMaker.dll和BCMakeCert.dll。在从我的解决方案中删除这些引用后,我得到了与演示相同的行为。

不幸的是,我不知道为什么这样做有效,但我希望这仍然能帮助一些人。


这个也可以用于iOS吗? - Cosmin
@Cosmin 我没有尝试过,但你可以轻松地检查一下。尝试在演示中运行并且有或没有对CertMaker.dll和BCMakeCert.dll的引用。在每种情况下:(1)启动应用程序,(2)在提示安装证书时单击“是”,(3)关闭应用程序,(4)再次启动应用程序以检查证书是否保留(如果再次提示,则未保留)。在我的Windows上,当这两个dll都不存在时,它会保留。 - Safron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接