对签名数据进行编码
签名数据 由任何类型的内容以及零个或多个签名者的内容加密消息 哈希 组成。 生成的哈希可以确认自签名以来未修改原始消息,以及特定人员或实体对数据进行了签名。
下图描述了对已签名消息进行编码的过程。 下图后面的列表描述了这些步骤。
消息可能有多个签名者、哈希算法和证书。 虽然此图仅显示证书、 CRL 和 CTL 可以使用同一过程。 无论证书显示在何处,它们都适合插图中。
编码 签名数据的 一般过程如下所示。
对已签名数据进行编码
- 如有必要,) (创建数据,并检索指向它的指针。
- 将打开包含签名者证书的证书 存储 。
- 检索证书的私钥。 在使用证书之前,必须对证书设置两个属性。 一个用于将证书绑定到特定 CSP,并在该 CSP 中将证书绑定到特定的 私钥容器。 另一个用于指示在调用哈希操作时要使用的 哈希 算法。 这些只需要设置一次。
- 证书的 属性确定哈希算法。
- 通过哈希函数发送数据来创建数据的哈希。
- 签名是通过使用私钥加密哈希来创建的,该私钥通过证书上的 属性获取。
- 以下数据包含在已完成的签名消息中:
- 要签名的原始数据
- 哈希算法
- 签名
- 签名者信息结构,其中包括签名者标识符 (证书颁发者和序列号)
- 签名者的证书 (可选)
此过程演示了一个简单的情况。 更复杂的情况涉及消息中包含的经过身份验证的属性。 如果内容类型不是 BYTE 字符串,或者至少有一个经过身份验证的属性以及任何数据类型,则需要两个经过身份验证的标准属性:内容 (数据) 类型,以及内容的哈希。 在这些情况下, CryptoAPI 会自动提供这两个必需属性。 低级别消息函数对经过身份验证的属性进行哈希处理,使用私钥加密哈希,并将其作为签名提供。
使用以下过程,使用低级别消息函数完成刚刚列出的任务。
对已签名消息进行编码
创建或检索内容。
获取加密提供程序。
获取签名者证书。
初始化 CMSG_SIGNER_ENCODE_INFO 结构。
初始化 CMSG_SIGNED_ENCODE_INFO 结构。
调用 CryptMsgCalculateEncodedLength 以获取编码的消息 BLOB 的大小。 为其分配内存。
调用 CryptMsgOpenToEncode,传入 dwMsgType 的CMSG_SIGNED和指向 pvMsgEncodeInfoCMSG_SIGNED_ENCODE_INFO的指针,以获取打开的消息句柄。
调用 CryptMsgUpdate,传入步骤 7 中检索到的句柄,以及指向要签名和编码的数据的指针。 可以根据需要多次调用此函数来完成编码过程。
调用 CryptMsgGetParam,传入步骤 7 中检索到的句柄和相应的参数类型,以访问所需的编码数据。 例如,传入 CMSG_CONTENT_PARAM 以获取指向整个 PKCS #7 消息的指针。
如果要将此编码的结果用作另一个编码消息(如信封消息) 的内部数据 ,则必须传递 CMSG_BARE_CONTENT_PARAM 参数。 有关显示此内容的示例,请参阅 用于编码信封邮件的备用代码。
通过调用 CryptMsgClose 关闭消息。
此过程的结果是包含原始数据的编码消息、该数据的加密哈希 (签名) 以及签名者信息。 还有一个指向所需编码 BLOB 的指针。
有关 C 编码的详细信息,请参阅 示例 C 程序:签名、编码、解码和验证消息。