EncryptMessage 返回 SEC_E_INVALID_TOKEN

发布于 2024-08-13 05:01:51 字数 2186 浏览 6 评论 0原文

当使用来自 win32 API 的 EncryptMessage (SChannel) 和有效上下文时,我以正确的顺序提供四个缓冲区,我得到 SEC_E_INVALID_TOKEN 响应,根据文档,该响应是 No SECBUFFER_DATA type buffer was found。我知道为了速度,应该从连续内存中分配 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 生成的。

When using the EncryptMessage (SChannel) from the win32 API with a valid context, I am supplying the four buffers in the correct order I get the SEC_E_INVALID_TOKEN response which according to the documentation is No SECBUFFER_DATA type buffer was found. I know that the set of pvBuffers should be allocated from contiguous memory for speed but for simplicity I have made it obvious what is what. Can anyone see what the problem could be?

Thanks,
Bruce

The code is the following;

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;

I used STRACE injected into the executable and this line looks interesting;

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) ***

Which looks as though the OS is getting the correct information.

I have searched a bit and found that 80090308 usually means something wrong with the certificate in that the full name of the server should be in the subject, CN=www.foobar.com but this didn't fix the problem either, the certificate and CA are generated with OpenSSL.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

姜生凉生 2024-08-20 05:01:51

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

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

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

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

  2. 添加“证书”管理单元并选择“计算机”如果您希望将其应用于计算机上的所有用户,

  3. 打开“受信任的根证书颁发机构 -> 证书”树节点。

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

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

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

我希望它有帮助。

Somewhat of a guess here since this seems like a common problem people run into when trying to do anything with asymmetric crypto on Windows.

If it is a self-signed CA and your cert is signed with the self signed CA, you need to import the CA into your computer's trusted CA store.

To do this, run MMC and do the following:

  1. File->Add/Remove Snap In

  2. Add the "Certificates" snap in and choose "Computer Account" if you want it to apply for all users on the computer.

  3. Open the "Trusted Root Certificate Authorities->Certificates" tree node.

  4. Right click on "Certificates" and choose import.

  5. Import the CA certificate file. (It should accept the PEM encoded version without a problem.)

While the CN will need to match the name of the machine in your machine certificate in most cases, the CA validation will fail if the CA is not imported into the Windows trust storage.

I hope it helps.

半世蒼涼 2024-08-20 05:01:51

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

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 您需要四个 SecBuffer;

SECBUFFER_STREAM_HEADER
SECBUFFER_DATA
SECBUFFER_STREAM_TRAILER
SECBUFFER_EMPTY

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

SECBUFFER_DATA
SECBUFFER_EMPTY
SECBUFFER_EMPTY
SECBUFFER_EMPTY

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

我希望这对某人有帮助。

布鲁斯

When you set up your context on both client and server using;

InitializeSecurityContext // Schannel Client
AcceptSecurityContext // Schannel Server

pay very special care to the flags you pass in for the type of context you want as that determines the types of SecBuffer(s) that you need for both EncryptMessage and DecryptMessage. For instance I am currently using;

  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;

which means that for EncryptMessage you need four SecBuffers of;

SECBUFFER_STREAM_HEADER
SECBUFFER_DATA
SECBUFFER_STREAM_TRAILER
SECBUFFER_EMPTY

and for DecryptMessage you also need four SecBuffers of;

SECBUFFER_DATA
SECBUFFER_EMPTY
SECBUFFER_EMPTY
SECBUFFER_EMPTY

My problem was that I had *_REQ_STREAM and *_REQ_CONNECTION which on closer reading of the documentation are essentially incompatible. This is on top of making sure you have a valid certificate/trusted etc.

I hope this helps someone.

Bruce

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文