对签名数据进行编码

签名数据 由任何类型的内容以及零个或多个签名者的内容加密消息 哈希 组成。 生成的哈希可以确认自签名以来未修改原始消息,以及特定人员或实体对数据进行了签名。

下图描述了对已签名消息进行编码的过程。 下图后面的列表描述了这些步骤。

消息可能有多个签名者、哈希算法和证书。 虽然此图仅显示证书、 CRL 和 CTL 可以使用同一过程。 无论证书显示在何处,它们都适合插图中。

对签名消息进行编码

编码 签名数据的 一般过程如下所示。

对已签名数据进行编码

  1. 如有必要,) (创建数据,并检索指向它的指针。
  2. 将打开包含签名者证书的证书 存储 。
  3. 检索证书的私钥。 在使用证书之前,必须对证书设置两个属性。 一个用于将证书绑定到特定 CSP,并在该 CSP 中将证书绑定到特定的 私钥容器。 另一个用于指示在调用哈希操作时要使用的 哈希 算法。 这些只需要设置一次。
  4. 证书的 属性确定哈希算法。
  5. 通过哈希函数发送数据来创建数据的哈希。
  6. 签名是通过使用私钥加密哈希来创建的,该私钥通过证书上的 属性获取。
  7. 以下数据包含在已完成的签名消息中:
    • 要签名的原始数据
    • 哈希算法
    • 签名
    • 签名者信息结构,其中包括签名者标识符 (证书颁发者和序列号)
    • 签名者的证书 (可选)

此过程演示了一个简单的情况。 更复杂的情况涉及消息中包含的经过身份验证的属性。 如果内容类型不是 BYTE 字符串,或者至少有一个经过身份验证的属性以及任何数据类型,则需要两个经过身份验证的标准属性:内容 (数据) 类型,以及内容的哈希。 在这些情况下, CryptoAPI 会自动提供这两个必需属性。 低级别消息函数对经过身份验证的属性进行哈希处理,使用私钥加密哈希,并将其作为签名提供。

使用以下过程,使用低级别消息函数完成刚刚列出的任务。

对已签名消息进行编码

  1. 创建或检索内容。

  2. 获取加密提供程序。

  3. 获取签名者证书。

  4. 初始化 CMSG_SIGNER_ENCODE_INFO 结构。

  5. 初始化 CMSG_SIGNED_ENCODE_INFO 结构。

  6. 调用 CryptMsgCalculateEncodedLength 以获取编码的消息 BLOB 的大小。 为其分配内存。

  7. 调用 CryptMsgOpenToEncode,传入 dwMsgType 的CMSG_SIGNED和指向 pvMsgEncodeInfoCMSG_SIGNED_ENCODE_INFO的指针,以获取打开的消息句柄。

  8. 调用 CryptMsgUpdate,传入步骤 7 中检索到的句柄,以及指向要签名和编码的数据的指针。 可以根据需要多次调用此函数来完成编码过程。

  9. 调用 CryptMsgGetParam,传入步骤 7 中检索到的句柄和相应的参数类型,以访问所需的编码数据。 例如,传入 CMSG_CONTENT_PARAM 以获取指向整个 PKCS #7 消息的指针。

    如果要将此编码的结果用作另一个编码消息(如信封消息) 的内部数据 ,则必须传递 CMSG_BARE_CONTENT_PARAM 参数。 有关显示此内容的示例,请参阅 用于编码信封邮件的备用代码。

  10. 通过调用 CryptMsgClose 关闭消息。

此过程的结果是包含原始数据的编码消息、该数据的加密哈希 (签名) 以及签名者信息。 还有一个指向所需编码 BLOB 的指针。

有关 C 编码的详细信息,请参阅 示例 C 程序:签名、编码、解码和验证消息。