ietf-smime
[Top] [All Lists]

Re: AlgorithmIdentifier, SHA-1, etc.

2007-04-06 13:37:02

Note that the DigestInfoValue is part of the structure that is "encrypted" with the RSA private key when generating a signature. It is recovered by "decrypting" the signature value with the RSA public key.

An implementation should check that the expected digest algorithm was used. As Eric point out, this check is easier to perform if the two values are encoded in exactly the same manner.

One needs to look deeper into signatures in certificates and CMS SignerInfo to see where these comparisons are really performed.

The certificate signature has this structure:

   Certificate  ::=  SEQUENCE  {
        tbsCertificate       TBSCertificate,
        signatureAlgorithm   AlgorithmIdentifier,
        signatureValue       BIT STRING  }

In practice, the signature algorithm tells the digest algorithm as well as the digital signature algorithm. The ones that are relevant to this question are:

   sha1WithRSAEncryption
   sha224WithRSAEncryption
   sha256WithRSAEncryption
   sha384WithRSAEncryption
   sha512WithRSAEncryption

There is no filed that explicitly carries a digest algorithm identifier. So, the digest algorithm for comparison to the DigestInfoValue inside the signature value must be generated in some manner by the implementation. I believe than many implementations use a simple internal table. Adding entries to this table is part of the work needed to add support for additional RSA signature algorithms. So, the table should contain exactly the octet string that will appear in DigestInfoValue, including the NULL parameter required by PKCS#1.

The CMS SignerInfo has this structure:

      SignerInfo ::= SEQUENCE {
        version CMSVersion,
        sid SignerIdentifier,
        digestAlgorithm DigestAlgorithmIdentifier,
        signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
        signatureAlgorithm SignatureAlgorithmIdentifier,
        signature SignatureValue,
        unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }

Again, the signature algorithm tells the digest algorithm. The same set of algorithm identifiers are used here.

In each case, the digestAlgorithm must contain the digest algorithm identifier that is implicitly named by the signature algorithm, and the DigestInfoValue must contain the same digest algorithm identifier.

As Eric has already explained, the parameter in DigestInfoValue must be NULL, but we are "forgiving" in the processing of the parameter for digestAlgorithm. The parameter can be NULL or absent.

In order to use the same signature validation routines for CMS and certificates, I believe that most implementations use the same internal table as discussed above for the DigestInfoValue comparison. Then, in addition, the digest algorithm identifier is compared to the digestAlgorithm field in SignerInfo. The signature value must contain exactly the expected digest algorithm identifier with a NULL parameter.

So, the only comparison that is not an exact match is the comparison from the internal table entry to the digestAlgorithm field. I suggest that the object identifiers must match, but one can ignore the parameters, after making sure they are either absent or NULL. That is, do not let the parameters carry some inappropriate value.

Russ


At 02:30 PM 4/6/2007, Eric Rescorla wrote:

I'm trying to get a handle on how one ought to encode AlgorithmIdentifier.

As people will perhaps remember, the ASN.1 is:


AlgorithmIdentifier  ::=  SEQUENCE  {
     algorithm               OBJECT IDENTIFIER,
     parameters              ANY DEFINED BY algorithm OPTIONAL  }
                                -- contains a value of the type
                                -- registered for use with the
                                -- algorithm object identifier value

Present hash functions do not take any useful parameters, leaving
us with two encoding options:

  - omit the parameter.
  - include a NULL

To make things more complicated, there are (at least) two different
contexts in which this production appears:

  - The S/MIME DigestAlgorithmIdentifier production.
  - Inside the DigestInfo of the S/MIME signature.

RFC 3370's guidance is to omit the parameter for SHA-1 and include
a NULL for MD5 (see S 2.1 and 2.2.).

However, the current PKCS#1 errata
(ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1errata.txt)
recommend that when one is encoding DigestInfo, one should
encode it as NULL:

  Exception: When formatting the DigestInfoValue in EMSA-PKCS1-V1.5
  (see 9.2), the parameters field associated with id-sha1, id-sha256,
  id-sha384 and id-sha512 SHALL have a value of type NULL. This is to
  maintain compatibility with existing implementations and with the
  numeric information values already published for EMSA-PKCS1-V1.5
  which are also reflected in IEEE 1363a-2004[27].

My understanding from discussions in Prague is that this reflects
NIST's current guidance as well.

Technically these don't conflict, but obviously, it's undesirable to
have the encoding in the message not match that in the DigestInfo,
since doing binary comparisons is common practice here. So, what's the
right answer here?

-Ekr