我用过
signtool
生成包含以下内容的PKCS#7包:
构建此PKCS#7文件的命令如下:
$signtool sign /f signer_certificate.pfx /p âââ /fd sha512 /p7 . /p7ce Embedded /p7co 0 my_file
这将输出一个名为的文件
my_file.p7
以DER形式(ASN.1)。
现在,我编写了一个C++程序来验证,我们可以从捆绑包中提取证书和消息。为此,我呼吁
CryptVerifyMessageSignature
:
#include <windows.h>
#include <wincrypt.h>
#include <vector>
std::vector<BYTE> InputPkcs7Data;
// read input file into InputPkcs7Data (CreateFile, GetFileSizeEx, ReadFile).
// out of scope.
CRYPT_VERIFY_MESSAGE_PARA Parameters = {};
Parameters.cbSize = sizeof(Parameters);
Parameters.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
Parameters.hCryptProv = NULL;
Parameters.pfnGetSignerCertificate = NULL;
Parameters.pvGetArg = NULL;
DWORD DecodedMessageLength = 0;
PCCERT_CONTEXT SignerCertificate = NULL;
BOOL Result = CryptVerifyMessageSignature(&Parameters, 0, InputPkcs7Data.data(), InputPkcs7Data.size(), NULL, &DecodedMessageLength, &SignerCertificate);
std::vector<BYTE> DecodedMessage;
DecodedMessage.assign(DecodedMessageLength, 0);
Result = CryptVerifyMessageSignature(&Parameters, 0, InputPkcs7Data.data(), InputPkcs7Data.size(), DecodedMessage.data(), &DecodedMessageLength, &SignerCertificate);
if (Result == FALSE) {
wprintf(L"Error: %lx\n", GetLastError());
}
else
{
// inspect Memory
CertFreeCertificateContext(SignerCertificate);
}
我的问题是,即使
加密验证消息签名
成功,我进入
DecodedMessage
这不是原始消息。总有几个前导字节起初看起来像垃圾,但包含有关消息长度的信息。我设法理解了
解码消息
根据原始消息的长度,顺序如下:
-
原始消息长度127字节:
-
128字节原始消息长度255字节:
-
256字节原始消息长度65535字节:
-
0x04
-
0x82
-
两个字节,以大端序表示消息的长度
-
消息
-
65536字节原始消息长度16777215字节:
-
0x04
-
0x83
-
三个字节,以大端序表示消息的长度
-
消息
-
原始消息长度16777216字节:
-
0x04
-
0x84
-
四个字节,以大端序表示消息的长度
-
信息。
(我没有尝试使用大于4GiB的消息)。
这对我来说真的很意外。这个标头信息从哪里来,在调用CryptVerifyCenter时,有没有办法避免得到它?
有可能吗
信号工具
不是生成签名消息的正确工具吗?