How to see what attributes are signed inside pkcs#7?

Konstantin Shemyak picture Konstantin Shemyak · Jul 4, 2014 · Viewed 8.2k times · Source

I have a pkcs#7 file, which contains signed data. It successfully verifies:

$ openssl smime -verify -in data.p7s -CAfile root-certificate.pem 
Verification successful
Signed data

But when I extract the signed part, I do not see that it is actually the same as what was signed. I mean the following steps:

$ openssl asn1parse -in data.p7s
...
   35:d=4  hl=2 l=   9 prim: OBJECT            :pkcs7-data
   46:d=4  hl=2 l=inf  cons: cont [ 0 ]        
   48:d=5  hl=2 l=inf  cons: OCTET STRING      
   50:d=6  hl=2 l=   5 prim: OCTET STRING      :(my data is here in plaintext)
...
(then the signed block starts:)
 2861:d=6  hl=2 l=   9 prim: OBJECT            :rsaEncryption
 2872:d=6  hl=2 l=   0 prim: NULL              
 2874:d=5  hl=4 l= 256 prim: OCTET STRING      [HEX DUMP]:<signed data is here>

I cut the [HEX DUMP] with the signed data:

$ dd if=data.p7s of=signed-part.bin bs=1 skip=2878 count=256

Decrypt it with the corresponding public key:

$ openssl rsautl -verify -in signed-part.bin -pubin -inkey root-public-key.pem -out verified-data.bin

and look inside the result:

$ openssl asn1parse -inform der -in verified-data.bin
    0:d=0  hl=2 l=  33 cons: SEQUENCE          
    2:d=1  hl=2 l=   9 cons: SEQUENCE          
    4:d=2  hl=2 l=   5 prim: OBJECT            :sha1
   11:d=2  hl=2 l=   0 prim: NULL              
   13:d=1  hl=2 l=  20 prim: OCTET STRING      [HEX DUMP]:<hash here>

This [HEX DUMP] is not the SHA1 sum of my original data.

I do not understand why the hash is different. Obviously, it's a hash of something different than my original data. Does the hash also cover any "Authenticated attributes"? If yes, how to see what exactly attributes have been hashed and signed?

Answer

mykhal picture mykhal · Jul 5, 2014

OK, you don't provide a full sample, but I'll try to navigate you nevertheless, with a different sample.

OpenSSL asn1parse does not help much identifying the authenticated attributes. You can use OpenSSL cms:

openssl cms -in data.p7s -noout -cmsout -print

Look for signedAttrs ("signed attributes" is how the "authenticated attributes" are now called, in CMS terminology)

It will look like this:

    ...
    signerInfos:
        ...
        signedAttrs:
            object: contentType (1.2.840.113549.1.9.3)
            value.set:
              OBJECT:pkcs7-data (1.2.840.113549.1.7.1)    
            object: signingTime (1.2.840.113549.1.9.5)
            ...

Now go back to asn1parse output, and find the corresponding part, which may look like:

 ...
 1343:d=5  hl=3 l= 216 cons:      cont [ 0 ]
 1346:d=6  hl=2 l=  24 cons:       SEQUENCE
 1348:d=7  hl=2 l=   9 prim:        OBJECT            :contentType
 1359:d=7  hl=2 l=  11 cons:        SET
 1361:d=8  hl=2 l=   9 prim:         OBJECT            :pkcs7-data
 1372:d=6  hl=2 l=  28 cons:       SEQUENCE
 1374:d=7  hl=2 l=   9 prim:        OBJECT            :signingTime
 ...

(for this nice indentation, add -i option)

Now, extract (dd ...) the data, including the DER context tag header, i.e. offset 1343, length 219, in this case. Then replace the 0xa0 byte at the beginning by 0x31. Why you have to do it, is described in DER encoding - How to convert implicit tag to explicit tag, or RFC5652, section 5.4

The sha1 hash of this data should now match.