大宝自习室

道路就在脚下

PKCS#7结构分析之签名

| 评论

PKCS#7简单介绍

PKCS#7,又称作加密消息语法标准,是RSA实验室制定的交换消息的一种标准。从RFC 2315文档中知道,PKCS#7一般结构包括两个部分,这两部分结构可以足够支持多种内容类型,文档中定义了6中类型,在稍后会写到。

PKCS#7结构

PKCS#7一般ASN.1结构描述:

ContentInfo ::= SEQUENCE {
    contentType ContentType,
    content  [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL 
}

类型解释:

ContentType

ContentType ::= OBJECT IDENTIFIER

ContentType标示了content的类型,经过ASN.1编码的类型是OBJECT IDENTIFIER,是唯一的整数串来标示。6种content类型,分别为:data, signedData, envelopedData, signedAndEnvelopedData, digestData 和encryptedData. 6中数据类型的标识如下定义:

pkcs-7 OBJECT IDENTIFIER ::=
     { iso(1) member-body(2) US(840) rsadsi(113549) pkcs(1) 7 }

有下列定义:

   data OBJECT IDENTIFIER ::= { pkcs-7 1 }
   signedData OBJECT IDENTIFIER ::= { pkcs-7 2 }
   envelopedData OBJECT IDENTIFIER ::= { pkcs-7 3 }
   signedAndEnvelopedData OBJECT IDENTIFIER ::= { pkcs-7 4 }
   digestedData OBJECT IDENTIFIER ::= { pkcs-7 5 }
   encryptedData OBJECT IDENTIFIER ::= { pkcs-7 6 }

根据上面的描述,很容易就查到6种类型的OBJECT IDENTIFIER的具体数值。 SignedData 的OBJECT IDENTIFIER为"1.2.840.113549.1.7.2”

下面的简单介绍一下content 6中类型的内容编码方式。

  1. Data

    Data :: = OCTET STRING
    
    data类型代表任意的8位字符串,比如ASCII字符串。该字符串不需要任何内部结构,但是有可能他们已经是经过编码(DER)后的字符串。
  2. Signed-data
    sign-data内容类型包括任何类型的数据和0个或者更多的签名者对内容的签名值。内容的任何类型都能够被多个签名者同时类似的签名。当然也有退化的情形,就像没有签名者,这种情况就是提供证书和CRL的分发。
SignedData ::= SEQUENCE {
    version Version,
    digestAlgorithms DigestAlgorithmIdentifiers,
    contentInfo ContentInfo,
    certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
    crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
    signerInfos SignerInfos 
}

其中具体项分析 Version

version Version

Version的编码为Integer,一般设为1;

DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier

DigestAlgorithmIdentifiers是SET结构,分别对应了如果有多个Signers是他们分别的摘要算法标识符或者0个。如果算法中需要某些参数,这其中还应该包含对应的参数。这个集合不存在顺序(SET),但是利于签名验证的一次性就通过。
ContentInfo
ContentInfo就是签名的内容。它能够包含任何定义的内容类型。
certificates
certificates是PKCS#6扩展的证书和X.509证书格式。它的目的是满足从根证书或者上层证书到签名者证书的链式结构。
crls
crls是CRL列表的集合。它的目的是用来决定这些证书是否在这些CRL列表中,但是这些相应的可能不是必须。有可能有比必须的CRL列表要多,也有可能要少。
SignerInfos
signerInfos是每个签名者信息的一个集合。有可能有任何数量的签名者信息,包括0.
Note
1.digestAlgorithms域在contentInfo域前并且signerInfo域在digestAlgorithm域后的安排是为了让它能够一次性的处理SignedData生成PKCS#7结构。
2.Version = 1和Version = 0之间的差别主要在digestAlogrithm,signerInfos和crls域。新版本允许前两个域可以包含0个元素,crls域不包含在就版本中。
3.在退化的情况,若没有签名者在content中,则在contentInfo中的"signed"的值就是不相关的。在这种情况下推荐contentInfo中的content type的值为"signed"值,其中的content中域的值就省略了。
下面的结构式SignerInfo,包含每个签名者的具体信息。

SignerInfo ::= SEQUENCE {
    version Version,
    issuerAndSerialNumber IssuerAndSerialNumber,
    digestAlgorithm DigestAlgorithmIdentifier,
    authenticatedAttributes    [0] IMPLICIT Attributes OPTIONAL,
    digestEncryptionAlgorithm  DigestEncryptionAlgorithmIdentifier,
    encryptedDigest            EncryptedDigest, 
    unauthenticatedAttributes  [1] IMPLICIT Attributes OPTIONAL 
}

version
version的值为1,整数编码。
IssuerAndSerialNumber
issuerAndSerialNumber就指定了签名者用来签名的数字证书,其中包括签名者唯一区别名和特定的证书序列号。
DigestAlgorithm identifies
digestAlgorithm identifies用来标识对消息进行摘要的算法和必要的参数(可选),
AuthenticatedAttributes
authenticatedAttributes是被签名者签名或者认证过的属性集合。这个域是可选的,但是当ContentInfo中content type的不是data类型时,必须包含,而且至少需要2中属性: 1.PKCS#9 content-type属性;
2.PKCS#9 messsage-digest属性;
其他类型的属性在这里也可能有用,像signing time(也定义在PKCS#9)。
DigestEncryptionAlgorithm digestEncryptionAlgorithm 标识着摘要加密的算法和相关的参数等。
EncryptedDigest encryptedDigest就是用签名者的私钥签名摘要后的结果值。
UnauthenticatedAttributes unauthenticatedAttributes是没有被签名或者认证的属性集,并且是可选的。属性类型有些可能会很有用处,像countersignatures(定义在PKCS#9)。

Note:
1.为了跟PEM的兼容性,推荐ContentInfo中content type的值被签名的是数据,并且没有认证的属性。 2.只生成Version为1的p7.

摘要处理过程
摘要处理过程是处理将被签名的content或者这个content和签名者认证过得属性。在这两种情况,开始都是对将被签名的content进行摘要处理。特别是开始输入的是ContentInfo经过DER编码后的值域范围的8位字节数据。只有这些数据的内容被计算摘要,8位字节标识和其长度都不包括在内。
消息摘要处理的结果取决于是否有authenticatedAttributes这项。若没有这项,就只对ContentInfo处理;当这项曾在时,消息摘要的计算范围包括所有认证后的属性的DER编码值(IMPLICIT[0]这个标签不包含在内,“SET OF"的标签包含在内,并且包括长度和编码后的内容).由于有属性值,当这个域曾在时

摘要加密处理
摘要的ASN.1描述:

DigestInfo ::= SEQUENCE {
    digestAlgorithm DigestAlgorithmIdentifier,
    digest Digest 
}
Digest ::= OCTET STRING

digestAlgorithm标识用来计算内容和鉴别属性的摘要的消息摘要算法(和相应的参数)。它应该和SignerInfo的digestAlgorithm域有同样的值。
digest是消息摘要处理的结果。
1.这里签名过程和PKCS#1中定义的签名算法的唯一不同在于PKCS#1中的签名用比特串表示(为了和X509的SIGNED宏一致),这里加密的消息摘要用字节串表示。
2.加密处理的输入通常有30个或更少字节。如果digestEncryptionAlgorithm是PKCS #1的rsaEncryption,则表示输入能够在一个单块中加密,并且只要RSA模块的长度至少有328比特,这是合理的并且和安全建议相一致。
3.消息摘要算法标识符包含在DigestInfo值中,这种情况杜绝了攻击者利用其他弱摘要算法了替代计算摘要的算法来逆向计算,伪造另外的消息来匹配该摘要值。如果指定了算法标识,这种攻击显然不成立了。
4.由于DigestInfo值中并没有指示digest域是否仅包含内容的消息摘要或是有authenticatedAttributes的完全DER编码的消息摘要,故存在一个潜在的含糊的地方。就是说,攻击有可能把包括鉴别属性上的签名转换成只在内容上的签名,通过改变将要DER编码的内容进而去掉authenticatedAttributes值。
PEM兼容性
如果待签名的ContentInfo的content type值是data类型,没有鉴别属性,消息摘要算法是md2或md5并且摘要加密算法是PKCS#1的rsaEncryption时,其与PEM的MIC-ONLY 和MIC-CLEAR处理类型兼容。

评论