DecryptMessage (Schannel) 函数

DecryptMessage (Schannel) 函数解密消息。 某些包不会加密和解密消息,而是执行并检查完整性 哈希

将此函数与 Schannel 安全支持提供程序 (SSP)一起使用,以向消息发送方发出请求,请求重新协商连接属性或关闭连接。

注释

如果一个线程正在加密,另一个线程正在解密,则可以同时从单个安全支持提供程序接口 (SSPI) 上下文中的两个不同的线程调用 EncryptMessage (Schannel) 和 DecryptMessage (Schannel)。 如果多个线程正在加密,或者多个线程正在解密,则每个线程应获取唯一的上下文。

语法

SECURITY_STATUS SEC_Entry DecryptMessage(
  _In_    PCtxtHandle    phContext,
  _Inout_ PSecBufferDesc pMessage,
  _In_    ULONG          MessageSeqNo,
  _Out_   PULONG         pfQOP
);

参数

phContext [in]

用于解密消息 的安全上下文 的句柄。

pMessage [in, out]

指向 SecBufferDesc 结构的指针。 在输入时,结构引用一个或多个 SecBuffer 结构。 其中一个缓冲区可以是类型SECBUFFER_DATA。 该缓冲区包含加密的消息。 该函数将就地解密加密消息,覆盖其缓冲区的原始内容。

将 Schannel SSP 用于不面向连接的上下文时,该结构必须包含输入上的四 个 SecBuffer 结构。 只有一个缓冲区的类型SECBUFFER_DATA并且包含加密的消息,函数将就地解密该消息。 其余缓冲区用于输出,并且必须为类型SECBUFFER_EMPTY。 对于面向连接的上下文,必须提供SECBUFFER_DATA类型缓冲区,如非连接型上下文所述。 此外,还必须提供包含安全令牌的第二个SECBUFFER_TOKEN类型缓冲区。

MessageSeqNo [in]

传输应用程序预期的序列号(如果有)。 如果传输应用程序不维护序列号,请将此参数设置为零。

使用 Schannel SSP 时,请将此参数设置为零。 Schannel SSP 不使用序列号。

pfQOP [out]

指向 ULONG 类型的变量的指针,该变量接收指示保护质量的包特定标志。

使用 Schannel SSP 时,请勿使用此参数。 将其设置为 NULL

此参数可以是以下标志。

价值 含义
SECQOP_WRAP_NO_ENCRYPT 消息未加密,但该函数生成了标头或预告片。
注意: KERB_WRAP_NO_ENCRYPT具有相同的值和相同的含义。

返回值

如果函数验证消息是否按正确的顺序接收,它将返回SEC_E_OK。

如果函数无法解密消息,它将返回以下错误代码之一。

返回代码 说明
SEC_E_INVALID_HANDLE phContext 参数指定无效的上下文句柄。 与 Schannel SSP 一起使用。
SEC_E_INVALID_TOKEN 缓冲区的类型不正确,或者找不到SECBUFFER_DATA类型的缓冲区。 与 Schannel SSP 一起使用。
SEC_E_MESSAGE_ALTERED 更改消息。 与 Schannel SSP 一起使用。
SEC_E_OUT_OF_SEQUENCE 消息未按正确的顺序接收。
SEC_I_CONTEXT_EXPIRED 消息发送方使用连接完成并启动关闭。 有关启动或识别关闭的信息,请参阅 关闭 Schannel 连接。 与 Schannel SSP 一起使用。
SEC_I_RENEGOTIATE 远程方需要新的握手序列,或者应用程序启动关闭。 返回到协商循环并调用 AcceptSecurityContext (Schannel)InitializeSecurityContext (Schannel),传递与 DecryptMessage 修改的缓冲区相同的缓冲区,确保 SecBuffer 类型设置为SECBUFFER_TOKEN。

注解

有时,应用程序从远程方读取数据,尝试使用 DecryptMessage(Schannel)对其进行解密,并发现 DecryptMessage(Schannel) 成功,但输出缓冲区为空。 此行为是正常的,应用程序必须能够处理它。

使用 Schannel SSP 时,当消息发送方关闭连接时, DecryptMessage (常规) 函数将返回SEC_I_CONTEXT_EXPIRED。 有关启动或识别关闭的信息,请参阅 关闭 Schannel 连接

如果使用 TLS 1.0,则可能需要多次调用此函数,调整每次调用的输入缓冲区,以解密整个消息。

当解密消息(Schannel)函数收到除应用程序数据以外的后握手 TLS 协议消息时,它将返回SEC_I_RENEGOTIATE。 当 DecryptMessage (Schannel) 返回SEC_I_RENEGOTIATE后,任何进一步的 EncryptMessage() 和 DecryptMessage() 调用将失败并SEC_E_CONTEXT_EXPIRED。 应用程序通过调用 AcceptSecurityContext(Schannel)(服务器端)InitializeSecurityContext(客户端) 并传递 与 DecryptMessage 修改的缓冲区相同的缓冲区来处理这种情况,确保 类型设置为 < a0/>。 请注意,当返回时 ,DecryptMessage 并不总是返回 SECBUFFER_EXTRA 缓冲区 SEC_I_RENEGOTIATE 。 此初始调用返回一个值后,继续作,就像应用程序正在创建新连接一样。 然后,应用程序可以继续调用 EncryptMessage() 和 DecryptMessage()。 有关详细信息,请参阅 创建 Schannel 安全上下文

要求

要求 价值
支持的最低客户端 Windows XP [仅限桌面应用]
支持的最低服务器 Windows Server 2003 [仅限桌面应用]
标题 Sspi.h(包括 Security.h)
图书馆 Secur32.lib
DLL Secur32.dll