Winapi EncryptMessage返回SEC_E_无效\u令牌
在使用win32 API的EncryptMessage(SChannel)和有效上下文时,我按照正确的顺序提供了四个缓冲区。我得到了SEC_E_INVALID_令牌响应,根据文档,没有找到SECBUFFER_数据类型缓冲区。我知道,为了提高速度,应该从连续内存中分配pvBuffers集,但为了简单起见,我已经明确说明了这是什么。有人知道问题出在哪里吗 谢谢, 布鲁斯 代码如下:Winapi EncryptMessage返回SEC_E_无效\u令牌,winapi,sspi,schannel,Winapi,Sspi,Schannel,在使用win32 API的EncryptMessage(SChannel)和有效上下文时,我按照正确的顺序提供了四个缓冲区。我得到了SEC_E_INVALID_令牌响应,根据文档,没有找到SECBUFFER_数据类型缓冲区。我知道,为了提高速度,应该从连续内存中分配pvBuffers集,但为了简单起见,我已经明确说明了这是什么。有人知道问题出在哪里吗 谢谢, 布鲁斯 代码如下: procedure TTCPSocket.SSPEncryptBuffer(SSPCtx: PCtxtHandle;
procedure TTCPSocket.SSPEncryptBuffer(SSPCtx: PCtxtHandle; InData: PAnsiChar; InDataLength: Cardinal);
var
SecStatus: TSecurityStatus;
SecBufDesc: TSecBufferDesc;
SecBufs: packed array [0 .. 3] of TSecBuffer;
begin
SecBufs[0].BufferType := SECBUFFER_STREAM_HEADER;
SecBufs[0].cbBuffer := FSecPkgSizes.cbHeader;
SecBufs[0].pvBuffer := AllocMem(FSecPkgSizes.cbHeader);
SecBufs[1].BufferType := SECBUFFER_DATA;
SecBufs[1].cbBuffer := InDataLength;
SecBufs[1].pvBuffer := InData;
SecBufs[2].BufferType := SECBUFFER_STREAM_TRAILER;
SecBufs[2].cbBuffer := FSecPkgSizes.cbTrailer;
SecBufs[2].pvBuffer := AllocMem(FSecPkgSizes.cbTrailer);
SecBufs[3].BufferType := SECBUFFER_EMPTY;
SecBufs[3].cbBuffer := 0;
SecBufs[3].pvBuffer := nil;
SecBufDesc.ulVersion := SECBUFFER_VERSION;
SecBufDesc.cBuffers := 4;
SecBufDesc.pBuffers := @SecBufs[0];
SecStatus := EncryptMessage(SSPCtx, 0, @SecBufDesc, 0);
if SecStatus <> SEC_E_OK then
begin
// Error code..
end;
end;
看起来操作系统获得了正确的信息
我搜索了一下,发现80090308通常意味着证书有问题,因为服务器的全名应该在主题中,CN=www.foobar.com,但这也没有解决问题,证书和CA是使用OpenSSL生成的。这里有点猜测,因为这似乎是人们在Windows上尝试使用非对称加密时遇到的常见问题 如果是自签名CA,并且您的证书是使用自签名CA签名的,则需要将CA导入计算机的受信任CA存储 要执行此操作,请运行MMC并执行以下操作:
我希望它能有所帮助。当您在客户端和服务器上使用
InitializeSecurityContext // Schannel Client
AcceptSecurityContext // Schannel Server
请特别注意为您想要的上下文类型传入的标志,因为它决定了EncryptMessage和DecryptMessage所需的SecBuffer类型。例如,我目前正在使用
FClientContextFlags :=
ISC_REQ_CONFIDENTIALITY or
ISC_REQ_STREAM or
ISC_REQ_ALLOCATE_MEMORY;
FServerContextFlags :=
ASC_REQ_CONFIDENTIALITY or
ASC_REQ_STREAM or
ASC_REQ_ALLOCATE_MEMORY;
这意味着对于EncryptMessage,您需要四个SecBuffers
SECBUFFER_STREAM_HEADER
SECBUFFER_DATA
SECBUFFER_STREAM_TRAILER
SECBUFFER_EMPTY
SECBUFFER_DATA
SECBUFFER_EMPTY
SECBUFFER_EMPTY
SECBUFFER_EMPTY
对于解密消息,您还需要四个SecBuffers
SECBUFFER_STREAM_HEADER
SECBUFFER_DATA
SECBUFFER_STREAM_TRAILER
SECBUFFER_EMPTY
SECBUFFER_DATA
SECBUFFER_EMPTY
SECBUFFER_EMPTY
SECBUFFER_EMPTY
我的问题是我有*_-REQ_流和*_-REQ_连接,仔细阅读文档后发现它们基本上是不兼容的。这是在确保您拥有有效的证书/受信任的证书等的基础上进行的
我希望这对某人有帮助
Bruce很高兴看到您正在进行压缩。您能否确认
FSecPkgSizes.cbHeader
值为5,InDataLength
值介于1和16362之间,FSecPkgSizes.cbTrailer
值为16?是的,正在进行压缩:)。再次感谢你以前的帮助。在本例中,cbHeader是5,InDataLength是23(它说如果太小它会抱怨),但CBTraile是36而不是16,我硬编码为16,但仍然没有乐趣。我已经对您提到的关于“解决方案”的问题()添加了一条注释。感谢您的思考,但是,我已经可以从商店获得有效的证书,而且握手可以正常工作。您是否建议您可以在握手双方都获得SEC_E__OK,但由于证书不“正确”,EncryptMessage仍将失败?可能上下文的建立只是一个3向TCP握手,并且在发送第一条消息之前不会进行TLS/SSL握手。您可以使用Wireshark之类的工具查看连接,并在尝试加密消息之前查看是否建立了TCP连接以外的连接。如果SChannel将TLS/SSL握手延迟到第一条消息,那么即使在成功建立上下文之后,它也可能确实失败。运行Filemon或Regmon(sysinternals)可能也会显示它何时访问本地CA存储。我正在用自己的代码处理握手,来回传递“令牌”,直到secu__OK和最后一个令牌被传输,所以我非常确定握手已经发生。我一直在使用系统事件查看器查看凭据是否已建立。