当使用带有有效上下文的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生成的。
答案 0 :(得分:2)
这里有点猜测,因为这似乎是人们在尝试使用Windows上的非对称加密做任何事情时遇到的常见问题。
如果是自签名CA且您的证书已使用自签名CA签名,则需要将CA导入计算机的可信CA存储。
为此,请运行MMC并执行以下操作:
文件 - >添加/删除管理单元
如果您希望它适用于计算机上的所有用户,请添加“证书”管理单元并选择“计算机帐户”。
打开“受信任的根证书颁发机构 - >证书”树节点。
右键单击“证书”并选择导入。
导入CA证书文件。 (它应该没有问题地接受PEM编码版本。)
虽然在大多数情况下CN需要与计算机证书中的计算机名称匹配,但如果CA未导入到Windows信任存储中,则CA验证将失败。
我希望它有所帮助。
答案 1 :(得分:1)
使用时在客户端和服务器上设置上下文;
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
对于DecryptMessage,您还需要四个SecBuffers;
SECBUFFER_DATA
SECBUFFER_EMPTY
SECBUFFER_EMPTY
SECBUFFER_EMPTY
我的问题是我有* _REQ_STREAM和* _REQ_CONNECTION,在仔细阅读文档时基本上是不兼容的。这是确保您拥有有效证书/信任等等。
我希望这有助于某人。
布鲁斯