【问题标题】:SChannel, SEC_E_ALGORITHM_MISMATCH (0x80090331)SChannel,SEC_E_ALGORITHM_MISMATCH (0x80090331)
【发布时间】:2015-06-26 16:25:28
【问题描述】:

在此问题上进行了数天的故障排除,在谷歌上搜索解决方案并重新阅读有关所需功能的 Microsoft 文档。改变变量,一次又一次地重试。非常感谢您的帮助,我敢肯定不仅仅是我遇到了这个问题。

我正在努力实现联网客户端和服务器应用程序,这些应用程序使用 SChannel 与 SSL/TLS 层进行通信(稍后还将使其与 OpenSSL 一起使用以实现交叉兼容性)。我有一个已知可以工作的客户端,因此我们可以专注于服务器端。

目前的目标是让它在不提供任何一方证书的情况下工作(它们应该根据需要即时生成)。我执行 AcquireCredentialsHandle,从客户端加载初始令牌(在同一主机上运行)并调用 AcceptSecurityContext。

似乎无论我更改什么变量,在第一次调用 AcceptSecurityContext 时总是会遇到相同的 0x80090331 错误。在 Windows 7 和 Windows Server 2012 上测试。

在我看来,我的代码之外肯定有一些东西,我需要修复一个操作系统设置。我在网上找到了相互矛盾的信息。 TLS 1.1 和 TLS 1.2 已添加到 SecurityProviders\SCHANNEL\Protocols* 下的注册表中,并使用数据 DisabledByDefault=0 进行设置。还在“SecurityProviders”中添加了“, schannel.dll”。

代码如下:

... snip ...(调用 AcquireCredentialsHandle 的代码)

PCCERT_CONTEXT serverCerts[1] = {0};

SCHANNEL_CRED sc = {0};
sc.dwVersion = SCHANNEL_CRED_VERSION;
//sc.grbitEnabledProtocols = SP_PROT_SSL3_SERVER | SP_PROT_TLS1_SERVER | SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_2_SERVER;
sc.grbitEnabledProtocols = SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_2_SERVER;
sc.dwFlags = 0;
sc.cCreds = 0; // Let Crypto API find the appropriate certificate for us
sc.paCred = serverCerts;

TimeStamp tsExpiry;
SECURITY_STATUS status = AcquireCredentialsHandle(
    NULL,
    UNISP_NAME,
    SECPKG_CRED_INBOUND,
    NULL,
    &sc,
    NULL,
    NULL,
    &hCredential,
    &tsExpiry);
std::cout << "AcquireCredentialsHandle result = 0x" << std::hex << status << std::endl;

... snip ...(调用 AcceptSecurityContext 的代码)

    // TOKEN is received from client into m_receivedData
    //std::vector<char> m_receivedData;

    m_ctxtFlags = ASC_REQ_ALLOCATE_MEMORY | ASC_REQ_STREAM;
    SecBuffer inBuffers[2];

    // Provide Schannel with the remote host's handshake data
    inBuffers[0].pvBuffer    = (char*)(&m_receivedData[0]);
    inBuffers[0].cbBuffer    = (unsigned long)m_receivedData.size();
    inBuffers[0].BufferType  = SECBUFFER_TOKEN;

    inBuffers[1].pvBuffer   = NULL;
    inBuffers[1].cbBuffer   = 0;
    inBuffers[1].BufferType = SECBUFFER_EMPTY;

    SecBufferDesc inBufferDesc = {0};
    inBufferDesc.cBuffers   = 2;
    inBufferDesc.pBuffers   = inBuffers;
    inBufferDesc.ulVersion  = SECBUFFER_VERSION;

    SecBuffer outBuffers[2];

    // We let Schannel allocate the output buffer for us
    outBuffers[0].pvBuffer   = NULL;
    outBuffers[0].cbBuffer   = 0;
    outBuffers[0].BufferType = SECBUFFER_TOKEN;

    // Contains alert data if an alert is generated
    outBuffers[1].pvBuffer   = NULL;
    outBuffers[1].cbBuffer   = 0;
    outBuffers[1].BufferType = SECBUFFER_ALERT;

    SecBufferDesc outBufferDesc = {0};
    outBufferDesc.cBuffers   = 2;
    outBufferDesc.pBuffers   = outBuffers;
    outBufferDesc.ulVersion  = SECBUFFER_VERSION;

    unsigned long fContextAttr;
    TimeStamp tsTimeStamp;

    SECURITY_STATUS status = NULL;
    if (isFirstCall) {
        status = AcceptSecurityContext(
            &hCredential,
            NULL,
            &inBufferDesc,
            m_ctxtFlags,
            0,
            &hNewContext,
            &outBufferDesc,
            &fContextAttr,
            NULL);
        std::cout << "AcceptSecurityContext (isFirstCall) result = 0x" << std::hex << status << std::endl;
    }

【问题讨论】:

  • 事件查看器显示以下内容:已生成以下致命警报:40。内部错误状态为 1205。

标签: ssl sspi schannel


【解决方案1】:

SSL/TLS 需要服务器端证书。缺少服务器端证书会生成 0x80090331 错误。下一步是根据需要创建自签名证书。见CertCreateSelfSignCertificate。使用 CryptoAPI 的 C 示例可以在 here 找到。

【讨论】:

    猜你喜欢
    • 2016-03-10
    • 1970-01-01
    • 2018-05-20
    • 2021-07-29
    • 2011-05-02
    • 2019-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多