【问题标题】:Adding a CA certificate for client certificates为客户端证书添加 CA 证书
【发布时间】:2012-11-05 20:54:24
【问题描述】:

我正在编写一个服务器应用程序,它使用 CryptoAPI 和 Schannel 来建立与客户端的安全 SSL 连接。服务器要求客户端提交证书进行验证(通过在AcceptSecurityContext 中设置ASC_REQ_MUTUAL_AUTH 标志)。

我遇到的问题是某些客户端(即使用javax.net.ssl 的客户端)没有传递他们的客户端证书(即使它已被配置为这样做)。我怀疑这是因为用于签署客户端证书的 CA 证书不在握手期间传递给客户端的 CA 列表中。

我已尝试执行以下变体以将 CA 证书添加到此列表中:

PCERT_CONTEXT caCertContext = ...; /* Imported from a DER formatted file */

HCERTSTORE systemStore = CertOpenStore(
                CERT_STORE_PROV_SYSTEM,
                0,
                0,
                CERT_STORE_OPEN_EXISTING_FLAG |
                    CERT_SYSTEM_STORE_LOCAL_MACHINE,
                L"ROOT");

bool ok = CertAddCertificateContextToStore(
                systemStore,
                caCertContext,
                CERT_STORE_ADD_USE_EXISTING,
                NULL);

if (!ok)
{
    std::cerr << "Could not add certificate to system store!" << std::endl;
}

在上面的例子中,CertAddCertificateContextToStorealways 失败了。如果我将CERT_SYSTEM_STORE_LOCAL_MACHINE更改为CERT_SYSTEM_STORE_CURRENT_USER,我会看到一个弹出窗口,要求我确认证书,但即使我接受 CA 证书也不会出现在发送给客户端的列表中。

我还尝试使用临时内存存储(我从here 获取的内容)扩展系统存储集合,但无济于事。

有人知道解决这个问题的方法吗?理想情况下以编程方式不使用任何 GUI 或外部工具?

【问题讨论】:

  • 调用 CertAddCertificateContextToStore() 后 GetLastError() 返回的值是多少?我做了一些非常相似的事情,但成功使用了 CertAddEncodedCertificateToStore()。
  • GetLastError() 返回“5”,不管这应该是什么意思......编辑:似乎错误 5 是 ERROR_ACCESS_DENIED

标签: winapi cryptography cryptoapi


【解决方案1】:

您收到该错误是因为您无权以读写方式访问存储,您只能以读取方式访问它。所以你要做的就是添加 CERT_STORE_READONLY_FLAG 所以它会是:

HCERTSTORE systemStore = CertOpenStore(
            CERT_STORE_PROV_SYSTEM,
            0,
            0,
            CERT_STORE_OPEN_EXISTING_FLAG |
                CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG ,
            L"ROOT");

如果您要对商店进行更改而不将其设置为只读,这意味着您在运行 C++ 应用程序时需要进行管理提升。

【讨论】:

  • 但如果它是只读的,我如何以编程方式扩展 CA 证书的集合?请注意,我不希望将其添加到系统存储中,因为这会使该计算机上的所有应用程序都具有全局性。
  • 我编辑我的答案。您需要将您的应用程序提升到管理员权限才能对商店进行更改。我知道我以这种方式解决了我的一个问题,所以你可以试试。您可以通过将此 添加到清单文件中来做到这一点。
【解决方案2】:

如果您不想在系统范围内添加它(正如您在评论中提到的),您可以使用 CERT_SYSTEM_STORE_CURRENT_USER 标志打开。

CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG |
              CERT_SYSTEM_STORE_CURRENT_USER, L"MY");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 2012-03-19
    • 1970-01-01
    • 2021-01-17
    • 1970-01-01
    • 2018-08-15
    相关资源
    最近更新 更多