3

I have to create a PKCS7 signature file signed by an X.509 certificate and I have to embed an XML file within.

How to do that with OpenSSL or any other tool?

3

To be clear, the data to be signed is exactly the contents of a file, XML or otherwise?

You can't sign with only a certificate. You must sign with a privatekey and then provide the matching certificate to allow the recipient(s) to verify the message when they receive it. When using a certificate issued by a well-known CA (e.g. Verisign) you usually must provide a certificate chain not just the single certificate. Some UIs (especially Windows and at least some other browsers) confusingly use the term "certificate" to mean either just a single cert by itself, or a combination of a privatekey plus one cert or a chain of certs.

OpenSSL actually supports CMS (Cryptographic Message Syntax) which is the updated IETF version of PKCS#7, like TLS is the updated IETF version of SSL. If the very small technical differences between the older version PKCS#7 and the current version CMS matter to you or your recipient(s), you will probably need to write a custom program, which can use the OpenSSL library. OpenSSL also supports S/MIME which is basically just CMS adapted to MIME format (used in Internet-email and HTTP). To confuse things a bit, current OpenSSL commandline has two subcommands:

  • openssl smime ... an older utility that actually supports both S/MIME and CMS

  • openssl cms ... a newer utility that also actually supports both CMS and S/MIME

See https://www.openssl.org/docs/apps/smime.html and https://www.openssl.org/docs/apps/cms.html .

The simplest case of signing with embedded (not "detached") data is if you have the X.509 cert and privatekey (both) in PEM format in a file:

openssl cms -in datafile -sign -signer keyandcertfile -nodetach -outform pem|der

Select -outform pem or der depending on which output format you want, but don't omit it; the default format is S/MIME which is not what you asked for. Output is normally on stdout, which you can redirect or pipe to something else as appropriate; add -out outputfile to write directly to a file.

Variations: If you have the key and cert in different files, but both PEM, you can either just concatenate them into one file, or use -signer certfile -inkey keyfile. If you need to supply a chain cert (or several) and you have it (or them) in PEM format in a file or files, add -certfile chaincertfile once or as many times as needed. If the "certificate" (and privatekey!) you have is in any other form(s), OpenSSL can convert many other forms (though not all) to the PEM files it prefers; provide more exact details. (Edit your question by clicking on the word "edit" at its bottom; for clarity state which data is added or changed.) If your data is not exactly one file, but can be selected or otherwise produced by some other program, omit -in inputfile and instead pipe the input of openssl from that other program.

All this assumes OpenSSL is available on the system you use, or equivalently you use a system where OpenSSL is available. If you need to obtain OpenSSL, specify your OS.

  • thank you for your clear answer,you realy saved me. This is what I looked for. I'm working on ubuntu, and I have to treat this signature by a java program. So in my program I have to open the file (pkcs7), verify the signature and extract the xml file. – Hakim Jun 26 '15 at 9:10
  • I didn't understand what I must edit in my question? – Hakim Jun 26 '15 at 9:12
  • @Hakim openssl cms only uses a privatekey and matching certificate(s) in PEM format. If you have the privatekey and cert(s) in some other form(s) not PEM, there are other OpenSSL operations that may be of use, but to give advice on them I need to know what other form(s) you have. So if you don't have PEM, specify what you do have. Also if you don't have OpenSSL, and want help to get it, specify your OS. Except for those two possibilities, I believe I've covered it and you don't need to edit. – dave_thompson_085 Jun 27 '15 at 1:48
  • yes i solved my problem thanks to your answer. I used openssl smime because I don't know if the api that I use in java supports the new version of PKCS7. So this is my command line : openssl smime -in example.xml -sign -signer myCA -inkey root.key -nodetach -outform pem -out test.p7b – Hakim Jun 29 '15 at 10:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.