对签名数据进行编码

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

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

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

对签名消息进行编码

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

对已签名数据进行编码

  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 程序:签名、编码、解码和验证消息