【问题标题】:EncryptMessage returns SEC_E_INVALID_TOKENEncryptMessage 返回 SEC_E_INVALID_TOKEN
【发布时间】:2009-11-25 00:14:35
【问题描述】:

当使用带有有效上下文的 win32 API 中的 EncryptMessage (SChannel) 时,我以正确的顺序提供了四个缓冲区,我得到了 SEC_E_INVALID_TOKEN 响应,根据文档,没有找到 SECBUFFER_DATA 类型的缓冲区。我知道应该从连续内存中分配 pvBuffers 集以提高速度,但为简单起见,我已经清楚地表明了什么是什么。谁能看出问题出在哪里?

谢谢, 布鲁斯

代码如下;

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;

我使用 STRACE 注入到可执行文件中,这一行看起来很有趣;

12/07/2009 23:10:30:635 - SecBuffer #0 BufferType:0x00000007 cbBuffer:5
12/07/2009 23:10:30:636 - SecBuffer #1 BufferType:0x00000001 cbBuffer:13
12/07/2009 23:10:30:636 - SECBUFFER_DATA - 13 byte(s) / EncryptMessage - INPUT 
=====================================================
      00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f   0123456789abcdef

0000: 68 65 6c 6c 6f 20 77 6f 72 6c 64 21 00            hello world!.
=====================================================
12/07/2009 23:10:30:636 - SecBuffer #2 BufferType:0x00000006 cbBuffer:36
12/07/2009 23:10:30:636 - SecBuffer #3 BufferType:0x00000000 cbBuffer:0
12/07/2009 23:10:30:636 - 

 *** WARNING : EncryptMessage failed (80090308) ***

看起来操作系统正在获取正确的信息。

我搜索了一下,发现 80090308 通常意味着证书有问题,因为服务器的全名应该在主题中,CN=www.foobar.com 但这也没有解决问题,证书和 CA 是使用 OpenSSL 生成的。

【问题讨论】:

  • 很高兴看到你的进步
  • 你能确认FSecPkgSizes.cbHeader的值为5,InDataLength的值在1到16362之间,FSecPkgSizes.cbTrailer的值为16吗?
  • 是的,正在取得进展:)。再次感谢您之前的帮助。在这种情况下,cbHeader 是 5,InDataLength 是 23(它说如果它太小它会抱怨)但是 cbTrailer 是 36 而不是 16,我将它硬编码为 16 但仍然没有乐趣。
  • 顺便说一句,我已对您提到的问题 (stackoverflow.com/questions/1727259) 添加了评论。

标签: winapi sspi schannel


【解决方案1】:

这里有点猜测,因为这似乎是人们在 Windows 上尝试使用非对称加密做任何事情时遇到的常见问题。

如果它是自签名 CA,并且您的证书是使用自签名 CA 签名的,则需要将该 CA 导入您计算机的受信任 CA 存储中。

为此,请运行 MMC 并执行以下操作:

  1. 文件->添加/删除管理单元

  2. 如果您希望它适用于计算机上的所有用户,请添加“证书”管理单元并选择“计算机帐户”。

  3. 打开“Trusted Root Certificate Authorities->Certificates”树节点。

  4. 右键单击“证书”并选择导入。

  5. 导入 CA 证书文件。 (它应该毫无问题地接受 PEM 编码版本。)

虽然在大多数情况下 CN 需要与计算机证书中的计算机名称匹配,但如果 CA 未导入 Windows 信任存储,CA 验证将失败。

希望对你有帮助。

【讨论】:

  • 感谢您的考虑,但是我已经可以从商店获得有效证书并且握手工作正常。您是否建议您可以在握手的双方都获得 SEC_E_OK 并且由于证书不“正确”而 EncryptMessage 仍然会失败?
  • 上下文的建立可能只是 3 次 TCP 握手,并且在发送第一条消息之前它不会通过 TLS/SSL 握手。在尝试加密消息之前,您可以使用 Wireshark 之类的东西观察连接,看看是否建立了不仅仅是 TCP 连接。如果 SChannel 将 TLS/SSL 握手延迟到第一条消息,那么即使在成功建立上下文之后它也可能确实会失败。运行 Filemon 或 Regmon (sysinternals) 也可能会在访问本地 CA 存储时向您显示。
  • 我在自己的代码中处理握手,来回传递“令牌”直到 SEC_E_OK 并且最后一个令牌已经传输,所以我很确定握手已经发生。我一直在使用系统事件查看器来查看已建立的凭据。
【解决方案2】:

当您在客户端和服务器上设置上下文时使用;

InitializeSecurityContext // Schannel Client
AcceptSecurityContext // Schannel Server

要特别注意您为所需上下文类型传入的标志,因为它决定了 EncryptMessage 和 DecryptMessage 所需的 SecBuffer(s) 类型。例如我目前正在使用;

  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

对于 DecryptMessage,您还需要四个 SecBuffers;

SECBUFFER_DATA
SECBUFFER_EMPTY
SECBUFFER_EMPTY
SECBUFFER_EMPTY

我的问题是我有 *_REQ_STREAM 和 *_REQ_CONNECTION 在仔细阅读文档时它们基本上是不兼容的。这是确保您拥有有效证书/受信任等的基础。

我希望这对某人有所帮助。

布鲁斯

【讨论】:

    猜你喜欢
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    • 2018-09-15
    • 2019-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多