15

I have PKCS7 message which is signed. It contains a data and a signing certificate (with the whole chain of trust).

I have a code which uses m2crypto to get a certificate out of it.

bio = BIO.MemoryBuffer(pkcs7message)
p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(bio._ptr()))
sk = X509.X509_Stack()
certStack = p7.get0_signers(sk)

It works. However, certStack returns only one certificate (instead of returning the whole chain of certificates.

Two questions:

  • Am I missing something (may be there is an option to let it know that I need the whole chain)
  • Are there other methods how to get the whole chain (may be using pyopenssl)?
mpromonet
  • 11,326
  • 43
  • 62
  • 91
Victor Ronin
  • 22,758
  • 18
  • 92
  • 184

1 Answers1

5

I guess you are making a confusion between signers and certificate chain of a signer. PKCS7_get0_signers return the list of signers.

In order to building a PKCS7 message with 2 signers, you can use following steps:

  1. Build key and certificate for first signer:

    openssl genrsa -out key1.pem
    openssl req -new -key key1.pem -subj "/CN=key1" | openssl x509 -req -signkey key1.pem -out cert1.pem
    
  2. Build key and certificate for second signer:

    openssl genrsa -out key2.pem
    openssl req -new -key key2.pem -subj "/CN=key2" | openssl x509 -req -signkey key2.pem -out cert2.pem
    
  3. Create an PKCS7 message using both signers :

    echo "Hello" | openssl smime -sign -nodetach \
      -out signature.der -outform DER \
      -inkey key1.pem -signer cert1.pem -inkey key2.pem -signer cert2.pem 
    

Then signers could be printed running your python script:

from M2Crypto import *

bio=BIO.File(open('signature.der'))
smime_object = SMIME.PKCS7(m2.pkcs7_read_bio_der(bio._ptr()))    
signers = smime_object.get0_signers(X509.X509_Stack())

for cert in signers:
    print(cert.get_issuer().as_text())

It give the signers' issuer:

CN=key1
CN=key2

mpromonet
  • 11,326
  • 43
  • 62
  • 91
  • I am aware of the difference between a signer and signer certificate chain. The code which you have is generally equivalent of my code (to extract signers). However, it doesn't do anything to certificate chains. I got my PKCS7 and was able to extract chain using "openssl pkcs7 print_certs" command (which shows that certificate chain is stored somewhere there). Generally speaking my question is how to extract (in python code) these certificate chain out of PKCS7 – Victor Ronin Jan 15 '16 at 17:03
  • 2
    @VictorRonin in order to get certificate chain `openssl pkcs7 -print_certs` (see [pkcs7.c](https://github.com/openssl/openssl/blob/master/apps/pkcs7.c) ) use `p7->d.sign->certs`. This is not accessible through the m2crypto interface directly, perhaps it could be retrieved using asn1 parsing... – mpromonet Jan 15 '16 at 19:30
  • @mpromonet please write this down as an answer, this comment helped me a lot – Benny Davidovitz Aug 11 '22 at 13:48