メッセージへの署名
クライアントとサーバーが セキュリティ コンテキストの設定を完了すると、メッセージ サポート関数を使用できます。 クライアントとサーバーは、セッションが確立されたときに作成されたセキュリティ コンテキスト トークンを使用して 、MakeSignature 関数と VerifySignature 関数を 呼び出します。 コンテキスト トークンは、通信のプライバシーのために EncryptMessage (General) と DecryptMessage (General) と共に使用できます。
次の例は、サーバーに送信する署名付きメッセージを生成するクライアント側を示しています。 MakeSignature を呼び出す前に、クライアントは SecPkgContext_Sizes 構造体を使用して QueryContextAttributes (General) を呼び出して、メッセージ署名を保持するために必要なバッファーの長さを決定します。 cbMaxSignature メンバーが 0 の場合、セキュリティ パッケージはメッセージの署名をサポートしません。 それ以外の場合、このメンバーは、署名を受信するために割り当てるバッファーのサイズを示します。
この例では、phContext という名前の SecHandle 変数と、 という名前のSOCKET 構造体が初期化されていることを前提としています。 これらの変数の宣言と開始については、「 Windows ソケット クライアントでの SSPI の使用」および「Windows ソケットサーバーでの SSPI の使用」を参照してください。 この例には、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 構造体自体や SecBufferDesc 構造体ではなく、SecBuffer 構造体のデータ内容が送信されます。 署名を確認するために、受信アプリケーションによって新しい SecBuffer 構造体と新しい SecBufferDesc 構造体が作成されます。