对消息进行签名

当客户端和服务器完成 安全上下文设置时,可以使用消息支持函数。 客户端和服务器使用建立会话时创建的安全上下文令牌来调用 MakeSignatureVerifySignature 函数。 上下文令牌可与 EncryptMessage (General) DecryptMessage (General) 一起使用,以用于通信 隐私

以下示例演示生成要发送到服务器的已签名消息的客户端。 在调用 MakeSignature 之前,客户端使用 SecPkgContext_Sizes 结构调用QueryContextAttributes (General) ,以确定保存消息签名所需的缓冲区长度。 如果 cbMaxSignature 成员为零,则 安全包 不支持对消息进行签名。 否则,此成员指示为接收签名而分配的缓冲区的大小。

该示例假定已初始化名为 phContextSecHandle 变量和名为 s 的SOCKET 结构。 有关这些变量的声明和启动,请参阅 将 SSPI 与 Windows 套接字客户端配合使用将 SSPI 与 Windows 套接字服务器配合使用。 此示例包括对 Secur32.lib 中的函数的调用,这些函数必须包含在链接库中。

//--------------------------------------------------------------------
//   Declare and initialize local variables.

SecPkgContext_Sizes ContextSizes;
char *MessageBuffer = "This is a sample buffer to be signed.";
DWORD MessageBufferSize = strlen(MessageBuffer);
SecBufferDesc InputBufferDescriptor;
SecBuffer InputSecurityToken[2];

ss = QueryContextAttributes(
    &phContext,
    SECPKG_ATTR_SIZES,
    &ContextSizes
    );
if(ContextSizes.cbMaxSignature == 0)
{
     MyHandleError("This session does not support message signing.");
}
//--------------------------------------------------------------------
// The message as a byte string is in the variable 
// MessageBuffer, and its length is in MessageBufferSize. 

//--------------------------------------------------------------------
// Build the buffer descriptor and the buffers 
// to pass to the MakeSignature call.

InputBufferDescriptor.cBuffers = 2;
InputBufferDescriptor.pBuffers = InputSecurityToken;
InputBufferDescriptor.ulVersion = SECBUFFER_VERSION;

//--------------------------------------------------------------------
// Build a security buffer for the message itself. If 
// the SECBUFFER_READONLY attribute is set, the buffer will not be
// signed.

InputSecurityToken[0].BufferType = SECBUFFER_DATA;
InputSecurityToken[0].cbBuffer = MessageBufferSize;
InputSecurityToken[0].pvBuffer = MessageBuffer;

//--------------------------------------------------------------------
// Allocate and build a security buffer for the message
// signature.

InputSecurityToken[1].BufferType = SECBUFFER_TOKEN;
InputSecurityToken[1].cbBuffer = ContextSizes.cbMaxSignature;
InputSecurityToken[1].pvBuffer = 
        (void *)malloc(ContextSizes.cbMaxSignature);

//--------------------------------------------------------------------
// Call MakeSignature 
// For the NTLM package, the sequence number need not be specified 
// because the package provides sequencing.
// The quality of service parameter is ignored.

Ss = MakeSignature(
    &phContext,
    0,                       // no quality of service
    &InputBufferDescriptor,  // input message descriptor
    0                        // no sequence number
    );
if (SEC_SUCCESS(ss))
{
     printf("Have made a signature.\n");
}
else
{ 
    MyHandleError("MakeSignature Failed."); 
}

//--------------------------------------------------------------------
//  Send the message.

if(!SendMsg(
    s,
    (BYTE *)InputSecurityToken[0].pvBuffer,
    InputSecurityToken[0].cbBuffer))
{
     MyHandleError("The message was not sent.");
}

//--------------------------------------------------------------------
//   Send the signature.

if(!SendMsg(
     s,
    (BYTE *)InputSecurityToken[1].pvBuffer,
    InputSecurityToken[1].cbBuffer ))
{
     MyHandleError("The signature was not sent.");
}

如果将上下文设置为允许对消息进行签名,并且输入缓冲区描述符格式正确,则 MakeSignature 将返回 TRUE。 对消息签名后,消息及其长度的签名将发送到远程计算机。

注意

发送 SecBuffer 结构的数据内容,而不是 SecBuffer 结构本身或 SecBufferDesc 结构。 接收应用程序会创建新的 SecBuffer 结构和新的 SecBufferDesc 结构来验证签名。