代码之家  ›  专栏  ›  技术社区  ›  Benoit

CryptVerifyMessageSignature返回带有附加标头的原始消息,为什么?

  •  0
  • Benoit  · 技术社区  · 4 年前

    我用过 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字节:
      • 0x04
      • 表示消息长度的字节
      • 消息
    • 128字节原始消息长度255字节:
      • 0x04
      • 0x81
      • 表示消息长度的字节
      • 消息
    • 256字节原始消息长度65535字节:
      • 0x04
      • 0x82
      • 两个字节,以大端序表示消息的长度
      • 消息
    • 65536字节原始消息长度16777215字节:
      • 0x04
      • 0x83
      • 三个字节,以大端序表示消息的长度
      • 消息
    • 原始消息长度16777216字节:
      • 0x04
      • 0x84
      • 四个字节,以大端序表示消息的长度
      • 信息。 (我没有尝试使用大于4GiB的消息)。

    这对我来说真的很意外。这个标头信息从哪里来,在调用CryptVerifyCenter时,有没有办法避免得到它?

    有可能吗 信号工具 不是生成签名消息的正确工具吗?

    0 回复  |  直到 4 年前
        1
  •  2
  •   Benoit    4 年前

    解码后的消息似乎是 OCTET STRING 根据区分编码规则进行编码 https://en.wikipedia.org/wiki/X.690#DER_encoding .04是八叉字符串的标签号。

    推荐文章