Question

How can i extract the public certificate from an smime message (pkcs7-signature) with OpenSSL?

Was it helpful?

Solution

With the command-line tool, assuming the S/MIME message itself is in file message:

openssl smime -verify -in message -noverify -signer cert.pem -out textdata

This writes the signer certificate (as embedded in the signature blob) into cert.pem, and the message text data in the textdata file.

Alternatively, you can save the signature blob as an independent file (it is just a kind of attachment, so any mailer application or library should be able to do that. Then, assuming that the said blob is in a file named smime.p7s, use:

openssl pkcs7 -in smime.p7s -inform DER -print_certs

which will print out all certificates which are embedded in the PKCS#7 signature. Note that there can be several: the signer's certificate itself, and any extra certificates that the signer found fit to include (e.g. intermediate CA certificates which may help in validating his certificate).

OTHER TIPS

Or just:

cat message.eml | openssl smime -pk7out | openssl pkcs7 -print_certs > senders-cert.pem

If you are writing C/C++, this code snippet would help

    //...assuming you have valid pkcs7, st1, m_store etc......

    verifyResult = PKCS7_verify( pkcs7, st1, m_store, content, out, flags);
    if(verifyResult != 1) {
        goto exit_free;
    }

    //Obtain the signers of this message. Certificates from st1 as well as any found included
    //in the message will be returned.
    signers = PKCS7_get0_signers(pkcs7, st1, flags);
    if (!save_certs(env, signerFilePath, signers)) {
        //Error log
    }

//This method will write the signer certificates into a file provided
int save_certs(JNIEnv *env, jstring signerFilePath, STACK_OF(X509) *signers)
{
    int result = 0;
    int i;
    BIO *tmp;
    int num_certificates = 0;

    if (signerFilePath == NULL) {
        return 0;
    }

    const char *signerfile = (const char *)env->GetStringUTFChars(signerFilePath, 0);
    tmp = BIO_new_file(signerfile, "w");
    if (!tmp) {
        //error. return
    }
    num_certificates = sk_X509_num(signers);
    for(i = 0; i < num_certificates; i++) {
        PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
    }
    result = 1;

    exit_free:
    BIO_free(tmp);
    if (signerfile) {
        env->ReleaseStringUTFChars(signerFilePath, signerfile);
        signerfile = 0;
    }
    return result;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top