翻译:《PKCS#7 - SignedData》

1,321 阅读4分钟

本文翻译于 PKI Globe的《PKCS#7 - SignedData》

(欢迎提出修改意见)

以下为翻译文


在开始PKCS#7 SignedData之前还是很有必要先了解下电子签名是如何产生和校验的。

签名和验签

以下是签名计算所需要的步骤:

  • 通过任何一种密钥对生成算法(如RSA)生成一对公钥和私钥。

  • 准备需要用于计算签名的数据。

  • 使用任何一种哈希算法(如SHA256)对数据做摘要。

  • 使用私钥对哈希后的数据进行加密,输出来的就是签名值。

为了验证签名,以下是所需的步骤

  • 为了验证签名,你需要知道已签的数据 (译者注:这里应该指的是原文),签名,哈希算法和公钥。

  • 使用签名过程用到的同样的哈希算法对数据进行哈希。

  • 利用公钥解密签名,你会得到哈希值。

  • 现在比较上面两步得到的哈希,如果它们相等,就意味着数据没有被篡改或者说这个签名是认证的,否则就是被篡改了。

一般来说,一方是签名,另一方是验签。如果你已经注意到了签名验签过程中里的第一步,你会发现在验签之前我们是需要一些标准的方法来存放这些信息。那么PKCS# 7的SignedData就是其中一种存放这些信息的格式。当然还有其它的一些格式,像PDF签名,XML签名等等,但这些它们底层的生成和验签的原理是一样的。

SignedData

PKCS# 7 SignedData是一种针对任意数据生成电子签名的标准格式。像有些数据如果他自身的格式规范不能让它有自己的电子签名,那么你就可以使用这种格式。比如说:你想签署一份文本文件,但因为它没有自己的签名规范,那就能用PKCS# 7 SignedData;而PDF文件因为有它自己的签名规范,所以它就可以用PDF的签名规范进行签名。此外微软的Office文档也有自己的签名规范。你也可以说PKCS# 7 SignedData可以对源数据进行签名。

在PKCS# 7 SignedData里,支持带原文和不带原文两种格式。在带原文的格式里,已签名的数据是SignedData里的一部分,那么在验签的时候,就不需要携带源数据了。而在不带原文的格式里,已签名的数据没有被放在SignedData里,而是在其它外部的地方,所以验签的时候就需要携带原文。

PKCS# 7 SignedData里支持两种类型的签名:

  • 独立签名

  • 会签

在独立签名里,所有的签名者签的都是同一份数据;而在会签里,一个签名者签完后,下一个签名者是在上一个签名者的签名上进行签名。

结构

以下展示的是ASN.1格式下的PKCS# 7 SignedData。因此你需要有能力阅读ASN.1才能完全理解下图。

1)指定了SignedData的结构;

2)指定了生成签名的哈希算法。OID 2.16.840.1.101.3.4.2.1显示使用的是SHA256哈希算法;

3)指定了使用的是不带原文的格式,因为当前没有内容;如果是带原文,那么这里应该是有内容的。

4)包含用于验签时需要用到的公钥的签名证书。它也可以包含签名者的完整证书链。

5)指定了签名信息结构,如果是独立签名,那么应该包含多个签名者的信息。

6)指定了证书发行者和序列号的结构。

7)指定了生成签名用到的哈希算法,这应该跟2)提到的是一样的。

8)显示认证属性的信息,这些属性是签名计算里的部分,如果任何一部分的属性被修改了,那么签名就会失效。另外如果对于未认证属性被修改了,那它就还是能照样验签通过。未认证的属性不会显示在ASN.1结构里。

9)指定了加密算法。

10)指定了签名值。

以上PKCS# 7 结构是用BouncyCastle库生成的。